yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/HrmAttendanceClockTypeEnum.java
@@ -28,4 +28,19 @@ return ARRAYS; } /** * æ ¹æ®ç±»åè·ååç§°ï¼æªç¥ç±»åè¿å null */ public static String getNameByType(Integer type) { if (type == null) { return null; } for (HrmAttendanceClockTypeEnum value : values()) { if (value.getType().equals(type)) { return value.getName(); } } return null; } } yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/HrmAttendanceRecordController.java
@@ -7,12 +7,14 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceMyStatusRespVO; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordImportExcelVO; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordImportReqVO; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordPageReqVO; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordRespVO; import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRecordDO; import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO; import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceClockTypeEnum; import cn.iocoder.yudao.module.hrm.service.attendance.HrmAttendanceRecordService; import cn.iocoder.yudao.module.hrm.service.employee.HrmEmployeeService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; @@ -25,11 +27,13 @@ import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @@ -37,6 +41,7 @@ import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.EMPLOYEE_NOT_EXISTS; @Tag(name = "管çåå° - HRM èå¤è®°å½") @@ -56,36 +61,46 @@ @PostMapping("/clock-in") @Operation(summary = "ä¸çæå¡") @PreAuthorize("@ss.hasPermission('hrm:attendance:clock')") public CommonResult<HrmAttendanceRecordRespVO> clockIn(@RequestParam("location") String location) { Long loginUserId = getLoginUserId(); HrmEmployeeDO employee = employeeService.getEmployeeByUserId(loginUserId); if (employee == null) { throw exception(EMPLOYEE_NOT_EXISTS, "å½åç¨æ·æªå ³èå工信æ¯ï¼æ æ³æå¡"); throw exception(EMPLOYEE_NOT_EXISTS, "å½åç»å½è´¦å·æªå ³èå工档æ¡ï¼æ æ³æå¡ã请è系管çåå¨ãå工管çãä¸å°è¯¥ç»å½è´¦å·ç»å®å°åå·¥ã"); } HrmAttendanceRecordDO record = attendanceRecordService.clockIn(employee.getId(), LocalDateTime.now(), location); HrmAttendanceRecordRespVO respVO = BeanUtils.toBean(record, HrmAttendanceRecordRespVO.class); respVO.setUserName(employee.getName()); if (record.getDeptId() != null) { DeptRespDTO dept = deptApi.getDept(record.getDeptId()); if (dept != null) { respVO.setDeptName(dept.getName()); } } return success(respVO); return success(buildClockRespVO(record, employee)); } @PostMapping("/clock-out") @Operation(summary = "ä¸çæå¡") @PreAuthorize("@ss.hasPermission('hrm:attendance:clock')") public CommonResult<HrmAttendanceRecordRespVO> clockOut(@RequestParam("location") String location) { Long loginUserId = getLoginUserId(); HrmEmployeeDO employee = employeeService.getEmployeeByUserId(loginUserId); if (employee == null) { throw exception(EMPLOYEE_NOT_EXISTS, "å½åç¨æ·æªå ³èå工信æ¯ï¼æ æ³æå¡"); throw exception(EMPLOYEE_NOT_EXISTS, "å½åç»å½è´¦å·æªå ³èå工档æ¡ï¼æ æ³æå¡ã请è系管çåå¨ãå工管çãä¸å°è¯¥ç»å½è´¦å·ç»å®å°åå·¥ã"); } HrmAttendanceRecordDO record = attendanceRecordService.clockOut(employee.getId(), LocalDateTime.now(), location); return success(buildClockRespVO(record, employee)); } @GetMapping("/my-status") @Operation(summary = "è·å¾å½åç»å½äººçèå¤ç¶æ") @Parameter(name = "date", description = "è夿¥æï¼æ ¼å¼ yyyy-MM-ddï¼é»è®¤æå¡å¨å½å¤©", example = "2026-10-17") public CommonResult<HrmAttendanceMyStatusRespVO> getMyStatus( @RequestParam(value = "date", required = false) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) LocalDate date) { return success(attendanceRecordService.getMyStatus(getLoginUserId(), date)); } /** * æå»ºæå¡è¿å VOï¼åæ®µä¸ my-status.record ä¿æä¸è´ */ private HrmAttendanceRecordRespVO buildClockRespVO(HrmAttendanceRecordDO record, HrmEmployeeDO employee) { HrmAttendanceRecordRespVO respVO = BeanUtils.toBean(record, HrmAttendanceRecordRespVO.class); respVO.setClockInTypeName(HrmAttendanceClockTypeEnum.getNameByType(record.getClockInType())); respVO.setClockOutTypeName(HrmAttendanceClockTypeEnum.getNameByType(record.getClockOutType())); respVO.setUserName(employee.getName()); if (record.getDeptId() != null) { DeptRespDTO dept = deptApi.getDept(record.getDeptId()); @@ -93,7 +108,7 @@ respVO.setDeptName(dept.getName()); } } return success(respVO); return respVO; } private Long getLoginUserId() { yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceMyStatusRespVO.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,67 @@ package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDate; import java.time.LocalDateTime; @Schema(description = "管çåå° - æçèå¤ç¶æ Response VO") @Data public class HrmAttendanceMyStatusRespVO { @Schema(description = "ç»å½ç¨æ·ID", example = "464") private Long userId; @Schema(description = "å工档æ¡ID", example = "233") private Long employeeId; @Schema(description = "åå·¥å§å", example = "é¿åæå çæ¨Â·å¾æä¾æ¨") private String employeeName; @Schema(description = "é¨é¨ID", example = "131") private Long deptId; @Schema(description = "é¨é¨åç§°", example = "é¢ç»æè½¦é´") private String deptName; @Schema(description = "è夿¥æ", example = "2026-10-17") private LocalDate date; @Schema(description = "æå¡å¨æ¶é´", example = "2026-10-17 18:30:00") private LocalDateTime serverTime; @Schema(description = "æ¯å¦å·¥ä½æ¥") private Boolean workDay; @Schema(description = "伿¯æ¥åå ï¼å¦ï¼å½åºèãå¨å ") private String restDayReason; @Schema(description = "å½åçæçèå¤è§åï¼æªé ç½®æ¶ä¸º null") private HrmAttendanceRuleRespVO rule; @Schema(description = "彿¥èå¤è®°å½ï¼æªæå¡æ¶ä¸º null") private HrmAttendanceRecordRespVO record; @Schema(description = "å½å坿å¡ç¶æ") private Clockable clockable; @Schema(description = "æå¡ç¶æ") @Data public static class Clockable { @Schema(description = "æ¯å¦å¯ä¸çæå¡") private Boolean clockIn; @Schema(description = "æ¯å¦å¯ä¸çæå¡") private Boolean clockOut; @Schema(description = "ä¸ä¸æ¥å¨ä½ï¼in-ä¸çæå¡ï¼out-ä¸çæå¡ï¼none-æ éæå¡") private String nextAction; @Schema(description = "æç¤ºææ¡", example = "å·²ä¸çæå¡ï¼å¯ä¸çæå¡") private String message; } } yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/HrmAttendanceRecordRespVO.java
@@ -55,11 +55,17 @@ @DictFormat("hrm_clock_type") private Integer clockInType; @Schema(description = "ä¸çæå¡ç±»ååç§°", example = "æ£å¸¸") private String clockInTypeName; @Schema(description = "ä¸çæå¡ç±»å") @ExcelProperty(value = "ä¸çæå¡ç±»å", converter = DictConvert.class) @DictFormat("hrm_clock_type") private Integer clockOutType; @Schema(description = "ä¸çæå¡ç±»ååç§°", example = "æ©é") private String clockOutTypeName; @Schema(description = "工使¶é¿ï¼å°æ¶ï¼") @ExcelProperty("工使¶é¿") private BigDecimal workHours; yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/attendance/HrmAttendanceRuleMapper.java
@@ -37,4 +37,16 @@ .orderByAsc(HrmAttendanceRuleDO::getName)); } /** * æ¥è¯¢é¨é¨ä¸å·²å¯ç¨çè§åï¼ææ°å建çæå¨åé¢ * * åä¸é¨é¨åå¨å¤æ¡å¯ç¨è§åæ¶ï¼ä»¥ææ°å建ç䏿¡ä¸ºå½åçæè§å */ default List<HrmAttendanceRuleDO> selectEnabledListByDeptId(Long deptId) { return selectList(new LambdaQueryWrapperX<HrmAttendanceRuleDO>() .eq(HrmAttendanceRuleDO::getDeptId, deptId) .eq(HrmAttendanceRuleDO::getStatus, 0) .orderByDesc(HrmAttendanceRuleDO::getId)); } } yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceRecordService.java
@@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.hrm.service.attendance; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceMyStatusRespVO; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordPageReqVO; import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRecordDO; import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceExceptionDO; @@ -37,6 +38,15 @@ */ HrmAttendanceRecordDO getAttendanceRecordByUserIdAndDate(Long userId, LocalDate date); /** * è·å¾å½åç»å½äººçèå¤ç¶æï¼èå¤è§å + æå®æ¥æçæå¡ç¶æ * * @param loginUserId ç»å½ç¨æ·IDï¼ç³»ç»ç¨æ·IDï¼ä¸æ¯åå·¥IDï¼ * @param date è夿¥æï¼ä¸ºç©ºæ¶åæå¡å¨å½å¤© * @return æçèå¤ç¶æ */ HrmAttendanceMyStatusRespVO getMyStatus(Long loginUserId, LocalDate date); /** åå»ºå¯¼å ¥çèå¤è®°å½ */ void createImportedRecord(HrmAttendanceRecordDO record); yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceRecordServiceImpl.java
@@ -2,7 +2,11 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceMyStatusRespVO; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordPageReqVO; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRecordRespVO; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceRuleRespVO; import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceHolidayDO; import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRecordDO; import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceRuleDO; import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceExceptionDO; @@ -11,7 +15,10 @@ import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceClockTypeEnum; import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceDataSourceEnum; import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceExceptionTypeEnum; import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceHolidayTypeEnum; import cn.iocoder.yudao.module.hrm.service.employee.HrmEmployeeService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -19,6 +26,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.time.DayOfWeek; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; @@ -45,6 +53,8 @@ private HrmAttendanceRuleService attendanceRuleService; @Resource private HrmAttendanceHolidayService attendanceHolidayService; @Resource private DeptApi deptApi; @Override public PageResult<HrmAttendanceRecordDO> getAttendanceRecordPage(HrmAttendanceRecordPageReqVO pageReqVO) { @@ -67,6 +77,162 @@ } @Override public HrmAttendanceMyStatusRespVO getMyStatus(Long loginUserId, LocalDate date) { LocalDate queryDate = date != null ? date : LocalDate.now(); // 1. ç»å½ç¨æ· -> åå·¥æ¡£æ¡ HrmEmployeeDO employee = employeeService.getEmployeeByUserId(loginUserId); if (employee == null) { throw exception(EMPLOYEE_NOT_EXISTS, "å½åç»å½è´¦å·æªå ³èå工档æ¡ï¼æ æ³æå¡ã请è系管çåå¨ãå工管çãä¸å°è¯¥ç»å½è´¦å·ç»å®å°åå·¥ã"); } HrmAttendanceMyStatusRespVO respVO = new HrmAttendanceMyStatusRespVO(); respVO.setUserId(loginUserId); respVO.setEmployeeId(employee.getId()); respVO.setEmployeeName(employee.getName()); respVO.setDeptId(employee.getDeptId()); if (employee.getDeptId() != null) { DeptRespDTO dept = deptApi.getDept(employee.getDeptId()); if (dept != null) { respVO.setDeptName(dept.getName()); } } respVO.setDate(queryDate); respVO.setServerTime(LocalDateTime.now()); // 2. æ¯å¦å·¥ä½æ¥ + 伿¯åå boolean workDay = attendanceHolidayService.isWorkDay(queryDate); respVO.setWorkDay(workDay); if (!workDay) { respVO.setRestDayReason(getRestDayReason(queryDate)); } // 3. å½åçæè§åï¼é¨é¨è§åä¼å ï¼å ¶æ¬¡å ¨å±è§åï¼ HrmAttendanceRuleDO rule = attendanceRuleService.getAttendanceRuleByDeptId(employee.getDeptId()); if (rule != null) { HrmAttendanceRuleRespVO ruleRespVO = BeanUtils.toBean(rule, HrmAttendanceRuleRespVO.class); if (rule.getDeptId() != null) { DeptRespDTO ruleDept = deptApi.getDept(rule.getDeptId()); if (ruleDept != null) { ruleRespVO.setDeptName(ruleDept.getName()); } } respVO.setRule(ruleRespVO); } // 4. 彿¥èå¤è®°å½ HrmAttendanceRecordDO record = attendanceRecordMapper.selectByUserIdAndDate(employee.getId(), queryDate); if (record != null) { respVO.setRecord(buildRecordRespVO(record, employee)); } // 5. å½å坿å¡ç¶æ respVO.setClockable(buildClockable(workDay, rule, record, queryDate)); return respVO; } /** * 伿¯æ¥åå ï¼ä¼å åè忥é ç½®åç§°ï¼æªé ç½®æ¶æææç»åºâå¨å /卿¥â */ private String getRestDayReason(LocalDate date) { List<HrmAttendanceHolidayDO> holidays = attendanceHolidayService.getAttendanceHolidayListByDateRange(date, date); for (HrmAttendanceHolidayDO holiday : holidays) { if (HrmAttendanceHolidayTypeEnum.REST_DAY.getType().equals(holiday.getType())) { return holiday.getName(); } } DayOfWeek dayOfWeek = date.getDayOfWeek(); if (dayOfWeek == DayOfWeek.SATURDAY) { return "å¨å "; } if (dayOfWeek == DayOfWeek.SUNDAY) { return "卿¥"; } return null; } /** * æå»ºæå¡è®°å½è¿å VOï¼è¡¥é½æå¡ç±»ååç§°ãåå·¥ä¸é¨é¨ä¿¡æ¯ */ private HrmAttendanceRecordRespVO buildRecordRespVO(HrmAttendanceRecordDO record, HrmEmployeeDO employee) { HrmAttendanceRecordRespVO recordRespVO = BeanUtils.toBean(record, HrmAttendanceRecordRespVO.class); recordRespVO.setClockInTypeName(HrmAttendanceClockTypeEnum.getNameByType(record.getClockInType())); recordRespVO.setClockOutTypeName(HrmAttendanceClockTypeEnum.getNameByType(record.getClockOutType())); if (employee != null) { recordRespVO.setUserName(employee.getName()); recordRespVO.setPhone(employee.getPhone()); } if (record.getDeptId() != null) { DeptRespDTO dept = deptApi.getDept(record.getDeptId()); if (dept != null) { recordRespVO.setDeptName(dept.getName()); } } return recordRespVO; } /** * æ ¹æ®å·¥ä½æ¥ãèå¤è§åä¸å½æ¥è®°å½è®¡ç®å¯æå¡ç¶æ */ private HrmAttendanceMyStatusRespVO.Clockable buildClockable(boolean workDay, HrmAttendanceRuleDO rule, HrmAttendanceRecordDO record, LocalDate date) { HrmAttendanceMyStatusRespVO.Clockable clockable = new HrmAttendanceMyStatusRespVO.Clockable(); if (!workDay) { clockable.setClockIn(false); clockable.setClockOut(false); clockable.setNextAction("none"); clockable.setMessage("仿¥ä¼æ¯ï¼æ éæå¡"); return clockable; } if (rule == null) { clockable.setClockIn(false); clockable.setClockOut(false); clockable.setNextAction("none"); clockable.setMessage("æªé ç½®èå¤è§åï¼è¯·è系管çå"); return clockable; } // åªæä¸çå¡ã没æä¸çå¡ï¼å½æ¥å·²ç»æï¼ä¸åå è®¸ç»§ç»æå¡ if (record != null && record.getClockInTime() == null && record.getClockOutTime() != null) { clockable.setClockIn(false); clockable.setClockOut(false); clockable.setNextAction("none"); clockable.setMessage("仿¥ç¼ºä¸çå¡ï¼å·²å®æä¸çæå¡"); return clockable; } // ä»å¤©è¿æ²¡æä¸çå¡ if (record == null || record.getClockInTime() == null) { clockable.setClockIn(true); clockable.setClockOut(false); clockable.setNextAction("in"); clockable.setMessage("å¯ä¸çæå¡"); // ä» å½å¤©æ¥è¯¢æ¶æç¤ºå·²è¿å°æ¶é¿ LocalDateTime now = LocalDateTime.now(); if (rule.getWorkStartTime() != null && date.equals(now.toLocalDate())) { LocalDateTime workStart = LocalDateTime.of(date, rule.getWorkStartTime()); int lateAllowMinutes = rule.getLateAllowMinutes() != null ? rule.getLateAllowMinutes() : 0; if (now.isAfter(workStart.plusMinutes(lateAllowMinutes))) { long lateMinutes = Duration.between(workStart, now).toMinutes(); clockable.setMessage("å·²è¶ è¿ä¸çæ¶é´ " + lateMinutes + " åé"); } } return clockable; } // å·²æä¸çå¡ãæªæä¸çå¡ if (record.getClockOutTime() == null) { clockable.setClockIn(false); clockable.setClockOut(true); clockable.setNextAction("out"); clockable.setMessage("å·²ä¸çæå¡ï¼å¯ä¸çæå¡"); return clockable; } // ä¸ä¸çå¡é½å·²æ clockable.setClockIn(false); clockable.setClockOut(false); clockable.setNextAction("none"); clockable.setMessage("仿¥å·²å®ææå¡"); return clockable; } @Override public void createImportedRecord(HrmAttendanceRecordDO record) { // æèå¤è§åéç®æå¡ç±»å䏿¶é¿ï¼ä¸ä¿¡ä»» Excel å¡«åçå¼ fillClockTypes(record); yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceRuleServiceImpl.java
@@ -20,9 +20,11 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -136,17 +138,26 @@ @Override public HrmAttendanceRuleDO getAttendanceRuleByDeptId(Long deptId) { // 1. å æ¥æ¾é¨é¨ä¸å±è§å List<HrmAttendanceRuleDO> deptRules = attendanceRuleMapper.selectList(new cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX<HrmAttendanceRuleDO>() .eq(HrmAttendanceRuleDO::getDeptId, deptId) .eq(HrmAttendanceRuleDO::getStatus, 0)); if (!deptRules.isEmpty()) { return deptRules.get(0); // 1. ä»åå·¥æå¨é¨é¨å¼å§é级å䏿¥æ¾ï¼é ç½®å¨ä¸çº§é¨é¨çè§åå¯¹å ¶åé¨é¨çæ Set<Long> visitedDeptIds = new HashSet<>(); Long currentDeptId = deptId; while (currentDeptId != null && currentDeptId != 0 && visitedDeptIds.add(currentDeptId)) { List<HrmAttendanceRuleDO> deptRules = attendanceRuleMapper.selectEnabledListByDeptId(currentDeptId); if (!deptRules.isEmpty()) { // åä¸é¨é¨ï¼å¦ãæ»å ¬å¸ãï¼å¯è½é ç½®äºå¤æ¡å¯ç¨è§åï¼ä»¥ææ°å建ç为å½åçæè§å return deptRules.get(0); } DeptRespDTO dept = deptApi.getDept(currentDeptId); if (dept == null) { break; } currentDeptId = dept.getParentId(); } // 2. æ¥æ¾å ¨å±è§åï¼deptId 为 nullï¼ List<HrmAttendanceRuleDO> globalRules = attendanceRuleMapper.selectList(new cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX<HrmAttendanceRuleDO>() .isNull(HrmAttendanceRuleDO::getDeptId) .eq(HrmAttendanceRuleDO::getStatus, 0)); .eq(HrmAttendanceRuleDO::getStatus, 0) .orderByDesc(HrmAttendanceRuleDO::getId)); if (!globalRules.isEmpty()) { return globalRules.get(0); }