| | |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalTime; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | import java.util.Set; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.*; |
| | |
| | | |
| | | @Override |
| | | public PageResult<HrmAttendanceRecordDO> getAttendanceRecordPage(HrmAttendanceRecordPageReqVO pageReqVO) { |
| | | return attendanceRecordMapper.selectPage(pageReqVO); |
| | | // 员工姓名模糊搜索:先按姓名查出员工ID集合,再按集合过滤 |
| | | // (hrm_attendance_record.user_id 存的是 hrm_employee.id) |
| | | Set<Long> nameMatchedIds = null; |
| | | if (StrUtil.isNotBlank(pageReqVO.getUserName())) { |
| | | List<HrmEmployeeDO> matched = employeeService.getEmployeeListByNameLike(pageReqVO.getUserName().trim()); |
| | | nameMatchedIds = matched.stream().map(HrmEmployeeDO::getId).collect(Collectors.toSet()); |
| | | if (nameMatchedIds.isEmpty()) { |
| | | // 姓名搜不到人时直接返回空,避免退化成查全部 |
| | | return PageResult.empty(); |
| | | } |
| | | } |
| | | return attendanceRecordMapper.selectPage(pageReqVO, nameMatchedIds); |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | |
| | | /** |
| | | * 按考勤规则重算上下班打卡类型(正常/迟到/早退),与打卡逻辑保持一致 |
| | | * 按考勤规则重算上下班打卡类型(正常/迟到/早退/缺卡),与打卡逻辑保持一致 |
| | | * |
| | | * <p>缺卡标记不依赖考勤规则:只要某一侧没有打卡时间就是缺卡。 |
| | | * 原实现只在「该侧有打卡时间」时才设置类型,导致「只打上班卡、没打下班卡」的记录 |
| | | * clockOutType 一直是 null;而考勤统计只认 MISSING 类型, |
| | | * 于是缺卡次数永远统计为 0(客户反馈「缺卡数据统计不对、没和考勤记录联动」)。 |
| | | */ |
| | | private void fillClockTypes(HrmAttendanceRecordDO record) { |
| | | // 1. 缺卡优先:某一侧没有打卡时间即为缺卡,不依赖部门与考勤规则 |
| | | if (record.getClockInTime() == null) { |
| | | record.setClockInType(HrmAttendanceClockTypeEnum.MISSING.getType()); |
| | | } |
| | | if (record.getClockOutTime() == null) { |
| | | record.setClockOutType(HrmAttendanceClockTypeEnum.MISSING.getType()); |
| | | } |
| | | |
| | | if (record.getDeptId() == null) { |
| | | return; |
| | | } |