| | |
| | | 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.*; |
| | |
| | | } |
| | | |
| | | @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()); |
| | | // 如果日期变更,校验新日期是否已存在配置 |
| | |
| | | } |
| | | |
| | | @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) { |
| | |
| | | } |
| | | |
| | | @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); |
| | | } |
| | |
| | | return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY; |
| | | } |
| | | |
| | | } |
| | | } |