feat(attendance): 增加考勤特殊日期功能并优化固定班制考勤逻辑

- 新增考勤特殊日期相关接口和实现类
- 优化固定班制考勤设置批量更新逻辑- 增加特殊日期处理逻辑,支持必打卡和无需打卡日期
- 调整考勤信息查询接口,支持特殊日期查询
This commit is contained in:
aikai 2024-12-18 14:34:06 +08:00
parent a25be935a1
commit b755b53c5a
10 changed files with 293 additions and 61 deletions

View File

@ -209,6 +209,7 @@ public interface ErrorCodeConstants {
ErrorCode INSUFFICIENT_NUMBER_OF_CARD_REFILLS = new ErrorCode(1_003_016_000, "补卡次数不足"); ErrorCode INSUFFICIENT_NUMBER_OF_CARD_REFILLS = new ErrorCode(1_003_016_000, "补卡次数不足");
ErrorCode ABNORMAL_CARD_REPLENISHMENT = new ErrorCode(1_003_017_000, "补卡异常"); ErrorCode ABNORMAL_CARD_REPLENISHMENT = new ErrorCode(1_003_017_000, "补卡异常");
ErrorCode CANNOT_FIND_THE_RECORD_THAT_NEEDS_TO_BE_REPLACED = new ErrorCode(1_003_018_000, "查询不到需要补卡的记录"); ErrorCode CANNOT_FIND_THE_RECORD_THAT_NEEDS_TO_BE_REPLACED = new ErrorCode(1_003_018_000, "查询不到需要补卡的记录");
ErrorCode THERE_ARE_DUPLICATE_SPECIAL_DATES = new ErrorCode(1_003_019_000, "存在重复的特殊日期,请检查!");
ErrorCode LOG_FORM_NOT_USE = new ErrorCode(1_009_010_004, "你不能使用该日志模板"); ErrorCode LOG_FORM_NOT_USE = new ErrorCode(1_009_010_004, "你不能使用该日志模板");

View File

@ -6,10 +6,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.system.controller.admin.fixed.dto.AttendanceFixedDTO;
import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedRespVO; import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedRespVO;
import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.attendance.attendancespecial.AttendanceSpecialDO;
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.fixed.AttendanceFixedDO; import cn.iocoder.yudao.module.system.dal.dataobject.attendance.fixed.AttendanceFixedDO;
import cn.iocoder.yudao.module.system.service.attendance.attendancespecial.AttendanceSpecialService;
import cn.iocoder.yudao.module.system.service.attendance.fixed.AttendanceFixedService; import cn.iocoder.yudao.module.system.service.attendance.fixed.AttendanceFixedService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@ -35,13 +37,14 @@ public class AttendanceFixedController {
@Resource @Resource
private AttendanceFixedService fixedService; private AttendanceFixedService fixedService;
@Resource
private AttendanceSpecialService attendanceSpecialService;
@PostMapping("/batchCreateOrUpdate") @PostMapping("/batchCreateOrUpdate")
@Operation(summary = "批量新增修改固定班制考勤设置") @Operation(summary = "批量新增修改固定班制考勤设置")
@PreAuthorize("@ss.hasPermission('attendance:fixed:create')") @PreAuthorize("@ss.hasPermission('attendance:fixed:create')")
public CommonResult<Long> batchCreateOrUpdate(@RequestParam Long attendanceGroupId, public CommonResult<Long> batchCreateOrUpdate(@RequestBody AttendanceFixedDTO dto) {
@Valid @RequestBody List<AttendanceFixedSaveReqVO> vos) { Long groupId = fixedService.batchCreateOrUpdate(dto.getAttendanceGroupId(), dto.getVos(), dto.getSpecialDOS());
Long groupId = fixedService.batchCreateOrUpdate(attendanceGroupId, vos);
return success(groupId); return success(groupId);
} }
@ -58,6 +61,14 @@ public class AttendanceFixedController {
return success(BeanUtils.toBean(fixed, AttendanceFixedRespVO.class)); return success(BeanUtils.toBean(fixed, AttendanceFixedRespVO.class));
} }
@GetMapping("/getAttendanceSpecialByGroupId")
@Operation(summary = "获取特殊日期列表")
public CommonResult<List<AttendanceSpecialDO>> getAttendanceSpecialByGroupId(@RequestParam("id") Long id) {
List<AttendanceSpecialDO> list = attendanceSpecialService.getByGroupId(id);
return success(list);
}
@GetMapping("/getListByGroupId") @GetMapping("/getListByGroupId")
@Operation(summary = "根据考勤组ID获得固定班制考勤设置列表") @Operation(summary = "根据考勤组ID获得固定班制考勤设置列表")
public CommonResult<List<AttendanceFixedRespVO>> getListByGroupId(@RequestParam Long attendanceGroupId) { public CommonResult<List<AttendanceFixedRespVO>> getListByGroupId(@RequestParam Long attendanceGroupId) {

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.system.controller.admin.fixed.dto;
import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.attendancespecial.AttendanceSpecialDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class AttendanceFixedDTO {
@Schema(description = "考勤组id", example = "19908")
private Long attendanceGroupId;
@Schema(description = "固定班制考勤设置", example = "19908")
private List<AttendanceFixedSaveReqVO> vos;
@Schema(description = "考勤特殊日期设置", example = "19908")
private List<AttendanceSpecialDO> specialDOS;
}

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.system.controller.admin.fixed.vo; package cn.iocoder.yudao.module.system.controller.admin.fixed.vo;
import cn.iocoder.yudao.module.system.controller.admin.groupshift.vo.AttendanceGroupShiftRespVO;
import cn.iocoder.yudao.module.system.controller.admin.groupshift.vo.AttendanceGroupShiftVO; import cn.iocoder.yudao.module.system.controller.admin.groupshift.vo.AttendanceGroupShiftVO;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;

View File

@ -1,11 +1,10 @@
package cn.iocoder.yudao.module.system.dal.dataobject.attendance.attendancespecial; package cn.iocoder.yudao.module.system.dal.dataobject.attendance.attendancespecial;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/** /**
* 考勤特殊日期 DO * 考勤特殊日期 DO
@ -44,4 +43,8 @@ public class AttendanceSpecialDO extends BaseDO {
*/ */
private String dateTime; private String dateTime;
/**
* 提示
*/
private String tips;
} }

View File

@ -1,11 +1,8 @@
package cn.iocoder.yudao.module.system.dal.dataobject.attendance.fixed; package cn.iocoder.yudao.module.system.dal.dataobject.attendance.fixed;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.*;
import lombok.*;
/** /**
* 固定班制考勤设置 DO * 固定班制考勤设置 DO

View File

@ -1,10 +1,59 @@
package cn.iocoder.yudao.module.system.service.attendance.attendancespecial; package cn.iocoder.yudao.module.system.service.attendance.attendancespecial;
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.attendancespecial.AttendanceSpecialDO;
import java.util.List;
/** /**
* 考勤特殊日期 Service 接口 * 考勤特殊日期 Service 接口
* *
* @author 艾楷 * @author 艾楷
*/ */
public interface AttendanceSpecialService { public interface AttendanceSpecialService {
/**
* 根据条件搜索
*
* @param groupId
* @param time
* @param type
* @return
*/
AttendanceSpecialDO getByGroupIdAndTimeAndType(Long groupId, String time, int type);
/**
* 根据条件搜索
*
* @param groupId
* @param time
* @return
*/
List<AttendanceSpecialDO> getByGroupIdAndTime(Long groupId, String time);
/**
* @param groupIds
* @param time
* @return
*/
List<AttendanceSpecialDO> getByGroupIdsAndTime(List<Long> groupIds, String time);
/**
* @param groupId
* @param times
* @return
*/
List<AttendanceSpecialDO> getByGroupIdAndTimes(Long groupId, List<String> times);
/**
* @param attendanceGroupId
* @return
*/
List<AttendanceSpecialDO> getByGroupId(Long attendanceGroupId);
/**
* 批处理
*
* @param attendanceGroupId
* @param attendanceSpecialList
*/
void insertUpdateDeleteBatch(Long attendanceGroupId, List<List<AttendanceSpecialDO>> attendanceSpecialList);
} }

View File

@ -1,8 +1,18 @@
package cn.iocoder.yudao.module.system.service.attendance.attendancespecial; package cn.iocoder.yudao.module.system.service.attendance.attendancespecial;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.attendancespecial.AttendanceSpecialDO;
import cn.iocoder.yudao.module.system.dal.mysql.attendance.attendancespecial.AttendanceSpecialMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
/** /**
* 考勤特殊日期 Service 实现类 * 考勤特殊日期 Service 实现类
* *
@ -11,5 +21,65 @@ import org.springframework.validation.annotation.Validated;
@Service @Service
@Validated @Validated
public class AttendanceSpecialServiceImpl implements AttendanceSpecialService { public class AttendanceSpecialServiceImpl implements AttendanceSpecialService {
@Resource
private AttendanceSpecialMapper attendanceSpecialMapper;
@Override
public AttendanceSpecialDO getByGroupIdAndTimeAndType(Long groupId, String time, int type) {
List<AttendanceSpecialDO> attendanceSpecialDOS = attendanceSpecialMapper.selectList(new LambdaQueryWrapper<AttendanceSpecialDO>()
.eq(AttendanceSpecialDO::getAttendanceGroupId, groupId)
.eq(AttendanceSpecialDO::getDateTime, time)
.eq(AttendanceSpecialDO::getType, type));
if (CollUtil.isNotEmpty(attendanceSpecialDOS)) {
return attendanceSpecialDOS.get(0);
}
return null;
}
@Override
public List<AttendanceSpecialDO> getByGroupIdAndTime(Long groupId, String time) {
return attendanceSpecialMapper.selectList(new LambdaQueryWrapper<AttendanceSpecialDO>()
.eq(AttendanceSpecialDO::getAttendanceGroupId, groupId)
.eq(AttendanceSpecialDO::getDateTime, time));
}
@Override
public List<AttendanceSpecialDO> getByGroupIdsAndTime(List<Long> groupIds, String time) {
if (CollUtil.isEmpty(groupIds)) {
return Collections.emptyList();
}
return attendanceSpecialMapper.selectList(new LambdaQueryWrapper<AttendanceSpecialDO>()
.in(AttendanceSpecialDO::getAttendanceGroupId, groupIds)
.eq(AttendanceSpecialDO::getDateTime, time));
}
@Override
public List<AttendanceSpecialDO> getByGroupIdAndTimes(Long groupId, List<String> times) {
if (CollUtil.isEmpty(times)) {
return Collections.emptyList();
}
return attendanceSpecialMapper.selectList(new LambdaQueryWrapper<AttendanceSpecialDO>()
.eq(AttendanceSpecialDO::getAttendanceGroupId, groupId)
.in(AttendanceSpecialDO::getDateTime, times));
}
@Override
public List<AttendanceSpecialDO> getByGroupId(Long attendanceGroupId) {
return attendanceSpecialMapper.selectList(new LambdaQueryWrapper<AttendanceSpecialDO>()
.eq(AttendanceSpecialDO::getAttendanceGroupId, attendanceGroupId));
}
@Override
public void insertUpdateDeleteBatch(Long attendanceGroupId, List<List<AttendanceSpecialDO>> attendanceSpecialList) {
if (CollUtil.isNotEmpty(attendanceSpecialList.get(0))) {
attendanceSpecialList.get(0).forEach(a -> a.setAttendanceGroupId(attendanceGroupId));
attendanceSpecialMapper.insertBatch(attendanceSpecialList.get(0));
}
if (CollUtil.isNotEmpty(attendanceSpecialList.get(1))) {
attendanceSpecialMapper.updateBatch(attendanceSpecialList.get(1));
}
if (CollUtil.isNotEmpty(attendanceSpecialList.get(2))) {
attendanceSpecialMapper.deleteBatchIds(convertList(attendanceSpecialList.get(2), AttendanceSpecialDO::getId));
}
}
} }

View File

@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedRespVO; import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedRespVO;
import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.groupuser.vo.AttendanceGroupUserCreateOrDelVO; import cn.iocoder.yudao.module.system.dal.dataobject.attendance.attendancespecial.AttendanceSpecialDO;
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.fixed.AttendanceFixedDO; import cn.iocoder.yudao.module.system.dal.dataobject.attendance.fixed.AttendanceFixedDO;
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.group.AttendanceGroupDO; import cn.iocoder.yudao.module.system.dal.dataobject.attendance.group.AttendanceGroupDO;
@ -24,9 +24,10 @@ public interface AttendanceFixedService {
* 创建固定班制考勤设置 * 创建固定班制考勤设置
* *
* @param vos 创建信息 * @param vos 创建信息
* @param specialDOS
* @return 编号 * @return 编号
*/ */
Long batchCreateOrUpdate(Long attendanceGroupId, @Valid List<AttendanceFixedSaveReqVO> vos); Long batchCreateOrUpdate(Long attendanceGroupId, List<AttendanceFixedSaveReqVO> vos, List<AttendanceSpecialDO> specialDOS);
/** /**
* 更新固定班制考勤设置 * 更新固定班制考勤设置
@ -67,6 +68,8 @@ public interface AttendanceFixedService {
*/ */
AttendanceFixedDO getByGroupIdAndWeek(Long attendanceGroupId, Integer week); AttendanceFixedDO getByGroupIdAndWeek(Long attendanceGroupId, Integer week);
List<AttendanceFixedDO> getByGroupIdAndWeeks(Long attendanceGroupId, List<Integer> weeks);
List<AttendanceFixedDO> getByGroupId(Long attendanceGroupId); List<AttendanceFixedDO> getByGroupId(Long attendanceGroupId);
List<AttendanceFixedDO> getByGroupIdAndWeek(List<Long> attendanceGroupIds, Integer week); List<AttendanceFixedDO> getByGroupIdAndWeek(List<Long> attendanceGroupIds, Integer week);

View File

@ -4,8 +4,10 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.Constants; import cn.iocoder.yudao.framework.common.Constants;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.api.attendance.dto.AttendanceTimeRangeInfoDTO; import cn.iocoder.yudao.module.system.api.attendance.dto.AttendanceTimeRangeInfoDTO;
@ -18,11 +20,13 @@ import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedP
import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedRespVO; import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedRespVO;
import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.groupshift.vo.AttendanceGroupShiftVO; import cn.iocoder.yudao.module.system.controller.admin.groupshift.vo.AttendanceGroupShiftVO;
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.attendancespecial.AttendanceSpecialDO;
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.fixed.AttendanceFixedDO; import cn.iocoder.yudao.module.system.dal.dataobject.attendance.fixed.AttendanceFixedDO;
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.group.AttendanceGroupDO; import cn.iocoder.yudao.module.system.dal.dataobject.attendance.group.AttendanceGroupDO;
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.groupshiftitem.AttendanceGroupShiftItemDO; import cn.iocoder.yudao.module.system.dal.dataobject.attendance.groupshiftitem.AttendanceGroupShiftItemDO;
import cn.iocoder.yudao.module.system.dal.mysql.attendance.fixed.AttendanceFixedMapper; import cn.iocoder.yudao.module.system.dal.mysql.attendance.fixed.AttendanceFixedMapper;
import cn.iocoder.yudao.module.system.service.attendance.AttendanceService; import cn.iocoder.yudao.module.system.service.attendance.AttendanceService;
import cn.iocoder.yudao.module.system.service.attendance.attendancespecial.AttendanceSpecialService;
import cn.iocoder.yudao.module.system.service.attendance.groupshift.AttendanceGroupShiftService; import cn.iocoder.yudao.module.system.service.attendance.groupshift.AttendanceGroupShiftService;
import cn.iocoder.yudao.module.system.service.attendance.groupshiftitem.AttendanceGroupShiftItemService; import cn.iocoder.yudao.module.system.service.attendance.groupshiftitem.AttendanceGroupShiftItemService;
import cn.iocoder.yudao.module.system.service.attendance.punch.PunchService; import cn.iocoder.yudao.module.system.service.attendance.punch.PunchService;
@ -40,6 +44,7 @@ import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.FIXED_NOT_EXISTS; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.FIXED_NOT_EXISTS;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.THERE_ARE_DUPLICATE_SPECIAL_DATES;
/** /**
* 固定班制考勤设置 Service 实现类 * 固定班制考勤设置 Service 实现类
@ -59,10 +64,12 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
private AttendanceGroupShiftService attendanceGroupShiftService; private AttendanceGroupShiftService attendanceGroupShiftService;
@Resource @Resource
private AttendanceGroupShiftItemService attendanceGroupShiftItemService; private AttendanceGroupShiftItemService attendanceGroupShiftItemService;
@Resource
private AttendanceSpecialService attendanceSpecialService;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Long batchCreateOrUpdate(Long attendanceGroupId, List<AttendanceFixedSaveReqVO> vos) { public Long batchCreateOrUpdate(Long attendanceGroupId, List<AttendanceFixedSaveReqVO> vos, List<AttendanceSpecialDO> specialDOS) {
Long groupId = null; Long groupId = null;
// 插入 // 插入
List<AttendanceFixedDO> oldList = attendanceFixedMapper.selectList(new LambdaQueryWrapper<AttendanceFixedDO>() List<AttendanceFixedDO> oldList = attendanceFixedMapper.selectList(new LambdaQueryWrapper<AttendanceFixedDO>()
@ -105,6 +112,22 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
attendanceFixedMapper.deleteBatchIds(delIds); attendanceFixedMapper.deleteBatchIds(delIds);
} }
} }
// - - - - - - - - - 特殊考勤日期 - - - - - - - -
if (CollUtil.isEmpty(specialDOS)) {
specialDOS = Collections.emptyList();
}
// -- 验证是否有同一天的数据 如果有则返回提醒
Map<String, List<AttendanceSpecialDO>> map = specialDOS.stream().collect(Collectors.groupingBy(AttendanceSpecialDO::getDateTime));
for (Map.Entry<String, List<AttendanceSpecialDO>> entry : map.entrySet()) {
if (entry.getValue().size() > 1) {
throw exception(THERE_ARE_DUPLICATE_SPECIAL_DATES);
}
}
//查询旧的
List<AttendanceSpecialDO> oldAttendanceSpecialDOS = attendanceSpecialService.getByGroupId(attendanceGroupId);
List<List<AttendanceSpecialDO>> attendanceSpecialList = CollectionUtils.diffList(oldAttendanceSpecialDOS, specialDOS,
(saveVal, newVal) -> ObjectUtil.equal(saveVal.getId(), newVal.getId()));
attendanceSpecialService.insertUpdateDeleteBatch(attendanceGroupId, attendanceSpecialList);
return groupId; return groupId;
} }
@ -152,6 +175,13 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
return null; return null;
} }
@Override
public List<AttendanceFixedDO> getByGroupIdAndWeeks(Long attendanceGroupId, List<Integer> weeks) {
return attendanceFixedMapper.selectList(new LambdaQueryWrapper<AttendanceFixedDO>()
.eq(attendanceGroupId != null, AttendanceFixedDO::getAttendanceGroupId, attendanceGroupId)
.in(CollUtil.isNotEmpty(weeks), AttendanceFixedDO::getWeekTime, weeks));
}
@Override @Override
public List<AttendanceFixedDO> getByGroupId(Long attendanceGroupId) { public List<AttendanceFixedDO> getByGroupId(Long attendanceGroupId) {
return attendanceFixedMapper.selectList(new LambdaQueryWrapper<AttendanceFixedDO>() return attendanceFixedMapper.selectList(new LambdaQueryWrapper<AttendanceFixedDO>()
@ -176,7 +206,23 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
List<AttendanceFixedDO> makeUpClassList = this.getByGroupIdAndWeek(groupIds, 8); List<AttendanceFixedDO> makeUpClassList = this.getByGroupIdAndWeek(groupIds, 8);
Map<Long, List<AttendanceFixedDO>> makeUpClassListMap = makeUpClassList.stream().collect(Collectors.groupingBy(AttendanceFixedDO::getAttendanceGroupId)); Map<Long, List<AttendanceFixedDO>> makeUpClassListMap = makeUpClassList.stream().collect(Collectors.groupingBy(AttendanceFixedDO::getAttendanceGroupId));
Map<Long, List<AttendanceFixedDO>> attendanceFixedMap = attendanceFixedDOS.stream().collect(Collectors.groupingBy(AttendanceFixedDO::getAttendanceGroupId)); Map<Long, List<AttendanceFixedDO>> attendanceFixedMap = attendanceFixedDOS.stream().collect(Collectors.groupingBy(AttendanceFixedDO::getAttendanceGroupId));
// -- 这里是考勤预设 - 不需要把加班的考勤规则考虑在内 - 需要考虑 必须打卡时间 - 和非必须打卡时间即可
List<AttendanceSpecialDO> specialDOS = attendanceSpecialService.getByGroupIdsAndTime(groupIds, localDateTime.format(Constants.REPO_DATE_FORMAT));
Map<String, AttendanceSpecialDO> specialMap = specialDOS.stream().collect(Collectors.toMap(a -> a.getAttendanceGroupId() + "_" + a.getType(), a -> a));
for (AttendanceGroupDO activationGroup : fixedList) { for (AttendanceGroupDO activationGroup : fixedList) {
AttendanceSpecialDO mustClockInTime = specialMap.get(activationGroup.getId() + "_" + 1);
// -- 判断是否有必须打卡时间 - 如果有的话直接摄入进去即可
if (mustClockInTime != null && mustClockInTime.getAttendanceGroupShiftId() != null) {
map.put(activationGroup.getId(), mustClockInTime.getAttendanceGroupShiftId());
continue;
}
// -- 判断是否有无需打卡时间 - 如果有的话直接返回 --- 无需打卡 直接返回结果
AttendanceSpecialDO noNeedToClockIn = specialMap.get(activationGroup.getId() + "_" + 0);
if (noNeedToClockIn != null) {
continue;
}
// -- 判断是否根据节假日自动排班 - 如果是的话 - 根据排班的来 // -- 判断是否根据节假日自动排班 - 如果是的话 - 根据排班的来
Boolean isHolidayFlag = Constants.TRUE.equals(activationGroup.getAutoHolidaysFlag()) ? Boolean isHolidayFlag = Constants.TRUE.equals(activationGroup.getAutoHolidaysFlag()) ?
attendanceService.isHoliday(localDateTime) : null; attendanceService.isHoliday(localDateTime) : null;
@ -233,6 +279,22 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
AttendancePunchPageVO vo = new AttendancePunchPageVO(); AttendancePunchPageVO vo = new AttendancePunchPageVO();
vo.setActivationGroup(dto.getActivationGroup()); vo.setActivationGroup(dto.getActivationGroup());
AttendanceGroupDO activationGroup = dto.getActivationGroup(); AttendanceGroupDO activationGroup = dto.getActivationGroup();
Long attendanceGroupShiftId = null;
// todo aiKai 获取特殊打卡日期 - 判断是否有存在 - 如果有的话 - 则按照必打卡日期所设置的班次返回 - 如果没有的话再 判断其他
List<AttendanceSpecialDO> specialDOS = attendanceSpecialService.getByGroupIdAndTime(activationGroup.getId(), dto.getLocalDateTime().format(Constants.REPO_DATE_FORMAT));
Map<Integer, AttendanceSpecialDO> map = specialDOS.stream().collect(Collectors.toMap(AttendanceSpecialDO::getType, a -> a));
if (map.get(1) != null && map.get(1).getAttendanceGroupShiftId() != null) {
attendanceGroupShiftId = map.get(1).getAttendanceGroupShiftId();
} else if (map.get(0) != null) {
// 当前为 不需要打卡时间 - 判断是否有加班班次 - 如果没有的话 直接跳过
AttendanceFixedDO attendanceFixedDO = this.getByGroupIdAndWeek(activationGroup.getId(), -1);
if (attendanceFixedDO == null || attendanceFixedDO.getAttendanceGroupShiftId() == null) {
return vo.setTodayNeedAttendance(Constants.FALSE);
} else {
vo.setWorkOvertimeFlag(Constants.ONE);
attendanceGroupShiftId = attendanceFixedDO.getAttendanceGroupShiftId();
}
} else {
// -- 判断是否根据节假日自动排班 - 如果是的话 - 根据排班的来 // -- 判断是否根据节假日自动排班 - 如果是的话 - 根据排班的来
Boolean isHolidayFlag = Constants.TRUE.equals(activationGroup.getAutoHolidaysFlag()) ? Boolean isHolidayFlag = Constants.TRUE.equals(activationGroup.getAutoHolidaysFlag()) ?
attendanceService.isHoliday(dto.getLocalDateTime()) : null; attendanceService.isHoliday(dto.getLocalDateTime()) : null;
@ -255,7 +317,9 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
} else if (week == -1) { } else if (week == -1) {
vo.setWorkOvertimeFlag(Constants.ONE); vo.setWorkOvertimeFlag(Constants.ONE);
} }
vo.setAttendanceGroupShiftId(attendanceFixedDO.getAttendanceGroupShiftId()); attendanceGroupShiftId = attendanceFixedDO.getAttendanceGroupShiftId();
}
vo.setAttendanceGroupShiftId(attendanceGroupShiftId);
attendanceService.calculatePunch(dto, vo); attendanceService.calculatePunch(dto, vo);
vo.setAttendanceGroupId(activationGroup.getId()); vo.setAttendanceGroupId(activationGroup.getId());
vo.setUser(dto.getUser()); vo.setUser(dto.getUser());
@ -300,9 +364,23 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
@Override @Override
public Map<String, AttendanceTimeRangeInfoVO> getAttendanceInfoByTimeRange(AttendanceTimeRangeInfoDTO dto) { public Map<String, AttendanceTimeRangeInfoVO> getAttendanceInfoByTimeRange(AttendanceTimeRangeInfoDTO dto) {
Map<String, AttendanceTimeRangeInfoVO> map = new HashMap<>(); Map<String, AttendanceTimeRangeInfoVO> map = new HashMap<>();
List<AttendanceSpecialDO> attendanceSpecials = attendanceSpecialService.getByGroupIdAndTimes(dto.getGroupId(), dto.getTimes());
Map<String, AttendanceSpecialDO> specialDOMap = attendanceSpecials.stream().collect(Collectors.toMap(a -> a.getDateTime() + "_" + a.getType(), a -> a));
//不在考勤组 //不在考勤组
for (String time : dto.getTimes()) { for (String time : dto.getTimes()) {
AttendanceTimeRangeInfoVO attendanceTimeRangeInfoVO = new AttendanceTimeRangeInfoVO(); AttendanceTimeRangeInfoVO attendanceTimeRangeInfoVO = new AttendanceTimeRangeInfoVO();
Long attendanceGroupShiftId = null;
// -- 判断是否有必须打卡时间 - 如果有的话直接摄入进去即可
AttendanceSpecialDO mustClockInTime = specialDOMap.get(time + "_" + 1);
// -- 判断是否有无需打卡时间 - 如果有的话直接返回 --- 无需打卡 直接返回结果
AttendanceSpecialDO noNeedToClockIn = specialDOMap.get(time + "_" + 0);
if (mustClockInTime != null && mustClockInTime.getAttendanceGroupShiftId() != null) {
attendanceGroupShiftId = mustClockInTime.getAttendanceGroupShiftId();
map.put(time, attendanceTimeRangeInfoVO.setDatType(Constants.ONE));
} else if (noNeedToClockIn != null) {
map.put(time, attendanceTimeRangeInfoVO.setDatType(Constants.TWO));
continue;
} else {
// -- 判断是否根据节假日自动排班 - 如果是的话 - 根据排班的来 // -- 判断是否根据节假日自动排班 - 如果是的话 - 根据排班的来
LocalDateTime localDateTime = LocalDateTimeUtil.parseDate(time, Constants.REPO_DATE_FORMAT).atStartOfDay(); LocalDateTime localDateTime = LocalDateTimeUtil.parseDate(time, Constants.REPO_DATE_FORMAT).atStartOfDay();
Boolean holiday = attendanceService.isHoliday(localDateTime); Boolean holiday = attendanceService.isHoliday(localDateTime);
@ -323,7 +401,10 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
map.put(time, attendanceTimeRangeInfoVO.setDatType(Constants.TWO)); map.put(time, attendanceTimeRangeInfoVO.setDatType(Constants.TWO));
continue; continue;
} }
List<AttendanceGroupShiftItemDO> attendanceGroupShiftItemDOList = attendanceGroupShiftItemService.getGroupShiftItemListByShiftId(attendanceFixedDO.getAttendanceGroupShiftId()); attendanceGroupShiftId = attendanceFixedDO.getAttendanceGroupShiftId();
}
// - 如果当前有班次 - 但是又不是需要打卡的时间 - 那么看有没有加班班次 - 有的话按照加班班次来 - 没有的话设为不需要打卡 - 解决单双休场景
List<AttendanceGroupShiftItemDO> attendanceGroupShiftItemDOList = attendanceGroupShiftItemService.getGroupShiftItemListByShiftId(attendanceGroupShiftId);
if (CollectionUtil.isNotEmpty(attendanceGroupShiftItemDOList)) { if (CollectionUtil.isNotEmpty(attendanceGroupShiftItemDOList)) {
List<AttendanceGroupShiftItemVO> items = BeanUtil.copyToList(attendanceGroupShiftItemDOList, AttendanceGroupShiftItemVO.class); List<AttendanceGroupShiftItemVO> items = BeanUtil.copyToList(attendanceGroupShiftItemDOList, AttendanceGroupShiftItemVO.class);
map.put(time, attendanceTimeRangeInfoVO.setNeedAttendance(1).setItems(items)); map.put(time, attendanceTimeRangeInfoVO.setNeedAttendance(1).setItems(items));