| | |
| | | package cn.iocoder.yudao.module.hrm.service.attendance; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceSummaryPageReqVO; |
| | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.YearMonth; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * 考勤统计汇总 Service 实现类 |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public PageResult<HrmAttendanceSummaryDO> getAttendanceSummaryPage(HrmAttendanceSummaryPageReqVO pageReqVO) { |
| | | return attendanceSummaryMapper.selectPage(pageReqVO, new LambdaQueryWrapperX<HrmAttendanceSummaryDO>() |
| | | PageResult<HrmAttendanceSummaryDO> pageResult = attendanceSummaryMapper.selectPage(pageReqVO, |
| | | new LambdaQueryWrapperX<HrmAttendanceSummaryDO>() |
| | | .eqIfPresent(HrmAttendanceSummaryDO::getUserId, pageReqVO.getUserId()) |
| | | .eqIfPresent(HrmAttendanceSummaryDO::getDeptId, pageReqVO.getDeptId()) |
| | | .eqIfPresent(HrmAttendanceSummaryDO::getYearMonth, pageReqVO.getYearMonth()) |
| | | .orderByDesc(HrmAttendanceSummaryDO::getYearMonth) |
| | | .orderByAsc(HrmAttendanceSummaryDO::getDeptId)); |
| | | refreshWorkDays(pageResult.getList()); |
| | | return pageResult; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public HrmAttendanceSummaryDO getMonthlySummary(Long userId, String yearMonth) { |
| | | return attendanceSummaryMapper.selectByUserIdAndYearMonth(userId, yearMonth); |
| | | HrmAttendanceSummaryDO summary = attendanceSummaryMapper.selectByUserIdAndYearMonth(userId, yearMonth); |
| | | if (summary != null) { |
| | | refreshWorkDays(List.of(summary)); |
| | | } |
| | | return summary; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public List<HrmAttendanceSummaryDO> getDeptMonthlySummaryList(Long deptId, String yearMonth) { |
| | | return attendanceSummaryMapper.selectListByDeptIdAndYearMonth(deptId, yearMonth); |
| | | List<HrmAttendanceSummaryDO> list = attendanceSummaryMapper.selectListByDeptIdAndYearMonth(deptId, yearMonth); |
| | | refreshWorkDays(list); |
| | | return list; |
| | | } |
| | | |
| | | /** |
| | | * 查询/导出时按“最新节假日配置”重算应出勤天数,并把变化的记录回写。 |
| | | * |
| | | * 节假日配置可能在生成汇总之后被调整(如新增调休/法定假日),若只返回旧值, |
| | | * 页面上的应出勤天数会与节假日配置长期不一致。 |
| | | */ |
| | | private void refreshWorkDays(List<HrmAttendanceSummaryDO> list) { |
| | | if (CollUtil.isEmpty(list)) { |
| | | return; |
| | | } |
| | | // 同一次请求内同一年月只计算一次 |
| | | Map<String, Integer> workDaysCache = new HashMap<>(); |
| | | for (HrmAttendanceSummaryDO summary : list) { |
| | | if (StrUtil.isBlank(summary.getYearMonth())) { |
| | | continue; |
| | | } |
| | | Integer expected; |
| | | try { |
| | | expected = workDaysCache.computeIfAbsent(summary.getYearMonth(), yearMonth -> { |
| | | YearMonth parsed = YearMonth.parse(yearMonth); |
| | | return calculateWorkDays(parsed.atDay(1), parsed.atEndOfMonth()); |
| | | }); |
| | | } catch (Exception e) { |
| | | log.warn("[refreshWorkDays][考勤汇总({}) 年月({}) 无法解析,跳过重算]", |
| | | summary.getId(), summary.getYearMonth(), e); |
| | | continue; |
| | | } |
| | | if (!Objects.equals(summary.getWorkDays(), expected)) { |
| | | log.info("[refreshWorkDays][考勤汇总({}) 年月({}) 应出勤天数 {} -> {},按最新节假日配置回写]", |
| | | summary.getId(), summary.getYearMonth(), summary.getWorkDays(), expected); |
| | | summary.setWorkDays(expected); |
| | | try { |
| | | attendanceSummaryMapper.updateById(HrmAttendanceSummaryDO.builder() |
| | | .id(summary.getId()).workDays(expected).build()); |
| | | } catch (Exception e) { |
| | | // 回写失败不影响本次查询结果,保留内存中重算后的值 |
| | | log.warn("[refreshWorkDays][考勤汇总({}) 应出勤天数回写失败]", summary.getId(), e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |