请假考勤调整
This commit is contained in:
parent
24d3508ea8
commit
2ae403942e
@ -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;
|
||||
}
|
@ -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<String> betweenDayList(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
List<String> 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 中文表示的星期几
|
||||
*/
|
||||
|
@ -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, "出差申请不存在");
|
||||
|
@ -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 {
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -25,6 +25,8 @@ public class AttendanceStatisticsVO {
|
||||
private List<AttendancePunchStatisticsVO> fieldServiceNumber;
|
||||
@Schema(description = "休息日")
|
||||
private List<AttendancePunchStatisticsVO> restDays;
|
||||
@Schema(description = "请假次数")
|
||||
private List<AttendancePunchStatisticsVO> leaveNumber;
|
||||
@Schema(description = "头部次数")
|
||||
private CalculateNum calculateNum;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 = "下班缺卡总次数")
|
||||
|
@ -30,6 +30,9 @@ public class TeamAttendanceStatisticsByCycleVO {
|
||||
@Schema(description = "外勤")
|
||||
private List<TeamAttendancePunchStatisticsVO> fieldServiceList;
|
||||
|
||||
@Schema(description = "请假")
|
||||
private List<TeamAttendancePunchStatisticsVO> 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;
|
||||
|
||||
|
@ -19,4 +19,6 @@ public class TeamAttendanceStatisticsByDayVO {
|
||||
private Integer leaveEarlyNum;
|
||||
@Schema(description = "外勤数量")
|
||||
private Integer fieldworkNum;
|
||||
@Schema(description = "请假数量")
|
||||
private Integer leaveNum;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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<AttendancePunch
|
||||
* @return
|
||||
*/
|
||||
List<AttendancePunchRecordDO> statistics(@Param("userList") List<Long> userList, @Param("dateList") List<String> dateList);
|
||||
}
|
||||
}
|
||||
|
@ -446,7 +446,12 @@ public class AttendanceServiceImpl implements AttendanceService {
|
||||
|
||||
Map<String, List<AttendancePunchRecordDO>> collect = list.stream().collect(Collectors.groupingBy(AttendancePunchRecordDO::getDayTime));
|
||||
|
||||
List<Integer> statusList = Arrays.asList(AttendanceOnTheDayDTO.PUNCH_STATUS_LATE, AttendanceOnTheDayDTO.PUNCH_STATUS_LEAVE_EARLY, AttendanceOnTheDayDTO.PUNCH_STATUS_MISS);
|
||||
List<Integer> 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<String, List<AttendancePunchRecordDO>> entry : collect.entrySet()) {
|
||||
AttendanceStatusByDayVO attendanceStatusByDayVO = new AttendanceStatusByDayVO();
|
||||
int status = 0;
|
||||
@ -504,6 +509,7 @@ public class AttendanceServiceImpl implements AttendanceService {
|
||||
List<AttendancePunchStatisticsVO> beLateNumber = new ArrayList<>();
|
||||
List<AttendancePunchStatisticsVO> earlyDeparturesNumber = new ArrayList<>();
|
||||
List<AttendancePunchStatisticsVO> missingCardsNumber = new ArrayList<>();
|
||||
List<AttendancePunchStatisticsVO> leaveNumber = new ArrayList<>();
|
||||
List<AttendancePunchStatisticsVO> minerDays = new ArrayList<>();
|
||||
List<AttendancePunchStatisticsVO> fieldServiceNumber = new ArrayList<>();
|
||||
CalculateNum calculateNum = new CalculateNum();
|
||||
@ -533,6 +539,10 @@ public class AttendanceServiceImpl implements AttendanceService {
|
||||
List<AttendancePunchStatisticsVO> missingCardsList = this.calculateMissingCardsList(day, weekChinese, workMap, calculateNum);
|
||||
missingCardsNumber.addAll(missingCardsList);
|
||||
|
||||
// -- 请假计算
|
||||
List<AttendancePunchStatisticsVO> 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<Long, List<AttendancePunchRecordDO>> workMap) {
|
||||
int todayLeaveNumber = 0;
|
||||
for (Map.Entry<Long, List<AttendancePunchRecordDO>> workEntry : workMap.entrySet()) {
|
||||
if (CollectionUtil.isNotEmpty(workEntry.getValue())) {
|
||||
// -- 请假计算
|
||||
List<AttendancePunchRecordDO> 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<Long, List<AttendancePunchRecordDO>> workMap, CalculateNum calculateNum) {
|
||||
int todayLeaveNumber = 0;
|
||||
for (Map.Entry<Long, List<AttendancePunchRecordDO>> workEntry : workMap.entrySet()) {
|
||||
if (CollectionUtil.isNotEmpty(workEntry.getValue())) {
|
||||
// -- 请假计算
|
||||
List<AttendancePunchRecordDO> 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<AttendancePunchStatisticsVO> calculateLeaveList(String day, String weekChinese, Map<Long, List<AttendancePunchRecordDO>> workMap, CalculateNum calculateNum) {
|
||||
List<AttendancePunchStatisticsVO> list = new ArrayList<>();
|
||||
int totalLeaveNumber = 0;
|
||||
for (Map.Entry<Long, List<AttendancePunchRecordDO>> workEntry : workMap.entrySet()) {
|
||||
if (CollectionUtil.isNotEmpty(workEntry.getValue())) {
|
||||
// -- 缺卡计算
|
||||
List<AttendancePunchRecordDO> 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<String, TeamAttendanceStatisticsByDayVO> teamStatisticsByDay(TeamAttendanceStatisticsByDayDTO dto) {
|
||||
Map<String, TeamAttendanceStatisticsByDayVO> 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<TeamAttendancePunchStatisticsVO> absenteeismList = new ArrayList<>();
|
||||
//外勤
|
||||
List<TeamAttendancePunchStatisticsVO> fieldServiceList = new ArrayList<>();
|
||||
//请假
|
||||
List<TeamAttendancePunchStatisticsVO> leaveList = new ArrayList<>();
|
||||
|
||||
Map<Long, List<AttendancePunchRecordDO>> 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<Integer, Integer> 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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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<AttendancePunchRecordDO> editList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请假修改状态
|
||||
*
|
||||
* @param dto
|
||||
*/
|
||||
void askingForLeaveAfterwardsToModifyAttendance(AttendancePunchRecordDTO dto);
|
||||
}
|
||||
|
@ -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<String, String[]> delLeaveMap = new HashMap<>();
|
||||
for (Map.Entry<Long, Long> 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<AttendanceOnTheDayDTO> attendanceOnTheDayDTOS = attendanceService.buildAttendanceOnTheDay(attendanceGroupShiftItemDOS);
|
||||
for (Long userId : userIds) {
|
||||
AdminUserDO adminUserDO = userMap.get(userId);
|
||||
Map<Object, Object> leaveRedisMap = this.getAttendanceLeaveRedisMap(userId);
|
||||
Long deptId = adminUserDO == null ? null : adminUserDO.getDeptId();
|
||||
List<String> 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<Object, Object> 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<String, String[]> delLeaveMap) {
|
||||
if (MapUtil.isNotEmpty(delLeaveMap)) {
|
||||
for (Map.Entry<String, String[]> entry : delLeaveMap.entrySet()) {
|
||||
stringRedisTemplate.opsForHash().delete(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户请假redisMap
|
||||
*
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
private Map<Object, Object> getAttendanceLeaveRedisMap(Long userId) {
|
||||
HashOperations<String, Object, Object> hashOps = stringRedisTemplate.opsForHash();
|
||||
String key = "leave" + "_" + userId.toString();
|
||||
return hashOps.entries(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AttendancePunchRecordDO> 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<AttendancePunchRecordDO>().eq(AttendancePunchRecordDO::getUserId, dto.getUserId())
|
||||
.ge(AttendancePunchRecordDO::getShouldPunchTime, dto.getStartTime())
|
||||
.le(AttendancePunchRecordDO::getShouldPunchTime, dto.getEndTime()));
|
||||
}
|
||||
|
||||
private Map<Long, Long> getAttendanceGroupShiftIdGroupByGroup(List<AttendanceGroupDO> attendanceGroupDOS, LocalDateTime localDateTime) {
|
||||
Map<Long, Long> map = new HashMap<>();
|
||||
List<AttendanceGroupDO> fixedList = attendanceGroupDOS.stream().filter(a -> a.getType().equals(1)).collect(Collectors.toList());
|
||||
@ -287,4 +350,4 @@ public class AttendancePunchRecordServiceImpl implements AttendancePunchRecordSe
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -32,4 +32,4 @@
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
</mapper>
|
||||
|
Loading…
Reference in New Issue
Block a user