考勤固定班制

This commit is contained in:
aikai 2024-04-18 09:40:08 +08:00
parent 4c780ef8e6
commit 4a551e9db9
10 changed files with 162 additions and 8 deletions

View File

@ -2,6 +2,10 @@ package cn.iocoder.yudao.framework.common.util.date;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.*; import java.time.*;
@ -278,4 +282,54 @@ public class DateUtils {
return buildTime(Integer.parseInt(yyyy_MM_dds[0]), Integer.parseInt(yyyy_MM_dds[1]), Integer.parseInt(yyyy_MM_dds[2]), return buildTime(Integer.parseInt(yyyy_MM_dds[0]), Integer.parseInt(yyyy_MM_dds[1]), Integer.parseInt(yyyy_MM_dds[2]),
0, 0, 0); 0, 0, 0);
} }
/**
* 判断是周几 1是周1 7是周天
*
* @param thisDate
* @return
*/
public static int dayOfWeek(Date thisDate) {
int week = DateUtil.dayOfWeek(thisDate);
return (week - 1) == 0 ? 7 : week - 1;
}
/**
* 判断是否为节假日
*
* @param date 日期 "2022-04-05"
* @return
*/
public static Boolean isHoliday(String date) {
// 获取该年份的节假日信息
JSONArray jsonArray = getHolidayOfYear(date.substring(0, 4));
System.out.println(jsonArray);
// 遍历节假日信息
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
// 如果传入的日期存在于该年的节假日中则返回对应的节假日信息(true为节假日, false为调休工作日)
if (jsonObject.getStr("date").equals(date)) {
return jsonObject.getBool("isOffDay");
}
}
// 如果不存在, 则直接返回正常计算(非节假日)
return null;
}
/**
* 获取指定年份的节假日信息
*
* @return
* @paramyear 年份 "2022"
*/
public static JSONArray getHolidayOfYear(String year) {
// 获取指定年份的url
String url = "https://cdn.jsdelivr.net/gh/NateScarlet/holiday-cn@master/" + year + ".json";
// 获取返回结果
String json = HttpUtil.get(url, 0);
// 解析返回结果
JSONObject jsonObject = JSONUtil.parseObj(json);
return jsonObject.getJSONArray("days");
}
} }

View File

@ -2,8 +2,10 @@ package cn.iocoder.yudao.module.system.controller.app.attendance.vo;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors;
@Data @Data
@Accessors(chain = true)
public class AttendancePunchPageVO { public class AttendancePunchPageVO {
@Schema(description = "是否在考勤组 0否 1是") @Schema(description = "是否在考勤组 0否 1是")
private Integer inGroup = 1; private Integer inGroup = 1;

View File

@ -0,0 +1,16 @@
package cn.iocoder.yudao.module.system.controller.app.attendance.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class HolidayVO {
@Schema(description = "时间")
private String date;
@Schema(description = "是否要上班(补班 false 放假 true)")
private Boolean isOffDay;
}

View File

@ -36,7 +36,7 @@ public class AttendanceFixedDO extends BaseDO {
*/ */
private Integer weekTime; private Integer weekTime;
/** /**
* 班次id * 班次id为空表示休息
*/ */
private Long attendanceGroupShiftId; private Long attendanceGroupShiftId;

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.system.job.worklog; package cn.iocoder.yudao.module.system.job.worklog;
import cn.hutool.core.date.DateUtil;
import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.system.controller.admin.worklog.vo.form.LogFormRuleVO; import cn.iocoder.yudao.module.system.controller.admin.worklog.vo.form.LogFormRuleVO;
@ -66,7 +65,7 @@ public class LogStatisticsJob {
continue; continue;
} }
if (logRuleDO.getType() == 1) { if (logRuleDO.getType() == 1) {
int weekNum = ((DateUtil.dayOfWeekEnum(thisDate).getValue() - 1) == 0 ? 7 : (DateUtil.dayOfWeekEnum(thisDate).getValue() - 1)); int weekNum = DateUtils.dayOfWeek(thisDate);
List<String> weekDays = Arrays.asList(logRuleDO.getWeekDays().split(",")); List<String> weekDays = Arrays.asList(logRuleDO.getWeekDays().split(","));
// -- 还没有到统计的时间/不需要统计 - 跳出循环 // -- 还没有到统计的时间/不需要统计 - 跳出循环
if (!weekDays.contains(Integer.toString(weekNum)) || thisDate.getTime() < DateUtils.buildHHmmTime(logRuleDO.getStatisticalTime()).getTime()) { if (!weekDays.contains(Integer.toString(weekNum)) || thisDate.getTime() < DateUtils.buildHHmmTime(logRuleDO.getStatisticalTime()).getTime()) {

View File

@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.system.service.attendance;
import cn.iocoder.yudao.module.system.controller.app.attendance.dto.AttendancePunchPageDTO; import cn.iocoder.yudao.module.system.controller.app.attendance.dto.AttendancePunchPageDTO;
import cn.iocoder.yudao.module.system.controller.app.attendance.vo.AttendancePunchPageVO; import cn.iocoder.yudao.module.system.controller.app.attendance.vo.AttendancePunchPageVO;
import java.util.Date;
/** /**
* 考勤 Service 接口 * 考勤 Service 接口
* *
@ -12,4 +14,13 @@ public interface AttendanceService {
AttendancePunchPageVO getPunchPage(AttendancePunchPageDTO attendancePunchPageDTO); AttendancePunchPageVO getPunchPage(AttendancePunchPageDTO attendancePunchPageDTO);
/**
* 判断当前传如时间是否是 节假日(节假日分 补班/放假) 补班的话返回false 放假的话返回 true
* 如果不是节假日的话返回null
*
* @param date
* @return
*/
Boolean isHoliday(Date date);
} }

View File

@ -1,15 +1,24 @@
package cn.iocoder.yudao.module.system.service.attendance; package cn.iocoder.yudao.module.system.service.attendance;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.module.system.controller.app.attendance.dto.AttendancePunchPageDTO; import cn.iocoder.yudao.module.system.controller.app.attendance.dto.AttendancePunchPageDTO;
import cn.iocoder.yudao.module.system.controller.app.attendance.vo.AttendancePunchPageVO; import cn.iocoder.yudao.module.system.controller.app.attendance.vo.AttendancePunchPageVO;
import cn.iocoder.yudao.module.system.controller.app.attendance.vo.HolidayVO;
import cn.iocoder.yudao.module.system.dal.dataobject.group.AttendanceGroupDO; import cn.iocoder.yudao.module.system.dal.dataobject.group.AttendanceGroupDO;
import cn.iocoder.yudao.module.system.handler.PunchHandler; import cn.iocoder.yudao.module.system.handler.PunchHandler;
import cn.iocoder.yudao.module.system.service.attendance.group.AttendanceGroupService; import cn.iocoder.yudao.module.system.service.attendance.group.AttendanceGroupService;
import cn.iocoder.yudao.module.system.service.attendance.punch.PunchService; import cn.iocoder.yudao.module.system.service.attendance.punch.PunchService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* 考勤 实现类 * 考勤 实现类
@ -21,6 +30,8 @@ public class AttendanceServiceImpl implements AttendanceService {
private PunchHandler punchHandler; private PunchHandler punchHandler;
@Resource @Resource
private AttendanceGroupService attendanceGroupService; private AttendanceGroupService attendanceGroupService;
@Resource
private StringRedisTemplate redisTemplate;
@Override @Override
public AttendancePunchPageVO getPunchPage(AttendancePunchPageDTO dto) { public AttendancePunchPageVO getPunchPage(AttendancePunchPageDTO dto) {
@ -36,4 +47,25 @@ public class AttendanceServiceImpl implements AttendanceService {
PunchService punchService = punchHandler.getResource(AttendanceGroupDO.getCodeByType(activationGroup.getType())); PunchService punchService = punchHandler.getResource(AttendanceGroupDO.getCodeByType(activationGroup.getType()));
return punchService.getPunchPage(dto.setActivationGroup(activationGroup)); return punchService.getPunchPage(dto.setActivationGroup(activationGroup));
} }
@Override
public Boolean isHoliday(Date date) {
String dateStr = DateUtils.dateFormat(date, "yyyy-MM-dd");
String year = dateStr.substring(0, 4);
String key = "holiday_" + year;
Boolean flag = redisTemplate.hasKey(key);
// 缓存不存在
if (Boolean.FALSE.equals(flag)) {
String url = "https://cdn.jsdelivr.net/gh/NateScarlet/holiday-cn@master/" + year + ".json";
String json = HttpUtil.get(url, 0);
JSONObject jsonObject = JSONUtil.parseObj(json);
Map<String, Boolean> map = jsonObject.getBeanList("days", HolidayVO.class).stream().collect(Collectors.toMap(HolidayVO::getDate, HolidayVO::getIsOffDay));
redisTemplate.opsForHash().putAll(key, map);
// -- 删除去年的
String lastKey = "holiday_" + (Integer.parseInt(year) - 1);
redisTemplate.delete(lastKey);
}
return (Boolean) redisTemplate.opsForHash().get(key, date);
}
} }

View File

@ -52,4 +52,11 @@ public interface AttendanceFixedService {
*/ */
PageResult<AttendanceFixedDO> getFixedPage(AttendanceFixedPageReqVO pageReqVO); PageResult<AttendanceFixedDO> getFixedPage(AttendanceFixedPageReqVO pageReqVO);
/**
* 通过考勤组id+周几 获取固定班制考勤设置
* @param attendanceGroupId
* @param week
* @return
*/
AttendanceFixedDO getByGroupIdAndWeek(Long attendanceGroupId, Integer week);
} }

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.system.service.attendance.fixed; package cn.iocoder.yudao.module.system.service.attendance.fixed;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
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.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.AttendanceFixedSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.fixed.vo.AttendanceFixedSaveReqVO;
@ -9,11 +10,15 @@ import cn.iocoder.yudao.module.system.controller.app.attendance.vo.AttendancePun
import cn.iocoder.yudao.module.system.dal.dataobject.fixed.AttendanceFixedDO; import cn.iocoder.yudao.module.system.dal.dataobject.fixed.AttendanceFixedDO;
import cn.iocoder.yudao.module.system.dal.dataobject.group.AttendanceGroupDO; import cn.iocoder.yudao.module.system.dal.dataobject.group.AttendanceGroupDO;
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.punch.PunchService; import cn.iocoder.yudao.module.system.service.attendance.punch.PunchService;
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 javax.annotation.Resource;
import java.util.Date;
import java.util.List;
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;
@ -28,6 +33,8 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.FIXED_NOT_
public class AttendanceFixedServiceImpl implements AttendanceFixedService, PunchService { public class AttendanceFixedServiceImpl implements AttendanceFixedService, PunchService {
@Resource @Resource
private AttendanceFixedMapper fixedMapper; private AttendanceFixedMapper fixedMapper;
@Resource
private AttendanceService attendanceService;
@Override @Override
public Long createFixed(AttendanceFixedSaveReqVO createReqVO) { public Long createFixed(AttendanceFixedSaveReqVO createReqVO) {
@ -71,14 +78,40 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
return fixedMapper.selectPage(pageReqVO); return fixedMapper.selectPage(pageReqVO);
} }
@Override
public AttendanceFixedDO getByGroupIdAndWeek(Long attendanceGroupId, Integer week) {
List<AttendanceFixedDO> list = fixedMapper.selectList(new LambdaQueryWrapper<AttendanceFixedDO>()
.eq(attendanceGroupId != null, AttendanceFixedDO::getAttendanceGroupId, attendanceGroupId)
.eq(week != null, AttendanceFixedDO::getWeekTime, week));
if (!list.isEmpty()) {
return list.get(0);
}
return null;
}
@Override @Override
public AttendancePunchPageVO getPunchPage(AttendancePunchPageDTO dto) { public AttendancePunchPageVO getPunchPage(AttendancePunchPageDTO dto) {
AttendancePunchPageVO vo = new AttendancePunchPageVO(); AttendancePunchPageVO vo = new AttendancePunchPageVO();
Date thisDate = new Date();
AttendanceGroupDO activationGroup = dto.getActivationGroup(); AttendanceGroupDO activationGroup = dto.getActivationGroup();
//判断当天是否需要考勤 - // -- 判断是否根据节假日自动排班 - 如果是的话 - 根据排班的来
Boolean isHolidayFlag = AttendanceGroupDO.TRUE.equals(activationGroup.getAutoHolidaysFlag()) ?
attendanceService.isHoliday(thisDate) : null;
// -- 当前是节假日 并且是放假
if (isHolidayFlag != null && isHolidayFlag) {
return vo.setTodayNeedAttendance(AttendanceGroupDO.FALSE);
}
//获取到当天是周几 //获取到当天是周几
int week = DateUtils.dayOfWeek(thisDate);
AttendanceFixedDO attendanceFixedDO = this.getByGroupIdAndWeek(activationGroup.getId(), week);
// -- 当前没有班次 - 不需要考勤
if (attendanceFixedDO == null || attendanceFixedDO.getAttendanceGroupShiftId() == null) {
return vo.setTodayNeedAttendance(AttendanceGroupDO.FALSE);
}
// TODO: 2024/4/17 明天在努力
return null; return null;
} }
} }

View File

@ -123,7 +123,7 @@ public class LogStatisticsServiceImpl implements LogStatisticsService {
boolean flag = false; boolean flag = false;
if (logRuleDO.getType() == 1 && StrUtil.isNotEmpty(logRuleDO.getWeekDays())) { if (logRuleDO.getType() == 1 && StrUtil.isNotEmpty(logRuleDO.getWeekDays())) {
// -- 判断今天是周几 需要提交的周做对比 // -- 判断今天是周几 需要提交的周做对比
int weekNum = ((DateUtil.dayOfWeekEnum(thisDate).getValue() - 1) == 0 ? 7 : (DateUtil.dayOfWeekEnum(thisDate).getValue() - 1)); int weekNum = DateUtils.dayOfWeek(thisDate);
List<String> weekDays = Arrays.asList(logRuleDO.getWeekDays().split(",")); List<String> weekDays = Arrays.asList(logRuleDO.getWeekDays().split(","));
if (weekDays.contains(Integer.toString(weekNum))) { if (weekDays.contains(Integer.toString(weekNum))) {
// -- 判断今天是周几 需要提交的周做对比 // -- 判断今天是周几 需要提交的周做对比
@ -231,7 +231,7 @@ public class LogStatisticsServiceImpl implements LogStatisticsService {
boolean flag = true; boolean flag = true;
if (logRuleDO.getType() == 1 && StrUtil.isNotEmpty(logRuleDO.getWeekDays())) { if (logRuleDO.getType() == 1 && StrUtil.isNotEmpty(logRuleDO.getWeekDays())) {
// -- 判断今天是周几 需要提交的周做对比 // -- 判断今天是周几 需要提交的周做对比
int weekNum = ((DateUtil.dayOfWeekEnum(thisDate).getValue() - 1) == 0 ? 7 : (DateUtil.dayOfWeekEnum(thisDate).getValue() - 1)); int weekNum = DateUtils.dayOfWeek(thisDate);
List<String> weekDays = Arrays.asList(logRuleDO.getWeekDays().split(",")); List<String> weekDays = Arrays.asList(logRuleDO.getWeekDays().split(","));
if (weekDays.contains(Integer.toString(weekNum))) { if (weekDays.contains(Integer.toString(weekNum))) {
vo.setCommitTimeRange("当天" + logRuleDO.getEndTime() + "截止提交"); vo.setCommitTimeRange("当天" + logRuleDO.getEndTime() + "截止提交");
@ -318,7 +318,7 @@ public class LogStatisticsServiceImpl implements LogStatisticsService {
Date thisDate = new Date(); Date thisDate = new Date();
if (logRuleDO.getType() == 1 && StrUtil.isNotEmpty(logRuleDO.getWeekDays())) { if (logRuleDO.getType() == 1 && StrUtil.isNotEmpty(logRuleDO.getWeekDays())) {
// -- 判断今天是周几 需要提交的周做对比 // -- 判断今天是周几 需要提交的周做对比
int weekNum = ((DateUtil.dayOfWeekEnum(thisDate).getValue() - 1) == 0 ? 7 : (DateUtil.dayOfWeekEnum(thisDate).getValue() - 1)); int weekNum = DateUtils.dayOfWeek(thisDate);
List<String> weekDays = Arrays.asList(logRuleDO.getWeekDays().split(",")); List<String> weekDays = Arrays.asList(logRuleDO.getWeekDays().split(","));
if (weekDays.contains(Integer.toString(weekNum))) { if (weekDays.contains(Integer.toString(weekNum))) {
return "当天" + logRuleDO.getEndTime() + "截止提交"; return "当天" + logRuleDO.getEndTime() + "截止提交";