| | |
| | | .divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP); |
| | | record.setWorkHours(workHours); |
| | | } |
| | | // 7. 计算加班时长:超过规则下班时间的部分 |
| | | record.setOvertimeHours(computeOvertimeHours(rule.getWorkEndTime(), clockTimeOnly)); |
| | | attendanceRecordMapper.updateById(record); |
| | | return record; |
| | | } |
| | | |
| | | /** |
| | | * 计算加班时长(小时):clockTimeOnly 晚于 workEndTime 的部分,否则为 0 |
| | | */ |
| | | private BigDecimal computeOvertimeHours(LocalTime workEndTime, LocalTime clockTimeOnly) { |
| | | if (workEndTime == null || clockTimeOnly == null || !clockTimeOnly.isAfter(workEndTime)) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | return BigDecimal.valueOf(Duration.between(workEndTime, clockTimeOnly).toMinutes()) |
| | | .divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void recordOvertime(HrmAttendanceExceptionDO exception) { |
| | | // 仅处理加班类型 |
| | | if (!HrmAttendanceExceptionTypeEnum.OVERTIME.getType().equals(exception.getType()) |
| | | || exception.getExceptionTime() == null) { |
| | | return; |
| | | } |
| | | // 1. 取员工考勤规则,用规则下班时间到异常时间(实际下班点)折算加班时长;无规则则无法折算,跳过 |
| | | BigDecimal overtimeHours = BigDecimal.ZERO; |
| | | HrmEmployeeDO employee = employeeService.getEmployee(exception.getUserId()); |
| | | HrmAttendanceRuleDO rule = employee == null ? null |
| | | : attendanceRuleService.getAttendanceRuleByDeptId(employee.getDeptId()); |
| | | if (rule != null) { |
| | | overtimeHours = computeOvertimeHours(rule.getWorkEndTime(), exception.getExceptionTime().toLocalTime()); |
| | | } |
| | | if (overtimeHours.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return; |
| | | } |
| | | // 2. 查询当日考勤记录,不存在则补建 |
| | | HrmAttendanceRecordDO record = attendanceRecordMapper.selectByUserIdAndDate(exception.getUserId(), exception.getExceptionDate()); |
| | | if (record == null) { |
| | | record = HrmAttendanceRecordDO.builder() |
| | | .userId(exception.getUserId()) |
| | | .deptId(employee != null ? employee.getDeptId() : exception.getDeptId()) |
| | | .date(exception.getExceptionDate()) |
| | | .dataSource(HrmAttendanceDataSourceEnum.SUPPLEMENT.getType()) |
| | | .build(); |
| | | record.setOvertimeHours(overtimeHours); |
| | | attendanceRecordMapper.insert(record); |
| | | return; |
| | | } |
| | | // 3. 已有记录则累加加班时长 |
| | | BigDecimal existed = record.getOvertimeHours() != null ? record.getOvertimeHours() : BigDecimal.ZERO; |
| | | record.setOvertimeHours(existed.add(overtimeHours)); |
| | | attendanceRecordMapper.updateById(record); |
| | | } |
| | | |
| | | @Override |
| | |
| | | LocalDate exceptionDate = exception.getExceptionDate(); |
| | | LocalDateTime exceptionTime = exception.getExceptionTime(); |
| | | Long userId = exception.getUserId(); |
| | | HrmEmployeeDO employee = employeeService.getEmployee(userId); |
| | | HrmAttendanceRuleDO rule = employee == null ? null |
| | | : attendanceRuleService.getAttendanceRuleByDeptId(employee.getDeptId()); |
| | | // 查询考勤记录 |
| | | HrmAttendanceRecordDO record = attendanceRecordMapper.selectByUserIdAndDate(userId, exceptionDate); |
| | | if (record == null) { |
| | | // 如果没有记录,创建一条 |
| | | HrmEmployeeDO employee = employeeService.getEmployee(userId); |
| | | record = HrmAttendanceRecordDO.builder() |
| | | .userId(userId) |
| | | .deptId(employee != null ? employee.getDeptId() : exception.getDeptId()) |
| | |
| | | // 下班补卡 |
| | | record.setClockOutTime(exceptionTime); |
| | | record.setClockOutType(HrmAttendanceClockTypeEnum.NORMAL.getType()); |
| | | // 下班补卡同时折算加班时长(超过规则下班时间部分) |
| | | record.setOvertimeHours(computeOvertimeHours(rule == null ? null : rule.getWorkEndTime(), time)); |
| | | } |
| | | // 更新数据来源为补卡审批 |
| | | record.setDataSource(HrmAttendanceDataSourceEnum.SUPPLEMENT.getType()); |