gaoluyang
7 小时以前 ef3cbc1c6882786e8218b08be3e52ea44587f03b
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/HrmAttendanceHolidayServiceImpl.java
@@ -1,19 +1,29 @@
package cn.iocoder.yudao.module.hrm.service.attendance;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
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.HrmAttendanceHolidayGroupRespVO;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayPageReqVO;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayRangeCreateReqVO;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidayRangeUpdateReqVO;
import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceHolidaySaveReqVO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceHolidayDO;
import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmAttendanceHolidayMapper;
import cn.iocoder.yudao.module.hrm.enums.HrmAttendanceHolidayTypeEnum;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.*;
@@ -42,6 +52,42 @@
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer createAttendanceHolidayRange(HrmAttendanceHolidayRangeCreateReqVO createReqVO) {
        if (createReqVO.getEndDate().isBefore(createReqVO.getStartDate())) {
            throw exception(ATTENDANCE_HOLIDAY_DATE_RANGE_INVALID);
        }
        return insertDays(createReqVO.getName(), createReqVO.getStartDate(), createReqVO.getEndDate(),
                createReqVO.getType(), createReqVO.getIsLegal(), createReqVO.getRemark());
    }
    /**
     * 按天写入节假日;写入前整体查重,任一日期已存在则整体不写入
     */
    private int insertDays(String name, LocalDate startDate, LocalDate endDate,
                           Integer type, Boolean isLegal, String remark) {
        // 先整体校验,区间内已存在任一日期时不做部分写入
        List<HrmAttendanceHolidayDO> existingList = attendanceHolidayMapper.selectListByDateBetween(startDate, endDate);
        if (!existingList.isEmpty()) {
            HrmAttendanceHolidayDO existing = existingList.get(0);
            throw exception(ATTENDANCE_HOLIDAY_RANGE_DATE_EXISTS, existing.getDate(), existing.getName());
        }
        int count = 0;
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            HrmAttendanceHolidayDO attendanceHoliday = HrmAttendanceHolidayDO.builder()
                    .name(name)
                    .date(date)
                    .type(type)
                    .isLegal(Boolean.TRUE.equals(isLegal) ? 1 : 0)
                    .remark(remark)
                    .build();
            attendanceHolidayMapper.insert(attendanceHoliday);
            count++;
        }
        return count;
    }
    @Override
    public void updateAttendanceHoliday(HrmAttendanceHolidaySaveReqVO updateReqVO) {
        validateAttendanceHolidayExists(updateReqVO.getId());
        // 如果日期变更,校验新日期是否已存在配置
@@ -55,9 +101,41 @@
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAttendanceHolidayRange(HrmAttendanceHolidayRangeUpdateReqVO updateReqVO) {
        // 1. 校验时间范围与区间记录
        if (updateReqVO.getEndDate().isBefore(updateReqVO.getStartDate())) {
            throw exception(ATTENDANCE_HOLIDAY_DATE_RANGE_INVALID);
        }
        List<Long> ids = updateReqVO.getIds().stream().filter(Objects::nonNull).distinct().toList();
        if (ids.isEmpty()) {
            throw exception(ATTENDANCE_HOLIDAY_RANGE_IDS_EMPTY);
        }
        List<HrmAttendanceHolidayDO> oldList = attendanceHolidayMapper.selectBatchIds(ids);
        if (oldList.size() != ids.size()) {
            throw exception(ATTENDANCE_HOLIDAY_RANGE_NOT_EXISTS);
        }
        // 2. 删除区间内原记录,再按新的起止日期整体重写(同一事务,异常会回滚)
        attendanceHolidayMapper.physicalDeleteByIds(ids);
        insertDays(updateReqVO.getName(), updateReqVO.getStartDate(), updateReqVO.getEndDate(),
                updateReqVO.getType(), updateReqVO.getIsLegal(), updateReqVO.getRemark());
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAttendanceHolidayRange(List<Long> ids) {
        List<Long> cleanIds = ids == null ? Collections.emptyList()
                : ids.stream().filter(Objects::nonNull).distinct().toList();
        if (cleanIds.isEmpty()) {
            throw exception(ATTENDANCE_HOLIDAY_RANGE_IDS_EMPTY);
        }
        attendanceHolidayMapper.physicalDeleteByIds(cleanIds);
    }
    @Override
    public void deleteAttendanceHoliday(Long id) {
        validateAttendanceHolidayExists(id);
        attendanceHolidayMapper.deleteById(id);
        attendanceHolidayMapper.physicalDeleteByIds(Collections.singletonList(id));
    }
    private void validateAttendanceHolidayExists(Long id) {
@@ -83,6 +161,72 @@
    }
    @Override
    public PageResult<HrmAttendanceHolidayGroupRespVO> getAttendanceHolidayGroupPage(
            HrmAttendanceHolidayPageReqVO pageReqVO) {
        List<HrmAttendanceHolidayDO> list = attendanceHolidayMapper.selectListByCondition(pageReqVO);
        if (list.isEmpty()) {
            return new PageResult<>(Collections.emptyList(), 0L);
        }
        // 1. 连续日期 + 名称/类型/是否法定/备注一致的记录合并为一行
        List<HrmAttendanceHolidayGroupRespVO> groups = new ArrayList<>();
        HrmAttendanceHolidayDO previous = null;
        for (HrmAttendanceHolidayDO current : list) {
            HrmAttendanceHolidayGroupRespVO last = groups.isEmpty() ? null : groups.get(groups.size() - 1);
            boolean sameGroup = last != null && previous != null
                    && previous.getDate().plusDays(1).equals(current.getDate())
                    && sameHoliday(previous, current);
            if (sameGroup) {
                last.setEndDate(current.getDate());
                last.getIds().add(current.getId());
                last.setDayCount(last.getDayCount() + 1);
            } else {
                HrmAttendanceHolidayGroupRespVO group = new HrmAttendanceHolidayGroupRespVO();
                group.setId(current.getId());
                List<Long> ids = new ArrayList<>();
                ids.add(current.getId());
                group.setIds(ids);
                group.setName(current.getName());
                group.setDate(current.getDate());
                group.setEndDate(current.getDate());
                group.setDayCount(1);
                group.setType(current.getType());
                group.setIsLegal(current.getIsLegal());
                group.setRemark(current.getRemark());
                group.setCreateTime(current.getCreateTime());
                groups.add(group);
            }
            previous = current;
        }
        // 2. 按日期倒序,与逐日列表保持一致
        groups.sort(Comparator.comparing(HrmAttendanceHolidayGroupRespVO::getDate).reversed());
        // 3. 分组后内存分页
        return pageGroups(groups, pageReqVO);
    }
    private boolean sameHoliday(HrmAttendanceHolidayDO a, HrmAttendanceHolidayDO b) {
        return StrUtil.equals(a.getName(), b.getName())
                && Objects.equals(a.getType(), b.getType())
                && Objects.equals(a.getIsLegal(), b.getIsLegal())
                && StrUtil.equals(a.getRemark(), b.getRemark());
    }
    private PageResult<HrmAttendanceHolidayGroupRespVO> pageGroups(
            List<HrmAttendanceHolidayGroupRespVO> groups, HrmAttendanceHolidayPageReqVO pageReqVO) {
        long total = groups.size();
        if (Objects.equals(PageParam.PAGE_SIZE_NONE, pageReqVO.getPageSize())) {
            return new PageResult<>(groups, total);
        }
        int pageNo = pageReqVO.getPageNo() == null ? 1 : pageReqVO.getPageNo();
        int pageSize = pageReqVO.getPageSize() == null ? 10 : pageReqVO.getPageSize();
        int from = Math.max(0, (pageNo - 1) * pageSize);
        if (from >= groups.size()) {
            return new PageResult<>(Collections.emptyList(), total);
        }
        int to = Math.min(groups.size(), from + pageSize);
        return new PageResult<>(new ArrayList<>(groups.subList(from, to)), total);
    }
    @Override
    public List<HrmAttendanceHolidayDO> getAttendanceHolidayListByDateRange(LocalDate startDate, LocalDate endDate) {
        return attendanceHolidayMapper.selectListByDateBetween(startDate, endDate);
    }
@@ -100,4 +244,4 @@
        return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY;
    }
}
}