From 2ae403942e056682246422848f5e3b7a3824a2aa Mon Sep 17 00:00:00 2001 From: aikai Date: Tue, 23 Jul 2024 17:14:00 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=B7=E5=81=87=E8=80=83=E5=8B=A4=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/pojo/BpmOALeaveDTO.java | 27 ++++ .../framework/common/util/date/DateUtils.java | 21 +++ .../module/bpm/enums/ErrorCodeConstants.java | 1 + .../rpc/config/RpcConfiguration.java | 5 +- .../bpm/service/oa/BpmOALeaveServiceImpl.java | 44 ++++-- .../system/api/attendance/AttendanceApi.java | 26 ++++ .../dto/AttendancePunchRecordDTO.java | 32 ++++ .../vo/AttendancePunchRecordVO.java | 138 ++++++++++++++++++ .../api/attendance/AttendanceApiImpl.java | 24 +++ .../attendance/vo/AttendanceStatisticsVO.java | 2 + .../vo/AttendanceStatusByDayVO.java | 2 +- .../admin/attendance/vo/CalculateNum.java | 2 + .../vo/TeamAttendanceStatisticsByCycleVO.java | 6 + .../vo/TeamAttendanceStatisticsByDayVO.java | 2 + .../punchrecord/AttendancePunchRecordDO.java | 16 +- .../AttendancePunchRecordMapper.java | 5 +- .../attendance/AttendanceServiceImpl.java | 130 ++++++++++++++++- .../punch/dto/AttendanceOnTheDayDTO.java | 8 +- .../AttendancePunchRecordService.java | 10 +- .../AttendancePunchRecordServiceImpl.java | 67 ++++++++- .../AttendancePunchRecordMapper.xml | 2 +- 21 files changed, 538 insertions(+), 32 deletions(-) create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/BpmOALeaveDTO.java create mode 100644 yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/AttendanceApi.java create mode 100644 yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/dto/AttendancePunchRecordDTO.java create mode 100644 yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/vo/AttendancePunchRecordVO.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/attendance/AttendanceApiImpl.java diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/BpmOALeaveDTO.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/BpmOALeaveDTO.java new file mode 100644 index 00000000..9be42ed6 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/BpmOALeaveDTO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.framework.common.pojo; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class BpmOALeaveDTO { + /** + * 请假表单主键 + */ + private Long id; + /** + * 申请人的用户编号 + * + * 关联 AdminUserDO 的 id 属性 + */ + private Long userId; + /** + * 开始时间 + */ + private LocalDateTime startTime; + /** + * 结束时间 + */ + private LocalDateTime endTime; +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java index 85371190..2f8ec208 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java @@ -8,6 +8,7 @@ import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONArray; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.framework.common.Constants; import java.text.SimpleDateFormat; import java.time.*; @@ -257,6 +258,25 @@ public class DateUtils { return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now()); } + /** + * 获取两个时间区间 - 获取两个时间区间的所有日期 + * + * @param beginTime + * @param endTime + * @return + */ + public static List betweenDayList(LocalDateTime beginTime, LocalDateTime endTime) { + List list = new ArrayList<>(); + long num = LocalDateTimeUtil.between(beginTime, endTime, ChronoUnit.DAYS); + + for (int i = 0; i <= num; i++) { + LocalDateTime dateTime = LocalDateTimeUtil.offset(beginTime, i, ChronoUnit.DAYS); + list.add(dateTime.format(Constants.REPO_DATE_FORMAT)); + } + return list; + } + + /** * 获取两个时间区间 - 获取两个时间区间的所有日期 * @@ -357,6 +377,7 @@ public class DateUtils { /** * 将1-7的数字转换为对应的中文星期表示 + * * @param dayOfWeek 数字形式的星期几,1-7分别代表星期一到星期日 * @return 中文表示的星期几 */ diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java index acdb42e2..7dbc39f6 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java @@ -20,6 +20,7 @@ public interface ErrorCodeConstants { ErrorCode OA_DEPART_BM_POST_NOT_EXISTS = new ErrorCode(1_009_001_005, "部门的部门经理不存在"); ErrorCode OA_HR_POST_NOT_EXISTS = new ErrorCode(1_009_001_006, "HR岗位未设置"); ErrorCode OA_DAY_LEAVE_ERROR = new ErrorCode(1_009_001_007, "请假天数必须>=1"); + ErrorCode FAILED_TO_APPLY_FOR_LEAVE = new ErrorCode(1_009_001_008, "请假失败"); ErrorCode OA_REIMBURSEMENT_NOT_EXISTS = new ErrorCode(1_009_001_100, "报销申请不存在"); ErrorCode OA_EVECTION_NOT_EXISTS = new ErrorCode(1_009_001_101, "出差申请不存在"); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java index aba9c98d..3aaeea2a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.bpm.framework.rpc.config; import cn.iocoder.yudao.module.infra.api.file.FileApi; +import cn.iocoder.yudao.module.system.api.attendance.AttendanceApi; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.PostApi; import cn.iocoder.yudao.module.system.api.dict.DictDataApi; @@ -15,8 +16,8 @@ import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) -@EnableFeignClients(clients = {FileApi.class,RoleApi.class, DeptApi.class, PostApi.class, AdminUserApi.class, SmsSendApi.class, DictDataApi.class, NotifyMessageSendApi.class, - SubscribeMessageSendApi.class, SocialClientApi.class, UsersExtApi.class +@EnableFeignClients(clients = {FileApi.class, RoleApi.class, DeptApi.class, PostApi.class, AdminUserApi.class, SmsSendApi.class, DictDataApi.class, NotifyMessageSendApi.class, + SubscribeMessageSendApi.class, SocialClientApi.class, UsersExtApi.class, AttendanceApi.class }) public class RpcConfiguration { } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java index 15907b62..a653c023 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java @@ -1,6 +1,10 @@ package cn.iocoder.yudao.module.bpm.service.oa; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.framework.common.pojo.BpmOALeaveDTO; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.api.oa.vo.BpmOALeaveRpcVO; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; @@ -12,17 +16,21 @@ import cn.iocoder.yudao.module.bpm.convert.oa.BpmOALeaveConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO; import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALeaveMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +import cn.iocoder.yudao.module.system.api.attendance.AttendanceApi; +import cn.iocoder.yudao.module.system.api.attendance.dto.AttendancePunchRecordDTO; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.FAILED_TO_APPLY_FOR_LEAVE; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_LEAVE_NOT_EXISTS; /** @@ -46,6 +54,8 @@ public class BpmOALeaveServiceImpl extends BpmOABaseService implements BpmOALeav private BpmProcessInstanceApi processInstanceApi; @Resource private StringRedisTemplate stringRedisTemplate; + @Resource + private AttendanceApi attendanceApi; @Override @Transactional(rollbackFor = Exception.class) @@ -77,6 +87,7 @@ public class BpmOALeaveServiceImpl extends BpmOABaseService implements BpmOALeav @Override + @Transactional(rollbackFor = Exception.class) public void updateLeaveResult(Long id, Integer result) { BpmOALeaveDO bpmOALeaveDO = validateLeaveExists(id); leaveMapper.updateById(new BpmOALeaveDO().setId(id).setResult(result)); @@ -84,17 +95,28 @@ public class BpmOALeaveServiceImpl extends BpmOABaseService implements BpmOALeav // -- 如果是的话 先插入到redis中 - (事前请假) // -- 如果不是 则查询相应的考勤 修改考勤状态 (事后请假 - 还需要判断结束时间是否) // -// if (result.equals(BpmProcessInstanceResultEnum.APPROVE.getResult())) { -// if (LocalDateTimeUtil.between(bpmOALeaveDO.getStartTime(), LocalDateTimeUtil.now()).toDays() > 0) { -// // -- 插入到redis中 -// LeaveVO leaveVO = new LeaveVO(); -// BeanUtil.copyProperties(bpmOALeaveDO, leaveVO); -// stringRedisTemplate.opsForHash().put("leave", bpmOALeaveDO.getUserId().toString(), JSONUtil.toJsonStr(leaveVO)); -// } else { -// // -- 查询相应的考勤 修改考勤状态 -// -// } -// } + LocalDateTime now = LocalDateTimeUtil.now(); + if (result.equals(BpmProcessInstanceResultEnum.APPROVE.getResult())) { + // 事后请假修改考勤 = 考勤的预设已经生成过了 - 并且已经在表里面存在了 - 所以要找到表中的数据 - 修改考勤状态 + CommonResult commonResult = attendanceApi.askingForLeaveAfterwardsToModifyAttendance(new AttendancePunchRecordDTO() + .setUserId(bpmOALeaveDO.getUserId()) + .setStartTime(bpmOALeaveDO.getStartTime()) + .setEndTime(bpmOALeaveDO.getEndTime()) + .setLeaveId(id) + ); + if (!commonResult.isSuccess()) { + throw exception(FAILED_TO_APPLY_FOR_LEAVE); + } + if (now.isBefore(bpmOALeaveDO.getEndTime())) { + // 事前请假 = 考勤预设可能还没有生成 - 因为可能请假好几天 - 所以这里处理就比较麻烦点 - 先看下考勤表里面有没有在这个区间的考勤 - 如果有的话先修改考勤状态 - + // 然后将数据先存入redis - 在设置考勤预设的时候 就去redis 中查询是否有请假 - 有的话预设的时候就预设进去 + BpmOALeaveDTO dto = new BpmOALeaveDTO(); + BeanUtil.copyProperties(bpmOALeaveDO, dto); + String key = "leave" + "_" + bpmOALeaveDO.getUserId().toString(); + stringRedisTemplate.opsForHash().put(key, id.toString(), JSONUtil.toJsonStr(dto)); + // -- 将请假put到redis的map中 - + } + } } private BpmOALeaveDO validateLeaveExists(Long id) { diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/AttendanceApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/AttendanceApi.java new file mode 100644 index 00000000..8d0c0ea8 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/AttendanceApi.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.system.api.attendance; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.system.api.attendance.dto.AttendancePunchRecordDTO; +import cn.iocoder.yudao.module.system.api.attendance.vo.AttendancePunchRecordVO; +import cn.iocoder.yudao.module.system.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; + +@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory = +@Tag(name = "RPC 服务 - 考勤") +public interface AttendanceApi { + + String PREFIX = ApiConstants.PREFIX + "/attendance"; + + + + @PostMapping(PREFIX + "/askingForLeaveAfterwardsToModifyAttendance") + @Operation(summary = "获取考勤记录") + CommonResult askingForLeaveAfterwardsToModifyAttendance(@RequestBody AttendancePunchRecordDTO attendancePunchRecordDTO); +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/dto/AttendancePunchRecordDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/dto/AttendancePunchRecordDTO.java new file mode 100644 index 00000000..43f8b009 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/dto/AttendancePunchRecordDTO.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.system.api.attendance.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +/** + * 用户打卡记录 DTO + * + * @author 艾楷 + */ +@Data +@Accessors(chain = true) +public class AttendancePunchRecordDTO { + /** + * 用户id + */ + private Long userId; + /** + * 开始时间 + */ + private LocalDateTime startTime; + /** + * 结束时间 + */ + private LocalDateTime endTime; + /** + * 请假id 对应bpm_oa_leave表id + */ + private Long leaveId; +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/vo/AttendancePunchRecordVO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/vo/AttendancePunchRecordVO.java new file mode 100644 index 00000000..0ed3b125 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/attendance/vo/AttendancePunchRecordVO.java @@ -0,0 +1,138 @@ +package cn.iocoder.yudao.module.system.api.attendance.vo; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 用户打卡记录 DO + * + * @author 艾楷 + */ +@Data +public class AttendancePunchRecordVO { + /** + * 编号 + */ + private Long id; + /** + * 考勤组管理员id + */ + private Long userId; + /** + * 部门id + */ + private Long deptId; + /** + * 考勤组id + */ + private Long attendanceGroupId; + /** + * 考勤组名称 + */ + private String attendanceGroupName; + /** + * 班次id + */ + private Long attendanceGroupShiftId; + /** + * 班次名称 + */ + private String attendanceGroupShiftName; + /** + * 班次子表id + */ + private Long attendanceGroupShiftItemId; + /** + * 考勤类型 1固定班制 2排班制 + */ + private Integer type; + /** + * 打卡类型 1考勤机 2小程序范围打卡 + */ + private Integer punchType; + + /** + * 上下班类型 0上班 1下班 + */ + private Integer workType; + + /** + * 级别 1到~ + */ + private Integer level; + + /** + * 打卡状态 0正常 1迟到 2早退 3缺卡 4未打卡(还没到打卡时间) 5补卡 6请假 + */ + private Integer status; + + /** + * 明天的打卡 0否 1是 (业务需要 先把明天的打卡统计出来) + */ + private Integer nextDayFlag; + + /** + * 是否外勤 0否 1是 + */ + private Integer fieldServiceFlag; + /** + * 日期yyyy-MM-dd格式 (归属于哪一天) + */ + private String dayTime; + + /** + * 日期yyyy-MM-dd格式 (实际是哪一天) + */ + private String actualDayTime; + /** + * 打卡时间 + */ + private LocalDateTime punchTime; + /** + * 应打卡时间 + */ + private LocalDateTime shouldPunchTime; + /** + * 最晚打卡时间(超过即为缺卡) + */ + private LocalDateTime latestPunchTime; + /** + * 打卡备注 + */ + private String remark; + /** + * 图片 + */ + private String image; + + /** + * 用户打卡地点 + */ + private String punchAddress; + + /** + * 迟到时长时间戳 + */ + private Long lateTime; + + /** + * 早退时长时间戳 + */ + private Long leaveEarlyTime; + + /** + * 加班时长时间戳 + */ + private Long workOvertimeTime; + + /** + * 是否已提醒 0否 1是 + */ + private Integer remindFlag; + + /** + * 请假json对象 + */ + private String leaveJson; +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/attendance/AttendanceApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/attendance/AttendanceApiImpl.java new file mode 100644 index 00000000..1ddf3f40 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/attendance/AttendanceApiImpl.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.system.api.attendance; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.system.api.attendance.dto.AttendancePunchRecordDTO; +import cn.iocoder.yudao.module.system.service.attendance.punchrecord.AttendancePunchRecordService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +@RestController // 提供 RESTful API 接口,给 Feign 调用 +@Validated +public class AttendanceApiImpl implements AttendanceApi { + + @Resource + private AttendancePunchRecordService attendancePunchRecordService; + + + @Override + public CommonResult askingForLeaveAfterwardsToModifyAttendance(AttendancePunchRecordDTO attendancePunchRecordDTO) { + attendancePunchRecordService.askingForLeaveAfterwardsToModifyAttendance(attendancePunchRecordDTO); + return CommonResult.success("ok"); + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceStatisticsVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceStatisticsVO.java index 6e65c83d..a51b5903 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceStatisticsVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceStatisticsVO.java @@ -25,6 +25,8 @@ public class AttendanceStatisticsVO { private List fieldServiceNumber; @Schema(description = "休息日") private List restDays; + @Schema(description = "请假次数") + private List leaveNumber; @Schema(description = "头部次数") private CalculateNum calculateNum; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceStatusByDayVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceStatusByDayVO.java index ff636358..e9b7daa0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceStatusByDayVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceStatusByDayVO.java @@ -9,7 +9,7 @@ import java.util.List; @Data @Accessors(chain = true) public class AttendanceStatusByDayVO { - @Schema(description = "状态 0正常 1异常(迟到/早退/缺卡)") + @Schema(description = "状态 0正常 1异常(迟到/早退/缺卡/请假/补卡)") private Integer status; @Schema(description = "是否有提交过 请假/加班/出差/外出/补卡 申请 0否 1是") private Integer submitStatus = 0; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/CalculateNum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/CalculateNum.java index 2cb3fce4..c3712516 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/CalculateNum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/CalculateNum.java @@ -27,6 +27,8 @@ public class CalculateNum { String totalEarlyDeparturesTimeStr; @Schema(description = "缺卡总次数") int totalMissingCardsNumber = 0; + @Schema(description = "请假总次数") + int totalLeaveNumber = 0; @Schema(description = "上班缺卡总次数") int totalUpMissingCardsNumber = 0; @Schema(description = "下班缺卡总次数") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/TeamAttendanceStatisticsByCycleVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/TeamAttendanceStatisticsByCycleVO.java index 268b3ba2..608d81b1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/TeamAttendanceStatisticsByCycleVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/TeamAttendanceStatisticsByCycleVO.java @@ -30,6 +30,9 @@ public class TeamAttendanceStatisticsByCycleVO { @Schema(description = "外勤") private List fieldServiceList; + @Schema(description = "请假") + private List leaveList; + @Schema(description = "顶部") private TeamAttendanceStatisticsNumVO teamAttendanceStatisticsNumVO; @@ -52,6 +55,9 @@ public class TeamAttendanceStatisticsByCycleVO { @Schema(description = "缺卡次数") private Integer missingCardNum; + @Schema(description = "请假次数") + private Integer leaveNum; + @Schema(description = "旷工次数") private Integer absenteeismNum; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/TeamAttendanceStatisticsByDayVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/TeamAttendanceStatisticsByDayVO.java index b1d66108..2be65791 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/TeamAttendanceStatisticsByDayVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/TeamAttendanceStatisticsByDayVO.java @@ -19,4 +19,6 @@ public class TeamAttendanceStatisticsByDayVO { private Integer leaveEarlyNum; @Schema(description = "外勤数量") private Integer fieldworkNum; + @Schema(description = "请假数量") + private Integer leaveNum; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/attendance/punchrecord/AttendancePunchRecordDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/attendance/punchrecord/AttendancePunchRecordDO.java index b8799f18..e1d7dc68 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/attendance/punchrecord/AttendancePunchRecordDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/attendance/punchrecord/AttendancePunchRecordDO.java @@ -77,7 +77,7 @@ public class AttendancePunchRecordDO extends BaseDO { private Integer level; /** - * 打卡状态 0正常 1迟到 2早退 3缺卡 4未打卡(还没到打卡时间) 5补卡 + * 打卡状态 0正常 1迟到 2早退 3缺卡 4未打卡(还没到打卡时间) 5补卡 6请假 */ private Integer status; @@ -91,9 +91,14 @@ public class AttendancePunchRecordDO extends BaseDO { */ private Integer fieldServiceFlag; /** - * 日期yyyy-MM-dd格式 + * 日期yyyy-MM-dd格式 (归属于哪一天) */ private String dayTime; + + /** + * 日期yyyy-MM-dd格式 (实际是哪一天) + */ + private String actualDayTime; /** * 打卡时间 */ @@ -140,6 +145,11 @@ public class AttendancePunchRecordDO extends BaseDO { */ private Integer remindFlag; + /** + * 请假单id + */ + private Long leaveId; + @TableField(exist = false) private String deptName; -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/attendance/punchrecord/AttendancePunchRecordMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/attendance/punchrecord/AttendancePunchRecordMapper.java index ac02dcc1..f753f1a8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/attendance/punchrecord/AttendancePunchRecordMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/attendance/punchrecord/AttendancePunchRecordMapper.java @@ -3,9 +3,10 @@ package cn.iocoder.yudao.module.system.dal.mysql.attendance.punchrecord; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.system.api.attendance.dto.AttendancePunchRecordDTO; +import cn.iocoder.yudao.module.system.api.attendance.vo.AttendancePunchRecordVO; import cn.iocoder.yudao.module.system.controller.admin.punchrecord.vo.AttendancePunchRecordPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.attendance.punchrecord.AttendancePunchRecordDO; -import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.attendance.punch.dto.AttendanceOnTheDayDTO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -47,4 +48,4 @@ public interface AttendancePunchRecordMapper extends BaseMapperX statistics(@Param("userList") List userList, @Param("dateList") List dateList); -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/AttendanceServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/AttendanceServiceImpl.java index 97ebbdd0..3a8175ac 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/AttendanceServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/AttendanceServiceImpl.java @@ -446,7 +446,12 @@ public class AttendanceServiceImpl implements AttendanceService { Map> collect = list.stream().collect(Collectors.groupingBy(AttendancePunchRecordDO::getDayTime)); - List statusList = Arrays.asList(AttendanceOnTheDayDTO.PUNCH_STATUS_LATE, AttendanceOnTheDayDTO.PUNCH_STATUS_LEAVE_EARLY, AttendanceOnTheDayDTO.PUNCH_STATUS_MISS); + List statusList = Arrays.asList(AttendanceOnTheDayDTO.PUNCH_STATUS_LATE, + AttendanceOnTheDayDTO.PUNCH_STATUS_LEAVE_EARLY, + AttendanceOnTheDayDTO.PUNCH_STATUS_MISS, + AttendanceOnTheDayDTO.REPLACEMENT_CARD, + AttendanceOnTheDayDTO.ASK_FOR_LEAVE + ); for (Map.Entry> entry : collect.entrySet()) { AttendanceStatusByDayVO attendanceStatusByDayVO = new AttendanceStatusByDayVO(); int status = 0; @@ -504,6 +509,7 @@ public class AttendanceServiceImpl implements AttendanceService { List beLateNumber = new ArrayList<>(); List earlyDeparturesNumber = new ArrayList<>(); List missingCardsNumber = new ArrayList<>(); + List leaveNumber = new ArrayList<>(); List minerDays = new ArrayList<>(); List fieldServiceNumber = new ArrayList<>(); CalculateNum calculateNum = new CalculateNum(); @@ -533,6 +539,10 @@ public class AttendanceServiceImpl implements AttendanceService { List missingCardsList = this.calculateMissingCardsList(day, weekChinese, workMap, calculateNum); missingCardsNumber.addAll(missingCardsList); + // -- 请假计算 + List leaveList = this.calculateLeaveList(day, weekChinese, workMap, calculateNum); + leaveNumber.addAll(leaveList); + // -- 旷工计算 AttendancePunchStatisticsVO miner = this.calculateMiner(day, weekChinese, entry.getValue(), calculateNum); if (miner != null) { @@ -553,6 +563,7 @@ public class AttendanceServiceImpl implements AttendanceService { vo.setBeLateNumber(beLateNumber); vo.setEarlyDeparturesNumber(earlyDeparturesNumber); vo.setMissingCardsNumber(missingCardsNumber); + vo.setLeaveNumber(leaveNumber); vo.setMinerDays(minerDays); vo.setFieldServiceNumber(fieldServiceNumber); vo.setRestDays(restDays); @@ -560,6 +571,80 @@ public class AttendanceServiceImpl implements AttendanceService { return vo; } + /** + * 请假计算 + * + * @param workMap + * @return + */ + private String calculateLeaveList(Map> workMap) { + int todayLeaveNumber = 0; + for (Map.Entry> workEntry : workMap.entrySet()) { + if (CollectionUtil.isNotEmpty(workEntry.getValue())) { + // -- 请假计算 + List leaveList = workEntry.getValue().stream().filter(a -> AttendanceOnTheDayDTO.ASK_FOR_LEAVE.equals(a.getStatus())).collect(Collectors.toList()); + if (CollectionUtil.isNotEmpty(leaveList)) { + todayLeaveNumber += leaveList.size(); + } + } + } + return String.valueOf(todayLeaveNumber); + } + + /** + * 请假计算 + * + * @param workMap + * @param calculateNum + * @return + */ + private void calculateLeaveList(Map> workMap, CalculateNum calculateNum) { + int todayLeaveNumber = 0; + for (Map.Entry> workEntry : workMap.entrySet()) { + if (CollectionUtil.isNotEmpty(workEntry.getValue())) { + // -- 请假计算 + List leaveList = workEntry.getValue().stream().filter(a -> AttendanceOnTheDayDTO.ASK_FOR_LEAVE.equals(a.getStatus())).collect(Collectors.toList()); + if (CollectionUtil.isNotEmpty(leaveList)) { + todayLeaveNumber += leaveList.size(); + } + } + } + calculateNum.setTotalLeaveNumber(calculateNum.getTotalLeaveNumber() + todayLeaveNumber); + } + + + /** + * 请假计算 + * + * @param day + * @param weekChinese + * @param workMap + * @param calculateNum + * @return + */ + private List calculateLeaveList(String day, String weekChinese, Map> workMap, CalculateNum calculateNum) { + List list = new ArrayList<>(); + int totalLeaveNumber = 0; + for (Map.Entry> workEntry : workMap.entrySet()) { + if (CollectionUtil.isNotEmpty(workEntry.getValue())) { + // -- 缺卡计算 + List missingCardsList = workEntry.getValue().stream().filter(a -> AttendanceOnTheDayDTO.ASK_FOR_LEAVE.equals(a.getStatus())).collect(Collectors.toList()); + if (CollectionUtil.isNotEmpty(missingCardsList)) { + totalLeaveNumber += missingCardsList.size(); + for (AttendancePunchRecordDO attendancePunchRecordDO : missingCardsList) { + AttendancePunchStatisticsVO earlyDepartures = new AttendancePunchStatisticsVO(); + earlyDepartures.setDay(day); + earlyDepartures.setWeek(weekChinese); + earlyDepartures.setShouldPunchTime(attendancePunchRecordDO.getShouldPunchTime().format(DateTimeFormatter.ofPattern("HH:mm"))); + list.add(earlyDepartures); + } + } + } + } + calculateNum.setTotalLeaveNumber(calculateNum.getTotalLeaveNumber() + totalLeaveNumber); + return list; + } + @Override public Map teamStatisticsByDay(TeamAttendanceStatisticsByDayDTO dto) { Map map = new HashMap<>(); @@ -587,6 +672,7 @@ public class AttendanceServiceImpl implements AttendanceService { int lateNum = 0; int leaveEarlyNum = 0; int fieldworkNum = 0; + int leaveNum = 0; for (AttendancePunchRecordDO attendancePunchRecordDO : entry.getValue()) { if (AttendanceOnTheDayDTO.PUNCH_STATUS_MISS.equals(attendancePunchRecordDO.getStatus())) { punchStatusMissNum++; @@ -600,6 +686,9 @@ public class AttendanceServiceImpl implements AttendanceService { if (Constants.TRUE.equals(attendancePunchRecordDO.getFieldServiceFlag())) { fieldworkNum++; } + if (AttendanceOnTheDayDTO.ASK_FOR_LEAVE.equals(attendancePunchRecordDO.getStatus())) { + leaveNum++; + } } TeamAttendanceStatisticsByDayVO vo = new TeamAttendanceStatisticsByDayVO(); vo.setAnswerNum(userMap.keySet().size()); @@ -608,6 +697,7 @@ public class AttendanceServiceImpl implements AttendanceService { vo.setLateNum(lateNum); vo.setLeaveEarlyNum(leaveEarlyNum); vo.setFieldworkNum(fieldworkNum); + vo.setLeaveNum(leaveNum); map.put(entry.getKey(), vo); } return map; @@ -661,6 +751,8 @@ public class AttendanceServiceImpl implements AttendanceService { List absenteeismList = new ArrayList<>(); //外勤 List fieldServiceList = new ArrayList<>(); + //请假 + List leaveList = new ArrayList<>(); Map> userPunchMap = list.stream().collect(Collectors.groupingBy(AttendancePunchRecordDO::getUserId)); // -- 根据用户分组 @@ -690,6 +782,8 @@ public class AttendanceServiceImpl implements AttendanceService { this.calculateEarlyDepartures(workMap, calculateNum); // -- 缺卡 this.calculateMissingCardsList(workMap, calculateNum); + // -- 请假 + this.calculateLeaveList(workMap, calculateNum); // -- 旷工 this.calculateMiner(dayEntry.getValue(), calculateNum); // -- 外勤 @@ -733,6 +827,14 @@ public class AttendanceServiceImpl implements AttendanceService { BeanUtil.copyProperties(averageWorkingHourVO, item); fieldServiceList.add(item.setTop(calculateNum.getTotalFieldServiceNumber() + "次").setDown("")); } + + // --- 请假漏卡 + if (calculateNum.getTotalLeaveNumber() > 0) { + TeamAttendancePunchStatisticsVO item = new TeamAttendancePunchStatisticsVO(); + BeanUtil.copyProperties(averageWorkingHourVO, item); + leaveList.add(item.setTop(calculateNum.getTotalLeaveNumber() + "次请假漏卡").setDown("")); + } + } vo.setAverageWorkingHoursList(averageWorkingHours); @@ -741,6 +843,8 @@ public class AttendanceServiceImpl implements AttendanceService { vo.setMissingCardList(missingCardList); vo.setAbsenteeismList(absenteeismList); vo.setFieldServiceList(fieldServiceList); + vo.setLeaveList(leaveList); + int sum = averageWorkingHours.stream().mapToInt(a -> a.getCalculateNum().getTotalAttendanceDays()).sum(); TeamAttendanceStatisticsByCycleVO.TeamAttendanceStatisticsNumVO teamAttendanceStatisticsByCycleVO = new TeamAttendanceStatisticsByCycleVO.TeamAttendanceStatisticsNumVO(); teamAttendanceStatisticsByCycleVO.setAverageWorkingHours( @@ -750,6 +854,7 @@ public class AttendanceServiceImpl implements AttendanceService { .setBeLateNum(beLateList.stream().mapToInt(a -> a.getCalculateNum().getTotalLateArrivalsNumber()).sum()) .setLeaveEarlyNum(leaveEarlyList.stream().mapToInt(a -> a.getCalculateNum().getTotalEarlyDeparturesNumber()).sum()) .setMissingCardNum(missingCardList.stream().mapToInt(a -> a.getCalculateNum().getTotalMissingCardsNumber()).sum()) + .setLeaveNum(leaveList.stream().mapToInt(a -> a.getCalculateNum().getTotalLeaveNumber()).sum()) .setAbsenteeismNum(absenteeismList.stream().mapToInt(a -> a.getCalculateNum().getTotalMinerDays()).sum()) .setFieldServiceNum(fieldServiceList.stream().mapToInt(a -> a.getCalculateNum().getTotalFieldServiceNumber()).sum()) ); @@ -913,6 +1018,10 @@ public class AttendanceServiceImpl implements AttendanceService { //早退时长 String leaveEarly = this.calculateEarlyDepartures(workMap); row.add(leaveEarly); + //请假漏卡次数 + String leaveList = this.calculateLeaveList(workMap); + row.add(leaveList); + Map missingCardsMap = this.calculateCommuteMissingCardsList(workMap); row.add(missingCardsMap.get(Constants.ZERO).toString()); row.add(missingCardsMap.get(Constants.ONE).toString()); @@ -926,7 +1035,8 @@ public class AttendanceServiceImpl implements AttendanceService { // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 try { - EasyExcel.write(response.getOutputStream()) +// EasyExcel.write(response.getOutputStream()) + EasyExcel.write("/Users/aikai/Downloads/" + System.currentTimeMillis() + "考勤统计按日导出.xls") .head(generateDailyHead(headTitle, detailedHead, maxSize)) .autoCloseStream(false) .excelType(ExcelTypeEnum.XLS) @@ -934,7 +1044,7 @@ public class AttendanceServiceImpl implements AttendanceService { .sheet("考勤统计按日导出") .doWrite(data); response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("考勤统计", StandardCharsets.UTF_8.name())); - response.setContentType("application/vnd.ms-excel;charset=UTF-8"); +// response.setContentType("application/vnd.ms-excel;charset=UTF-8"); } catch (IOException e) { throw new RuntimeException(e); @@ -980,6 +1090,8 @@ public class AttendanceServiceImpl implements AttendanceService { return "未打卡"; } else if (status == 5) { return "补卡"; + } else if (status == 6) { + return "请假"; } return ""; } @@ -1035,6 +1147,8 @@ public class AttendanceServiceImpl implements AttendanceService { this.calculateCommuteMissingCardsList(workMap, calculateNum); // -- 旷工 this.calculateMiner(dayEntry.getValue(), calculateNum); + // -- 请假 + this.calculateLeaveList(workMap, calculateNum); } //休息天数 this.calculateRestDay(dateList, dayMap.keySet().stream().distinct().collect(Collectors.toList()), calculateNum); @@ -1058,6 +1172,7 @@ public class AttendanceServiceImpl implements AttendanceService { row.add(String.valueOf(calculateNum.getTotalEarlyDeparturesNumber())); row.add(String.valueOf(calculateNum.getTotalEarlyDeparturesTimeStr())); + row.add(String.valueOf(calculateNum.getTotalLeaveNumber())); row.add(String.valueOf(calculateNum.getTotalUpMissingCardsNumber())); row.add(String.valueOf(calculateNum.getTotalDownMissingCardsNumber())); row.add(String.valueOf(calculateNum.getTotalMinerDays())); @@ -1067,7 +1182,8 @@ public class AttendanceServiceImpl implements AttendanceService { } try { - EasyExcel.write(response.getOutputStream()) +// EasyExcel.write(response.getOutputStream()) + EasyExcel.write("/Users/aikai/Downloads/" + System.currentTimeMillis() + "考勤统计按日导出.xls") .head(generateHead(headTitle, detailedHead)) .autoCloseStream(false) .excelType(ExcelTypeEnum.XLS) @@ -1075,7 +1191,7 @@ public class AttendanceServiceImpl implements AttendanceService { .sheet("考勤统计按月导出") .doWrite(data); response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("考勤统计", StandardCharsets.UTF_8.name())); - response.setContentType("application/vnd.ms-excel;charset=UTF-8"); +// response.setContentType("application/vnd.ms-excel;charset=UTF-8"); } catch (IOException e) { throw new RuntimeException(e); @@ -1096,6 +1212,7 @@ public class AttendanceServiceImpl implements AttendanceService { head.add(Arrays.asList(headTitle, detailedHead, "迟到时长", "迟到时长")); head.add(Arrays.asList(headTitle, detailedHead, "早退次数", "早退次数")); head.add(Arrays.asList(headTitle, detailedHead, "早退时长", "早退时长")); + head.add(Arrays.asList(headTitle, detailedHead, "请假漏卡次数", "请假漏卡次数")); head.add(Arrays.asList(headTitle, detailedHead, "上班缺卡次数", "上班缺卡次数")); head.add(Arrays.asList(headTitle, detailedHead, "下班缺卡次数", "下班缺卡次数")); head.add(Arrays.asList(headTitle, detailedHead, "旷工天数", "旷工天数")); @@ -1140,6 +1257,7 @@ public class AttendanceServiceImpl implements AttendanceService { head.add(Arrays.asList(headTitle, detailedHead, "迟到时长", "迟到时长")); // head.add(Arrays.asList(headTitle, detailedHead, "早退次数", "早退次数")); head.add(Arrays.asList(headTitle, detailedHead, "早退时长", "早退时长")); + head.add(Arrays.asList(headTitle, detailedHead, "请假漏卡次数", "请假漏卡次数")); head.add(Arrays.asList(headTitle, detailedHead, "上班缺卡次数", "上班缺卡次数")); head.add(Arrays.asList(headTitle, detailedHead, "下班缺卡次数", "下班缺卡次数")); // head.add(Arrays.asList(headTitle, detailedHead, "旷工天数", "旷工天数")); @@ -1319,7 +1437,7 @@ public class AttendanceServiceImpl implements AttendanceService { } /** - * 迟到次数 + * 缺卡次数 - 上下班区分开 * * @param workMap */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punch/dto/AttendanceOnTheDayDTO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punch/dto/AttendanceOnTheDayDTO.java index a30b3c24..67131a8d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punch/dto/AttendanceOnTheDayDTO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punch/dto/AttendanceOnTheDayDTO.java @@ -9,13 +9,15 @@ import java.time.LocalDateTime; public class AttendanceOnTheDayDTO { /** - * 打卡状态 0正常 1迟到 2早退 3缺卡 4未打卡(还没到打卡时间) + * 打卡状态 0正常 1迟到 2早退 3缺卡 4未打卡(还没到打卡时间) 5补卡 6请假 */ public static final Integer PUNCH_STATUS_NORMAL = 0; public static final Integer PUNCH_STATUS_LATE = 1; public static final Integer PUNCH_STATUS_LEAVE_EARLY = 2; public static final Integer PUNCH_STATUS_MISS = 3; public static final Integer PUNCH_STATUS_UN_PUNCH = 4; + public static final Integer REPLACEMENT_CARD = 5; + public static final Integer ASK_FOR_LEAVE = 6; @Schema(description = "子表id") private Long id; @@ -44,7 +46,7 @@ public class AttendanceOnTheDayDTO { @Schema(description = "后打卡时间(分钟) 默认 120分钟") private Integer afterPunchTime; - @Schema(description = "打卡状态 0正常 1迟到 2早退 3缺卡 4未打卡(还没到打卡时间)") + @Schema(description = "打卡状态 0正常 1迟到 2早退 3缺卡 4未打卡(还没到打卡时间) 5补卡 6请假") private Integer punchStatus; @Schema(description = "是否外勤 0否 1是", example = "1") @@ -75,4 +77,4 @@ public class AttendanceOnTheDayDTO { @Schema(description = "早退时长时间戳") private Long leaveEarlyTime; -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punchrecord/AttendancePunchRecordService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punchrecord/AttendancePunchRecordService.java index d8e54ab1..bc04b7d3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punchrecord/AttendancePunchRecordService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punchrecord/AttendancePunchRecordService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.service.attendance.punchrecord; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.api.attendance.dto.AttendancePunchRecordDTO; import cn.iocoder.yudao.module.system.controller.admin.punchrecord.vo.AttendancePunchRecordPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.punchrecord.vo.AttendancePunchRecordSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.attendance.group.AttendanceGroupDO; @@ -112,4 +113,11 @@ public interface AttendancePunchRecordService { * @param editList */ void batchUpdate(List editList); -} \ No newline at end of file + + /** + * 请假修改状态 + * + * @param dto + */ + void askingForLeaveAfterwardsToModifyAttendance(AttendancePunchRecordDTO dto); +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punchrecord/AttendancePunchRecordServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punchrecord/AttendancePunchRecordServiceImpl.java index c4a72155..5d1c590f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punchrecord/AttendancePunchRecordServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/punchrecord/AttendancePunchRecordServiceImpl.java @@ -6,9 +6,11 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.common.Constants; +import cn.iocoder.yudao.framework.common.pojo.BpmOALeaveDTO; 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.module.system.api.attendance.dto.AttendancePunchRecordDTO; import cn.iocoder.yudao.module.system.controller.admin.punchrecord.vo.AttendancePunchRecordPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.punchrecord.vo.AttendancePunchRecordSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.attendance.group.AttendanceGroupDO; @@ -26,7 +28,9 @@ import cn.iocoder.yudao.module.system.service.attendance.punch.dto.AttendanceOnT import cn.iocoder.yudao.module.system.service.attendance.scheduling.AttendanceSchedulingService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.springframework.context.annotation.Lazy; +import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -206,7 +210,7 @@ public class AttendancePunchRecordServiceImpl implements AttendancePunchRecordSe // // } // } - + Map delLeaveMap = new HashMap<>(); for (Map.Entry entry : map.entrySet()) { String key = Constants.ATTENDANCE + Constants.UNDERLINE + entry.getKey() + Constants.UNDERLINE; // + 时间 AttendanceGroupDO attendanceGroupDO = groupMap.get(entry.getKey()); @@ -221,7 +225,9 @@ public class AttendancePunchRecordServiceImpl implements AttendancePunchRecordSe List attendanceOnTheDayDTOS = attendanceService.buildAttendanceOnTheDay(attendanceGroupShiftItemDOS); for (Long userId : userIds) { AdminUserDO adminUserDO = userMap.get(userId); + Map leaveRedisMap = this.getAttendanceLeaveRedisMap(userId); Long deptId = adminUserDO == null ? null : adminUserDO.getDeptId(); + List leaveIds = new ArrayList<>(); for (AttendanceOnTheDayDTO attendanceOnTheDayDTO : attendanceOnTheDayDTOS) { AttendancePunchRecordDO attendancePunchRecordDO = new AttendancePunchRecordDO(); attendancePunchRecordDO.setUserId(userId); @@ -239,21 +245,67 @@ public class AttendancePunchRecordServiceImpl implements AttendancePunchRecordSe attendancePunchRecordDO.setFieldServiceFlag(Constants.FALSE); attendancePunchRecordDO.setNextDayFlag(Constants.TRUE); attendancePunchRecordDO.setDayTime(time); + LocalDateTime shouldPunchTime = LocalDateTime.ofInstant(DateUtils.buildHHmmTime(attendanceOnTheDayDTO.getTime(), (attendanceOnTheDayDTO.getNextDayFlag() == 0 ? localDateTime : nextDayLocalDateTime)).toInstant(), ZoneId.systemDefault()); + // -- 请假插入预设 + for (Map.Entry leaveEntry : leaveRedisMap.entrySet()) { + BpmOALeaveDTO dto = JSONUtil.toBean(leaveEntry.getValue().toString(), BpmOALeaveDTO.class); + // - 如果在这个区间之内 - 那么就是需要设为请假的 + if ((dto.getStartTime().isBefore(shouldPunchTime) || dto.getStartTime().equals(shouldPunchTime)) && + (dto.getEndTime().isAfter(shouldPunchTime) || dto.getEndTime().equals(shouldPunchTime))) { + attendancePunchRecordDO.setStatus(AttendanceOnTheDayDTO.ASK_FOR_LEAVE); + attendancePunchRecordDO.setLeaveId(dto.getId()); + } else if (dto.getEndTime().isBefore(shouldPunchTime)) { + leaveIds.add(dto.getId().toString()); + } + } + + String actualDayTime = shouldPunchTime.format(Constants.REPO_DATE_FORMAT); + attendancePunchRecordDO.setActualDayTime(actualDayTime); attendancePunchRecordDO.setShouldPunchTime(shouldPunchTime); attendancePunchRecordDO.setLatestPunchTime(shouldPunchTime.plusMinutes(attendanceOnTheDayDTO.getAfterPunchTime())); attendancePunchRecordDOList.add(attendancePunchRecordDO); } stringRedisTemplate.opsForHash().put(key + time, userId.toString(), JSONUtil.toJsonStr(attendanceOnTheDayDTOS)); + if (!leaveIds.isEmpty()) { + delLeaveMap.put("leave" + "_" + userId, leaveIds.toArray(new String[0])); + } } //设置缓存 2天 stringRedisTemplate.expire(key + time, 2, TimeUnit.DAYS); } + // -- 删除redis中的请假数据 + this.delLeave(delLeaveMap); // -- 批量 this.saveBatch(attendancePunchRecordDOList); } + /** + * 删除redis中的请假数据 + * + * @param delLeaveMap + */ + private void delLeave(Map delLeaveMap) { + if (MapUtil.isNotEmpty(delLeaveMap)) { + for (Map.Entry entry : delLeaveMap.entrySet()) { + stringRedisTemplate.opsForHash().delete(entry.getKey(), entry.getValue()); + } + } + } + + /** + * 获取用户请假redisMap + * + * @param userId + * @return + */ + private Map getAttendanceLeaveRedisMap(Long userId) { + HashOperations hashOps = stringRedisTemplate.opsForHash(); + String key = "leave" + "_" + userId.toString(); + return hashOps.entries(key); + } + @Override public List getNotReminded(LocalDateTime localDateTime) { String targetDayStr = localDateTime.format(Constants.REPO_DATE_FORMAT); @@ -268,6 +320,17 @@ public class AttendancePunchRecordServiceImpl implements AttendancePunchRecordSe punchRecordMapper.updateBatch(editList); } + + @Override + public void askingForLeaveAfterwardsToModifyAttendance(AttendancePunchRecordDTO dto) { + punchRecordMapper.update(new AttendancePunchRecordDO() + .setStatus(AttendanceOnTheDayDTO.ASK_FOR_LEAVE) + .setLeaveId(dto.getLeaveId()), + new LambdaUpdateWrapper().eq(AttendancePunchRecordDO::getUserId, dto.getUserId()) + .ge(AttendancePunchRecordDO::getShouldPunchTime, dto.getStartTime()) + .le(AttendancePunchRecordDO::getShouldPunchTime, dto.getEndTime())); + } + private Map getAttendanceGroupShiftIdGroupByGroup(List attendanceGroupDOS, LocalDateTime localDateTime) { Map map = new HashMap<>(); List fixedList = attendanceGroupDOS.stream().filter(a -> a.getType().equals(1)).collect(Collectors.toList()); @@ -287,4 +350,4 @@ public class AttendancePunchRecordServiceImpl implements AttendancePunchRecordSe return map; } -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/punchrecord/AttendancePunchRecordMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/punchrecord/AttendancePunchRecordMapper.xml index f03fe327..5a6756fe 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/punchrecord/AttendancePunchRecordMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/punchrecord/AttendancePunchRecordMapper.xml @@ -32,4 +32,4 @@ - \ No newline at end of file +