This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package jnpf.attendance.annotation;
|
||||
|
||||
import jnpf.enums.attendance.ActionEnum;
|
||||
import jnpf.enums.attendance.MachineEnum;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Machine {
|
||||
|
||||
/** 操作动作(打卡, 下发人员, 删除人员) */
|
||||
ActionEnum dealAction();
|
||||
|
||||
/** 厂商 */
|
||||
MachineEnum factory();
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
package jnpf.attendance.annotation;
|
||||
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import jnpf.attendance.mapper.AttendanceGroupMapper;
|
||||
import jnpf.attendance.mapper.AttendanceMachineLogMapper;
|
||||
import jnpf.attendance.service.AttendanceUserService;
|
||||
import jnpf.base.UserInfo;
|
||||
import jnpf.entity.AttendanceGroupUser;
|
||||
import jnpf.entity.attendance.AttendanceMachineLog;
|
||||
import jnpf.enums.attendance.ActionEnum;
|
||||
import jnpf.enums.attendance.MachineEnum;
|
||||
import jnpf.model.attendance.vo.GroupInfoVo;
|
||||
import jnpf.model.attendance.vo.attendance.UserTenantVo;
|
||||
import jnpf.util.ConstantUtil;
|
||||
import jnpf.util.DateUtil;
|
||||
import jnpf.util.FtbUtil;
|
||||
import jnpf.util.JsonUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.*;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 考勤机切面
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2024-07-30
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@RefreshScope
|
||||
public class MachineAspect {
|
||||
|
||||
@Value("${machine-log}")
|
||||
private Integer machineLog;
|
||||
|
||||
@Resource
|
||||
private AttendanceMachineLogMapper attendanceMachineLogMapper;
|
||||
|
||||
@Resource
|
||||
private AttendanceUserService attendanceUserService;
|
||||
|
||||
@Resource
|
||||
private AttendanceGroupMapper attendanceGroupMapper;
|
||||
|
||||
private static final ThreadLocal<AttendanceMachineLog> threadLocal = new ThreadLocal<>();
|
||||
|
||||
@Pointcut("@annotation(jnpf.attendance.annotation.Machine)")
|
||||
public void machineLog() {
|
||||
}
|
||||
|
||||
@Around(value = "machineLog()")
|
||||
public Object generateLog(ProceedingJoinPoint point) throws Throwable {
|
||||
|
||||
if (null == machineLog || machineLog.equals(ConstantUtil.NUM_FALSE)) {
|
||||
return point.proceed();
|
||||
}
|
||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
Machine annotation = method.getAnnotation(Machine.class);
|
||||
Object[] args = point.getArgs();
|
||||
ActionEnum actionEnum = annotation.dealAction();
|
||||
MachineEnum machineEnum = annotation.factory();
|
||||
JSONArray array = new JSONArray();
|
||||
AttendanceMachineLog machineLog = new AttendanceMachineLog();
|
||||
if (null != args && args.length > 0) {
|
||||
String str;
|
||||
if (actionEnum.equals(ActionEnum.DA_KA)) {
|
||||
str = "arg[0]";
|
||||
String paramStr = args[0].toString();
|
||||
if (StringUtils.isNotEmpty(paramStr)) {
|
||||
paramStr = paramStr.replaceAll("checkPic=[^,]+,", "");
|
||||
paramStr = paramStr.replaceAll("\"photo\":\"[^\"]*\",", "");
|
||||
}
|
||||
if (MachineEnum.KE_MI.equals(machineEnum)) {
|
||||
paramStr = JsonUtil.getObjectToString(args[0]);
|
||||
}
|
||||
MutablePair<String, String> pair = this.getUserInfo(paramStr, machineEnum);
|
||||
if (StringUtils.isNotEmpty(pair.getLeft())) {
|
||||
String[] split = pair.getLeft().split("@");
|
||||
String tenantId = split[0];
|
||||
String userId = split[1];
|
||||
// 查询当前考勤组信息
|
||||
UserInfo userInfo = new UserInfo();
|
||||
userInfo.setTenantId(tenantId);
|
||||
userInfo.setUserId(userId);
|
||||
GroupInfoVo group = null;
|
||||
try {
|
||||
List<AttendanceGroupUser> groupList = attendanceUserService.getAttendanceGroupUsersOfSecondment(DateUtil.getNowDate(), DateUtil.getNowDate(), List.of(userId), null, false);
|
||||
if (null != groupList && !groupList.isEmpty()) {
|
||||
String groupName = attendanceGroupMapper.getGroupName(groupList.get(0).getGroupId());
|
||||
group = new GroupInfoVo(groupList.get(0).getGroupId(), groupName);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
machineLog.setUserId(userId);
|
||||
machineLog.setUserName(pair.getRight());
|
||||
if (null != group) {
|
||||
machineLog.setGroupId(group.getGroupId());
|
||||
machineLog.setGroupName(group.getGroupName());
|
||||
}
|
||||
}
|
||||
JSONObject json = new JSONObject();
|
||||
json.set(str, paramStr);
|
||||
array.add(json);
|
||||
} else {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
str = "arg[" + i + "]";
|
||||
JSONObject json = new JSONObject();
|
||||
try {
|
||||
if (args[i] != null) {
|
||||
if (i == 0) {
|
||||
JSONObject arg = new JSONObject(args[i]);
|
||||
json.set(str, arg.get("userName"));
|
||||
arg.clear();
|
||||
} else {
|
||||
json.set(str, args[i].toString());
|
||||
}
|
||||
} else {
|
||||
json.set(str, "null");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
json.set(str, e.getMessage());
|
||||
}
|
||||
array.add(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
machineLog.setId(FtbUtil.getId());
|
||||
machineLog.setFactoryCode(machineEnum.getValue());
|
||||
machineLog.setAction(actionEnum.getDescription());
|
||||
machineLog.setParamJson(array.toString());
|
||||
machineLog.setCreatorTime(new Date());
|
||||
threadLocal.set(machineLog);
|
||||
return point.proceed();
|
||||
}
|
||||
|
||||
private MutablePair<String, String> getUserInfo(String paramStr, MachineEnum machineEnum) {
|
||||
|
||||
String userId = null;
|
||||
String userName = null;
|
||||
String regexUserId;
|
||||
String regexUserName;
|
||||
switch (machineEnum) {
|
||||
case KAI_JIA_YI:
|
||||
regexUserId = "\\\"userId\\\":\\\"([^\\\"]*)\\\"";
|
||||
regexUserName = "name=(.*?)(,|\\})";
|
||||
String regexTenantId = "\\\"tenantId\\\":\\\"([^\\\"]*)\\\"";
|
||||
Matcher kjyMatcher = Pattern.compile(regexUserId + "|" + regexUserName + "|" + regexTenantId).matcher(paramStr);
|
||||
String tenantId = "";
|
||||
while (kjyMatcher.find()) {
|
||||
if (kjyMatcher.group(1) != null) {
|
||||
userId = kjyMatcher.group(1);
|
||||
}
|
||||
if (kjyMatcher.group(2) != null) {
|
||||
userName = kjyMatcher.group(2);
|
||||
}
|
||||
if (kjyMatcher.group(4) != null) {
|
||||
tenantId = kjyMatcher.group(4);
|
||||
}
|
||||
}
|
||||
userId = tenantId + "@" + userId;
|
||||
break;
|
||||
case MAO_TONG:
|
||||
regexUserId = "user_id=(.*?)(?=,)";
|
||||
regexUserName = "user_name=(.*?)(?=,)";
|
||||
Matcher matcher = Pattern.compile(regexUserId + "|" + regexUserName).matcher(paramStr);
|
||||
while (matcher.find()) {
|
||||
if (matcher.group(1) != null) {
|
||||
userId = matcher.group(1);
|
||||
}
|
||||
if (matcher.group(2) != null) {
|
||||
userName = matcher.group(2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KE_MI:
|
||||
UserTenantVo userTenant = JsonUtil.getJsonToBean(paramStr, UserTenantVo.class);
|
||||
userId = userTenant.getTenantId() + "@" + userTenant.getUserId();
|
||||
userName = userTenant.getUserName();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return MutablePair.of(userId, userName);
|
||||
}
|
||||
|
||||
@AfterReturning(pointcut = "machineLog()", returning = "result")
|
||||
public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
|
||||
|
||||
if (null == machineLog || machineLog.equals(ConstantUtil.NUM_FALSE)) {
|
||||
return;
|
||||
}
|
||||
// 这里可以访问目标方法的返回值
|
||||
AttendanceMachineLog machineLog = threadLocal.get();
|
||||
if (null != machineLog) {
|
||||
machineLog.setMethodResult(null == result ? "无返回值" : result.toString());
|
||||
attendanceMachineLogMapper.insert(machineLog);
|
||||
threadLocal.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@AfterThrowing(pointcut = "machineLog()", throwing = "ex")
|
||||
public void afterThrowingAdvice(JoinPoint joinPoint, Throwable ex) {
|
||||
|
||||
if (null == machineLog || machineLog.equals(ConstantUtil.NUM_FALSE)) {
|
||||
return;
|
||||
}
|
||||
// 这里可以访问目标方法抛出的异常
|
||||
AttendanceMachineLog machineLog = threadLocal.get();
|
||||
if (null != machineLog) {
|
||||
machineLog.setMethodResult(ex.getMessage());
|
||||
attendanceMachineLogMapper.insert(machineLog);
|
||||
threadLocal.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
package jnpf.attendance.antifreeze;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import jnpf.authority.FtbAuthorityApi;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.file.FileUploadApi;
|
||||
import jnpf.model.personnels.dto.staff.roster.FtbPersonnelsStaffRosterDto;
|
||||
import jnpf.model.personnels.dto.staff.roster.WorkerGroupDataDto;
|
||||
import jnpf.model.personnels.req.roster.StaffRosterListReq;
|
||||
import jnpf.permission.V2UserApi;
|
||||
import jnpf.permission.entity.UserEntity;
|
||||
import jnpf.permission.eum.v2.UserWorkStatusEnums;
|
||||
import jnpf.permission.model.user.PartUserInfoVo;
|
||||
import jnpf.permission.vo.v2.user.UserBoundInfoVO;
|
||||
import jnpf.permission.vo.v2.user.UserBoundVO;
|
||||
import jnpf.personnels.FtbPersonnelsRosterManagerApi;
|
||||
import jnpf.util.StringUtil;
|
||||
import jnpf.util.UploaderUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class UserAntifreeze {
|
||||
@Resource
|
||||
private V2UserApi v2UserApi;
|
||||
@Resource
|
||||
private FileUploadApi fileUploadApi;
|
||||
@Resource
|
||||
private FtbAuthorityApi ftbAuthorityApi;
|
||||
@Resource
|
||||
private FtbPersonnelsRosterManagerApi managerApi;
|
||||
|
||||
/**
|
||||
* 请求用户服务接口
|
||||
*
|
||||
* @param userIds 用户ID集合
|
||||
* @return 用户信息
|
||||
*/
|
||||
public List<PartUserInfoVo> getInfoByIds(List<String> userIds, String tenantId) {
|
||||
List<PartUserInfoVo> infoByIds = CollUtil.newArrayList();
|
||||
try {
|
||||
ActionResult<List<UserBoundVO>> userList = v2UserApi.getAllUserInfoBatch(userIds, tenantId);
|
||||
if (200 == userList.getCode() && CollectionUtil.isNotEmpty(userList.getData())) {
|
||||
infoByIds = getPartUserInfoVos(userList.getData());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("用户接口请求失败:", e);
|
||||
}
|
||||
return infoByIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求用户服务接口
|
||||
*
|
||||
* @param orgId 组织ID
|
||||
* @param workGroupId 班组ID
|
||||
* @return 用户信息
|
||||
*/
|
||||
public List<UserBoundVO> getInfoByIds(String orgId, String workGroupId) {
|
||||
List<UserBoundVO> userBoundVoList = ftbAuthorityApi.listTargetOrganizeIdAuthApi(orgId,
|
||||
List.of(UserWorkStatusEnums.NONE));
|
||||
if (StringUtil.isEmpty(workGroupId)) {
|
||||
return userBoundVoList;
|
||||
}
|
||||
return userBoundVoList.stream().filter(vo -> StringUtil.equals(vo.getStoreTeamId(), workGroupId)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求用户服务接口
|
||||
*
|
||||
* @param orgIds 组织ID集合
|
||||
* @param workStatusEnums 用户工作状态
|
||||
* @return 用户信息
|
||||
*/
|
||||
public List<UserBoundVO> batchGetInfoByIds(List<String> orgIds, List<UserWorkStatusEnums> workStatusEnums) {
|
||||
return ftbAuthorityApi.listTargetOrganizeIdsAuthApi(orgIds,
|
||||
UserWorkStatusEnums.getDifferenceEnumsFromBase(workStatusEnums));
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求用户服务接口
|
||||
*
|
||||
* @param userIds 用户ID集合
|
||||
* @return 用户信息
|
||||
*/
|
||||
public List<PartUserInfoVo> getStaffRosterListInfoByIds(List<String> userIds) {
|
||||
List<PartUserInfoVo> infoByIds = CollUtil.newArrayList();
|
||||
try {
|
||||
StaffRosterListReq req = new StaffRosterListReq();
|
||||
req.setUserIds(userIds);
|
||||
req.setIsQueryAuth("0");
|
||||
List<FtbPersonnelsStaffRosterDto> userBoundVos = managerApi.postWithSalaryNoPage(req);
|
||||
infoByIds = getStaffRosterVos(userBoundVos);
|
||||
} catch (Exception e) {
|
||||
log.error("用户接口请求失败:", e);
|
||||
}
|
||||
return infoByIds;
|
||||
}
|
||||
|
||||
private List<PartUserInfoVo> getStaffRosterVos(List<FtbPersonnelsStaffRosterDto> userBoundVos) {
|
||||
List<PartUserInfoVo> infoByIds;
|
||||
if (CollUtil.isEmpty(userBoundVos)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
infoByIds = userBoundVos.stream().map(x -> {
|
||||
PartUserInfoVo bean = BeanUtil.toBean(x, PartUserInfoVo.class);
|
||||
bean.setUserId(x.getUserId());
|
||||
bean.setRealName(StringUtil.isNotEmpty(x.getName()) ? x.getName() : "");
|
||||
bean.setMobilePhone(StringUtil.isNotEmpty(x.getPhone()) ? x.getPhone() : "");
|
||||
bean.setWorkerStatus(Objects.nonNull(x.getWorkerStatus()) ? x.getWorkerStatus() : "");
|
||||
bean.setHeadIcon(StringUtil.isNotEmpty(x.getHeadLogo()) ? fileUploadApi.getHeadIcon(UploaderUtil.uploaderImg(x.getHeadLogo())) : "");
|
||||
if(CollUtil.isNotEmpty(x.getOrgList())){
|
||||
WorkerGroupDataDto groupDataDto = x.getOrgList().stream().findFirst().orElse(null);
|
||||
if(Objects.nonNull(groupDataDto)){
|
||||
bean.setOrganizeName(groupDataDto.getAffiliatedOrgName());
|
||||
bean.setOrganizeId(groupDataDto.getAffiliatedOrg());
|
||||
bean.setPositionId(groupDataDto.getAffiliatedPosition());
|
||||
bean.setPositionName(groupDataDto.getAffiliatedPositionName());
|
||||
}
|
||||
// Optional.ofNullable(groupDataDto).ifPresent(groupDataDto1 -> {
|
||||
// bean.setOrganizeName(groupDataDto1.getAffiliatedOrgName());
|
||||
// bean.setOrganizeId(groupDataDto1.getAffiliatedOrg());
|
||||
// bean.setPositionId(groupDataDto1.getAffiliatedPosition());
|
||||
// bean.setPositionName(groupDataDto1.getAffiliatedPositionName());
|
||||
// });
|
||||
}
|
||||
return bean;
|
||||
}).collect(Collectors.toList());
|
||||
return infoByIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求用户服务接口
|
||||
*
|
||||
* @param userIds 用户ID集合
|
||||
* @return 用户信息
|
||||
*/
|
||||
public List<PartUserInfoVo> getInfoByIdsManyAndCopyPost(List<String> userIds, String tenantId) {
|
||||
List<PartUserInfoVo> infoByIds = CollUtil.newArrayList();
|
||||
try {
|
||||
List<UserBoundVO> userBoundVos = v2UserApi.userListAndCopy(userIds, null, tenantId);
|
||||
infoByIds = getPartUserInfoVos(userBoundVos);
|
||||
} catch (Exception e) {
|
||||
log.error("用户接口请求失败:", e);
|
||||
}
|
||||
return infoByIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求用户服务接口
|
||||
*
|
||||
* @param userIds 用户ID集合
|
||||
* @return 用户信息
|
||||
*/
|
||||
public List<PartUserInfoVo> getAllByIds(List<String> userIds, String tenantId) {
|
||||
List<PartUserInfoVo> infoByIds = CollUtil.newArrayList();
|
||||
try {
|
||||
ActionResult<List<UserBoundVO>> userList = v2UserApi.getAllUserInfoBatch(userIds, tenantId);
|
||||
if (200 == userList.getCode() && CollectionUtil.isNotEmpty(userList.getData())) {
|
||||
infoByIds = getPartUserInfoVos(userList.getData());
|
||||
}
|
||||
if (CollUtil.isEmpty(infoByIds)) {
|
||||
List<UserBoundVO> userBoundVos = v2UserApi.userListAndCopy(userIds, true, tenantId);
|
||||
infoByIds = getPartUserInfoVos(userBoundVos);
|
||||
return infoByIds;
|
||||
}
|
||||
if (infoByIds.size() < userIds.size()) {
|
||||
List<String> collect = infoByIds.stream().map(PartUserInfoVo::getUserId).collect(Collectors.toList());
|
||||
userIds = userIds.stream().filter(userId -> !collect.contains(userId)).collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(userIds)) {
|
||||
List<UserBoundVO> userBoundVos = v2UserApi.userListAndCopy(userIds, true, tenantId);
|
||||
List<PartUserInfoVo> partUserInfoVos = getPartUserInfoVos(userBoundVos);
|
||||
infoByIds.addAll(partUserInfoVos);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("用户接口请求失败:", e);
|
||||
}
|
||||
return infoByIds;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<PartUserInfoVo> getPartUserInfoVos(List<UserBoundVO> userList) {
|
||||
List<PartUserInfoVo> infoByIds;
|
||||
if (CollUtil.isEmpty(userList)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
infoByIds = userList.stream().map(x -> {
|
||||
PartUserInfoVo bean = BeanUtil.toBean(x, PartUserInfoVo.class);
|
||||
bean.setUserId(x.getId());
|
||||
bean.setRealName(StringUtil.isNotEmpty(x.getUserName()) ? x.getUserName() : "");
|
||||
bean.setMobilePhone(StringUtil.isNotEmpty(x.getPhone()) ? x.getPhone() : "");
|
||||
bean.setWorkerStatus(Objects.nonNull(x.getWorkStatusEnums()) ? x.getWorkStatusEnums().getCode() : "");
|
||||
bean.setHeadIcon(StringUtil.isNotEmpty(x.getHeadIcon()) ? fileUploadApi.getHeadIcon(UploaderUtil.uploaderImg(x.getHeadIcon())) : "");
|
||||
return bean;
|
||||
}).collect(Collectors.toList());
|
||||
return infoByIds;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<UserEntity> getUserInfoVos(List<UserBoundVO> userList) {
|
||||
if (CollUtil.isEmpty(userList)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
return userList.stream().map(x -> {
|
||||
UserEntity bean = BeanUtil.toBean(x, UserEntity.class);
|
||||
bean.setId(x.getId());
|
||||
bean.setRealName(x.getUserName());
|
||||
bean.setMobilePhone(x.getPhone());
|
||||
bean.setHeadIcon(fileUploadApi.getHeadIcon(UploaderUtil.uploaderImg(x.getHeadIcon())));
|
||||
return bean;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求用户服务接口
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 用户信息
|
||||
*/
|
||||
public PartUserInfoVo getInfo(String userId, String tenantId) {
|
||||
try {
|
||||
List<PartUserInfoVo> infoByIds = getAllByIds(CollUtil.newArrayList(userId), tenantId);
|
||||
if (CollUtil.isEmpty(infoByIds)) {
|
||||
return null;
|
||||
}
|
||||
return infoByIds.get(0);
|
||||
} catch (Exception e) {
|
||||
log.error("用户接口请求失败:", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求用户服务接口
|
||||
*
|
||||
* @param userIds 用户ID集合
|
||||
* @return 用户信息
|
||||
*/
|
||||
public List<UserEntity> getInfoByIds(List<String> userIds) {
|
||||
List<UserEntity> infoByIds = CollUtil.newArrayList();
|
||||
try {
|
||||
List<UserBoundVO> userBoundVos = v2UserApi.userListAndCopy(userIds, false, null);
|
||||
infoByIds = getUserInfoVos(userBoundVos);
|
||||
if (CollUtil.isEmpty(infoByIds)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
infoByIds.stream().filter(Objects::nonNull).filter(user -> StringUtil.isNotEmpty(user.getHeadIcon())).forEach(user -> user.setHeadIcon(fileUploadApi.getHeadIcon(UploaderUtil.uploaderImg(user.getHeadIcon()))));
|
||||
} catch (Exception e) {
|
||||
log.error("用户接口请求失败:", e);
|
||||
}
|
||||
return infoByIds;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 请求用户服务接口
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 用户信息
|
||||
*/
|
||||
public UserEntity getInfo(String userId) {
|
||||
try {
|
||||
ActionResult<UserBoundInfoVO> usersBound = v2UserApi.getUsersBound(userId, null);
|
||||
if (200 == usersBound.getCode() && null != usersBound.getData()) {
|
||||
UserEntity infoById = BeanUtil.copyProperties(usersBound.getData(), UserEntity.class);
|
||||
infoById.setRealName(usersBound.getData().getUserName());
|
||||
return infoById;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("用户接口请求失败:", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求用户服务接口
|
||||
*
|
||||
* @param keyword 关键字
|
||||
* @return 用户信息
|
||||
*/
|
||||
public List<UserEntity> getInfoByLikeName(String keyword) {
|
||||
List<UserEntity> infoByIds = CollUtil.newArrayList();
|
||||
if (StringUtil.isEmpty(keyword)) {
|
||||
return infoByIds;
|
||||
}
|
||||
try {
|
||||
List<UserBoundVO> userBoundVos = v2UserApi.userListAndCopyLikeName(keyword, null, null);
|
||||
infoByIds = getUserInfoVos(userBoundVos);
|
||||
} catch (Exception e) {
|
||||
log.error("用户接口请求失败:", e);
|
||||
}
|
||||
return infoByIds;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package jnpf.attendance.bean;
|
||||
|
||||
import jnpf.enums.attendance.ClockInStatusEnum;
|
||||
import jnpf.util.ConstantUtil;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 变更配置
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2024-11-11
|
||||
*/
|
||||
@Configuration
|
||||
@Getter
|
||||
@Setter
|
||||
public class ChangeConfig {
|
||||
|
||||
private Map<Integer, Map<ClockInStatusEnum, List<ClockInStatusEnum>>> changeMap = new HashMap<>();
|
||||
|
||||
public ChangeConfig() {
|
||||
changeMap.put(ConstantUtil.ON_WORK, getOnWorkMap());
|
||||
changeMap.put(ConstantUtil.OFF_WORK, getOffWorkMap());
|
||||
}
|
||||
|
||||
private Map<ClockInStatusEnum, List<ClockInStatusEnum>> getOnWorkMap() {
|
||||
|
||||
Map<ClockInStatusEnum, List<ClockInStatusEnum>> map = new HashMap<>();
|
||||
map.put(ClockInStatusEnum.NORMAL, List.of(ClockInStatusEnum.WORK_LATE, ClockInStatusEnum.NO_CLOCK));
|
||||
map.put(ClockInStatusEnum.WORK_LATE, List.of(ClockInStatusEnum.NORMAL, ClockInStatusEnum.WORK_LATE, ClockInStatusEnum.NO_CLOCK));
|
||||
map.put(ClockInStatusEnum.NO_CLOCK, List.of(ClockInStatusEnum.NORMAL, ClockInStatusEnum.WORK_LATE));
|
||||
map.put(ClockInStatusEnum.ABSENCE, List.of(ClockInStatusEnum.NORMAL, ClockInStatusEnum.WORK_LATE));
|
||||
return map;
|
||||
}
|
||||
|
||||
private Map<ClockInStatusEnum, List<ClockInStatusEnum>> getOffWorkMap() {
|
||||
|
||||
Map<ClockInStatusEnum, List<ClockInStatusEnum>> map = new HashMap<>();
|
||||
map.put(ClockInStatusEnum.NORMAL, List.of(ClockInStatusEnum.HOME_EARLY, ClockInStatusEnum.NO_CLOCK));
|
||||
map.put(ClockInStatusEnum.HOME_EARLY, List.of(ClockInStatusEnum.NORMAL, ClockInStatusEnum.HOME_EARLY, ClockInStatusEnum.NO_CLOCK));
|
||||
map.put(ClockInStatusEnum.NO_CLOCK, List.of(ClockInStatusEnum.NORMAL, ClockInStatusEnum.HOME_EARLY));
|
||||
map.put(ClockInStatusEnum.ABSENCE, List.of(ClockInStatusEnum.NORMAL, ClockInStatusEnum.HOME_EARLY));
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package jnpf.attendance.bean;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 线程池配置类
|
||||
* 根据任务类型(CPU密集、IO密集、混合)创建合适的线程池。
|
||||
*/
|
||||
@Configuration
|
||||
public class FtbThreadPoolExecutor {
|
||||
// 队列边界
|
||||
private static final int QUEUE_CAPACITY = 200;
|
||||
// 线程存活时间 s(秒)
|
||||
private static final long KEEP_ALIVE_TIME = 15L;
|
||||
|
||||
private static final String THREAD_NAME_PREFIX = "FTB服务-考勤模块";
|
||||
@Bean(name = "attendanceRuleThreadPool", destroyMethod = "shutdown")
|
||||
public ThreadPoolExecutor attendanceRuleThreadPool() {
|
||||
return createNamedThreadPool("attendance-rule", TaskType.CPU_INTENSIVE);
|
||||
}
|
||||
@Bean(name = "cpuIntensiveThreadPool", destroyMethod = "shutdown")
|
||||
public ThreadPoolExecutor cpuIntensiveThreadPool() {
|
||||
return createThreadPool(TaskType.CPU_INTENSIVE);
|
||||
}
|
||||
|
||||
@Bean(name = "ioIntensiveThreadPool", destroyMethod = "shutdown")
|
||||
public ThreadPoolExecutor ioIntensiveThreadPool() {
|
||||
return createThreadPool(TaskType.IO_INTENSIVE);
|
||||
}
|
||||
|
||||
@Bean(name = "mixedThreadPool", destroyMethod = "shutdown")
|
||||
public ThreadPoolExecutor mixedThreadPool() {
|
||||
return createThreadPool(TaskType.MIXED);
|
||||
}
|
||||
|
||||
@Bean(name = "cultivateThreadPool", destroyMethod = "shutdown")
|
||||
public ThreadPoolExecutor cultivateThreadPool() {
|
||||
return createNamedThreadPool("cultivate-thread-v2", TaskType.IO_INTENSIVE);
|
||||
}
|
||||
|
||||
private ThreadPoolExecutor createNamedThreadPool(String name, TaskType type) {
|
||||
int actualProcessors = Math.min(Runtime.getRuntime().availableProcessors(), 42);
|
||||
int runTime, cpuTime;
|
||||
switch (type) {
|
||||
case CPU_INTENSIVE:
|
||||
runTime = 10;
|
||||
cpuTime = 1;
|
||||
break;
|
||||
case IO_INTENSIVE:
|
||||
runTime = 5;
|
||||
cpuTime = 1;
|
||||
break;
|
||||
case MIXED:
|
||||
default:
|
||||
runTime = 50;
|
||||
cpuTime = 1;
|
||||
break;
|
||||
}
|
||||
int maxPoolSize = calculateMaxPoolSize(actualProcessors, runTime, cpuTime, type);
|
||||
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(QUEUE_CAPACITY);
|
||||
|
||||
return new ThreadPoolExecutor(
|
||||
actualProcessors,
|
||||
maxPoolSize,
|
||||
KEEP_ALIVE_TIME, TimeUnit.SECONDS,
|
||||
queue,
|
||||
new ThreadFactory() {
|
||||
private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
|
||||
private final AtomicInteger count = new AtomicInteger(1);
|
||||
|
||||
@Override
|
||||
public Thread newThread(@NotNull Runnable r) {
|
||||
Thread thread = defaultFactory.newThread(r);
|
||||
thread.setName("FTB服务-考勤模块-" + name + "-thread-" + count.getAndIncrement());
|
||||
return thread;
|
||||
}
|
||||
},
|
||||
new ThreadPoolExecutor.CallerRunsPolicy()
|
||||
);
|
||||
}
|
||||
private ThreadPoolExecutor createThreadPool(TaskType type) {
|
||||
// 限制为实际核心数
|
||||
int actualProcessors = Math.min(Runtime.getRuntime().availableProcessors(), 42);
|
||||
int runTime, cpuTime;
|
||||
switch (type) {
|
||||
case CPU_INTENSIVE:
|
||||
runTime = 10;
|
||||
cpuTime = 1;
|
||||
break;
|
||||
case IO_INTENSIVE:
|
||||
runTime = 5;
|
||||
cpuTime = 1;
|
||||
break;
|
||||
case MIXED:
|
||||
default:
|
||||
runTime = 50;
|
||||
cpuTime = 1;
|
||||
break;
|
||||
}
|
||||
int maxPoolSize = calculateMaxPoolSize(actualProcessors, runTime, cpuTime, type);
|
||||
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(QUEUE_CAPACITY);
|
||||
|
||||
return new ThreadPoolExecutor(
|
||||
actualProcessors,
|
||||
maxPoolSize,
|
||||
KEEP_ALIVE_TIME, TimeUnit.SECONDS,
|
||||
queue,
|
||||
new ThreadFactory() {
|
||||
private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
|
||||
private final AtomicInteger count = new AtomicInteger(1);
|
||||
|
||||
@Override
|
||||
public Thread newThread(@NotNull Runnable r) {
|
||||
Thread thread = defaultFactory.newThread(r);
|
||||
thread.setName(THREAD_NAME_PREFIX + "-" + type.name().toLowerCase() + "-thread-" + count.getAndIncrement());
|
||||
return thread;
|
||||
}
|
||||
},
|
||||
new ThreadPoolExecutor.CallerRunsPolicy()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据公式:最佳线程数 = N * (1 + (WT / ST))
|
||||
* 其中 WT = runTime - cpuTime,即线程等待时间
|
||||
*
|
||||
* @param availableProcessors CPU核心数
|
||||
* @param runTime 线程总运行时间(单位可自定,如毫秒)
|
||||
* @param cpuTime 线程CPU计算时间
|
||||
* @return 最佳线程池大小
|
||||
*/
|
||||
private int calculateMaxPoolSize(int availableProcessors, int runTime, int cpuTime, TaskType type) {
|
||||
if (cpuTime <= 0) {
|
||||
throw new IllegalArgumentException("参数不合法:cpuTime 应大于 0");
|
||||
}
|
||||
if (type == TaskType.IO_INTENSIVE) {
|
||||
// I/O 密集型:4 倍核心数,上限 200
|
||||
return Math.min(availableProcessors * 4, 200);
|
||||
} else if (type == TaskType.CPU_INTENSIVE) {
|
||||
// CPU 密集型:等于核心数
|
||||
return availableProcessors;
|
||||
} else {
|
||||
// 混合型
|
||||
long ratio = 1L + (long) runTime / cpuTime;
|
||||
long calculated = (long) availableProcessors * ratio;
|
||||
return (int) Math.min(calculated, 200);
|
||||
}
|
||||
}
|
||||
|
||||
public enum TaskType {
|
||||
CPU_INTENSIVE,
|
||||
IO_INTENSIVE,
|
||||
MIXED
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jnpf.attendance.service.AppStatisticsService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.exception.QueryException;
|
||||
import jnpf.model.attendance.dto.*;
|
||||
import jnpf.model.attendance.vo.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤统计APP
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/app/statistics")
|
||||
public class AppStatisticsController {
|
||||
|
||||
@Resource
|
||||
private AppStatisticsService appStatisticsService;
|
||||
|
||||
@Operation(summary = "我的考勤-主页")
|
||||
@GetMapping(value = "/home")
|
||||
public ActionResult<AppStatisticsListVo> getHomeData(@Valid AppStatisticsListDto req) throws QueryException {
|
||||
try {
|
||||
log.info("我的考勤-主页,入参=>{}", JSONObject.toJSON(req));
|
||||
long st = System.currentTimeMillis();
|
||||
AppStatisticsListVo listVo = appStatisticsService.getAppHomeData(req);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("我的考勤-主页,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(listVo);
|
||||
} catch (QueryException e) {
|
||||
if (e.getMessage().contains("用户暂无考勤组")) {
|
||||
return ActionResult.success(e.getMessage());
|
||||
} else {
|
||||
throw new QueryException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "我的考勤-出勤情况")
|
||||
@GetMapping("/record")
|
||||
public ActionResult<List<AppStatisticsRecordVo>> getRecordData(@Valid AppStatisticsRecordDto req) throws QueryException {
|
||||
try {
|
||||
List<AppStatisticsRecordVo> list = appStatisticsService.getRecordData(req);
|
||||
return ActionResult.success(list);
|
||||
} catch (Exception e) {
|
||||
if (e.getMessage().contains("暂无数据") || e.getMessage().contains("用户暂无考勤组") || e.getMessage().contains("用户暂无排班")) {
|
||||
return ActionResult.success("暂无数据");
|
||||
} else {
|
||||
throw new QueryException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "我的考勤-更多统计-默认")
|
||||
@GetMapping("/moreDefault")
|
||||
public ActionResult<AppStatisticsMoreVo> getMoreDefaultData(@Valid AppStatisticsMoreDto req) throws Exception {
|
||||
log.info("我的考勤-更多统计-默认,入参=>{}", JSONObject.toJSON(req));
|
||||
long st = System.currentTimeMillis();
|
||||
AppStatisticsMoreVo moreVo = appStatisticsService.getMoreDefaultData(req);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("我的考勤-更多统计-默认,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(moreVo);
|
||||
}
|
||||
|
||||
@Operation(summary = "我的考勤-更多统计-展开")
|
||||
@GetMapping("/moreExpand")
|
||||
public ActionResult<AppStatisticsMoreInfoVo> getMoreExpandData(@Valid AppStatisticsMoreInfoDto req) throws Exception {
|
||||
log.info("我的考勤-更多统计-展开,入参=>{}", JSONObject.toJSON(req));
|
||||
long st = System.currentTimeMillis();
|
||||
AppStatisticsMoreInfoVo moreInfoVo = appStatisticsService.getMoreExpandData(req);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("我的考勤-更多统计-展开,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(moreInfoVo);
|
||||
}
|
||||
|
||||
@Operation(summary = "团队考勤-首页")
|
||||
@PostMapping("/team/home")
|
||||
public ActionResult<AppStatisticsTeamListVo> getTeamHomeData(@Valid @RequestBody AppStatisticsTeamListDto req) throws QueryException {
|
||||
log.info("团队考勤-首页,入参=>{}", JSONObject.toJSON(req));
|
||||
long st = System.currentTimeMillis();
|
||||
AppStatisticsTeamListVo teamListVo = appStatisticsService.getTeamHomeData(req);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("团队考勤-首页,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(teamListVo);
|
||||
}
|
||||
|
||||
@Operation(summary = "团队考勤-tab列表数据")
|
||||
@PostMapping("/team/tabList")
|
||||
public ActionResult<List<AppStatisticsTeamTabVo>> getTabListData(@Valid @RequestBody AppTeamStatisticsTabDto req) {
|
||||
log.info("团队考勤-tab列表数据,入参=>{}", JSONObject.toJSON(req));
|
||||
long st = System.currentTimeMillis();
|
||||
List<AppStatisticsTeamTabVo> teamTabVoList = appStatisticsService.getTabListData(req);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("团队考勤-tab列表数据,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(teamTabVoList);
|
||||
}
|
||||
|
||||
@Operation(summary = "团队考勤-团队统计")
|
||||
@PostMapping("/team/statistics")
|
||||
public ActionResult<AppTeamStatisticsVo> getStatisticsData(@Valid @RequestBody AppTeamStatisticsDto req) throws ParseException {
|
||||
log.info("团队考勤-团队统计,入参=>{}", JSONObject.toJSON(req));
|
||||
long st = System.currentTimeMillis();
|
||||
AppTeamStatisticsVo statisticsVo = appStatisticsService.getStatisticsData(req);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("团队考勤-团队统计,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(statisticsVo);
|
||||
}
|
||||
|
||||
@Operation(summary = "团队考勤-团队统计-详情列表")
|
||||
@PostMapping("/team/statisticsList")
|
||||
public ActionResult<List<AppTeamStatisticsListVo>> getStatisticsListData(@Valid @RequestBody AppTeamStatisticsListDto req) throws QueryException, ParseException {
|
||||
log.info("团队考勤-团队统计-详情列表,入参=>{}", JSONObject.toJSON(req));
|
||||
long st = System.currentTimeMillis();
|
||||
List<AppTeamStatisticsListVo> statisticsListVoList = appStatisticsService.getStatisticsListData(req);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("团队考勤-团队统计-详情列表,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(statisticsListVoList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import jnpf.SocketApi;
|
||||
import jnpf.attendance.annotation.Machine;
|
||||
import jnpf.attendance.service.AttenceMachineService;
|
||||
import jnpf.attendance.service.AttendanceUserFaceService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.enums.attendance.ActionEnum;
|
||||
import jnpf.enums.attendance.MachineEnum;
|
||||
import jnpf.model.attendance.dto.UserFaceDto;
|
||||
import jnpf.model.attendance.vo.UserFaceVo;
|
||||
import jnpf.util.CustomTenantUtil;
|
||||
import jnpf.util.DateDetail;
|
||||
import jnpf.util.NoDataSourceBind;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 考勤机控制器
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2023-11-08
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
public class AttenceMachineController {
|
||||
|
||||
@Resource
|
||||
private AttenceMachineService attenceMachineService;
|
||||
|
||||
@Resource
|
||||
private AttendanceUserFaceService attendanceUserFaceService;
|
||||
|
||||
@Autowired
|
||||
private CustomTenantUtil customTenantUtil;
|
||||
|
||||
@Autowired
|
||||
private SocketApi socketApi;
|
||||
|
||||
/**
|
||||
* 查询用户人脸
|
||||
* @param userId 用户id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/userface/{userId}")
|
||||
public Object getUserFace(@PathVariable(value = "userId") String userId) {
|
||||
|
||||
UserFaceVo userFace = attendanceUserFaceService.getUserFace(userId);
|
||||
return ActionResult.success(userFace);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增人脸
|
||||
* @param userFaceDto 人脸数据
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PostMapping(value = "/userface")
|
||||
public Object addUserFace(@RequestBody @Valid UserFaceDto userFaceDto) {
|
||||
|
||||
attendanceUserFaceService.addUserFace(userFaceDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改人脸
|
||||
* @param userFaceDto 人脸数据
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PutMapping(value = "/userface")
|
||||
public Object updateUserFace(@RequestBody @Valid UserFaceDto userFaceDto) {
|
||||
|
||||
attendanceUserFaceService.updateUserFace(userFaceDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除人脸
|
||||
* @param userId 用户id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@DeleteMapping(value = "/userface/{userId}")
|
||||
public Object deleteUserFace(@PathVariable(value = "userId") String userId) {
|
||||
|
||||
attendanceUserFaceService.deleteUserFace(userId);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传打卡记录
|
||||
* @param params 打卡数据
|
||||
* @return java.util.Map<java.lang.String,java.lang.Object>
|
||||
*/
|
||||
@PostMapping(value = "/record/face")
|
||||
@NoDataSourceBind
|
||||
// @Machine(dealAction = ActionEnum.DA_KA, factory = MachineEnum.MAO_TONG)
|
||||
public Map<String, Object> uploadRecordFace(@RequestBody Map<String, Object> params) {
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("Result", 0);
|
||||
map.put("Msg", "");
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 识别后在线验证
|
||||
* @param params 打卡数据
|
||||
* @return java.util.Map<java.lang.String,java.lang.Object>
|
||||
*/
|
||||
@PostMapping(value = "/verify_user")
|
||||
@NoDataSourceBind
|
||||
@Machine(dealAction = ActionEnum.DA_KA, factory = MachineEnum.MAO_TONG)
|
||||
public Map<String, Object> verifyUser(@RequestBody Map<String, Object> params) {
|
||||
|
||||
log.info("MaoTong-Clock: {}", params);
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
Object sn = params.get("sn");
|
||||
if (null == sn) {
|
||||
map.put("Result", 3);
|
||||
map.put("Msg", "设备id不能为空");
|
||||
return map;
|
||||
}
|
||||
Object userIdObj = params.get("user_id");
|
||||
if (null == userIdObj || StringUtils.isEmpty(userIdObj.toString())) {
|
||||
map.put("Result", 3);
|
||||
map.put("Msg", sn + "打卡用户不能为空");
|
||||
return map;
|
||||
}
|
||||
log.error("开始打卡,设备号:{},用户:{}", sn, userIdObj);
|
||||
String[] split = userIdObj.toString().split("@");
|
||||
String tenantId = split[0];
|
||||
String userId = split[1];
|
||||
customTenantUtil.checkOutTenant(tenantId, userId);
|
||||
String b = attenceMachineService.clockIn(sn.toString(), userId, tenantId);
|
||||
String message;
|
||||
switch (b) {
|
||||
case "0":
|
||||
message = "已记录";
|
||||
break;
|
||||
case "1":
|
||||
message = "打卡成功";
|
||||
break;
|
||||
case "2":
|
||||
message = "迟到";
|
||||
break;
|
||||
case "3":
|
||||
message = "早退";
|
||||
break;
|
||||
default:
|
||||
message = b;
|
||||
break;
|
||||
}
|
||||
map.put("Result", 0);
|
||||
map.put("Msg", message);
|
||||
JSONObject json = new JSONObject();
|
||||
json.set("voice_code", -2);
|
||||
json.set("voice_text", message);
|
||||
map.put("Content", json);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 陌生人打卡
|
||||
* @return java.util.Map<java.lang.String,java.lang.Object>
|
||||
*/
|
||||
@PostMapping(value = "/stranger")
|
||||
@NoDataSourceBind
|
||||
public Map<String, Object> strangerClockIn(@RequestBody Map<String, Object> params) {
|
||||
|
||||
String sn = params.get("sn").toString();
|
||||
log.error("陌生人打卡,设备号:{},打卡时间:{}", sn, DateDetail.getDateTime2Str(new Date()));
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("Result", 0);
|
||||
map.put("Msg", "");
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设备录入自定义编号判断
|
||||
* @return java.util.Map<java.lang.String,java.lang.Object>
|
||||
*/
|
||||
@PostMapping(value = "/addFace")
|
||||
@NoDataSourceBind
|
||||
public Map<String, Object> addFace(@RequestBody Map<String, Object> params) {
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("Result", 0);
|
||||
map.put("Msg", "");
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户信息
|
||||
* @return java.util.Map<java.lang.String,java.lang.Object>
|
||||
*/
|
||||
@PostMapping(value = "/user/inf_photo")
|
||||
@NoDataSourceBind
|
||||
public Map<String, Object> updateUserInfoPhoto(@RequestBody Map<String, Object> params) {
|
||||
|
||||
log.error("更新用户信息...");
|
||||
return attenceMachineService.updateUserInfoPhoto(params);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/sendUser")
|
||||
public Object testSendUser(@RequestParam(value = "code") String code, @RequestParam(value = "userId") String userId, @RequestParam(value = "sn") String sn) {
|
||||
|
||||
attenceMachineService.sendUserToMachine(code, userId, sn);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
@GetMapping(value = "/changeImg")
|
||||
public Object testChangeImg() {
|
||||
String img = attenceMachineService.changeImg();
|
||||
return ActionResult.success(img);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/testSendMsg")
|
||||
public void testSendMsg() {
|
||||
|
||||
socketApi.sendMsg2Client("kaijiayi", "123", "虚空消息...");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import jnpf.attendance.service.AttendanceAIService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.model.attendance.dto.AttendanceReqDto;
|
||||
import jnpf.model.attendance.vo.attendance.ClockDataReqVo;
|
||||
import jnpf.model.attendance.vo.attendance.OvertimeRuleVo;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 考勤AI接口支持
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2026-05-07
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/ai")
|
||||
public class AttendanceAIController {
|
||||
|
||||
@Resource
|
||||
private AttendanceAIService attendanceAIService;
|
||||
|
||||
/**
|
||||
* 根据日期查询考勤打卡记录
|
||||
* @param dto 查询条件
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.attendance.ClockDataReqVo>
|
||||
*/
|
||||
@GetMapping(value = "/clock-record")
|
||||
public ActionResult<ClockDataReqVo> getClockRecordByDate(AttendanceReqDto dto) {
|
||||
|
||||
ClockDataReqVo req = attendanceAIService.getClockRecordByDate(dto);
|
||||
return ActionResult.success(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询考勤组加班规则
|
||||
* @param groupId 考勤组id
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.attendance.OvertimeRuleVo>
|
||||
*/
|
||||
@GetMapping(value = "/overtime-rule/{groupId}")
|
||||
public ActionResult<OvertimeRuleVo> getOvertimeRule(@PathVariable(value = "groupId") String groupId) {
|
||||
|
||||
OvertimeRuleVo vo = attendanceAIService.getOvertimeRule(groupId);
|
||||
return ActionResult.success(vo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,829 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.attendance.AttendanceApi;
|
||||
import jnpf.attendance.service.AttendanceApproveService;
|
||||
import jnpf.attendance.service.AttendanceGroupService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.UserInfo;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.config.ConfigValueUtil;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.engine.FlowTaskApi;
|
||||
import jnpf.entity.attendance.AttendanceApprovalAdminVo;
|
||||
import jnpf.entity.workflow.AttendanceWorkOvertimeApprove;
|
||||
import jnpf.entity.workflow.SelfApprove;
|
||||
import jnpf.enums.attendance.ApprovalSettingTypeEnum;
|
||||
import jnpf.enums.personnel.FtbPersonnelsCheckStatusCodeEnum;
|
||||
import jnpf.exception.ApproveException;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.exception.LoginException;
|
||||
import jnpf.model.attendance.dto.*;
|
||||
import jnpf.model.attendance.vo.*;
|
||||
import jnpf.model.attendance.vo.attendance.AttendanceToThousandsFacesVo;
|
||||
import jnpf.model.attendance.vo.attendance.GroupMiniVo;
|
||||
import jnpf.model.attendance.vo.attendance.LeaveConsumptionDetailVo;
|
||||
import jnpf.model.attendance.vo.attendance.TimeVo;
|
||||
import jnpf.model.attendance.vo.flow.HandlerVo;
|
||||
import jnpf.model.doclibrary.vo.UseDetailVo;
|
||||
import jnpf.model.workflow.dto.AttendanceBusinessTripApproveOaDto;
|
||||
import jnpf.model.workflow.dto.AttendanceWorkOvertimeApproveDto;
|
||||
import jnpf.model.workflow.dto.SelfApproveDto;
|
||||
import jnpf.util.*;
|
||||
import jnpf.util.data.DataSourceContextHolder;
|
||||
import jnpf.workflow.service.SelfApproveService;
|
||||
import jnpf.workflow.service.WorkOvertimeApproveService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* describe
|
||||
* 考勤审批相关
|
||||
*
|
||||
* @author HuangLinPan
|
||||
* @date 2023/11/22
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance")
|
||||
@Slf4j
|
||||
public class AttendanceApproveController implements AttendanceApi {
|
||||
|
||||
@Resource
|
||||
private AttendanceApproveService attendanceApproveService;
|
||||
@Autowired
|
||||
private WorkOvertimeApproveService workApproveService;
|
||||
@Resource
|
||||
private UserProvider userProvider;
|
||||
|
||||
@Autowired
|
||||
private ConfigValueUtil configValueUtil;
|
||||
|
||||
@Resource
|
||||
private AttendanceGroupService attendanceGroupService;
|
||||
|
||||
/**
|
||||
* 假期劵的使用记录
|
||||
*
|
||||
* @param id 劵的id
|
||||
* @param balanceQueryDto 参数
|
||||
* @return jnpf.base.ActionResult<java.lang.String>
|
||||
* @author hlp
|
||||
*/
|
||||
@GetMapping("/useDetail/{id}")
|
||||
public ActionResult<PageListVO<UseDetailVo>> getUseDetail(@PathVariable("id") String id, BalanceQueryDto balanceQueryDto) {
|
||||
PageInfo<UseDetailVo> vo = attendanceApproveService.getUseDetail(id, balanceQueryDto);
|
||||
return ActionResult.page(vo.getList(), FtbUtil.getPagination(vo));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 定时失效劵
|
||||
*
|
||||
* @param tenantId 租户id
|
||||
* @return java.lang.Boolean
|
||||
* @author hlp
|
||||
*/
|
||||
@Override
|
||||
@PostMapping(value = "/invalidationCoupons")
|
||||
public Boolean invalidationCoupons(@RequestParam String tenantId) {
|
||||
return attendanceApproveService.invalidationCoupons(tenantId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 每月定时计算用户存休
|
||||
*
|
||||
* @param tenantId 租户Id
|
||||
*/
|
||||
@Override
|
||||
@PostMapping(value = "/storageRest")
|
||||
public Boolean storageRest(@RequestParam(value = "tenantId") String tenantId) {
|
||||
return attendanceApproveService.storageRest(tenantId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加班--开始日期选择后触发接口返回当天及后一天的排班信息
|
||||
*
|
||||
* @param balanceQueryDto 参数
|
||||
* @return jnpf.base.ActionResult<java.util.List < jnpf.model.attendance.vo.UserClassesVo>>
|
||||
* @author hlp
|
||||
*/
|
||||
@GetMapping("/workOverTime/getClasses")
|
||||
public ActionResult<List<UserClassesVo>> getClasses(BalanceQueryDto balanceQueryDto) {
|
||||
List<UserClassesVo> vo = attendanceApproveService.getClasses(balanceQueryDto);
|
||||
return ActionResult.success(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加班--加班明细
|
||||
*
|
||||
* @param balanceQueryDto 参数
|
||||
* @return jnpf.base.ActionResult<java.util.List < jnpf.model.attendance.vo.UserClassesVo>>
|
||||
* @author hlp
|
||||
*/
|
||||
@GetMapping("/workOverTime/shifts")
|
||||
public ActionResult<LeaveShiftVo> getWorkOverTimeShifts(BalanceQueryDto balanceQueryDto) {
|
||||
try {
|
||||
LeaveShiftVo vo = attendanceApproveService.getWorkOverTimeShifts(balanceQueryDto);
|
||||
return ActionResult.success(vo);
|
||||
} catch (Exception e) {
|
||||
return ActionResult.fail(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取请假申请时长及设计班次(请假时选择了开始和结束时间后请求该接口)
|
||||
*
|
||||
* @param leaveQueryDto 参数
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.LeaveShiftVo>
|
||||
* @author hlp
|
||||
*/
|
||||
@GetMapping("/leaveDuration")
|
||||
public ActionResult<LeaveShiftVo> getLeaveDuration(LeaveQueryDto leaveQueryDto) throws HandleException {
|
||||
if (null == leaveQueryDto.getStartTime() || leaveQueryDto.getStartTime().isEmpty()) {
|
||||
return ActionResult.fail("开始时间不能为空");
|
||||
}
|
||||
if (null == leaveQueryDto.getEndTime() || leaveQueryDto.getEndTime().isEmpty()) {
|
||||
return ActionResult.fail("结束时间不能为空");
|
||||
}
|
||||
LeaveShiftVo vo = attendanceApproveService.getLeaveDuration(leaveQueryDto);
|
||||
return ActionResult.success(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请假审批通过后的触发接口
|
||||
*
|
||||
* @param tenantId 租户id
|
||||
* @param applyId 审批的唯一id 对应表f_id
|
||||
* @param status 是否审核通过 0.待审核 1.通过 2.未通过
|
||||
* @param userId 审批用户Id
|
||||
*/
|
||||
@GetMapping(value = "/approve/leave/pass")
|
||||
@NoDataSourceBind
|
||||
public void leaveApprove(@RequestParam(value = "tenantId") String tenantId, @RequestParam(value = "applyId") String applyId, @RequestParam(value = "status") Integer status, @RequestParam("userId") String userId, @RequestParam("userName") String userName) throws ApproveException {
|
||||
log.error("请假审批通过后的触发接口 tenantId : {},入参applyId:{}", tenantId, applyId);
|
||||
checkOutTenant(tenantId);
|
||||
attendanceApproveService.leaveApprove(applyId, status, tenantId, userId, userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加班审批通过后触发接口
|
||||
*
|
||||
* @param tenantId 租户id
|
||||
* @param applyId 审批的唯一id 对应表f_id
|
||||
* @param status 是否审核通过 0.待审核 2.未通过 1.通过
|
||||
* @param userId 审批用户Id
|
||||
* @author hlp
|
||||
*/
|
||||
@GetMapping(value = "/approve/work/pass")
|
||||
@NoDataSourceBind
|
||||
public void workApprove(@RequestParam(value = "tenantId") String tenantId, @RequestParam(value = "applyId") String applyId, @RequestParam(value = "status") Integer status, @RequestParam("userId") String userId, @RequestParam("userName") String userName) throws ApproveException {
|
||||
log.error("加班审批通过后的触发接口 tenantId : {},入参applyId:{}", tenantId, applyId);
|
||||
checkOutTenant(tenantId);
|
||||
attendanceApproveService.workApprove(applyId, status, tenantId, userId, userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 借调审批通过后触发接口
|
||||
*
|
||||
* @param tenantId 租户id
|
||||
* @param applyId 审批的唯一id 对应表f_id
|
||||
* @param status 是否审核通过 0.待审核 2.未通过 1.通过
|
||||
* @param userId 审批用户Id
|
||||
* @author hlp
|
||||
*/
|
||||
@GetMapping(value = "/approve/self/pass")
|
||||
@NoDataSourceBind
|
||||
public void selfApprove(@RequestParam(value = "tenantId") String tenantId, @RequestParam(value = "applyId") String applyId, @RequestParam(value = "departureTime") String departureTime, @RequestParam(value = "backTime") String backTime, @RequestParam(value = "status") Integer status, @RequestParam("userId") String userId, @RequestParam("userName") String userName) throws ApproveException, HandleException {
|
||||
log.error("借调审批通过后的触发接口 tenantId : {},入参applyId:{}", tenantId, applyId);
|
||||
checkOutTenant(tenantId);
|
||||
attendanceApproveService.selfApprove(applyId, departureTime, backTime, status, userId, userName, tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 审批校验接口
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @param type 审批类型 1.常规补卡审批 2.调整出勤结果审批 3.外勤审批 4.请假审批 5.加班审批 6.借调审批 7.外出 8.出差
|
||||
* @return jnpf.base.ActionResult<java.lang.Object>
|
||||
* @author hlp
|
||||
*/
|
||||
@PostMapping("/approvalCheck")
|
||||
public ActionResult<Object> getApprovalAdmin(@RequestParam("taskId") String taskId, @RequestParam("type") String type) {
|
||||
return attendanceApproveService.getApprovalAdmin(taskId, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交时审批校验接口
|
||||
*
|
||||
* @param type 审批类型 1.常规补卡审批 2.调整出勤结果审批 3.外勤审批 4.请假审批 5.加班审批 6.借调审批 7.外出 8.出差
|
||||
* @return jnpf.base.ActionResult<java.lang.Object>
|
||||
* @author hlp
|
||||
*/
|
||||
@PostMapping("/submitApprovalCheck")
|
||||
public ActionResult<Object> submitValidation(@RequestParam("type") String type) {
|
||||
String body = getBody(ServletUtil.getRequest());
|
||||
return attendanceApproveService.submitValidation(body, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考勤组审批管理员
|
||||
*
|
||||
* @param taskId 考勤组id
|
||||
* @param type 审批类型 1.常规补卡审批 2.调整出勤结果审批 3.外勤审批 4.请假审批 5.加班审批 6.外出 7.出差 其他:借调
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/getApprovalAdmin")
|
||||
public ActionResult<HandlerVo> getApprovalAdmin(HttpServletRequest request, String taskId, String type) throws Exception {
|
||||
ServletInputStream inputStream = request.getInputStream();
|
||||
byte[] bytes = IOUtils.toByteArray(inputStream);
|
||||
String body = new String(bytes, "UTF-8");
|
||||
|
||||
type = type.split("\\?")[0];
|
||||
Integer typeInt = Integer.parseInt(type);
|
||||
HandlerVo handlerVo = new HandlerVo();
|
||||
if (ApprovalSettingTypeEnum.LEAVE.getCode().equals(typeInt)) {
|
||||
/** 请假审批*/
|
||||
// System.out.println("请假审批...");
|
||||
AttendanceApprovalAdminVo approveUser = attendanceApproveService.getLeaveApproveUser(body);
|
||||
List<AttendanceUserVo> userList = approveUser.getUserList();
|
||||
if (CollectionUtil.isEmpty(userList)) {
|
||||
log.error("没有找到该考勤组请假审批管理员");
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
String idsStr = toUserIdsStr(userList);
|
||||
handlerVo.setHandleId(idsStr);
|
||||
// System.out.println("请假审批-userIds:" + handlerVo);
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
if (ApprovalSettingTypeEnum.OVERTIME.getCode().equals(typeInt)) {
|
||||
/** 加班审批*/
|
||||
// System.out.println("加班审批...");
|
||||
AttendanceApprovalAdminVo approveUser = attendanceApproveService.getOvertimeApproveUser(body);
|
||||
// System.out.println("approveUser:" + approveUser.toString());
|
||||
if (CollectionUtil.isEmpty(approveUser.getUserList())) {
|
||||
log.error("没有找到该考勤组加班审批管理员");
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
handlerVo.setHandleId(toUserIdsStr(approveUser.getUserList()));
|
||||
// System.out.println("加班审批-userIds:" + handlerVo);
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
if (ApprovalSettingTypeEnum.ROUTINE.getCode().equals(typeInt)) {
|
||||
/** 补卡审批*/
|
||||
// System.out.println("补卡审批...");
|
||||
AttendanceApprovalAdminVo approveUser = attendanceApproveService.getReplacementCardApproveUser(body);
|
||||
List<AttendanceUserVo> userList = approveUser.getUserList();
|
||||
if (CollectionUtil.isEmpty(userList)) {
|
||||
log.error("没有找到该考勤组补卡审批管理员");
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
String idsStr = toUserIdsStr(userList);
|
||||
handlerVo.setHandleId(idsStr);
|
||||
// System.out.println("补卡审批-userIds:" + handlerVo);
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
if (ApprovalSettingTypeEnum.ACTION_RESULT.getCode().equals(typeInt)) {
|
||||
/** 调整出勤结果*/
|
||||
// System.out.println("调整出勤结果审批...");
|
||||
AttendanceApprovalAdminVo approvalUser = attendanceApproveService.getAttendanceAlter(body);
|
||||
List<AttendanceUserVo> userList = approvalUser.getUserList();
|
||||
if (CollectionUtil.isEmpty(userList)) {
|
||||
log.error("没有找到该考勤组调整出勤结果审批管理员");
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
String idsStr = toUserIdsStr(userList);
|
||||
handlerVo.setHandleId(idsStr);
|
||||
// System.out.println("调整出勤审批-userIds:" + handlerVo);
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
if (ApprovalSettingTypeEnum.OUT.getCode().equals(typeInt)) {
|
||||
/** 外勤审批*/
|
||||
// System.out.println("外勤审批...");
|
||||
AttendanceApprovalAdminVo approvalUser = attendanceApproveService.getFieldApproval();
|
||||
List<AttendanceUserVo> userList = approvalUser.getUserList();
|
||||
if (CollectionUtil.isEmpty(userList)) {
|
||||
log.error("没有找到该考勤组外勤审批管理员");
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
String idsStr = toUserIdsStr(userList);
|
||||
handlerVo.setHandleId(idsStr);
|
||||
// System.out.println("外勤审批-userIds:" + handlerVo);
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
if (ApprovalSettingTypeEnum.GO_OUT.getCode().equals(typeInt)) {
|
||||
/** 外出审批*/
|
||||
AttendanceApprovalAdminVo approvalUser = attendanceApproveService.getGoOutApproval();
|
||||
List<AttendanceUserVo> userList = approvalUser.getUserList();
|
||||
if (CollectionUtil.isEmpty(userList)) {
|
||||
log.error("没有找到该考勤组外出审批管理员");
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
String idsStr = toUserIdsStr(userList);
|
||||
handlerVo.setHandleId(idsStr);
|
||||
// System.out.println("外勤审批-userIds:" + handlerVo);
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
if (ApprovalSettingTypeEnum.BUSINESS_TRIP.getCode().equals(typeInt)) {
|
||||
/** 出差审批*/
|
||||
// System.out.println("出差审批...");
|
||||
AttendanceApprovalAdminVo approvalUser = attendanceApproveService.getBusinessTripApproval();
|
||||
List<AttendanceUserVo> userList = approvalUser.getUserList();
|
||||
if (CollectionUtil.isEmpty(userList)) {
|
||||
log.error("没有找到该考勤组出差审批管理员");
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
String idsStr = toUserIdsStr(userList);
|
||||
handlerVo.setHandleId(idsStr);
|
||||
// System.out.println("出差审批-userIds:" + handlerVo);
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
/** 借调审批*/
|
||||
// System.out.println("借调审批...");
|
||||
List<String> managerIds = attendanceApproveService.secondedApproval(body);
|
||||
if (CollectionUtil.isEmpty(managerIds)) {
|
||||
log.error("没有找到该考勤组借调审批管理员");
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
String idsStr = CollectionUtil.join(managerIds, ",");
|
||||
handlerVo.setHandleId(idsStr);
|
||||
// System.out.println("借调审批-userIds:" + handlerVo);
|
||||
return ActionResult.success(handlerVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考勤组管理员具体信息
|
||||
*
|
||||
* @param type 审批类型 1.常规补卡审批 2.调整出勤结果审批 3.外勤审批 4.请假审批 5.加班审批 6.外出 7.出差 0:借调
|
||||
* @return ActionResult<AttendanceApprovalAdminVo>
|
||||
*/
|
||||
@GetMapping("/getGroupAdminInfo/{type}")
|
||||
public ActionResult<AttendanceApprovalAdminVo> getGroupAdminInfo(@PathVariable("type") Integer type,
|
||||
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
|
||||
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime,
|
||||
@RequestParam(required = false) String clockInResultId,
|
||||
@RequestParam(required = false) String selfGroupId
|
||||
) throws HandleException {
|
||||
|
||||
AttendanceApprovalAdminVo approvalAdminVo = attendanceApproveService.getGroupAdminInfo(type, startTime, endTime, clockInResultId, selfGroupId);
|
||||
return ActionResult.success(approvalAdminVo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 返回用户id
|
||||
*
|
||||
* @param userVoList
|
||||
* @return
|
||||
*/
|
||||
private String toUserIdsStr(List<AttendanceUserVo> userVoList) {
|
||||
List<String> userIds = userVoList.stream().map(AttendanceUserVo::getUserId).collect(Collectors.toList());
|
||||
return CollectionUtil.join(userIds, ",");
|
||||
}
|
||||
|
||||
|
||||
public void checkOutTenant(String tenantId) {
|
||||
if (configValueUtil.isMultiTenancy()) {
|
||||
// 判断是不是从外面直接请求
|
||||
if (StringUtil.isNotEmpty(tenantId)) {
|
||||
//切换成租户库
|
||||
try {
|
||||
TenantDataSourceUtil.switchTenant(tenantId);
|
||||
} catch (LoginException e) {
|
||||
throw new RuntimeException("切换租户失败");
|
||||
}
|
||||
} else {
|
||||
UserInfo userInfo = UserProvider.getUser();
|
||||
Assert.notNull(userInfo.getUserId(), "缺少租户信息");
|
||||
DataSourceContextHolder.setDatasource(userInfo.getTenantId(), userInfo.getTenantDbConnectionString(), userInfo.isAssignDataSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取远程请求参数
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private String getBody(HttpServletRequest request) {
|
||||
ServletInputStream inputStream = null;
|
||||
try {
|
||||
inputStream = request.getInputStream();
|
||||
byte[] bytes = IOUtils.toByteArray(inputStream);
|
||||
String body = new String(bytes, "UTF-8");
|
||||
return body;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考勤组用户余额
|
||||
*
|
||||
* @param groupId 考勤组
|
||||
* @param month 年月(2024-5-13)
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.UserBalanceVo>
|
||||
* @author hlp
|
||||
*/
|
||||
@GetMapping("/userBalanceByGroupId")
|
||||
public ActionResult<List<UserBalanceVo>> getBalanceDetailS(@RequestParam String groupId, @RequestParam String month) {
|
||||
List<UserBalanceVo> vo = attendanceApproveService.getBalanceDetailS(groupId, month);
|
||||
return ActionResult.success(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 外出审批通/拒绝时调用接口
|
||||
*
|
||||
* @param tenantId 租户Id
|
||||
* @param applyId 审批的唯一id 对应表f_id
|
||||
* @param status 是否审核通过 0.待审核 1.通过 2.未通过
|
||||
* @param userId 审批用户Id
|
||||
* @throws ApproveException
|
||||
*/
|
||||
@GetMapping(value = "/approve/goOut/pass")
|
||||
@NoDataSourceBind
|
||||
public void goOutApprove(@RequestParam(value = "tenantId") String tenantId, @RequestParam(value = "applyId") String applyId, @RequestParam(value = "status") Integer status, @RequestParam("userId") String userId, @RequestParam("userName") String userName) throws ApproveException {
|
||||
log.error("外出审批通过后的触发接口 tenantId : {}", tenantId);
|
||||
log.error("外出审批通过后的触发接口 入参applyId : {}", applyId);
|
||||
checkOutTenant(tenantId);
|
||||
attendanceApproveService.goOutApprove(applyId, status, tenantId, userId, userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 出差审批通/拒绝时调用接口
|
||||
*
|
||||
* @param tenantId 租户Id
|
||||
* @param applyId 审批的唯一id 对应表f_id
|
||||
* @param status 是否审核通过 0.待审核 1.通过 2.未通过
|
||||
* @param userId 审批用户Id
|
||||
* @throws ApproveException
|
||||
*/
|
||||
@GetMapping(value = "/approve/businessTrip/pass")
|
||||
@NoDataSourceBind
|
||||
public void businessTripApprove(@RequestParam(value = "tenantId") String tenantId, @RequestParam(value = "applyId") String applyId, @RequestParam(value = "status") Integer status, @RequestParam("userId") String userId, @RequestParam("userName") String userName) throws ApproveException {
|
||||
checkOutTenant(tenantId);
|
||||
attendanceApproveService.businessTripApprove(applyId, status, tenantId, userId, userName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发消息通知下一节点审核人
|
||||
*
|
||||
* @param workflowImQueryDto 审批参数信息
|
||||
*/
|
||||
@GetMapping("/im")
|
||||
@NoDataSourceBind
|
||||
public ActionResult workIm(WorkflowImQueryDto workflowImQueryDto) {
|
||||
log.error("发消息通知下一节点审核人入参: {}", workflowImQueryDto.toString());
|
||||
// 因OA流调用时会等待流程完成后才会提交事务,本接口会依赖于事务的提交结果,所以单独开一个线程执行
|
||||
new Thread(() -> {
|
||||
checkOutTenant(workflowImQueryDto.getTenantId());
|
||||
attendanceApproveService.sendIm(workflowImQueryDto);
|
||||
}).start();
|
||||
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户当前时间所在考勤组的请假类型
|
||||
*/
|
||||
// @GetMapping("/leaveList")
|
||||
// public ActionResult getLeaveList() throws HandleException {
|
||||
// return attendanceApproveService.getLeaveList();
|
||||
// }
|
||||
|
||||
/***************************************以下为考勤V1.7版本提供的新接口****************************************************/
|
||||
|
||||
/**
|
||||
* 新版OA收拢保存考勤出差审批
|
||||
*
|
||||
* @param approveOaDto 出差对象
|
||||
*/
|
||||
@PostMapping("/businessTripForOa")
|
||||
public ActionResult<Void> createBusinessTrip(@RequestBody @Valid AttendanceBusinessTripApproveOaDto approveOaDto) {
|
||||
log.error("FoeOa开始出差了参数................: {}", approveOaDto);
|
||||
// AttendanceBusinessTripApproveOaDto(id=null, userId=["450558716723340421"],
|
||||
// departure=[{"detailAddress":"","areaLabels":"贵州省/贵阳市/市辖区","areaIds":["354094501027910","354094501027911","354094501027912"]}],
|
||||
// destination=[{"detailAd"四川省/南充市/市辖区","areaIds":["354094498033736","354094499168330","354094499168331"]}],
|
||||
// startTime=null, endTime=null, dayNum=null, transportationVehicles=4, reason=------------, fileJs, time=[1730390400000, 1730476800000])
|
||||
return attendanceApproveService.createBusinessTrip(approveOaDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新版OA收拢出差审批通过后触发接口
|
||||
*
|
||||
* @param taskId 审批的唯一id 对应表f_id
|
||||
* @param status 是否审核通过 0.待审核 2.未通过 1.通过
|
||||
* @author hlp
|
||||
*/
|
||||
@GetMapping(value = "/oaApprove/businessTrip/pass")
|
||||
public ActionResult<Void> businessTripApprove(@RequestParam(value = "taskId") String taskId, @RequestParam(value = "status") Integer status) {
|
||||
ActionResult<Void> result = new ActionResult<>();
|
||||
result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
|
||||
result.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
|
||||
try {
|
||||
UserInfo userInfo = userProvider.get();
|
||||
log.error("出差taskId:{},status:{},userInfo:{}", taskId, status, userInfo);
|
||||
attendanceApproveService.businessTripApprove(taskId, status, userInfo.getTenantId(), userInfo.getUserId(), userInfo.getUserName());
|
||||
} catch (ApproveException e) {
|
||||
result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
|
||||
result.setMsg(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过传入的开始结束时间及单位获取时长
|
||||
*
|
||||
* @param dto 时长对象
|
||||
*/
|
||||
@GetMapping("/getDurationForOa")
|
||||
public ActionResult<Void> getDurationForOa(@RequestBody DurationForOaDto dto) {
|
||||
log.error("FoeOa通过传入的开始结束时间及单位获取时长了参数................: {}", dto);
|
||||
return attendanceApproveService.getDurationForOa(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新版OA收拢保存考勤外出审批 小时外出逻辑
|
||||
*
|
||||
* @param dto 对象
|
||||
*/
|
||||
@PostMapping("/goOutForOa")
|
||||
public ActionResult<Void> createGoOutForOa(@RequestBody GoOutApproveForOaDto dto) {
|
||||
log.error("FoeOa开始外出了参数................: {}", dto);
|
||||
return attendanceApproveService.createGoOutForOa(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新版OA收拢外出审批通过后触发接口 小时外出逻辑
|
||||
*
|
||||
* @param taskId 审批的唯一id 对应表f_id
|
||||
* @param status 是否审核通过 0.待审核 2.未通过 1.通过
|
||||
* @author hlp
|
||||
*/
|
||||
@GetMapping(value = "/oaApprove/goOut/pass")
|
||||
public ActionResult<Void> goOutApproveForOa(@RequestParam(value = "taskId") String taskId, @RequestParam(value = "status") Integer status) {
|
||||
ActionResult<Void> result = new ActionResult<>();
|
||||
result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
|
||||
result.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
|
||||
try {
|
||||
UserInfo userInfo = userProvider.get();
|
||||
log.error("外出taskId:{},status:{},userInfo:{}", taskId, status, userInfo);
|
||||
attendanceApproveService.goOutApprove(taskId, status, userInfo.getTenantId(), userInfo.getUserId(), userInfo.getUserName());
|
||||
} catch (ApproveException e) {
|
||||
result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
|
||||
result.setMsg(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新版OA收拢保存考勤请假审批
|
||||
*
|
||||
* @param dto 对象
|
||||
*/
|
||||
@PostMapping("/leaveForOa")
|
||||
public ActionResult<Void> createLeaveForOa(@RequestBody LeaveApproveForOaDto dto) {
|
||||
log.error("FoeOa开始请假了参数................: {}", dto);
|
||||
return attendanceApproveService.createLeaveForOa(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请假审批通过后的触发接口
|
||||
*
|
||||
* @param taskId 审批的唯一id 对应表f_id
|
||||
* @param status 是否审核通过 0.待审核 1.通过 2.未通过
|
||||
*/
|
||||
@GetMapping(value = "/oaApprove/leave/pass")
|
||||
public ActionResult<Void> leaveApproveForOa(@RequestParam(value = "taskId") String taskId, @RequestParam(value = "status") Integer status) {
|
||||
ActionResult<Void> result = new ActionResult<>();
|
||||
result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
|
||||
result.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
|
||||
try {
|
||||
UserInfo userInfo = userProvider.get();
|
||||
log.error("请假taskId:{},status:{},userInfo:{}", taskId, status, userInfo);
|
||||
attendanceApproveService.leaveApprove(taskId, status, userInfo.getTenantId(), userInfo.getUserId(), userInfo.getUserName());
|
||||
} catch (Exception e) {
|
||||
log.error("exception", e);
|
||||
result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
|
||||
result.setMsg(e.getMessage());
|
||||
}
|
||||
log.error("请假 result:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 新建加班申请
|
||||
*
|
||||
* @param attendanceWorkOvertimeApproveDto 表单对象
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PostMapping("/createWorkOvertimeForOa")
|
||||
public Object createWorkOvertimeForOa(@RequestBody @Valid AttendanceWorkOvertimeApproveDto attendanceWorkOvertimeApproveDto) {
|
||||
// AttendanceWorkOvertimeApproveDto(super=AttendanceBaseForOa(super=jnpf.model.workflow.dto.AttendanceWorkOvertimeApproveDto@dc44583a, taskId=623849038774196101, status=null, fFlowtaskid=null, fFlowid=null, uniqueId=null, tenantId=null, flowTitle=null, applyUser=["450558466533106821"], startTime=Wed Nov 06 14:12:00 CST 2024, endTime=Wed Nov 06 15:13:00 CST 2024, time=[1730873520000, 1730877180000], unit=null), id=null, userId=null, workDay=null, startTime=Wed Nov 06 14:12:00 CST 2024, endTime=Wed Nov 06 15:13:00 CST 2024, time=[1730873520000, 1730877180000], reason=null, flowtaskid=null, flowid=null, uniqueid=null, tenantId=null, picture=null, fileJson=null, flowTitle=null, applyUser=["450558466533106821"], applyDate=null, submitStatus=null, shiftInvolved=null, groupId=504574013792892037)
|
||||
log.error("新建加班申请 参数 : {}", attendanceWorkOvertimeApproveDto);
|
||||
ActionResult<Void> result = new ActionResult<>();
|
||||
result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
|
||||
result.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
|
||||
String userId = userProvider.get().getUserId();
|
||||
attendanceWorkOvertimeApproveDto.setUserId(userId);
|
||||
attendanceWorkOvertimeApproveDto.setTenantId(userProvider.get().getTenantId());
|
||||
attendanceWorkOvertimeApproveDto.setId(attendanceWorkOvertimeApproveDto.getTaskId());
|
||||
AttendanceWorkOvertimeApprove entity = JsonUtil.getJsonToBean(attendanceWorkOvertimeApproveDto, AttendanceWorkOvertimeApprove.class);
|
||||
// 处理加班日期
|
||||
entity.setWorkDay(attendanceWorkOvertimeApproveDto.getStartTime());
|
||||
try {
|
||||
attendanceApproveService.submitCheckWorkForOa(attendanceWorkOvertimeApproveDto);
|
||||
entity.setId(attendanceWorkOvertimeApproveDto.getTaskId());
|
||||
workApproveService.saveForOa(entity);
|
||||
} catch (Exception e) {
|
||||
result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
|
||||
result.setMsg(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加班审批通过后触发接口
|
||||
*
|
||||
* @param taskId 审批的唯一id 对应表f_id
|
||||
* @param status 是否审核通过 0.待审核 2.未通过 1.通过
|
||||
* @author hlp
|
||||
*/
|
||||
@GetMapping(value = "/oaApprove/work/pass")
|
||||
public ActionResult workApproveForOa(@RequestParam(value = "taskId") String taskId, @RequestParam(value = "status") Integer status) {
|
||||
ActionResult<Void> result = new ActionResult<>();
|
||||
result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
|
||||
result.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
|
||||
try {
|
||||
UserInfo user = UserProvider.getUser();
|
||||
log.error("加班审批通过后的触发接口 tenantId : {},入参applyId:{}", user.getTenantId(), taskId);
|
||||
attendanceApproveService.checkWork(taskId);
|
||||
attendanceApproveService.workApprove(taskId, status, user.getTenantId(), user.getUserId(), user.getUserName());
|
||||
} catch (Exception e) {
|
||||
result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
|
||||
result.setMsg(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户所选时间段所在考勤组
|
||||
*/
|
||||
@PostMapping("/getUserGroupByTime")
|
||||
public ActionResult getUserGroupByTime(@RequestBody GroupOaDto groupOaDto) {
|
||||
log.error("getUserGroupByTime groupOaDto:{}", groupOaDto.toString());
|
||||
if (groupOaDto.isFromOaCondition()){
|
||||
List<AttendanceGroupVo> attendanceGroupVos = attendanceGroupService.secondedApprovalGroupListNew();
|
||||
return ActionResult.success(attendanceGroupVos.stream().map(vo->{
|
||||
GroupMiniVo groupMiniVo = new GroupMiniVo();
|
||||
groupMiniVo.setGroupId(vo.getId());
|
||||
groupMiniVo.setGroupName(vo.getGroupName());
|
||||
return groupMiniVo;
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
if (null == groupOaDto.getUserId()) {
|
||||
groupOaDto.setUserIdStr(userProvider.get().getUserId());
|
||||
} else {
|
||||
groupOaDto.setUserIdStr(groupOaDto.getUserId()[0]);
|
||||
}
|
||||
log.error("getUserGroupByTime groupOaDto:{}", groupOaDto);
|
||||
return attendanceApproveService.getUserGroupByTime(groupOaDto);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* oa收拢获取请假申请时长及设计班次(请假时选择了开始和结束时间后请求该接口)
|
||||
*
|
||||
* @param leaveQueryForOaDto 参数
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.LeaveShiftVo>
|
||||
* @author hlp
|
||||
*/
|
||||
@PostMapping("/leaveDurationForOa")
|
||||
public ActionResult<LeaveShiftVo> getLeaveDuration(@RequestBody LeaveQueryForOaDto leaveQueryForOaDto) throws HandleException {
|
||||
log.error("leaveDurationForOa leaveQueryForOaDto:{}", leaveQueryForOaDto);
|
||||
if (null == leaveQueryForOaDto.getTime() || leaveQueryForOaDto.getTime().length < 1) {
|
||||
return ActionResult.fail("时间参数不能为空");
|
||||
}
|
||||
LeaveQueryDto leaveQueryDto = new LeaveQueryDto(leaveQueryForOaDto.getUnit(), leaveQueryForOaDto.getStartTime().getTime() + "", leaveQueryForOaDto.getEndTime().getTime() + "", leaveQueryForOaDto.getStartTimeType(), leaveQueryForOaDto.getEndTimeType(), leaveQueryForOaDto.getApplyId(), leaveQueryForOaDto.getTypeId());
|
||||
log.error("leaveDurationForOa leaveQueryDto:{}", leaveQueryDto);
|
||||
LeaveShiftVo vo = attendanceApproveService.getLeaveDuration(leaveQueryDto);
|
||||
return ActionResult.success(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户当前时间所在考勤组
|
||||
*/
|
||||
@GetMapping("/nowGroup")
|
||||
public ActionResult getNowGroup() {
|
||||
return attendanceApproveService.getNowGroup();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 提供OA使用时长计算
|
||||
*
|
||||
* @param time 时间数组
|
||||
* @return 时长
|
||||
*/
|
||||
@GetMapping("/oaForTime")
|
||||
public ActionResult getOaForTime(String[] time) {
|
||||
Date startTime = new Date(Long.valueOf(time[0]));
|
||||
Date endTime = new Date(Long.valueOf(time[1]));
|
||||
// 校验结束时间不能小于开始时间
|
||||
if (endTime.before(startTime)) {
|
||||
return ActionResult.fail("结束时间不能小于开始时间");
|
||||
}
|
||||
|
||||
BigDecimal totalDuration = FtbUtil.getTimeDifference(startTime, endTime);
|
||||
TimeVo timeVo = new TimeVo();
|
||||
timeVo.setTotalDuration(totalDuration);
|
||||
return ActionResult.success(timeVo);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@PostMapping(value = "/attendanceToThousandsFaces")
|
||||
public AttendanceToThousandsFacesVo attendanceToThousandsFaces() {
|
||||
return attendanceApproveService.attendanceToThousandsFaces();
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择了请假类型和请假时间后请求接口,获取用户余额使用情况:
|
||||
*
|
||||
* @param leaveQueryForOaDto 参数
|
||||
* @return 用户剩余请假时长
|
||||
*/
|
||||
|
||||
@PostMapping("/residueBalance")
|
||||
public ActionResult getResidueBalance(@RequestBody LeaveQueryForOaDto leaveQueryForOaDto) {
|
||||
log.error("leaveDurationForOa leaveQueryForOaDto:{}", leaveQueryForOaDto);
|
||||
if (null == leaveQueryForOaDto.getTime() || leaveQueryForOaDto.getTime().length < 1) {
|
||||
return ActionResult.fail("时间参数不能为空");
|
||||
}
|
||||
LeaveQueryDto leaveQueryDto = new LeaveQueryDto(leaveQueryForOaDto.getUnit(), leaveQueryForOaDto.getStartTime().getTime() + "", leaveQueryForOaDto.getEndTime().getTime() + "", leaveQueryForOaDto.getStartTimeType(), leaveQueryForOaDto.getEndTimeType(), leaveQueryForOaDto.getApplyId(), leaveQueryForOaDto.getTypeId());
|
||||
if (null == leaveQueryDto.getStartTime() || leaveQueryDto.getStartTime().isEmpty()) {
|
||||
return ActionResult.fail("开始时间不能为空");
|
||||
}
|
||||
if (null == leaveQueryDto.getEndTime() || leaveQueryDto.getEndTime().isEmpty()) {
|
||||
return ActionResult.fail("结束时间不能为空");
|
||||
}
|
||||
if (null == leaveQueryDto.getTypeId() || leaveQueryDto.getTypeId().isEmpty()) {
|
||||
return ActionResult.fail("请选择请假类型");
|
||||
}
|
||||
LeaveConsumptionDetailVo residueBalance = null;
|
||||
try {
|
||||
residueBalance = attendanceApproveService.getResidueBalance(leaveQueryDto);
|
||||
} catch (Exception e) {
|
||||
ActionResult<Void> result = new ActionResult<>();
|
||||
result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
|
||||
result.setMsg(e.getMessage());
|
||||
return result;
|
||||
}
|
||||
// 3天调休假+0.5天存休(剩余5.5天)
|
||||
StringBuilder sb = new StringBuilder();
|
||||
assert residueBalance != null;
|
||||
if (residueBalance.getInputTypeBalance().compareTo(BigDecimal.ZERO) > 0) {
|
||||
sb.append(residueBalance.getInputTypeBalanceStr());
|
||||
}
|
||||
if (residueBalance.getInputTypeBalance().compareTo(BigDecimal.ZERO) > 0 && residueBalance.getRetirementLeave().compareTo(BigDecimal.ZERO) > 0) {
|
||||
sb.append("+");
|
||||
}
|
||||
if (residueBalance.getRetirementLeave().compareTo(BigDecimal.ZERO) > 0) {
|
||||
sb.append(residueBalance.getRetirementLeaveStr());
|
||||
}
|
||||
if (residueBalance.getBalance().compareTo(BigDecimal.ZERO) > 0) {
|
||||
sb.append("(剩余").append(residueBalance.getBalance().setScale(2, RoundingMode.HALF_UP)).append("天)");
|
||||
}
|
||||
return ActionResult.success(new HashMap<>(){{put("residueBalance",sb.toString());}});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import jnpf.attendance.service.AttendanceBaseSettingService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.UserInfo;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.AttendanceBaseSettingDto;
|
||||
import jnpf.model.attendance.vo.AttendanceBaseSettingVo;
|
||||
import jnpf.model.attendance.vo.attendance.QuickCheckInVo;
|
||||
import jnpf.util.ConstantUtil;
|
||||
import jnpf.util.UserProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 考勤基础设置表 前端控制器
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2023-11-29
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/base/setting")
|
||||
public class AttendanceBaseSettingController {
|
||||
@Autowired
|
||||
private AttendanceBaseSettingService attendanceBaseSettingService;
|
||||
|
||||
/**
|
||||
* 保存考勤基础设置信息。
|
||||
*
|
||||
* @param attendanceBaseSettingDto 考勤基础设置数据传输对象
|
||||
* @throws HandleException 处理异常
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult<Void> save(@RequestBody AttendanceBaseSettingDto attendanceBaseSettingDto) throws HandleException {
|
||||
attendanceBaseSettingService.save(attendanceBaseSettingDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据考勤组ID获取单个考勤基础设置。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @return 考勤基础设置视图对象
|
||||
*/
|
||||
@GetMapping("{groupId}")
|
||||
public ActionResult<AttendanceBaseSettingVo> getOne(@PathVariable String groupId) {
|
||||
return ActionResult.success(attendanceBaseSettingService.getOne(groupId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改考勤基础设置的启用状态。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @param enable 启用状态(0禁用,1启用)
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PutMapping
|
||||
public ActionResult<Void> changeStatus(@RequestParam String groupId, @RequestParam Integer enable) {
|
||||
attendanceBaseSettingService.changeStatus(groupId, enable, attendanceBaseSettingService.getOne(groupId));
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户外勤是否必须拍照
|
||||
* @param isFromOaCondition 是否来自OA条件 是需要返回所有可能选项
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/takePhoto")
|
||||
public Object getTakePhotoSetting(@RequestParam(required = false) boolean isFromOaCondition) throws Exception {
|
||||
if (isFromOaCondition) {
|
||||
JSONArray array = new JSONArray();
|
||||
JSONObject json = new JSONObject();
|
||||
json.set("state", ConstantUtil.NUM_TRUE);
|
||||
json.set("name", "是");
|
||||
array.put(json);
|
||||
JSONObject json1 = new JSONObject();
|
||||
json1.set("state", ConstantUtil.NUM_FALSE);
|
||||
json1.set("name", "否");
|
||||
array.put(json1);
|
||||
return ActionResult.success(array);
|
||||
}
|
||||
UserInfo user = UserProvider.getUser();
|
||||
JSONArray shouldTakePhoto = attendanceBaseSettingService.getTakePhotoSetting(user);
|
||||
return ActionResult.success(shouldTakePhoto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户外勤是否必须拍照
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/takePhoto2")
|
||||
public Object getTakePhotoSetting2() throws Exception {
|
||||
|
||||
UserInfo user = UserProvider.getUser();
|
||||
JSONArray shouldTakePhoto = attendanceBaseSettingService.getTakePhotoSetting(user);
|
||||
return ActionResult.success(shouldTakePhoto.get(0));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户当前时间所处考勤组的内勤打卡基础设置。(过度使用)
|
||||
*/
|
||||
@GetMapping("/getNowGroupAttendancePhoto")
|
||||
public ActionResult<Integer> getNowGroupAttendancePhoto() {
|
||||
return ActionResult.success(attendanceBaseSettingService.getNowGroupAttendancePhoto());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户当前时间所处考勤组是否能快速打卡
|
||||
* 和用户当前所处考勤组的基础设置中的是否需要拍照,是否需要人脸识别以及App个人设置中的上下班快速打开相关
|
||||
*/
|
||||
@GetMapping("/quickCheckIn")
|
||||
public ActionResult<QuickCheckInVo> quickCheckIn() {
|
||||
return ActionResult.success(attendanceBaseSettingService.quickCheckIn());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jnpf.attendance.service.AttendanceBookConfigService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.*;
|
||||
import jnpf.model.attendance.vo.AttendanceBookConfigVo;
|
||||
import jnpf.model.attendance.vo.AttendanceResultOptionGroupVo;
|
||||
import jnpf.model.attendance.vo.AttendanceResultOptionVo;
|
||||
import jnpf.model.attendance.vo.BookConfigCreatorVo;
|
||||
import jnpf.model.attendance.vo.BookPersonnelVo;
|
||||
import jnpf.permission.model.user.PartUserInfoVo;
|
||||
import jnpf.util.FtbUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤本配置Controller
|
||||
*
|
||||
* @author Generated
|
||||
* @create 2026-04-15
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/attendance/book-config")
|
||||
@Tag(name = "考勤本配置", description = "考勤本配置管理")
|
||||
public class AttendanceBookConfigController {
|
||||
|
||||
@Resource
|
||||
private AttendanceBookConfigService attendanceBookConfigService;
|
||||
|
||||
/**
|
||||
* web-分页查询考勤本配置列表
|
||||
*
|
||||
* @param queryDto 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
@Operation(summary = "web/app-分页查询考勤本配置列表(app用于当前登录人为负责人的考勤本列表)")
|
||||
@PostMapping("/list")
|
||||
public ActionResult<PageListVO<AttendanceBookConfigVo>> getList(@RequestBody AttendanceBookConfigQueryDto queryDto) {
|
||||
try {
|
||||
log.info("分页查询考勤本配置列表,入参=>{}", JSONObject.toJSON(queryDto));
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
PageInfo<AttendanceBookConfigVo> pageInfo = attendanceBookConfigService.getPageList(queryDto);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("分页查询考勤本配置列表,耗时=>{} 毫秒", ent - st);
|
||||
return ActionResult.page(pageInfo.getList(), FtbUtil.getPagination(pageInfo));
|
||||
} catch (Exception e) {
|
||||
log.error("分页查询考勤本配置列表异常", e);
|
||||
return ActionResult.fail("查询失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* web-新增或更新考勤本配置
|
||||
* <p>根据DTO中的id判断:id为空则新增,id不为空则更新</p>
|
||||
*
|
||||
* @param configDto 考勤本配置DTO
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Operation(summary = "web-新增或更新考勤本配置")
|
||||
@PostMapping("/save-or-update")
|
||||
public ActionResult saveOrUpdate(@Valid @RequestBody AttendanceBookConfigDto configDto) {
|
||||
try {
|
||||
String action = StringUtils.isBlank(configDto.getId()) ? "新增" : "更新";
|
||||
log.info("{}考勤本配置,入参=>{}", action, JSONObject.toJSON(configDto));
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
attendanceBookConfigService.saveOrUpdateAttendanceBookConfig(configDto);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("{}考勤本配置,耗时=>{} 毫秒", action, ent - st);
|
||||
return ActionResult.success(action + "成功");
|
||||
} catch (HandleException e) {
|
||||
log.error("保存考勤本配置业务异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("保存考勤本配置异常", e);
|
||||
return ActionResult.fail("保存失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* web-删除考勤本配置
|
||||
*
|
||||
* @param id 考勤本ID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Operation(summary = "web-删除考勤本配置")
|
||||
@DeleteMapping("/{id}")
|
||||
public ActionResult delete(@PathVariable String id) {
|
||||
try {
|
||||
log.info("删除考勤本配置,id=>{}", id);
|
||||
attendanceBookConfigService.deleteAttendanceBookConfig(id);
|
||||
return ActionResult.success("删除成功");
|
||||
} catch (Exception e) {
|
||||
log.error("删除考勤本配置异常", e);
|
||||
return ActionResult.fail("删除失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* web-更新启用状态
|
||||
*
|
||||
* @param id 考勤本ID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Operation(summary = "web-更新启用状态")
|
||||
@PutMapping("/{id}/status")
|
||||
public ActionResult updateStatus(@PathVariable String id) {
|
||||
try {
|
||||
log.info("更新考勤本启用状态,id=>{}", id);
|
||||
attendanceBookConfigService.updateEnableStatus(id);
|
||||
return ActionResult.success("状态更新成功");
|
||||
} catch (HandleException e) {
|
||||
log.error("更新考勤本状态业务异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("更新考勤本状态异常", e);
|
||||
return ActionResult.fail("状态更新失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* web-获取考勤本配置详情
|
||||
*
|
||||
* @param id 考勤本ID
|
||||
* @return 考勤本配置详情
|
||||
*/
|
||||
@Operation(summary = "web-获取考勤本配置详情")
|
||||
@GetMapping("/{id}")
|
||||
public ActionResult<AttendanceBookConfigVo> getDetail(@PathVariable String id) {
|
||||
try {
|
||||
log.info("获取考勤本配置详情,id=>{}", id);
|
||||
AttendanceBookConfigVo vo = attendanceBookConfigService.getDetail(id);
|
||||
return ActionResult.success(vo);
|
||||
} catch (Exception e) {
|
||||
log.error("获取考勤本配置详情异常", e);
|
||||
return ActionResult.fail("获取详情失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* app-增量添加使用范围人员
|
||||
* <p>向指定考勤本配置的使用范围中增量添加用户列表(不会覆盖已有人员)</p>
|
||||
*
|
||||
* @param addUserDto 添加用户DTO
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Operation(summary = "app-增量添加使用范围人员")
|
||||
@PostMapping("/add-scope-users")
|
||||
public ActionResult addScopeUsers(@Valid @RequestBody AttendanceBookConfigAddUserDto addUserDto) {
|
||||
try {
|
||||
log.info("增量添加使用范围人员,考勤本ID=>{}, 用户数=>{}",
|
||||
addUserDto.getBookConfigId(), addUserDto.getUserIdList().size());
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
attendanceBookConfigService.addScopeUsers(addUserDto);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("增量添加使用范围人员,耗时=>{} 毫秒", ent - st);
|
||||
return ActionResult.success("添加成功");
|
||||
} catch (HandleException e) {
|
||||
log.error("增量添加使用范围人员业务异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("增量添加使用范围人员异常", e);
|
||||
return ActionResult.fail("添加失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* app-判断当前登录人是否为考勤本负责人
|
||||
*
|
||||
* @param bookConfigId 考勤本配置ID
|
||||
* @return true-是负责人,false-不是负责人
|
||||
*/
|
||||
@Operation(summary = "app-判断当前登录人是否为考勤本负责人")
|
||||
@GetMapping("/{bookConfigId}/is-manager")
|
||||
public ActionResult<Boolean> isCurrentUserManager(@PathVariable String bookConfigId) {
|
||||
try {
|
||||
log.info("判断当前登录人是否为考勤本负责人,考勤本ID=>{}", bookConfigId);
|
||||
boolean isManager = attendanceBookConfigService.isCurrentUserManager(bookConfigId);
|
||||
return ActionResult.success(isManager);
|
||||
} catch (HandleException e) {
|
||||
log.error("判断负责人业务异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("判断负责人异常", e);
|
||||
return ActionResult.fail("判断失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* web-获取指定组织集合及用户集合在当前时间下的所有涉及用户(筛选考勤本负责人)
|
||||
* <p>查询这些组织和用户在当前时间的有效用户集合,返回完整的用户信息列表</p>
|
||||
*
|
||||
* @param dto 查询参数(组织ID列表、用户ID列表)
|
||||
* @return 有效用户信息列表
|
||||
*/
|
||||
@Operation(summary = "web-获取指定组织集合及用户集合在当前时间下的所有涉及用户(筛选考勤本负责人)")
|
||||
@PostMapping("/get-valid-users")
|
||||
public ActionResult<List<PartUserInfoVo>> getValidUsers(@RequestBody GetValidUsersDto dto) {
|
||||
try {
|
||||
log.info("获取有效用户列表,入参=>{}", JSONObject.toJSON(dto));
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
List<PartUserInfoVo> userList = attendanceBookConfigService.getValidUsers(dto);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取有效用户列表,耗时=>{} 毫秒,返回用户数: {}", ent - st, userList.size());
|
||||
return ActionResult.success(userList);
|
||||
} catch (Exception e) {
|
||||
log.error("获取有效用户列表异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* app-获取考勤结果下拉列表
|
||||
* <p>根据考勤本配置返回可用的考勤状态选项,包括基础考勤状态和该考勤本配置的请假类型</p>
|
||||
*
|
||||
* @param bookConfigId 考勤本配置ID
|
||||
* @return 考勤结果下拉选项列表
|
||||
*/
|
||||
@Operation(summary = "app-获取考勤结果下拉列表(分组)")
|
||||
@GetMapping("/{bookConfigId}/result-options")
|
||||
public ActionResult<AttendanceResultOptionGroupVo> getAttendanceResultOptions(@PathVariable String bookConfigId) {
|
||||
try {
|
||||
log.info("获取考勤结果下拉列表(分组),考勤本ID=>{}", bookConfigId);
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
AttendanceResultOptionGroupVo options = attendanceBookConfigService.getAttendanceResultOptions(bookConfigId);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取考勤结果下拉列表(分组),耗时=>{} 毫秒", ent - st);
|
||||
return ActionResult.success(options);
|
||||
} catch (HandleException e) {
|
||||
log.error("获取考勤结果下拉列表业务异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("获取考勤结果下拉列表异常", e);
|
||||
return ActionResult.fail("获取失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 需求2:获取考勤本配置创建人列表
|
||||
*
|
||||
* @return 创建人列表
|
||||
*/
|
||||
@Operation(summary = "web-获取考勤本配置创建人列表")
|
||||
@GetMapping("/creator-list")
|
||||
public ActionResult<List<BookConfigCreatorVo>> getCreatorList() {
|
||||
try {
|
||||
log.info("获取考勤本配置创建人列表");
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
List<BookConfigCreatorVo> creatorList = attendanceBookConfigService.getCreatorList();
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取考勤本配置创建人列表,耗时=>{} 毫秒,创建人数: {}", ent - st, creatorList.size());
|
||||
return ActionResult.success(creatorList);
|
||||
} catch (Exception e) {
|
||||
log.error("获取考勤本配置创建人列表异常", e);
|
||||
return ActionResult.fail("获取失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 需求3:获取考勤本配置人员列表
|
||||
*
|
||||
* @param dto 考勤本配置ID
|
||||
* @return 人员列表
|
||||
*/
|
||||
@Operation(summary = "app-获取考勤本配置人员列表")
|
||||
@PostMapping("/personnel-list")
|
||||
public ActionResult<List<BookPersonnelVo>> getPersonnelList(@RequestBody BookRecordMonthListDto dto) {
|
||||
try {
|
||||
log.info("获取考勤本配置人员列表,考勤本ID=>{}", dto.getBookId());
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
List<BookPersonnelVo> personnelList = attendanceBookConfigService.getBookPersonnelList(dto.getBookId(),dto.getMonth());
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取考勤本配置人员列表,耗时=>{} 毫秒,人员数: {}", ent - st, personnelList.size());
|
||||
return ActionResult.success(personnelList);
|
||||
} catch (Exception e) {
|
||||
log.error("获取考勤本配置人员列表异常", e);
|
||||
return ActionResult.fail("获取失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jnpf.attendance.service.AttendanceBookOperationLogService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.entity.attendance.AttendanceBookOperationLogEntity;
|
||||
import jnpf.model.attendance.dto.OperationLogQueryDto;
|
||||
import jnpf.model.attendance.vo.OperationLogPageVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 考勤本操作日志Controller
|
||||
*
|
||||
* @author Generated
|
||||
* @create 2026-04-15
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/attendance/book-operation-log")
|
||||
@Tag(name = "考勤本操作日志", description = "考勤本操作日志管理")
|
||||
public class AttendanceBookOperationLogController {
|
||||
|
||||
@Resource
|
||||
private AttendanceBookOperationLogService attendanceBookOperationLogService;
|
||||
|
||||
/**
|
||||
* 新增操作日志
|
||||
*
|
||||
* @param entity 操作日志实体
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Operation(summary = "新增操作日志")
|
||||
@PostMapping
|
||||
public ActionResult create(@Valid @RequestBody AttendanceBookOperationLogEntity entity) {
|
||||
try {
|
||||
log.info("新增操作日志,入参=>{}", JSONObject.toJSON(entity));
|
||||
attendanceBookOperationLogService.saveLog(entity);
|
||||
return ActionResult.success("操作成功");
|
||||
} catch (Exception e) {
|
||||
log.error("新增操作日志异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* web-分页查询操作日志
|
||||
*
|
||||
* @param queryDto 查询参数
|
||||
* @return 分页结果
|
||||
*/
|
||||
@Operation(summary = "web-分页查询操作日志")
|
||||
@GetMapping("/page")
|
||||
public ActionResult<Page<OperationLogPageVo>> queryPage(@Valid OperationLogQueryDto queryDto) {
|
||||
try {
|
||||
log.info("分页查询操作日志,入参=>{}", JSONObject.toJSON(queryDto));
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
Page<OperationLogPageVo> result = attendanceBookOperationLogService.queryPage(queryDto);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("分页查询操作日志,耗时=>{} 毫秒,返回记录数: {}", ent - st, result.getRecords().size());
|
||||
return ActionResult.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("分页查询操作日志异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取操作日志详情
|
||||
*
|
||||
* @param id 日志ID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Operation(summary = "获取操作日志详情")
|
||||
@GetMapping("/{id}")
|
||||
public ActionResult<AttendanceBookOperationLogEntity> getById(@PathVariable String id) {
|
||||
try {
|
||||
log.info("获取操作日志详情,id=>{}", id);
|
||||
AttendanceBookOperationLogEntity entity = attendanceBookOperationLogService.getById(id);
|
||||
if (entity == null) {
|
||||
return ActionResult.fail("记录不存在");
|
||||
}
|
||||
return ActionResult.success(entity);
|
||||
} catch (Exception e) {
|
||||
log.error("获取操作日志详情异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除操作日志
|
||||
*
|
||||
* @param id 日志ID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Operation(summary = "删除操作日志")
|
||||
@DeleteMapping("/{id}")
|
||||
public ActionResult delete(@PathVariable String id) {
|
||||
try {
|
||||
log.info("删除操作日志,id=>{}", id);
|
||||
boolean removed = attendanceBookOperationLogService.removeById(id);
|
||||
if (!removed) {
|
||||
return ActionResult.fail("删除失败,记录不存在");
|
||||
}
|
||||
return ActionResult.success("删除成功");
|
||||
} catch (Exception e) {
|
||||
log.error("删除操作日志异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jnpf.attendance.service.AttendanceBookRecordService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.model.attendance.dto.*;
|
||||
import jnpf.model.attendance.vo.*;
|
||||
import jnpf.util.FtbUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤本记录表Controller
|
||||
*
|
||||
* @author Generated
|
||||
* @create 2026-04-15
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/attendance/book-record")
|
||||
@Tag(name = "考勤本记录", description = "考勤本记录管理")
|
||||
public class AttendanceBookRecordController {
|
||||
|
||||
@Resource
|
||||
private AttendanceBookRecordService attendanceBookRecordService;
|
||||
|
||||
/**
|
||||
* app-新增或修改考勤记录(Upsert)
|
||||
* 根据考勤本ID、员工ID、考勤日期、时段类型唯一确定一条记录
|
||||
* 如果记录存在则更新,不存在则新增
|
||||
*
|
||||
* @param dto 考勤记录DTO
|
||||
* @return 操作结果(包含记录ID)
|
||||
*/
|
||||
@Operation(summary = "app-新增或修改考勤记录")
|
||||
@PostMapping("/saveOrUpdate")
|
||||
public ActionResult<String> saveOrUpdate(@Valid @RequestBody AttendanceBookRecordDto dto) {
|
||||
try {
|
||||
log.info("新增或修改考勤记录,入参=>{}", JSONObject.toJSON(dto));
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
String recordId = attendanceBookRecordService.saveOrUpdateRecord(dto);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("新增或修改考勤记录,耗时=>{} 毫秒,记录ID: {}", ent - st, recordId);
|
||||
return ActionResult.success(recordId);
|
||||
} catch (Exception e) {
|
||||
log.error("新增或修改考勤记录异常", e);
|
||||
return ActionResult.fail("系统异常,请联系管理员");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* web-获取考勤本月统计数据
|
||||
*
|
||||
* @param req 统计请求参数
|
||||
* @return 本月统计结果(按员工维度,支持分页)
|
||||
*/
|
||||
@Operation(summary = "web/app-获取考勤本月统计")
|
||||
@PostMapping("/monthStatistics")
|
||||
public ActionResult<PageListVO<BookRecordMonthStatisticsVo>> getMonthStatistics(@Valid @RequestBody BookRecordMonthStatisticsDto req) {
|
||||
try {
|
||||
log.info("获取考勤本月统计,入参=>{}", JSONObject.toJSON(req));
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
PageInfo<BookRecordMonthStatisticsVo> pageInfo = attendanceBookRecordService.getMonthStatistics(req);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
// 防止pageInfo或list为null
|
||||
List<BookRecordMonthStatisticsVo> resultList = pageInfo.getList() != null ? pageInfo.getList() : new ArrayList<>();
|
||||
log.info("获取考勤本月统计,耗时=>{} 毫秒,返回记录数: {}", ent - st, resultList.size());
|
||||
return ActionResult.page(resultList, FtbUtil.getPagination(pageInfo));
|
||||
} catch (Exception e) {
|
||||
log.error("获取考勤本月统计异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* web-考勤本导入
|
||||
*
|
||||
* @param importDto 导入参数(包含bookId、month、fileUrl)
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Operation(summary = "web-考勤本导入")
|
||||
@PostMapping("/import")
|
||||
public ActionResult bookRecordImport(@RequestBody SchedulesImportDto importDto) {
|
||||
try {
|
||||
log.info("考勤本导入,入参=>{}", JSONObject.toJSON(importDto));
|
||||
attendanceBookRecordService.bookRecordImport(importDto);
|
||||
return ActionResult.success("导入成功");
|
||||
} catch (Exception e) {
|
||||
log.error("考勤本导入异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* web-考勤本导出
|
||||
*
|
||||
* @param bookId 考勤本ID
|
||||
* @param month 月份(格式:yyyy-MM)
|
||||
*/
|
||||
@Operation(summary = "web-考勤本导出")
|
||||
@GetMapping("/export")
|
||||
public ActionResult bookRecordExport(@RequestParam String bookId, @RequestParam String month) {
|
||||
try {
|
||||
log.info("考勤本导出,bookId=>{}, month=>{}", bookId, month);
|
||||
attendanceBookRecordService.bookRecordExport(bookId, month);
|
||||
} catch (Exception e) {
|
||||
log.error("考勤本导出异常", e);
|
||||
throw new RuntimeException("导出失败:" + e.getMessage());
|
||||
}
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* web-导出考勤本模板(直接流导出)
|
||||
* <p>返回的Excel文件与导出接口具有相同的表头结构,但不包含任何实际数据记录</p>
|
||||
*
|
||||
* @param bookId 考勤本ID
|
||||
* @param month 月份(格式:yyyy-MM)
|
||||
* @param response HTTP响应对象
|
||||
*/
|
||||
@Operation(summary = "web-导出考勤本模板")
|
||||
@GetMapping("/export-template")
|
||||
public void exportTemplate(@RequestParam String bookId, @RequestParam String month, javax.servlet.http.HttpServletResponse response) {
|
||||
try {
|
||||
log.info("导出考勤本模板,bookId=>{}, month=>{}", bookId, month);
|
||||
attendanceBookRecordService.exportTemplate(bookId, month, response);
|
||||
} catch (Exception e) {
|
||||
log.error("导出考勤本模板异常", e);
|
||||
throw new RuntimeException("导出模板失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* app-获取日考勤本列表
|
||||
* <p>根据考勤本的使用范围获取人员列表,展示指定日期的考勤记录</p>
|
||||
*
|
||||
* @param req 查询参数(考勤本ID、日期)
|
||||
* @return 日考勤本列表(按员工分组)
|
||||
*/
|
||||
@Operation(summary = "app-获取日考勤本列表")
|
||||
@PostMapping("/day-list")
|
||||
public ActionResult<List<BookRecordDayListVo>> getDayList(@Valid @RequestBody BookRecordDayListDto req) {
|
||||
try {
|
||||
log.info("获取日考勤本列表,入参=>{}", JSONObject.toJSON(req));
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
List<BookRecordDayListVo> result = attendanceBookRecordService.getDayList(req);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取日考勤本列表,耗时=>{} 毫秒,返回记录数: {}", ent - st, result.size());
|
||||
return ActionResult.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取日考勤本列表异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* app-获取月考勤本列表
|
||||
* <p>根据考勤本的使用范围获取人员列表,展示该月所有日期的考勤记录</p>
|
||||
*
|
||||
* @param req 查询参数(考勤本ID、月份)
|
||||
* @return 月考勤本列表(按员工分组)
|
||||
*/
|
||||
@Operation(summary = "app-获取月考勤本列表")
|
||||
@PostMapping("/month-list")
|
||||
public ActionResult<List<BookRecordMonthListVo>> getMonthList(@Valid @RequestBody BookRecordMonthListDto req) {
|
||||
try {
|
||||
log.info("获取月考勤本列表,入参=>{}", JSONObject.toJSON(req));
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
List<BookRecordMonthListVo> result = attendanceBookRecordService.getMonthList(req);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取月考勤本列表,耗时=>{} 毫秒,返回记录数: {}", ent - st, result.size());
|
||||
return ActionResult.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取月考勤本列表异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 需求10:批量新增或修改考勤记录
|
||||
*
|
||||
* @param dto 批量考勤记录DTO
|
||||
* @return 批量操作结果
|
||||
*/
|
||||
@Operation(summary = "app-批量新增或修改考勤记录")
|
||||
@PostMapping("/batch-save-or-update")
|
||||
public ActionResult<BatchOperationResultVo> batchSaveOrUpdate(@Valid @RequestBody BatchAttendanceBookRecordDto dto) {
|
||||
try {
|
||||
log.info("批量新增或修改考勤记录,记录数=>{}", dto.getRecords().size());
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
BatchOperationResultVo result = attendanceBookRecordService.batchSaveOrUpdateRecord(dto);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("批量新增或修改考勤记录,耗时=>{} 毫秒,成功: {}, 失败: {}",
|
||||
ent - st, result.getSuccessCount(), result.getFailCount());
|
||||
return ActionResult.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("批量新增或修改考勤记录异常", e);
|
||||
return ActionResult.fail("系统异常,请联系管理员");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取假勤汇总信息
|
||||
*
|
||||
* @param dto 统计请求参数
|
||||
* @return 假勤汇总信息
|
||||
*/
|
||||
@Operation(summary = "app-获取假勤汇总信息")
|
||||
@PostMapping("/leave-attendance-summary")
|
||||
public ActionResult<LeaveRemarkSummaryVo> getLeaveAttendanceSummary(@Valid @RequestBody LeaveRemarkSummaryDto dto) {
|
||||
try {
|
||||
log.info("获取假勤汇总信息,入参=>{}", JSONObject.toJSON(dto));
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
LeaveRemarkSummaryVo result = attendanceBookRecordService.getLeaveAttendanceSummary(dto);
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取假勤汇总信息,耗时=>{} 毫秒,备注数: {}", ent - st, result.getTotalCount());
|
||||
return ActionResult.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取假勤汇总信息异常", e);
|
||||
return ActionResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import jnpf.attendance.service.AttendanceChangeService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.UserInfo;
|
||||
import jnpf.enums.personnel.FtbPersonnelsCheckStatusCodeEnum;
|
||||
import jnpf.model.attendance.dto.NoApprovalDto;
|
||||
import jnpf.model.attendance.vo.ChangeInfoVo;
|
||||
import jnpf.util.UserProvider;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 考勤变更控制器
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2024-11-08
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/change")
|
||||
public class AttendanceChangeController {
|
||||
|
||||
@Resource
|
||||
private AttendanceChangeService attendanceChangeService;
|
||||
|
||||
/**
|
||||
* 被变更记录的信息
|
||||
* @param clockInResultId 结果id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/info/{clockInResultId}")
|
||||
public Object getChangeInfo(@PathVariable(value = "clockInResultId") String clockInResultId) throws Exception {
|
||||
|
||||
ChangeInfoVo info = attendanceChangeService.getChangeInfo(clockInResultId);
|
||||
return ActionResult.success(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据考勤组id及用户id查询过去一年内的变更涉及打卡记录
|
||||
* @param groupId 考勤组id
|
||||
* @param userId 用户id
|
||||
* @return jnpf.base.ActionResult
|
||||
*/
|
||||
@GetMapping(value = "/getChangeInfoList")
|
||||
public ActionResult<List<ChangeInfoVo>> getChangeInfoList(@RequestParam String groupId,@RequestParam String userId) {
|
||||
List<ChangeInfoVo> infos = attendanceChangeService.getChangeInfoList(groupId, userId);
|
||||
return ActionResult.success(infos);
|
||||
}
|
||||
|
||||
/**
|
||||
* 出勤变更(无需审批)
|
||||
* @param noApprovalDto 出勤变更参数
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PostMapping(value = "/noApproval")
|
||||
public Object attendanceChangeNoApproval(@RequestBody @Valid NoApprovalDto noApprovalDto) throws Exception {
|
||||
|
||||
attendanceChangeService.attendanceChangeNoApproval(noApprovalDto);
|
||||
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 出勤变更(需审批)
|
||||
* @param taskId 审批id
|
||||
* @param passed 是否通过(0: 否, 1: 是, 2: 撤回)
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/approval")
|
||||
public Object attendanceChangeApproval(@RequestParam(value = "taskId") String taskId, @RequestParam(value = "passed") String passed) {
|
||||
|
||||
UserInfo user = UserProvider.getUser();
|
||||
ActionResult<Void> actionResult = new ActionResult<>();
|
||||
try {
|
||||
attendanceChangeService.attendanceChangeApproval(taskId, passed, user);
|
||||
} catch (Exception e) {
|
||||
actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
|
||||
actionResult.setMsg(e.getMessage());
|
||||
return actionResult;
|
||||
}
|
||||
actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
|
||||
actionResult.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
|
||||
return actionResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 出勤变更撤回
|
||||
* @param clockInResultId 打卡结果id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PutMapping(value = "/rollback/{clockInResultId}")
|
||||
public Object rollbackChange(@PathVariable(value = "clockInResultId") String clockInResultId) throws Exception {
|
||||
|
||||
attendanceChangeService.rollbackChange(clockInResultId);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询能否撤回变更
|
||||
* @param clockInResultId 打卡结果id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/rollback/status")
|
||||
public Object getRollbackStatus(@RequestParam(value = "clockInResultId") String clockInResultId) {
|
||||
|
||||
Integer status = attendanceChangeService.getRollbackStatus(clockInResultId);
|
||||
return ActionResult.success(status);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,385 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import jnpf.aspect.FtbApiCallLog;
|
||||
import jnpf.attendance.FtbClockInApi;
|
||||
import jnpf.attendance.service.AttendanceClockInService;
|
||||
import jnpf.attendance.service.DailyRuleChangeService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.UserInfo;
|
||||
import jnpf.enums.personnel.FtbPersonnelsCheckStatusCodeEnum;
|
||||
import jnpf.exception.QueryException;
|
||||
import jnpf.model.attendance.dto.ClockInDto;
|
||||
import jnpf.model.attendance.dto.NoApprovalDto;
|
||||
import jnpf.model.attendance.vo.*;
|
||||
import jnpf.util.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 打卡控制器
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2023-11-21
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/clockIn")
|
||||
public class AttendanceClockInController implements FtbClockInApi {
|
||||
|
||||
@Resource
|
||||
private AttendanceClockInService attendanceClockInService;
|
||||
|
||||
@Resource
|
||||
private UserProvider userProvider;
|
||||
|
||||
@Resource
|
||||
private CustomTenantUtil customTenantUtil;
|
||||
|
||||
@Resource
|
||||
private DailyRuleChangeService dailyRuleChangeService;
|
||||
|
||||
/**
|
||||
* 打卡 - 主页
|
||||
* @return jnpf.base.ActionResult<java.util.List<jnpf.model.attendance.vo.GroupInfoVo>>
|
||||
*/
|
||||
@GetMapping(value = "/mainInfo")
|
||||
public ActionResult<List<GroupInfoVo>> getClockInMainInfo(@RequestParam(required = false) String day) throws Exception {
|
||||
|
||||
try {
|
||||
Date date = StringUtils.isEmpty(day) ? new Date() : DateDetail.getStr2Date10(day);
|
||||
List<GroupInfoVo> list = attendanceClockInService.getClockInMainInfo(date, userProvider.get(), ConstantUtil.NUM_TRUE);
|
||||
return ActionResult.success(list);
|
||||
} catch (QueryException e) {
|
||||
if (e.getMessage().equals("当前用户暂无考勤组")) {
|
||||
return ActionResult.success(e.getMessage());
|
||||
} else {
|
||||
throw new QueryException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询考勤组审批列表
|
||||
* @param queryDto 查询条件
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.GroupApprovalVo>
|
||||
*/
|
||||
@PostMapping(value = "/group-approval/list")
|
||||
public ActionResult<List<GroupApprovalVo>> getGroupApprovalList(@RequestBody ApprovalQueryDto queryDto) {
|
||||
|
||||
List<GroupApprovalVo> list = attendanceClockInService.getGroupApprovalList(queryDto);
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打卡
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@FtbApiCallLog(name = "考勤打卡")
|
||||
@PostMapping(value = "/record")
|
||||
public Object clockIn(@RequestBody @Valid ClockInDto clockInDto) throws Exception {
|
||||
|
||||
MutablePair<Integer, String> pair = attendanceClockInService.clockIn(clockInDto);
|
||||
return ActionResult.success(pair.getLeft());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新打卡记录
|
||||
* @param clockInId 打卡id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PutMapping(value = "/record/{clockInId}")
|
||||
public Object updateClockIn(@PathVariable(value = "clockInId") String clockInId, @RequestBody @Valid ClockInDto clockInDto) throws Exception {
|
||||
|
||||
MutablePair<Integer, String> pair = attendanceClockInService.updateClockIn(clockInId, clockInDto);
|
||||
return ActionResult.success(pair.getLeft());
|
||||
}
|
||||
|
||||
@PostMapping(value = "/testChangeRule")
|
||||
public void changeAttendanceRule(@RequestBody List<UserDayVo> userDayList) {
|
||||
|
||||
UserInfo userInfo = userProvider.get();
|
||||
attendanceClockInService.changeAttendanceRuleBatch(userDayList, userInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 外勤打卡
|
||||
* @param applyId 审批id
|
||||
*/
|
||||
@GetMapping(value = "/outside")
|
||||
public Object outsideClockIn(@RequestParam(value = "taskId") String applyId, @RequestParam(value = "clockInId", required = false) String clockInId) throws Exception {
|
||||
|
||||
UserInfo user = userProvider.get();
|
||||
ActionResult<Void> actionResult = new ActionResult<>();
|
||||
try {
|
||||
attendanceClockInService.outsideClockIn(applyId, user.getUserId(), clockInId);
|
||||
} catch (Exception e) {
|
||||
actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
|
||||
actionResult.setMsg(e.getMessage());
|
||||
return actionResult;
|
||||
}
|
||||
actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
|
||||
actionResult.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
|
||||
return actionResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 外勤打卡审批(通过/不通过/撤回)
|
||||
* @param applyId 审批id
|
||||
* @param passed - 是否通过(0: 否, 1: 是, 2: 撤回) <br>
|
||||
*/
|
||||
@GetMapping(value = "/outside/approval")
|
||||
public Object approvalOutsideClockIn(@RequestParam(value = "taskId") String applyId, @RequestParam(value = "passed") String passed) throws Exception {
|
||||
|
||||
UserInfo userInfo = userProvider.get();
|
||||
ActionResult<Void> actionResult = new ActionResult<>();
|
||||
try {
|
||||
attendanceClockInService.approvalOutsideClockIn(applyId, passed, userInfo);
|
||||
} catch (Exception e) {
|
||||
actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
|
||||
actionResult.setMsg(e.getMessage());
|
||||
return actionResult;
|
||||
}
|
||||
actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
|
||||
actionResult.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
|
||||
return actionResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异常打卡审批(通过/不通过/撤回)
|
||||
* @param applyId 审批id
|
||||
* @param passed - 是否通过(0: 否, 1: 是, 2: 撤回) <br>
|
||||
*/
|
||||
@GetMapping(value = "/unusual-phone/approval")
|
||||
public Object unusualPhoneClockIn(@RequestParam(value = "taskId") String applyId, @RequestParam(value = "passed") String passed) throws Exception {
|
||||
|
||||
UserInfo userInfo = userProvider.get();
|
||||
ActionResult<Void> actionResult = new ActionResult<>();
|
||||
try {
|
||||
attendanceClockInService.approvalUnusualPhoneClockIn(applyId, passed, userInfo);
|
||||
} catch (Exception e) {
|
||||
actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
|
||||
actionResult.setMsg(e.getMessage());
|
||||
return actionResult;
|
||||
}
|
||||
actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
|
||||
actionResult.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
|
||||
return actionResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成用户补卡次数记录
|
||||
* @param tenantId 租户id
|
||||
* @param groupId 考勤组id
|
||||
* @param userId 用id
|
||||
* @param type 生成类型(1: 新增组成员, 2: 借调到新组)
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/generateRepairNum/{tenantId}")
|
||||
@NoDataSourceBind
|
||||
public Object generateRepairNumForUser(@PathVariable(value = "tenantId") String tenantId, @RequestParam String groupId, @RequestParam String userId, @RequestParam Integer type) {
|
||||
|
||||
customTenantUtil.checkOutTenant(tenantId);
|
||||
boolean b = attendanceClockInService.generateRepairNumForUser(groupId, userId, type);
|
||||
return ActionResult.success(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描是否有未执行的班次变更任务
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/daily-rule-change/execute")
|
||||
public Boolean dailyRuleChangeExecute() {
|
||||
|
||||
return dailyRuleChangeService.dailyRuleChangeExecute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 补卡
|
||||
* @param applyId 审批id
|
||||
* @param passed 是否通过(0: 否, 1: 是, 2: 撤回)
|
||||
*/
|
||||
@GetMapping(value = "/repair")
|
||||
public ActionResult<Void> repairClockIn(@RequestParam(value = "taskId") String applyId, @RequestParam(value = "passed") String passed) {
|
||||
|
||||
log.error("补卡入参 -> applyId: {}, passed: {}", applyId, passed);
|
||||
UserInfo userInfo = userProvider.get();
|
||||
String approveUserId = userInfo.getUserId();
|
||||
ActionResult<Void> actionResult = new ActionResult<>();
|
||||
try {
|
||||
attendanceClockInService.repairClockIn(applyId, passed, approveUserId, userInfo.getTenantId());
|
||||
} catch (Exception e) {
|
||||
actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
|
||||
actionResult.setMsg(e.getMessage());
|
||||
return actionResult;
|
||||
}
|
||||
actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
|
||||
actionResult.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
|
||||
return actionResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 出勤变更
|
||||
* @param tenantId 租户id
|
||||
* @param applyId 申请id
|
||||
* @param passed 是否通过(0: 否, 1: 是, 2: 撤回)
|
||||
*/
|
||||
@GetMapping(value = "/change")
|
||||
@NoDataSourceBind
|
||||
public void attendanceChange(@RequestParam(value = "tenantId") String tenantId, @RequestParam(value = "applyId") String applyId,
|
||||
@RequestParam(value = "passed") String passed, @RequestParam(value = "approveUserId") String approveUserId) throws Exception {
|
||||
|
||||
log.error("出勤变更 -> tenantId: {}, applyId: {}, passed: {}", tenantId, applyId, passed);
|
||||
customTenantUtil.checkOutTenant(tenantId, approveUserId);
|
||||
attendanceClockInService.attendanceChange(applyId, passed, approveUserId,tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 出勤变更(不审批)
|
||||
* @param noApprovalDto 出勤变更无需审批dto
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PutMapping(value = "/change/noApproval")
|
||||
public Object attendanceChangeNoApproval(@RequestBody @Valid NoApprovalDto noApprovalDto) throws Exception {
|
||||
|
||||
attendanceClockInService.attendanceChangeNoApproval(noApprovalDto.getClockInResultId(), noApprovalDto.getChangeType());
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 可选择的补卡列表
|
||||
* @param userId 用户id
|
||||
* @return jnpf.base.ActionResult<java.util.List<jnpf.model.attendance.vo.AbnormalClockInVo>>
|
||||
*/
|
||||
@GetMapping(value = "/repair/list/{userId}")
|
||||
public ActionResult<List<GroupRepairVo>> getRepairList(@PathVariable(value = "userId") String userId) throws Exception {
|
||||
|
||||
List<GroupRepairVo> list = attendanceClockInService.getRepairList(userId);
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行打卡旷工逻辑
|
||||
* @return java.lang.Boolean
|
||||
*/
|
||||
@Override
|
||||
@PostMapping(value = "/absenceRecord")
|
||||
public Boolean generateFtbAbsenceRecord(@RequestParam(value = "tenantId") String tenantId) {
|
||||
return attendanceClockInService.generateFtbAbsenceRecord(tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成打卡旷工任务
|
||||
* @return java.lang.Boolean
|
||||
*/
|
||||
@Override
|
||||
@PostMapping(value = "/absenceTask")
|
||||
public Boolean generateAbsenceTask(@RequestParam(value = "tenantId") String tenantId) {
|
||||
return attendanceClockInService.generateAbsenceTask(ConstantUtil.NUM_TRUE, tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成打卡提醒记录
|
||||
* @return java.lang.Boolean
|
||||
*/
|
||||
@Override
|
||||
@PostMapping(value = "/remindRecord")
|
||||
public Boolean generateBeforeWorkRemind(@RequestParam(value = "tenantId") String tenantId) {
|
||||
return attendanceClockInService.generateBeforeWorkRemind(tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成补卡次数
|
||||
* @param tenantId 租户id
|
||||
* @return java.lang.Boolean
|
||||
*/
|
||||
@Override
|
||||
@PostMapping(value = "/repairNum")
|
||||
public Boolean generateRepairNum(@RequestParam(value = "tenantId") String tenantId) {
|
||||
return attendanceClockInService.generateRepairNum();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判定连续动作(排班/旷工)
|
||||
* @param tenantId 租户id
|
||||
* @return java.lang.Boolean
|
||||
*/
|
||||
@Override
|
||||
@PostMapping(value = "/continuousCheck")
|
||||
public Boolean continuousCheck(@RequestParam(value = "tenantId") String tenantId) {
|
||||
return attendanceClockInService.continuousCheck(tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 临时调用
|
||||
* @return java.lang.Boolean
|
||||
*/
|
||||
@NoDataSourceBind
|
||||
@PostMapping(value = "/repairNum/all")
|
||||
public Boolean generateRepairNumAll(@RequestParam String tenantId) {
|
||||
customTenantUtil.checkOutTenant(tenantId);
|
||||
return attendanceClockInService.generateRepairNumAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 临时调用
|
||||
*/
|
||||
@PostMapping(value = "/test/{tenantId}")
|
||||
public void test(@PathVariable(value = "tenantId") String tenantId) {
|
||||
|
||||
attendanceClockInService.generateFtbAbsenceRecord(tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询每日出勤及打卡记录
|
||||
* @param userId 用户id
|
||||
* @param queryDate 查询日期
|
||||
* @param currentGroupId 当前考勤组
|
||||
* @return jnpf.base.ActionResult<java.util.List<jnpf.model.attendance.vo.MiniGroupVo>>
|
||||
*/
|
||||
@GetMapping(value = "/dailyClockInRecord")
|
||||
public ActionResult<List<MiniGroupVo>> getDailyClockInRecord(@RequestParam(value = "userId") String userId,
|
||||
@RequestParam(value = "queryDate") String queryDate,
|
||||
@RequestParam(value = "currentGroupId") String currentGroupId) {
|
||||
|
||||
List<MiniGroupVo> list = attendanceClockInService.getDailyClockInRecord(userId, queryDate, currentGroupId);
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询每日出勤及打卡记录 - v2
|
||||
* @param userId 用户id
|
||||
* @param queryDate 查询日期
|
||||
* @param currentGroupId 当前考勤组
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.DailyInfoVo>
|
||||
*/
|
||||
@GetMapping(value = "/dailyClockInRecord/v2")
|
||||
public ActionResult<DailyInfoVo> getDailyClockInRecordV2(@RequestParam(value = "userId") String userId,
|
||||
@RequestParam(value = "queryDate") String queryDate,
|
||||
@RequestParam(value = "currentGroupId") String currentGroupId,
|
||||
@RequestParam(value = "queryOldData", required = false) Integer queryOldData) throws QueryException {
|
||||
|
||||
queryOldData = null == queryOldData ? 0 : queryOldData;
|
||||
DailyInfoVo dailyInfoVo = attendanceClockInService.getDailyClockInRecordV2(userId, queryDate, currentGroupId, queryOldData);
|
||||
return ActionResult.success(dailyInfoVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询考勤组补卡规则
|
||||
* @param groupId 考勤组id
|
||||
* @return jnpf.base.ActionResult<java.lang.Boolean>
|
||||
*/
|
||||
@GetMapping(value = "/clockInRepair/rule/{groupId}")
|
||||
public ActionResult<RepairRuleVo> getClockInRepairRule(@PathVariable(value = "groupId") String groupId) {
|
||||
|
||||
RepairRuleVo rule = attendanceClockInService.getClockInRepairCheck(groupId);
|
||||
return ActionResult.success(rule);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jnpf.attendance.service.AttendanceClockInPicService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.entity.attendance.AttendanceClockInPic;
|
||||
import jnpf.model.attendance.vo.ClockInPicVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 打卡图片控制器
|
||||
*
|
||||
* @author shitou
|
||||
* @create 2024-10-30
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/clockIn/pic")
|
||||
public class AttendanceClockInPicController {
|
||||
|
||||
@Resource
|
||||
private AttendanceClockInPicService attendanceClockInPicService;
|
||||
|
||||
@Operation(summary = "查询外勤打卡图片列表")
|
||||
@GetMapping(value = "/list/{clockInId}")
|
||||
public ActionResult<List<ClockInPicVo>> getClockInPicList(@Valid @PathVariable("clockInId") String clockInId) {
|
||||
log.info("查询外勤打卡图片列表,入参=>{}", clockInId);
|
||||
long st = System.currentTimeMillis();
|
||||
List<ClockInPicVo> clockInPicList = attendanceClockInPicService.getClockInPicList(clockInId);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("查询外勤打卡图片列表,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(clockInPicList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jnpf.attendance.service.AttendanceCloudAlbumService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.model.attendance.dto.CloudAlbumBatchSaveDto;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤云相册
|
||||
*
|
||||
* @Description: 考勤云相册控制类
|
||||
* @Author: shiTou(他是小石头)
|
||||
* @Date: 2024-10-30 10:26
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/cloudAlbum")
|
||||
public class AttendanceCloudAlbumController {
|
||||
@Resource
|
||||
private AttendanceCloudAlbumService attendanceCloudAlbumService;
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "列表查询")
|
||||
@GetMapping("/getDataList")
|
||||
public ActionResult<List<String>> getDataList() {
|
||||
long st = System.currentTimeMillis();
|
||||
List<String> dataList = attendanceCloudAlbumService.getDataList();
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("列表查询,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(dataList);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "批量保存图片")
|
||||
@PostMapping("/batchSave")
|
||||
public ActionResult<Boolean> batchSave(@Valid @RequestBody CloudAlbumBatchSaveDto dto) {
|
||||
long st = System.currentTimeMillis();
|
||||
attendanceCloudAlbumService.batchSave(dto.getPicUrlList());
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("批量保存图片,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "获取登录用户水印")
|
||||
@GetMapping("/getUserWatermark")
|
||||
public ActionResult<String> getUserWatermark() {
|
||||
long st = System.currentTimeMillis();
|
||||
String watermark = attendanceCloudAlbumService.getUserWatermark();
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取登录用户水印,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success("获取成功",watermark);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jnpf.attendance.AttendanceConfirmApi;
|
||||
import jnpf.attendance.service.AttendanceConfirmService;
|
||||
import jnpf.attendance.service.AttendanceConfirmSettingService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.model.attendance.dto.ConfirmPageListDto;
|
||||
import jnpf.model.attendance.dto.ConfirmSettingSubmitDto;
|
||||
import jnpf.model.attendance.dto.ConfirmStatisticsDto;
|
||||
import jnpf.model.attendance.vo.attendance.ConfirmDetailsVo;
|
||||
import jnpf.model.attendance.vo.attendance.ConfirmPageListVo;
|
||||
import jnpf.model.attendance.vo.attendance.ConfirmSettingInfoVo;
|
||||
import jnpf.model.attendance.vo.attendance.ConfirmStatisticsVo;
|
||||
import jnpf.model.thousandsfaces.TodayWorkVo;
|
||||
import jnpf.util.FtbUtil;
|
||||
import jnpf.util.NoDataSourceBind;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤确认
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/confirm")
|
||||
public class AttendanceConfirmController implements AttendanceConfirmApi {
|
||||
@Resource
|
||||
private AttendanceConfirmService attendanceConfirmService;
|
||||
@Resource
|
||||
private AttendanceConfirmSettingService confirmSettingService;
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "获取考勤确认设置")
|
||||
@GetMapping(value = "/getConfirmSetting")
|
||||
public ActionResult<ConfirmSettingInfoVo> getConfirmSetting() {
|
||||
long st = System.currentTimeMillis();
|
||||
ConfirmSettingInfoVo result = confirmSettingService.getConfirmSetting(Boolean.TRUE);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取考勤确认设置,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "考勤确认设置提交")
|
||||
@PostMapping(value = "/confirmSettingSubmit")
|
||||
public ActionResult<Boolean> confirmSettingSubmit(@Valid @RequestBody ConfirmSettingSubmitDto dto) {
|
||||
log.info("考勤确认设置提交,入参=>{}", JSONObject.toJSON(dto));
|
||||
long st = System.currentTimeMillis();
|
||||
Boolean result = confirmSettingService.confirmSettingSubmit(dto);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("考勤确认设置提交,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "获取考勤月份")
|
||||
@GetMapping(value = "/getConfirmMonth")
|
||||
public ActionResult<String> getConfirmMonth() {
|
||||
long st = System.currentTimeMillis();
|
||||
String result = attendanceConfirmService.getConfirmMonth();
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取考勤月份,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success("获取成功", result);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "考勤确认聚合统计")
|
||||
@PostMapping(value = "/getStatistics")
|
||||
public ActionResult<ConfirmStatisticsVo> getStatistics(@Valid @RequestBody ConfirmStatisticsDto dto) {
|
||||
log.info("考勤确认聚合统计,入参=>{}", JSONObject.toJSON(dto));
|
||||
long st = System.currentTimeMillis();
|
||||
ConfirmStatisticsVo result = attendanceConfirmService.getStatistics(dto);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("考勤确认聚合统计,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "考勤确认列表展示")
|
||||
@PostMapping(value = "/getPageList")
|
||||
public ActionResult<PageListVO<ConfirmPageListVo>> getPageList(@Valid @RequestBody ConfirmPageListDto dto) {
|
||||
log.info("考勤确认列表展示,入参=>{}", JSONObject.toJSON(dto));
|
||||
long st = System.currentTimeMillis();
|
||||
PageInfo<ConfirmPageListVo> page = attendanceConfirmService.getPageList(dto);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("考勤确认列表展示,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "获取考勤确认详情")
|
||||
@GetMapping(value = "/getConfirmDetails/{id}")
|
||||
public ActionResult<ConfirmDetailsVo> getConfirmDetails(@PathVariable("id") String id) {
|
||||
log.info("获取考勤确认详情,入参=>{}", id);
|
||||
long st = System.currentTimeMillis();
|
||||
ConfirmDetailsVo result = attendanceConfirmService.getConfirmDetails(id);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取考勤确认详情,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@Operation(summary = "自动生成考勤确认数据")
|
||||
@GetMapping(value = "/autoConfirm")
|
||||
public ActionResult<Boolean> autoCreateConfirm() {
|
||||
long st = System.currentTimeMillis();
|
||||
boolean result = attendanceConfirmService.autoCreateConfirm();
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("自动生成考勤确认数据,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@Operation(summary = "逾期自动确认")
|
||||
@GetMapping(value = "/confirmAutoSlippage")
|
||||
public ActionResult<Boolean> confirmAutoSlippage() {
|
||||
long st = System.currentTimeMillis();
|
||||
boolean result = attendanceConfirmService.confirmAutoSlippage();
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("逾期自动确认,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "今日工作-考勤确认列表(0-待确认 1-已确认 2-已逾期)")
|
||||
@GetMapping(value = "/getTodayWorkConfirmList")
|
||||
public List<TodayWorkVo> getTodayWorkConfirmList() {
|
||||
long st = System.currentTimeMillis();
|
||||
List<TodayWorkVo> result = attendanceConfirmService.getTodayWorkConfirmList();
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取App考勤确认详情,耗时=>{}", ent - st + " 毫秒");
|
||||
return result;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "获取App考勤确认详情")
|
||||
@GetMapping(value = "/getAppConfirmDetails")
|
||||
public ActionResult<ConfirmDetailsVo> getAppConfirmDetails(@RequestParam(value = "id", required = false) String id) {
|
||||
long st = System.currentTimeMillis();
|
||||
ConfirmDetailsVo result = attendanceConfirmService.getAppConfirmDetails(id);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("获取App考勤确认详情,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "App温馨提示关闭")
|
||||
@GetMapping(value = "/tipsClos/{id}")
|
||||
public ActionResult<Boolean> tipsClos(@PathVariable("id") String id) {
|
||||
log.info("温馨提示关闭,入参=>{}", id);
|
||||
long st = System.currentTimeMillis();
|
||||
Boolean result = attendanceConfirmService.tipsClos(id);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("温馨提示关闭,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "App已查看")
|
||||
@GetMapping(value = "/look/{id}")
|
||||
public ActionResult<Boolean> look(@PathVariable("id") String id) {
|
||||
log.info("App已查看,入参=>{}", id);
|
||||
long st = System.currentTimeMillis();
|
||||
Boolean result = attendanceConfirmService.look(id);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("App已查看,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Operation(summary = "App考勤确认提交")
|
||||
@GetMapping(value = "/confirmDetailsSubmit/{id}")
|
||||
public ActionResult<Boolean> confirmDetailsSubmit(@PathVariable("id") String id) {
|
||||
log.info("App考勤确认提交,入参=>{}", id);
|
||||
long st = System.currentTimeMillis();
|
||||
Boolean result = attendanceConfirmService.confirmDetailsSubmit(id);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("App考勤确认提交,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jnpf.attendance.service.AttendanceCustomizeTableService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.model.attendance.vo.attendance.AttendanceCustomizeTableVo;
|
||||
import jnpf.model.attendance.vo.attendance.CustomizeTableUpdateVo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤统计WEB
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2024-09-03
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/attendance/customizeTable")
|
||||
public class AttendanceCustomizeTableController {
|
||||
@Autowired
|
||||
private AttendanceCustomizeTableService tableService;
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "自定义报表设置-列表查询")
|
||||
public ActionResult<List<AttendanceCustomizeTableVo>> findList(@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) Integer status,
|
||||
@RequestParam(required = false, defaultValue = "1") Integer type) {
|
||||
return ActionResult.success(tableService.findList(keyword, status, type));
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@Operation(summary = "自定义报表设置-设置")
|
||||
public ActionResult<Void> update(@Valid @RequestBody CustomizeTableUpdateVo tableVos) {
|
||||
tableService.update(tableVos);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jnpf.attendance.AttendanceDailyRuleApi;
|
||||
import jnpf.attendance.service.AttendanceDailyRuleService;
|
||||
import jnpf.attendance.service.AttendanceLeaveRulesService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.entity.attendance.ApplyParam;
|
||||
import jnpf.enums.attendance.AttendanceTypeEnum;
|
||||
import jnpf.enums.attendance.v2.ClockOutHandleParam;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.LineDrawingSchedulesConfigDto;
|
||||
import jnpf.model.attendance.dto.SchedulesImportDto;
|
||||
import jnpf.model.attendance.dto.SchedulesSetDto;
|
||||
import jnpf.model.attendance.dto.UnifiedSchedulesDto;
|
||||
import jnpf.model.attendance.dto.UserDayShiftQueryDto;
|
||||
import jnpf.model.attendance.vo.DayReceivableRevenueVo;
|
||||
import jnpf.model.attendance.vo.DayShiftRevenueStatVo;
|
||||
import jnpf.model.attendance.vo.ScheduleRuleDetailVo;
|
||||
import jnpf.model.attendance.vo.SchedulesV2Vo;
|
||||
import jnpf.model.attendance.vo.attendance.OvertimeRuleDetailVo;
|
||||
import jnpf.model.attendance.vo.LineSchedulesVo;
|
||||
import jnpf.model.attendance.vo.UserDayShiftInfoVo;
|
||||
import jnpf.util.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 排班规则
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2023-11-22
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/arranging/work")
|
||||
@Slf4j
|
||||
public class AttendanceDailyRuleController implements AttendanceDailyRuleApi {
|
||||
@Resource
|
||||
private CustomTenantUtil customTenantUtil;
|
||||
@Autowired
|
||||
private AttendanceDailyRuleService attendanceDailyRuleService;
|
||||
@Autowired
|
||||
private AttendanceLeaveRulesService attendanceLeaveRulesService;
|
||||
|
||||
/**
|
||||
* 根据指定条件查询某个群体在特定月份的调度情况
|
||||
*
|
||||
* @param groupId 群体ID,用于标识特定的群体
|
||||
* @param realName 真实姓名,用于筛选特定的个人
|
||||
* @param month 月份,格式为YYYY-MM,用于指定查询的时间范围
|
||||
* @param userIds 用户ID列表,用于限定查询的用户范围
|
||||
* @param isSchedules 是否仅查询已调度的记录,true表示仅查询已调度记录,false表示查询所有记录
|
||||
* @return 返回根据条件查询到的调度情况结果
|
||||
*/
|
||||
@GetMapping(value = "/schedulesExport")
|
||||
public ActionResult<Boolean> schedulesExport(@RequestParam String groupId, @RequestParam(required = false) String workGroupId, @RequestParam(required = false) String realName, @RequestParam String month, @RequestParam(required = false) List<String> userIds, @RequestParam(required = false, defaultValue = "1") Integer isSchedules) {
|
||||
attendanceDailyRuleService.schedulesExport(groupId, workGroupId, realName, month, userIds, isSchedules);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 划线排班导出
|
||||
*
|
||||
* @param groupId 考勤组id
|
||||
* @param workGroupId 班组ID
|
||||
* @param month 月份
|
||||
* @param userIdList 用户ID列表
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/lineSchedulesExport")
|
||||
public ActionResult<Boolean> lineSchedulesExport(@RequestParam String groupId, @RequestParam(required = false) String workGroupId, @RequestParam String month, @RequestParam(required = false) List<String> userIdList) {
|
||||
attendanceDailyRuleService.lineSchedulesExport(groupId, workGroupId, month, userIdList);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 排班导入
|
||||
*
|
||||
* @param schedulesImportDto 参数
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/schedulesImport")
|
||||
public ActionResult<List<SchedulesV2Vo>> schedulesImport(@RequestBody SchedulesImportDto schedulesImportDto) throws IOException {
|
||||
return ActionResult.success(attendanceDailyRuleService.schedulesImport(schedulesImportDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 划线排班导入
|
||||
*
|
||||
* @param schedulesImportDto 参数
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/lineSchedulesImport")
|
||||
public ActionResult lineSchedulesImport(@RequestBody SchedulesImportDto schedulesImportDto) throws IOException {
|
||||
attendanceDailyRuleService.lineSchedulesImport(schedulesImportDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 晚走晚到
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/clockOutHandle")
|
||||
public ActionResult clockOutHandle(@RequestParam String userId, @RequestParam String tenantId, @RequestParam String clockOut, @RequestParam String clockInTime) {
|
||||
ClockOutHandleParam param = new ClockOutHandleParam();
|
||||
param.setUserId(userId);
|
||||
param.setTenantId(tenantId);
|
||||
param.setAttendanceType(AttendanceTypeEnum.ORDINARY.getCode());
|
||||
param.setStart(DateUtil.stringToDate(clockOut));
|
||||
param.setEnd(DateUtil.stringToDate(clockInTime));
|
||||
param.setApplyId("");
|
||||
param.setRuleId("");
|
||||
param.setDay(new Date());
|
||||
OvertimeRuleDetailVo overtimeRuleDetailVo = new OvertimeRuleDetailVo();
|
||||
overtimeRuleDetailVo.setOvertimeType(1);
|
||||
overtimeRuleDetailVo.setMinOvertimeMinute(30);
|
||||
overtimeRuleDetailVo.setEnabled(1);
|
||||
overtimeRuleDetailVo.setCalcMethod(3);
|
||||
overtimeRuleDetailVo.setTimeUnit(1);
|
||||
overtimeRuleDetailVo.setCompensateRatio(BigDecimal.ONE);
|
||||
overtimeRuleDetailVo.setCompensateType(1);
|
||||
param.setRuleDetail(overtimeRuleDetailVo);
|
||||
attendanceDailyRuleService.workOvertimeNotApprove(param);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排班列表V2版本。
|
||||
*
|
||||
* @param groupId 考勤组id
|
||||
* @param workGroupId 班组ID
|
||||
* @param realName 真实姓名(可选)
|
||||
* @param month 月份
|
||||
* @param userIds 用户ID列表(可选)
|
||||
* @param isSchedules 是否排班标识(可选,默认值为1)
|
||||
* @return 排班列表V2版本视图对象
|
||||
*/
|
||||
@GetMapping("v2")
|
||||
public ActionResult<List<SchedulesV2Vo>> getSchedulesListV2(@RequestParam String groupId, @RequestParam(required = false) String workGroupId, @RequestParam(required = false) String realName, @RequestParam String month, @RequestParam(required = false) List<String> userIds, @RequestParam(required = false, defaultValue = "1") Integer isSchedules) {
|
||||
return ActionResult.success(attendanceDailyRuleService.getSchedulesListV2(groupId, workGroupId, realName, month, userIds, isSchedules));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排班列表 V2(按开始日期、结束日期,其它参数与 v2 一致)
|
||||
*/
|
||||
@GetMapping("v2/range")
|
||||
public ActionResult<List<SchedulesV2Vo>> getSchedulesListV2ByDateRange(@RequestParam String groupId, @RequestParam(required = false) String workGroupId, @RequestParam(required = false) String realName, @RequestParam String startDate, @RequestParam String endDate, @RequestParam(required = false) List<String> userIds, @RequestParam(required = false, defaultValue = "1") Integer isSchedules) {
|
||||
return ActionResult.success(attendanceDailyRuleService.getSchedulesListV2ByDateRange(groupId, workGroupId, realName, startDate, endDate, userIds, isSchedules));
|
||||
}
|
||||
|
||||
/**
|
||||
* 预排班草稿转排班列表 V2(按员工 + 日期区间);草稿 Redis 不存在时返回空列表。
|
||||
*/
|
||||
@GetMapping("v2/preSchedule/draft")
|
||||
public ActionResult<List<SchedulesV2Vo>> getSchedulesListV2ByPreScheduleDraft(
|
||||
@RequestParam String groupId,
|
||||
@RequestParam String startDate,
|
||||
@RequestParam String endDate,
|
||||
@RequestParam String draftId) {
|
||||
return ActionResult.success(
|
||||
attendanceDailyRuleService.getSchedulesListV2ByPreScheduleDraft(
|
||||
groupId, startDate, endDate, draftId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取排班规则详情。
|
||||
*
|
||||
* @param id 排班规则ID
|
||||
* @return 排班规则详情视图对象
|
||||
* @throws HandleException 处理异常
|
||||
*/
|
||||
@GetMapping("{id}")
|
||||
public ActionResult<ScheduleRuleDetailVo> getSchedulesList(@PathVariable String id) throws HandleException {
|
||||
return ActionResult.success(attendanceDailyRuleService.getDetail(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置排班。
|
||||
*
|
||||
* @param schedulesSets 排班设置列表
|
||||
* @return 处理结果字符串
|
||||
* @throws HandleException 处理异常
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult<String> setSchedules(@RequestBody List<SchedulesSetDto> schedulesSets) throws HandleException {
|
||||
return ActionResult.success(attendanceDailyRuleService.setSchedules(schedulesSets));
|
||||
}
|
||||
|
||||
/**
|
||||
* 自己排班调整排班
|
||||
*
|
||||
* @param shiftId 班次id
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/selfSchedules")
|
||||
public ActionResult<String> setSchedulesForSelfSchedules(@RequestParam("shiftId") String shiftId) throws HandleException {
|
||||
return ActionResult.success(attendanceDailyRuleService.setSchedulesForSelfSchedules(shiftId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 定时执行初始化下个月固定排班。
|
||||
*/
|
||||
@PostMapping("initFixedScheduleRule")
|
||||
public ActionResult initFixedScheduleRule(@RequestParam("tenantId") String tenantId) {
|
||||
attendanceDailyRuleService.initFixedScheduleRule(tenantId);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理日常规则申请。
|
||||
*
|
||||
* @param applyParam 申请参数类
|
||||
* @return 处理结果字符串
|
||||
* @throws HandleException 处理异常
|
||||
*/
|
||||
@PostMapping("applyDailyRuleHandle")
|
||||
public ActionResult applyDailyRuleHandle(@RequestBody ApplyParam applyParam) throws HandleException {
|
||||
return ActionResult.success(attendanceDailyRuleService.applyDailyRuleHandle(applyParam));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理借调申请日规则。
|
||||
*
|
||||
* @param userId 借调用户ID
|
||||
* @param fromGroupId 原考勤组ID
|
||||
* @param toGroupId 借调考勤组ID
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
* @param departureTime 离岗时间
|
||||
* @param backTime 回岗时间
|
||||
* @return 处理结果视图对象
|
||||
* @throws HandleException 处理异常
|
||||
*/
|
||||
@PostMapping("secondmentDailyRuleHandle")
|
||||
public ActionResult secondmentDailyRuleHandle(@RequestParam String userId, @RequestParam String fromGroupId, @RequestParam String toGroupId, @RequestParam String start, @RequestParam String end, @RequestParam String departureTime, @RequestParam String backTime) throws HandleException {
|
||||
return ActionResult.success(attendanceDailyRuleService.secondmentDailyRuleHandle(CollUtil.newArrayList(userId), fromGroupId, toGroupId, DateDetail.getStr2DateTime(start), DateDetail.getStr2DateTime(end), DateDetail.getStr2DateTime(departureTime), DateDetail.getStr2DateTime(backTime), "yawentest2"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动授予假期余额。
|
||||
*
|
||||
* @param tenantId 租户ID
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PostMapping("autoGrantBalance")
|
||||
public ActionResult autoGrantBalance(@RequestParam("tenantId") String tenantId) {
|
||||
// 2.0 节日不发劵了
|
||||
// attendanceFestivalSettingService.autoGrantBalance();
|
||||
// 需要修改
|
||||
// attendanceHolidaySettingService.autoGrantBalance(tenantId);
|
||||
attendanceLeaveRulesService.autoGrantBalance(tenantId);
|
||||
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户是否排班
|
||||
*
|
||||
* @param tenantId 租户ID
|
||||
* @param userId 用户ID
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@NoDataSourceBind
|
||||
@GetMapping("userIsScheduling")
|
||||
public ActionResult<Boolean> userIsScheduling(@RequestParam("tenantId") String tenantId, @RequestParam("userId") String userId) {
|
||||
customTenantUtil.checkOutTenant(tenantId);
|
||||
return ActionResult.success(attendanceDailyRuleService.userIsScheduling(userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户是否排班
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("userIsSchedulingOrdinary")
|
||||
@Override
|
||||
public ActionResult<List<String>> userIsSchedulingOrdinary(@RequestBody List<String> organizeIds) {
|
||||
return ActionResult.success(attendanceDailyRuleService.userIsSchedulingOrdinary(organizeIds));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param userId
|
||||
* @param start
|
||||
* @param end
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("hasRuleByUserIdAndTime")
|
||||
@Override
|
||||
public ActionResult<Boolean> hasRuleByUserIdAndTime(@RequestParam String userId, @RequestParam Date start, @RequestParam Date end) {
|
||||
return ActionResult.success(attendanceDailyRuleService.hasRuleByUserIdAndTime(userId, start, end));
|
||||
}
|
||||
/**
|
||||
* 设置划线排班
|
||||
*
|
||||
* @param configDto 划线排班配置DTO
|
||||
* @return 处理结果
|
||||
* @throws HandleException 处理异常
|
||||
*/
|
||||
@PostMapping("lineDrawingSchedules")
|
||||
public ActionResult<String> setLineDrawingSchedules(@RequestBody LineDrawingSchedulesConfigDto configDto) throws HandleException {
|
||||
return ActionResult.success(attendanceDailyRuleService.setLineDrawingSchedules(configDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一排班接口(支持固定排班和划线排班)
|
||||
*
|
||||
* @param dto 统一排班DTO
|
||||
* @return 处理结果
|
||||
* @throws HandleException 处理异常
|
||||
*/
|
||||
@PostMapping("unifiedSchedules")
|
||||
public ActionResult<String> setUnifiedSchedules(@RequestBody UnifiedSchedulesDto dto) throws HandleException {
|
||||
return ActionResult.success(attendanceDailyRuleService.setUnifiedSchedules(dto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定用户日期是否存在划线排班
|
||||
*
|
||||
* @param configDto 划线排班配置DTO
|
||||
* @return 处理结果
|
||||
*/
|
||||
@PostMapping("queryLineSchedulingExist")
|
||||
public ActionResult<Boolean> queryLineSchedulingExist(@RequestBody LineDrawingSchedulesConfigDto configDto) {
|
||||
return ActionResult.success(attendanceDailyRuleService.queryLineSchedulingExist(configDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取划线排班列表
|
||||
*
|
||||
* @param groupId 考勤组id
|
||||
* @param workGroupId 班组ID
|
||||
* @param dayList 日期列表
|
||||
* @param finalUserIdList 用户ID列表
|
||||
* @return 划线排班列表
|
||||
*/
|
||||
@GetMapping("getLineSchedulesList")
|
||||
public ActionResult<List<LineSchedulesVo>> getLineSchedulesList(@RequestParam String groupId, @RequestParam(required = false) String workGroupId, @RequestParam(required = false) String dayList, @RequestParam(required = false) List<String> finalUserIdList) {
|
||||
return ActionResult.success(attendanceDailyRuleService.getLineSchedulesList(groupId, workGroupId, Arrays.asList(StringUtil.split(dayList, ",")), finalUserIdList));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定用户指定日期的班次信息,包含有效请假及普班
|
||||
*
|
||||
* @param queryDto 查询参数(用户ID、查询日期)
|
||||
* @return 用户指定日期的班次信息
|
||||
*/
|
||||
/**
|
||||
* 按自然日查询考勤组所属门店营业额预估
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @param startTime 开始日期(含),yyyy-MM-dd
|
||||
* @param endTime 结束日期(含),yyyy-MM-dd
|
||||
*/
|
||||
@Operation(summary = "按自然日查询考勤组营业额预估")
|
||||
@GetMapping("/group-receivable-revenue-by-day")
|
||||
public ActionResult<List<DayReceivableRevenueVo>> listReceivableRevenueByDay(
|
||||
@RequestParam String groupId,
|
||||
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime,
|
||||
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date endTime) {
|
||||
return ActionResult.success(attendanceDailyRuleService.listReceivableRevenueByDay(groupId, startTime, endTime));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询指定用户指定日期的班次信息")
|
||||
@PostMapping("/user-day-shift-info")
|
||||
public ActionResult<UserDayShiftInfoVo> getUserDayShiftInfo(@Valid @RequestBody UserDayShiftQueryDto queryDto) {
|
||||
try {
|
||||
log.info("查询用户指定日期班次信息,userId=>{}, queryDate=>{}",
|
||||
queryDto.getUserId(), DateUtil.dateToString(queryDto.getQueryDate(), "yyyy-MM-dd"));
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
UserDayShiftInfoVo result = attendanceDailyRuleService.getUserDayShiftInfo(
|
||||
queryDto.getUserId(),
|
||||
queryDto.getQueryDate());
|
||||
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("查询用户指定日期班次信息完成,耗时=>{} 毫秒", ent - st);
|
||||
return ActionResult.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("查询用户指定日期班次信息异常", e);
|
||||
return ActionResult.fail("查询失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.attendance.service.AttendanceFestivalRulesService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.model.attendance.dto.AttendanceFestivalRulesDto;
|
||||
import jnpf.model.attendance.dto.FestivalRulesQueryDto;
|
||||
import jnpf.model.attendance.vo.attendance.AttendanceFestivalRulesVo;
|
||||
import jnpf.util.FtbUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
/**
|
||||
* 节日规则
|
||||
*
|
||||
* @author 盼盼
|
||||
* @create 2025-09-18
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/festival-rules")
|
||||
@Slf4j
|
||||
public class AttendanceFestivalRulesController {
|
||||
|
||||
@Autowired
|
||||
private AttendanceFestivalRulesService attendanceFestivalRulesService;
|
||||
|
||||
|
||||
/**
|
||||
* 获取考勤节日管理列表
|
||||
* @param queryDto 节日名称模糊查询非必传及年份筛选必传
|
||||
*/
|
||||
@PostMapping("/list")
|
||||
public ActionResult<PageListVO<AttendanceFestivalRulesVo>> list(@RequestBody FestivalRulesQueryDto queryDto) {
|
||||
PageInfo<AttendanceFestivalRulesVo> vo = attendanceFestivalRulesService.getPageList(queryDto);
|
||||
return ActionResult.page(vo.getList(), FtbUtil.getPagination(vo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增节日
|
||||
* @param festivalRulesDto 节日
|
||||
*/
|
||||
@PostMapping()
|
||||
public ActionResult<Void> add(@RequestBody AttendanceFestivalRulesDto festivalRulesDto) throws Exception {
|
||||
attendanceFestivalRulesService.add(festivalRulesDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新法定节假日信息。
|
||||
*
|
||||
* @param year 年份
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PutMapping("statutoryUpdate")
|
||||
public ActionResult statutoryUpdate(@RequestParam String year) {
|
||||
attendanceFestivalRulesService.statutoryUpdate(year);
|
||||
return ActionResult.success();
|
||||
}
|
||||
/**
|
||||
* 修改节日
|
||||
* @param festivalRulesDto 节日
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
public ActionResult<Void> put(@PathVariable("id") String id, @RequestBody AttendanceFestivalRulesDto festivalRulesDto) throws Exception {
|
||||
festivalRulesDto.setId( id);
|
||||
attendanceFestivalRulesService.update(festivalRulesDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节日详情
|
||||
* @param id 节日 ID
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public ActionResult<AttendanceFestivalRulesVo> detail(@PathVariable("id") String id) {
|
||||
return ActionResult.success(attendanceFestivalRulesService.detail(id));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除节日
|
||||
* @param id 节日 ID
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public ActionResult<Void> delete(@PathVariable("id") String id) {
|
||||
attendanceFestivalRulesService.delete(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用、停用节日
|
||||
* @param festivalRulesDto 节日
|
||||
*/
|
||||
@PutMapping("/updateState")
|
||||
public ActionResult<Void> updateState( @RequestBody AttendanceFestivalRulesDto festivalRulesDto) {
|
||||
attendanceFestivalRulesService.updateState(festivalRulesDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
|
||||
import jnpf.attendance.service.AttendanceFestivalSettingService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.AttendanceFestivalSettingDto;
|
||||
import jnpf.model.attendance.dto.EnableUpdateDto;
|
||||
import jnpf.model.attendance.vo.AttendanceFestivalSettingVo;
|
||||
import jnpf.model.attendance.vo.HolidayOptionVo;
|
||||
import jnpf.util.PageUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤配置-节日配置 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2023-11-29
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/festival/setting")
|
||||
public class AttendanceFestivalSettingController {
|
||||
@Autowired
|
||||
private AttendanceFestivalSettingService attendanceFestivalSettingService;
|
||||
/**
|
||||
* 保存节假日设置信息。
|
||||
*
|
||||
* @param attendanceFestivalSettingDto 节假日设置数据传输对象
|
||||
* @throws HandleException 处理异常
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult save(@RequestBody AttendanceFestivalSettingDto attendanceFestivalSettingDto) throws HandleException {
|
||||
attendanceFestivalSettingService.save(attendanceFestivalSettingDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询节假日设置信息。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @param year 年份(可选)
|
||||
* @param currentPage 当前页码
|
||||
* @param pageSize 每页大小
|
||||
* @return 分页的节假日设置视图对象列表
|
||||
* @throws HandleException 处理异常
|
||||
*/
|
||||
@GetMapping
|
||||
public ActionResult<PageListVO<AttendanceFestivalSettingVo>> page(@RequestParam String groupId, @RequestParam(required = false) String year, @RequestParam Integer currentPage, @RequestParam Integer pageSize) throws HandleException {
|
||||
PageDTO<AttendanceFestivalSettingVo> page1 = attendanceFestivalSettingService.page(groupId, year, currentPage, pageSize);
|
||||
return ActionResult.page(page1.getRecords(), PageUtil.page(page1));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取单个节假日设置信息。
|
||||
*
|
||||
* @param id 节假日设置ID
|
||||
* @return 节假日设置视图对象
|
||||
*/
|
||||
@GetMapping("{id}")
|
||||
public ActionResult<AttendanceFestivalSettingVo> getOne(@PathVariable String id) {
|
||||
return ActionResult.success(attendanceFestivalSettingService.getOne(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定的节假日设置信息。
|
||||
*
|
||||
* @param id 节假日设置ID
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@DeleteMapping("{id}")
|
||||
public ActionResult del(@PathVariable String id) {
|
||||
attendanceFestivalSettingService.del(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改节假日设置信息的启用状态。
|
||||
*
|
||||
* @param enableUpdateDto 启用状态更新数据传输对象
|
||||
* @throws HandleException 处理异常
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PutMapping("updateStatus")
|
||||
public ActionResult updateStatus(@RequestBody EnableUpdateDto enableUpdateDto) throws HandleException {
|
||||
attendanceFestivalSettingService.updateStatus(enableUpdateDto.getId(), enableUpdateDto.getEnable());
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新法定节假日信息。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @param year 年份
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PutMapping("statutoryUpdate")
|
||||
public ActionResult statutoryUpdate(@RequestParam String groupId, @RequestParam String year) {
|
||||
attendanceFestivalSettingService.statutoryUpdate(groupId, year);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节假日选项列表。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @return 节假日选项视图对象列表
|
||||
*/
|
||||
@GetMapping("options")
|
||||
public ActionResult<List<HolidayOptionVo>> getHolidayOptions(@RequestParam String groupId) {
|
||||
return ActionResult.success(attendanceFestivalSettingService.getHolidayOptions(groupId));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,615 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import jnpf.attendance.AttendanceGroupApi;
|
||||
import jnpf.attendance.dto.AttendanceUserGroupVo;
|
||||
import jnpf.attendance.dto.AttendanceUserListGroupVO;
|
||||
import jnpf.attendance.service.AttendanceGroupService;
|
||||
import jnpf.attendance.service.AttendanceUserService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.entity.AttendanceGroup;
|
||||
import jnpf.entity.AttendanceGroupUser;
|
||||
import jnpf.entity.attendance.AppointPermission;
|
||||
import jnpf.enums.attendance.GroupUserTypeEnum;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.*;
|
||||
import jnpf.model.attendance.vo.*;
|
||||
import jnpf.model.attendance.vo.attendance.GroupLockVo;
|
||||
import jnpf.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 考勤组控制器
|
||||
*
|
||||
* @author yier
|
||||
* @create 2023-11-21
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/group")
|
||||
public class AttendanceGroupController implements AttendanceGroupApi {
|
||||
@Resource
|
||||
private AttendanceUserService attendanceUserService;
|
||||
@Resource
|
||||
private AttendanceGroupService attendanceGroupService;
|
||||
|
||||
/**
|
||||
* 查询考勤组管理列表
|
||||
*
|
||||
* @param groupQueryDto 考勤组名称查询实体
|
||||
* @return List<AttendanceGroupVo>
|
||||
*/
|
||||
@GetMapping
|
||||
public ActionResult<List<AttendanceGroupVo>> list(GroupQueryDto groupQueryDto) {
|
||||
return ActionResult.success(attendanceGroupService.groupManagerList(groupQueryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增考勤组
|
||||
*
|
||||
* @param saveAttendanceGroupDto 考勤组保存实体
|
||||
* @return ActionResult<Void>
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult<Void> add(@RequestBody SaveAttendanceGroupDto saveAttendanceGroupDto) throws Exception {
|
||||
ParamUtil.checkParam(saveAttendanceGroupDto);
|
||||
int num = attendanceGroupService.save(saveAttendanceGroupDto);
|
||||
if (num < 0) {
|
||||
return ActionResult.fail("考勤组名称重复,请换一个名称!");
|
||||
}
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改考勤组信息
|
||||
*
|
||||
* @param saveAttendanceGroupDto 考勤组保存实体
|
||||
* @return Void
|
||||
*/
|
||||
@PutMapping
|
||||
public ActionResult<Void> update(@RequestBody SaveAttendanceGroupDto saveAttendanceGroupDto) throws Exception {
|
||||
ParamUtil.checkParam(saveAttendanceGroupDto);
|
||||
int num = attendanceGroupService.save(saveAttendanceGroupDto);
|
||||
if (num < 0) {
|
||||
return ActionResult.fail("考勤组名称重复,请换一个名称!");
|
||||
}
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除考勤组
|
||||
*
|
||||
* @param saveAttendanceGroupDto 考勤组保存实体
|
||||
* @return Void
|
||||
*/
|
||||
@DeleteMapping("/deleteGroup")
|
||||
public ActionResult<Void> delete(@RequestBody SaveAttendanceGroupDto saveAttendanceGroupDto) throws HandleException {
|
||||
/*移动考勤组*/
|
||||
String parentId = saveAttendanceGroupDto.getParentId();
|
||||
if (StrUtil.isNotBlank(parentId)) {
|
||||
AttendanceGroup moveGroup = attendanceGroupService.getById(parentId);
|
||||
if (moveGroup.getLevelCode().contains(saveAttendanceGroupDto.getId())) {
|
||||
throw new HandleException("不能将删除考勤组移动到本组获取子组!");
|
||||
}
|
||||
}
|
||||
|
||||
String id = saveAttendanceGroupDto.getId();
|
||||
AttendanceGroup group = attendanceGroupService.getById(id);
|
||||
if (group.getDeleteMark() == 1) {
|
||||
throw new HandleException("该考勤组已删除,请勿频繁操作!");
|
||||
}
|
||||
|
||||
attendanceGroupService.delete(saveAttendanceGroupDto.getId(), saveAttendanceGroupDto.getParentId());
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 借调时展示我能查看到的考勤组列表
|
||||
*
|
||||
* @return ActionResult<List < AttendanceGroupVo>>
|
||||
*/
|
||||
@GetMapping("/secondedQueryGroup")
|
||||
public ActionResult<List<AttendanceGroupVo>> queryManagerGroupList(String keyword) {
|
||||
List<AttendanceGroupVo> attendanceGroupVoList = attendanceGroupService.queryManagerGroupList(keyword);
|
||||
return ActionResult.success(attendanceGroupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有考勤组
|
||||
*/
|
||||
@GetMapping("/getAllGroup")
|
||||
public ActionResult<List<AttendanceGroupVo>> getAllGroup(String keyword) {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.queryList(keyword);
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据考勤组名称模糊查询考勤组列表(带权限控制)
|
||||
* 返回用户有管理权限的考勤组,支持名称模糊查询
|
||||
*
|
||||
* @param groupName 考勤组名称(支持模糊查询)
|
||||
* @return ActionResult<List<AttendanceGroupVo>>
|
||||
*/
|
||||
@GetMapping("/searchByName")
|
||||
public ActionResult<List<AttendanceGroupVo>> searchGroupByName(@RequestParam String groupName) {
|
||||
return ActionResult.success(attendanceGroupService.searchGroupByName(groupName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询我所在的考勤组列表(In:app/考勤规则)
|
||||
*
|
||||
* @return ActionResult<List < AttendanceGroupVo>>
|
||||
*/
|
||||
@GetMapping("/queryMyGroupList")
|
||||
public ActionResult<List<AttendanceGroup>> queryMyGroupList() {
|
||||
List<AttendanceGroup> groupList = attendanceGroupService.queryMyGroups();
|
||||
return ActionResult.success(groupList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询考勤组下成员
|
||||
*
|
||||
* @param id 考勤组id
|
||||
* @return ActionResult<List < AttendanceGroupUserVo>>
|
||||
*/
|
||||
@GetMapping("/{id}/userList")
|
||||
public ActionResult<List<AttendanceGroupUserVo>> queryUserList(@PathVariable String id, String name, Integer type, String month) {
|
||||
Date start = DateDetail.getMonthBeginDate(month);
|
||||
Date end = DateDetail.getMonthEndDate(month);
|
||||
return ActionResult.success(attendanceUserService.queryUsersByGroupId(id, name, type, null, start,end));
|
||||
}
|
||||
|
||||
/**
|
||||
* 借调查询考勤组下成员
|
||||
*
|
||||
* @param id 考勤组id
|
||||
* @return ActionResult<List < AttendanceGroupUserVo>>
|
||||
*/
|
||||
@GetMapping("/userList")
|
||||
public ActionResult<List<AttendanceGroupUserVo>> queryUserListOfSecondment(@RequestParam String id, @RequestParam(required = false) String name, @RequestParam(required = false) Integer type, @RequestParam(required = false) String time) {
|
||||
Assert.isFalse(StringUtil.isBlank(time), "未选择借调时间");
|
||||
String[] split = StringUtil.split(time, ",");
|
||||
Assert.isFalse(split.length < 2, "未选择借调时间");
|
||||
Date secondedStartTime = new Date(Long.parseLong(split[0]));
|
||||
Date secondedEndTime = new Date(Long.parseLong(split[1]));
|
||||
List<AttendanceGroupUserVo> listActionResult = attendanceUserService.queryUsersByGroupId(id, name, type,null, secondedStartTime, secondedEndTime);
|
||||
if (listActionResult!= null) {
|
||||
listActionResult.forEach(v -> {
|
||||
v.setRealName(v.getRealName() + "(" + v.getPositionName() + ")");
|
||||
});
|
||||
}
|
||||
return ActionResult.success(listActionResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 考勤组下拉列表
|
||||
*
|
||||
* @return ActionResult<List < AttendanceGroup>>
|
||||
*/
|
||||
@GetMapping("/dropList")
|
||||
public ActionResult<List<AttendanceGroup>> dropList() {
|
||||
List<AttendanceGroup> dropList = attendanceGroupService.queryDropList();
|
||||
return ActionResult.success(dropList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 借调开始
|
||||
*
|
||||
* @param attendanceSecondedDto 借调参数数据
|
||||
* @return ActionResult<Void>
|
||||
*/
|
||||
@PostMapping("/secondedStart")
|
||||
public ActionResult<Void> secondedStart(@RequestBody AttendanceSecondedDto attendanceSecondedDto) throws HandleException {
|
||||
attendanceGroupService.secondedStart(attendanceSecondedDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换考勤组配置状态
|
||||
*
|
||||
* @param dto 考勤组配置状态参数
|
||||
* @return ActionResult<Void>
|
||||
*/
|
||||
@PutMapping("/exchangeGroupStatus")
|
||||
public ActionResult<Void> exchangeGroupStatus(@RequestBody AttendanceGroupStatusDto dto) {
|
||||
attendanceGroupService.exchangeGroupStatus(dto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考勤组配置状态
|
||||
*
|
||||
* @param groupId 考勤组id
|
||||
* @return ActionResult<Void>
|
||||
*/
|
||||
@GetMapping("groupSettingStatus")
|
||||
public ActionResult<AttendanceGroupStatusDto> groupSettingStatus(@RequestParam String groupId) {
|
||||
return ActionResult.success(attendanceGroupService.groupSettingStatus(groupId, Boolean.FALSE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认考勤组
|
||||
*
|
||||
* @return ActionResult<AttendanceGroup>
|
||||
*/
|
||||
@GetMapping("/getDefaultGroup")
|
||||
public ActionResult<AttendanceGroupVo> getDefaultGroup() {
|
||||
AttendanceGroupVo defaultGroup = attendanceGroupService.getDefaultGroup();
|
||||
return ActionResult.success(defaultGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换考勤组
|
||||
*
|
||||
* @param groupId 考勤组Id
|
||||
* @return ActionResult<Void>
|
||||
*/
|
||||
@GetMapping("/handoffGroup")
|
||||
public ActionResult<Void> handoffGroup(String groupId) {
|
||||
attendanceGroupService.handoffGroup(groupId);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 排班考勤组列表
|
||||
*
|
||||
* @return ActionResult<AttendanceGroupVo>
|
||||
*/
|
||||
@GetMapping("/schedulingGroupList")
|
||||
public ActionResult<List<AttendanceGroupVo>> schedulingGroupList() {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.schedulingGroupList();
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 排班考勤组列表过滤固定班
|
||||
*
|
||||
* @return ActionResult<AttendanceGroupVo>
|
||||
*/
|
||||
@GetMapping("/schedulingGroupListByNotFixed")
|
||||
public ActionResult<List<AttendanceGroupVo>> schedulingGroupListByNotFixed() {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.schedulingGroupListByNotFixed();
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 余额考勤组列表
|
||||
*
|
||||
* @return ActionResult<AttendanceGroupVo>
|
||||
*/
|
||||
@GetMapping("/balanceManagementGroupList")
|
||||
public ActionResult<List<AttendanceGroupVo>> balanceManagementGroupList() {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.balanceManagement();
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询我有借调权限的考勤组管理列表
|
||||
*
|
||||
*/
|
||||
@GetMapping("/querySecondedApprovalGroupList")
|
||||
public ActionResult<List<AttendanceGroupVo>> querySecondedApprovalGroupList() {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.secondedApprovalGroupList();
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换考勤组查询我管理的考勤组
|
||||
*
|
||||
*/
|
||||
@GetMapping("/handoffGroupTreeList")
|
||||
public ActionResult<List<AttendanceGroupVo>> handoffGroupTreeList() {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.handoffGroupTreeList();
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过组织Id找到组织下的考勤组
|
||||
*
|
||||
* @param orgId 组织Id
|
||||
*/
|
||||
@GetMapping("/groupListByOrgId/{orgId}")
|
||||
public ActionResult<List<AttendanceGroupVo>> groupListByOrgId(@PathVariable("orgId") String orgId) {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.groupListByOrgId(orgId);
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过组织Id找到组织下的考勤组
|
||||
*
|
||||
* @param orgId 组织Id
|
||||
*/
|
||||
@GetMapping("/groupListByOrgId")
|
||||
public ActionResult<List<AttendanceGroupVo>> groupListByOrgIds(@RequestParam("orgId") String orgId) {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.groupListByOrgId(orgId);
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过考勤组Id获取绑定的组织名称(拼接好的)及考勤组人数
|
||||
*
|
||||
* @param groupId 考勤组Id
|
||||
*/
|
||||
@GetMapping("/getGroupBindingOrg/{groupId}")
|
||||
public ActionResult<AttendanceGroupVo> getGroupBindingOrg(@PathVariable("groupId") String groupId,@RequestParam(value = "workGroupId",required = false) String workGroupId) {
|
||||
return ActionResult.success(attendanceGroupService.getGroupBindingOrg(groupId, workGroupId));
|
||||
}
|
||||
/**
|
||||
* 划线排班-通过考勤组Id获取绑定的组织名称(拼接好的)及考勤组人数
|
||||
*
|
||||
* @param groupId 考勤组Id
|
||||
*/
|
||||
@GetMapping("/line/getGroupBindingOrg/{groupId}")
|
||||
public ActionResult<AttendanceGroupVo> getGroupBindingOrgForLine(@PathVariable("groupId") String groupId,@RequestParam(value = "workGroupId",required = false) String workGroupId) {
|
||||
return ActionResult.success(attendanceGroupService.getGroupBindingOrgForLine(groupId, workGroupId));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 绑定考勤组的组织
|
||||
*
|
||||
* @param attendanceGroupOrgDto 考勤组和组织信息
|
||||
*/
|
||||
@PutMapping("/updateGroupOrg")
|
||||
public ActionResult<Void> updateGroupOrg(@RequestBody AttendanceGroupOrgDto attendanceGroupOrgDto) {
|
||||
attendanceGroupService.updateGroupOrg(attendanceGroupOrgDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考勤组名称
|
||||
*
|
||||
* @param groupId 考勤组Id
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/queryTheNameOfTheAttendanceGroup")
|
||||
public AttendanceGroup queryTheNameOfTheAttendanceGroup(@RequestParam(value = "groupId") String groupId) {
|
||||
LambdaQueryWrapper<AttendanceGroup> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(AttendanceGroup::getId, groupId);
|
||||
queryWrapper.eq(AttendanceGroup::getDeleteMark, 0);
|
||||
return attendanceGroupService.getOne(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户考勤组
|
||||
*
|
||||
* @param userIds 用户ids
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/attendanceUserGroup")
|
||||
public List<AttendanceUserGroupVo> getAttendanceUserGroup(@RequestParam("userIds") List<String> userIds) {
|
||||
return attendanceGroupService.getAttendanceUserGroup(userIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取用户绑定的考勤组 ,包含全名称 xxx/xxx/xxx
|
||||
*
|
||||
* @param userIds 用户ids
|
||||
*/
|
||||
@Override
|
||||
@PostMapping("/list/user_bound")
|
||||
public ActionResult<List<AttendanceUserListGroupVO>> getAttendanceUserListGroupVO(@RequestBody List<String> userIds) {
|
||||
|
||||
return ActionResult.success(attendanceGroupService.getAttendanceUserListGroupVO(userIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取组织下的考勤组
|
||||
*
|
||||
* @param organizeId 组织id
|
||||
* @return List<AttendanceGroup>
|
||||
*/
|
||||
@GetMapping("/getGroupListByOrgId")
|
||||
@Override
|
||||
public List<AttendanceGroup> getGroupListByOrgId(@RequestParam("organizeId") String organizeId) {
|
||||
QueryWrapper<AttendanceGroup> groupQuery = new QueryWrapper<>();
|
||||
groupQuery.lambda()
|
||||
.eq(AttendanceGroup::getOrgId, organizeId);
|
||||
return attendanceGroupService.getByOrgId(organizeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情---获取一个考勤组
|
||||
*
|
||||
* @param organizeName 组织名称
|
||||
* @param groupName 考勤组名称
|
||||
* @return 一个考勤组
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/info/organize_group/name")
|
||||
public ActionResult<AttendanceGroupVo> getAttendanceGroupByName(@RequestParam("organizeName") String organizeName, @RequestParam("groupName") String groupName) {
|
||||
|
||||
return ActionResult.success(attendanceGroupService.getAttendanceGroupByNameOrganizeAndGroup(organizeName, groupName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 锁定考勤组
|
||||
*
|
||||
* @param groupId 考勤组id
|
||||
*/
|
||||
@PutMapping(value = "/lock/{groupId}")
|
||||
public Object lockGroup(@PathVariable(value = "groupId") String groupId) {
|
||||
|
||||
attendanceGroupService.lockGroup(groupId);
|
||||
return ActionResult.success();
|
||||
}
|
||||
/**
|
||||
* 考勤组2.0历史数据处理
|
||||
*
|
||||
* @param tenantId 考勤组id
|
||||
*/
|
||||
@GetMapping(value = "/oldDataProcessing/{tenantId}")
|
||||
@NoDataSourceBind
|
||||
public Object oldDataProcessing(@PathVariable(value = "tenantId") String tenantId) {
|
||||
attendanceGroupService.oldDataProcessing(tenantId);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户当前考勤组锁定信息
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/lockInfo/{userId}")
|
||||
public Object getUserCurrentGroupLockInfo(@PathVariable(value = "userId") String userId) throws Exception {
|
||||
|
||||
GroupLockVo groupLockVo = attendanceGroupService.getUserCurrentGroupLockInfo(userId);
|
||||
return ActionResult.success(groupLockVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前考勤组锁定信息
|
||||
*
|
||||
* @param groupId 考勤组id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/groupLockInfo/{groupId}")
|
||||
public Object getGroupLockInfo(@PathVariable(value = "groupId") String groupId) throws Exception {
|
||||
|
||||
GroupLockVo groupLockVo = attendanceGroupService.getGroupLockInfo(groupId);
|
||||
return ActionResult.success(groupLockVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户所在考勤组是否有指定权限
|
||||
* @param appointPermission 参数
|
||||
*/
|
||||
@GetMapping("/appointPermission")
|
||||
public ActionResult<Boolean> appointPermission(AppointPermission appointPermission) {
|
||||
return ActionResult.success(attendanceGroupService.appointPermission(appointPermission));
|
||||
}
|
||||
|
||||
//*************************************考勤V1.9***************************************************/
|
||||
|
||||
/**
|
||||
* V1.9 查询考勤组管理列表
|
||||
* @param groupQueryDto 考勤组名称查询实体
|
||||
* @return List<AttendanceGroupVo>
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public ActionResult<List<AttendanceGroupVo>> groupList(GroupQueryDto groupQueryDto) {
|
||||
return ActionResult.success(attendanceGroupService.groupMyManagerList(groupQueryDto));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* V1.9 排班考勤组列表过滤固定班
|
||||
* @return ActionResult<AttendanceGroupVo>
|
||||
*/
|
||||
@GetMapping("/schedulingGroupListByNotFixedNew")
|
||||
public ActionResult<List<AttendanceGroupVo>> schedulingGroupListByNotFixedNew() {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.schedulingGroupListByNotFixedNew();
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* V1.9 切换考勤组查询我管理的考勤组
|
||||
*/
|
||||
@GetMapping("/handoffGroupTreeListNew")
|
||||
public ActionResult<List<AttendanceGroupVo>> handoffGroupTreeListNew() {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.handoffGroupTreeListNew();
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* v1.9获取默认考勤组
|
||||
*
|
||||
* @return ActionResult<AttendanceGroup>
|
||||
*/
|
||||
@GetMapping("/getDefaultGroupNew")
|
||||
public ActionResult<AttendanceGroupVo> getDefaultGroupNew() {
|
||||
AttendanceGroupVo defaultGroup = attendanceGroupService.getDefaultGroupNew();
|
||||
return ActionResult.success(defaultGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* v1.9排班考勤组列表
|
||||
*/
|
||||
@GetMapping("/schedulingGroupListNew")
|
||||
public ActionResult<List<AttendanceGroupVo>> schedulingGroupListNew() {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.schedulingGroupListNew();
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* v1.9余额考勤组列表
|
||||
*/
|
||||
@GetMapping("/balanceManagementGroupListNew")
|
||||
public ActionResult<List<AttendanceGroupVo>> balanceManagementGroupListNew() {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.balanceManagementNew();
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* V2.0 出勤变更查询考勤组列表
|
||||
*/
|
||||
@GetMapping("/querySecondedApprovalGroupListNew")
|
||||
public ActionResult<List<AttendanceGroupVo>> querySecondedApprovalGroupListNew() {
|
||||
List<AttendanceGroupVo> groupVoList = attendanceGroupService.secondedApprovalGroupListNew();
|
||||
return ActionResult.success(groupVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有考勤组排班权限排班
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/checkScheduling")
|
||||
public boolean checkScheduling() {
|
||||
return attendanceGroupService.checkScheduling();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取有指定模块的权限的考勤组管理列表
|
||||
*
|
||||
* @param positionModuleName 权限模块名称
|
||||
* @return List<AttendanceGroupVo>
|
||||
*/
|
||||
@GetMapping("/getPermissionsGroupList")
|
||||
public ActionResult<List<AttendanceGroupVo>> getPermissionsGroupList(@RequestParam("positionModuleName") String positionModuleName) {
|
||||
return ActionResult.success(attendanceGroupService.getPermissionsGroupList(positionModuleName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取端考勤组列表(左侧选择组织||考勤组)
|
||||
*/
|
||||
@GetMapping("/getOrgOrGroupList")
|
||||
public ActionResult<List<AttendanceOrgOrGroupVo>> getOrgOrGroupList(String keyword) {
|
||||
return ActionResult.success(attendanceGroupService.getOrgOrGroupList(keyword));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置考勤组负责人
|
||||
*
|
||||
* @param dto 考勤组负责人信息
|
||||
* @return Boolean
|
||||
*/
|
||||
@PutMapping(value = "/setGroupCharge")
|
||||
public ActionResult<Boolean> setGroupCharge(@Valid @RequestBody AttendanceGroupChargeDto dto) {
|
||||
return ActionResult.success(attendanceGroupService.setGroupCharge(dto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考勤组负责人
|
||||
*
|
||||
* @param groupId 考勤组id
|
||||
* @return List<AttendanceGroupVo>
|
||||
*/
|
||||
@GetMapping(value = "/getGroupChargeInfo/{groupId}")
|
||||
public ActionResult<AttendanceGroupChargeVo> getGroupChargeInfo(@PathVariable(value = "groupId") String groupId) {
|
||||
return ActionResult.success(attendanceGroupService.getGroupChargeInfo(groupId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jnpf.attendance.AttendanceUserApi;
|
||||
import jnpf.attendance.dto.GroupUpdateByUserDTO;
|
||||
import jnpf.attendance.service.AttendanceDayStatisticsService;
|
||||
import jnpf.attendance.service.AttendanceGroupService;
|
||||
import jnpf.attendance.service.AttendanceUserService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.entity.AttendanceGroup;
|
||||
import jnpf.entity.AttendanceGroupUser;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.ExportUserTemplateDto;
|
||||
import jnpf.model.attendance.dto.GroupUserQueryDto;
|
||||
import jnpf.model.attendance.dto.JoinUserDto;
|
||||
import jnpf.model.attendance.dto.UserSortModel;
|
||||
import jnpf.model.attendance.vo.AttendanceGroupUserVo;
|
||||
import jnpf.model.attendance.vo.attendance.JoinGroupVo;
|
||||
import jnpf.permission.vo.v2.user.UserBoundVO;
|
||||
import jnpf.util.CustomTenantUtil;
|
||||
import jnpf.util.EasyExcelUtil;
|
||||
import jnpf.util.NoDataSourceBind;
|
||||
import jnpf.util.ParamUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 考勤组/成员管理
|
||||
*
|
||||
* @author yier
|
||||
* @Time 2023-11-23
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping(value = "/user")
|
||||
public class AttendanceGroupUserController implements AttendanceUserApi {
|
||||
|
||||
@Resource
|
||||
private AttendanceUserService attendanceUserService;
|
||||
@Resource
|
||||
private AttendanceGroupService attendanceGroupService;
|
||||
@Resource
|
||||
private AttendanceDayStatisticsService dayStaService;
|
||||
@Resource
|
||||
private CustomTenantUtil customTenantUtil;
|
||||
|
||||
/**
|
||||
* 成员管理-查询系统用户(附带考勤组名称)
|
||||
*
|
||||
* @param orgId 部门id
|
||||
* @param name 用户姓名 字段模糊搜索
|
||||
* @return ActionResult<AttendanceGroupUserVo>
|
||||
*/
|
||||
@GetMapping("/getSysUsers")
|
||||
public ActionResult<List<AttendanceGroupUserVo>> get(String orgId, String name) {
|
||||
List<AttendanceGroupUserVo> voList = attendanceUserService.querySysUserList(orgId, name);
|
||||
return ActionResult.success(voList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 用户排序
|
||||
*
|
||||
* @param userSortModel
|
||||
*/
|
||||
@PutMapping("/sort")
|
||||
public ActionResult sort(@RequestBody UserSortModel userSortModel) {
|
||||
Assert.isFalse(CollUtil.isEmpty(userSortModel.getUserSortList()), "未传入用户数据");
|
||||
attendanceUserService.sort(userSortModel);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户加入考勤组
|
||||
*
|
||||
* @param joinUserDto
|
||||
* @return ActionResult<Void>
|
||||
* @throws Exception
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult<Void> addUsers(@RequestBody JoinUserDto joinUserDto) throws Exception {
|
||||
ParamUtil.checkParam(joinUserDto);
|
||||
attendanceUserService.joinUsers(joinUserDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量移除考勤组成员
|
||||
*
|
||||
* @param joinUserDto
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping
|
||||
public ActionResult<Void> batchRemove(@RequestBody JoinUserDto joinUserDto) {
|
||||
attendanceUserService.batchDeleteUsersForSendNotice(joinUserDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 花名册考勤组变更
|
||||
*
|
||||
* @param groupUpdateByUserDTO
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("groupUpdateByPersonnel")
|
||||
@NoDataSourceBind
|
||||
@Deprecated
|
||||
public ActionResult<Void> groupUpdateByPersonnel(@RequestBody GroupUpdateByUserDTO groupUpdateByUserDTO) {
|
||||
customTenantUtil.checkOutTenant(groupUpdateByUserDTO.getTenantId());
|
||||
attendanceUserService.groupUpdateByPersonnel(groupUpdateByUserDTO);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否已经加入
|
||||
*
|
||||
* @param userIds
|
||||
* @return ActionResult<List < String>>
|
||||
*/
|
||||
@GetMapping("/checkUserJoinGroup")
|
||||
public ActionResult<List<String>> checkUserJoinGroup(String userIds) throws HandleException {
|
||||
List<String> userNameList = attendanceUserService.checkUserGroup(userIds);
|
||||
return ActionResult.success(userNameList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查用户是否已经加入1.9
|
||||
* @param userIds 用户ids
|
||||
* @return ActionResult<List < String>>
|
||||
*/
|
||||
@PostMapping("/checkUserJoinGroupToObject")
|
||||
public ActionResult<List<JoinGroupVo>> checkUserJoinGroupToObject(@RequestBody String userIds) throws HandleException {
|
||||
List<JoinGroupVo> userNameList = attendanceUserService.checkUserJoinGroupToObject(userIds);
|
||||
return ActionResult.success(userNameList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出用户模版
|
||||
*/
|
||||
@GetMapping("/downloadTemplate")
|
||||
@NoDataSourceBind
|
||||
public void downloadTemplate(HttpServletResponse response, @RequestParam String tenantId) throws Exception {
|
||||
customTenantUtil.checkOutTenant(tenantId);
|
||||
EasyExcelUtil.export(response, "考勤组成员.xlsx", "考勤组成员", ExportUserTemplateDto.class, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 筛选考勤组下成员,去重,入参考勤组ids 出参用户集合 借调用户也要查询出来
|
||||
*
|
||||
* @param groupUserQueryDto 考勤组信息
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/getUsersByGroupIds")
|
||||
public ActionResult<List<AttendanceGroupUserVo>> getUsersByGroupIds(@RequestBody @Valid GroupUserQueryDto groupUserQueryDto) {
|
||||
List<UserBoundVO> voList = dayStaService.getUserIdArr(groupUserQueryDto.getFilterList(),
|
||||
groupUserQueryDto.getStartTime(), groupUserQueryDto.getEndTime(), groupUserQueryDto.getUserIds(), "0");
|
||||
List<AttendanceGroupUserVo> userVoList = CollectionUtil.isEmpty(voList) ? new ArrayList<>() :
|
||||
voList.stream().map(vo -> {
|
||||
AttendanceGroupUserVo userVo = new AttendanceGroupUserVo();
|
||||
userVo.setUserId(vo.getId());
|
||||
userVo.setRealName(vo.getUserName());
|
||||
userVo.setNickname(vo.getNickname());
|
||||
return userVo;
|
||||
}).collect(Collectors.toList());
|
||||
return ActionResult.success(userVoList);
|
||||
}
|
||||
|
||||
@Operation(summary = "借调考勤组变动通知")
|
||||
@GetMapping(value = "/userGroupUpdateBySecondNotice")
|
||||
public ActionResult<Boolean> userGroupUpdateBySecondNotice(@RequestParam(value = "tenantId") String tenantId) {
|
||||
try {
|
||||
log.info("执行借调考勤组变动通知");
|
||||
return ActionResult.success(attendanceUserService.userGroupUpdateBySecondNotice(tenantId));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return ActionResult.success(Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定考勤组成员列表
|
||||
*
|
||||
* @param id 考勤组Id
|
||||
* @param isPermissions 是否权限控制
|
||||
*/
|
||||
@GetMapping("/getGroupUserList")
|
||||
public ActionResult<List<AttendanceGroupUserVo>> getGroupUserList(@RequestParam(value = "id") String id,
|
||||
@RequestParam(value = "isPermissions") Boolean isPermissions) {
|
||||
List<AttendanceGroupUserVo> voList = attendanceUserService.getGroupUserList(id, isPermissions);
|
||||
return ActionResult.success(voList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取现在考勤组成员列表包含借调不含权限
|
||||
* @param id 考勤组Id
|
||||
*/
|
||||
@GetMapping("/getGroupNowAllUserList")
|
||||
public ActionResult<List<AttendanceGroupUserVo>> getGroupNowAllUserList(@RequestParam(value = "id") String id) {
|
||||
List<AttendanceGroupUserVo> attendanceGroupUsersOfSecondment = attendanceUserService.getGroupNowAllUserList(id);
|
||||
return ActionResult.success(attendanceGroupUsersOfSecondment);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID查询当前时间所在考勤组(包含借调)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return ActionResult<List<AttendanceGroup>>
|
||||
*/
|
||||
@GetMapping("/getUserCurrentGroup")
|
||||
public ActionResult<List<AttendanceGroup>> getUserCurrentGroup(@RequestParam String userId) {
|
||||
Assert.isFalse(StrUtil.isBlank(userId), "用户ID不能为空");
|
||||
List<AttendanceGroup> groups = attendanceGroupService.getUserCurrentGroups(userId);
|
||||
return ActionResult.success(groups);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
|
||||
import jnpf.attendance.service.AttendanceHolidaySettingService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.model.attendance.dto.AttendanceHolidaySettingDto;
|
||||
import jnpf.model.attendance.dto.EnableUpdateDto;
|
||||
import jnpf.model.attendance.vo.AttendanceHolidaySettingVo;
|
||||
import jnpf.util.PageUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤配置-假日设置 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2023-11-29
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/holiday/setting")
|
||||
public class AttendanceHolidaySettingController {
|
||||
|
||||
@Autowired
|
||||
private AttendanceHolidaySettingService attendanceHolidaySettingService;
|
||||
|
||||
/**
|
||||
* 分页查询节假日设置信息。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @param name 节假日名称(可选)
|
||||
* @param paidSalaryEnable 是否计入薪酬标识(可选)
|
||||
* @param currentPage 当前页码
|
||||
* @param pageSize 每页大小
|
||||
* @return 分页的节假日设置视图对象列表
|
||||
*/
|
||||
@GetMapping
|
||||
public ActionResult<PageListVO<AttendanceHolidaySettingVo>> page(@RequestParam String groupId,
|
||||
@RequestParam(required = false) String name,
|
||||
@RequestParam(required = false) Integer paidSalaryEnable,
|
||||
@RequestParam Integer currentPage,
|
||||
@RequestParam Integer pageSize){
|
||||
PageDTO<AttendanceHolidaySettingVo> page1 = attendanceHolidaySettingService.page(groupId, name, paidSalaryEnable, currentPage, pageSize);
|
||||
return ActionResult.page(page1.getRecords(), PageUtil.page(page1));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取单个节假日设置信息。
|
||||
*
|
||||
* @param id 节假日设置ID
|
||||
* @return 节假日设置视图对象
|
||||
*/
|
||||
@GetMapping("{id}")
|
||||
public ActionResult<AttendanceHolidaySettingVo> getOne(@PathVariable String id){
|
||||
return ActionResult.success(attendanceHolidaySettingService.getOne(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定的节假日设置信息。
|
||||
*
|
||||
* @param id 节假日设置ID
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@DeleteMapping("{id}")
|
||||
public ActionResult del(@PathVariable String id){
|
||||
attendanceHolidaySettingService.del(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存节假日设置信息。
|
||||
*
|
||||
* @param dto 节假日设置数据传输对象
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult save(@RequestBody AttendanceHolidaySettingDto dto){
|
||||
attendanceHolidaySettingService.save(dto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改节假日设置信息的启用状态。
|
||||
*
|
||||
* @param enableUpdateDto 启用状态更新数据传输对象
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PutMapping("updateStatus")
|
||||
public ActionResult changeStatus(@RequestBody EnableUpdateDto enableUpdateDto){
|
||||
attendanceHolidaySettingService.changeStatus(enableUpdateDto.getId(), enableUpdateDto.getEnable());
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.attendance.service.AttendanceLeaveRulesService;
|
||||
import jnpf.attendance.service.AttendanceLeaveTypeService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.entity.attendance.AttendanceLeaveType;
|
||||
import jnpf.enums.attendance.LeaveTypeEnum;
|
||||
import jnpf.enums.attendance.LeaveUnitEnum;
|
||||
import jnpf.exception.ApproveException;
|
||||
import jnpf.model.attendance.dto.AttendanceLeaveRulesDto;
|
||||
import jnpf.model.attendance.dto.AttendanceLeaveRulesQueryDto;
|
||||
import jnpf.model.attendance.vo.attendance.AttendanceLeaveRulesVo;
|
||||
import jnpf.model.attendance.vo.attendance.GroupMiniVo;
|
||||
import jnpf.util.FtbUtil;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* 假期规则
|
||||
*
|
||||
* @author panpan
|
||||
* @create 2025-09-18
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/leave-rules")
|
||||
@Slf4j
|
||||
public class AttendanceLeaveRulesController {
|
||||
|
||||
@Autowired
|
||||
private AttendanceLeaveRulesService attendanceLeaveRulesService;
|
||||
|
||||
@Resource
|
||||
private AttendanceLeaveTypeService attendanceLeaveTypeService;
|
||||
|
||||
/**
|
||||
* 获取考勤假期管理列表
|
||||
* @param attendanceLeaveRulesQueryDto 查询参数
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public ActionResult<PageListVO<AttendanceLeaveRulesVo>> list(AttendanceLeaveRulesQueryDto attendanceLeaveRulesQueryDto) {
|
||||
PageInfo<AttendanceLeaveRulesVo> vo = attendanceLeaveRulesService.list(attendanceLeaveRulesQueryDto);
|
||||
return ActionResult.page(vo.getList(), FtbUtil.getPagination(vo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增假期
|
||||
* @param attendanceLeaveRulesDto 假期
|
||||
*/
|
||||
@PostMapping()
|
||||
public ActionResult<Void> add(@RequestBody AttendanceLeaveRulesDto attendanceLeaveRulesDto) throws Exception {
|
||||
attendanceLeaveRulesService.create(attendanceLeaveRulesDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改假期
|
||||
* @param attendanceLeaveRulesDto 假期
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
public ActionResult<Void> put(@PathVariable("id") String id, @RequestBody AttendanceLeaveRulesDto attendanceLeaveRulesDto) throws Exception {
|
||||
attendanceLeaveRulesDto.setId(id);
|
||||
attendanceLeaveRulesService.update(attendanceLeaveRulesDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取假期详情
|
||||
* @param id 假期 ID
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public ActionResult<AttendanceLeaveRulesVo> detail(@PathVariable("id") String id) {
|
||||
return ActionResult.success(attendanceLeaveRulesService.detail(id));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除假期
|
||||
* @param id 假期 ID
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public ActionResult<Void> delete(@PathVariable("id") String id) {
|
||||
attendanceLeaveRulesService.delete(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用、停用假期
|
||||
* @param attendanceLeaveRulesDto 假期
|
||||
*/
|
||||
@PutMapping("/updateState")
|
||||
public ActionResult<Void> updateState( @RequestBody AttendanceLeaveRulesDto attendanceLeaveRulesDto) {
|
||||
attendanceLeaveRulesService.updateState(attendanceLeaveRulesDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户请假列表
|
||||
*/
|
||||
@GetMapping("/getUserLeaveList")
|
||||
public ActionResult<List<AttendanceLeaveRulesVo>> getUserLeaveList(@RequestParam(required = false) boolean isFromOaCondition) {
|
||||
if (isFromOaCondition){
|
||||
List<AttendanceLeaveType> list = attendanceLeaveTypeService.list(new LambdaQueryWrapper<AttendanceLeaveType>()
|
||||
.eq(AttendanceLeaveType::getDeleteMark, 0)
|
||||
.orderByAsc(AttendanceLeaveType::getCreatorTime));
|
||||
return ActionResult.success(list.stream().map(vo->{
|
||||
AttendanceLeaveRulesVo attendanceLeaveRulesVo = new AttendanceLeaveRulesVo();
|
||||
attendanceLeaveRulesVo.setLeaveTypeId(vo.getId());
|
||||
attendanceLeaveRulesVo.setLeaveTypeName(vo.getName());
|
||||
return attendanceLeaveRulesVo;
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
return ActionResult.success(attendanceLeaveTypeService.getUserLeaveList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户请假详情
|
||||
*/
|
||||
|
||||
@GetMapping("/getUserLeaveDetail")
|
||||
public ActionResult<List<AttendanceLeaveRulesVo>> getUserLeaveDetail(AttendanceLeaveType attendanceLeaveType ,@RequestParam(required = false) boolean isFromOaCondition) throws ApproveException {
|
||||
if (isFromOaCondition) {
|
||||
List<AttendanceLeaveRulesVo> list = new ArrayList<>();
|
||||
for (LeaveTypeEnum value : LeaveTypeEnum.values()) {
|
||||
AttendanceLeaveRulesVo attendanceLeaveRulesVo = new AttendanceLeaveRulesVo();
|
||||
attendanceLeaveRulesVo.setUnit(value.getCode());
|
||||
attendanceLeaveRulesVo.setUnitName(value.getMsg());
|
||||
list.add(attendanceLeaveRulesVo);
|
||||
}
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
AttendanceLeaveRulesVo vo = attendanceLeaveTypeService.getUserLeaveDetail(attendanceLeaveType.getId(),null);
|
||||
List<AttendanceLeaveRulesVo> list = new ArrayList<>();
|
||||
list.add(vo);
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户请假详情
|
||||
*/
|
||||
@GetMapping("/getLeaveDetailForOa")
|
||||
public ActionResult<AttendanceLeaveRulesVo> getLeaveDetailForOa(AttendanceLeaveType attendanceLeaveType) throws ApproveException {
|
||||
return ActionResult.success(attendanceLeaveTypeService.getUserLeaveDetail(attendanceLeaveType.getId(),null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请假类型列表
|
||||
*/
|
||||
@GetMapping("/type/list")
|
||||
public ActionResult<List<AttendanceLeaveType>> leaveTypeList(@RequestParam(value = "keyword", required = false) String keyword) {
|
||||
List<AttendanceLeaveType> vo = attendanceLeaveTypeService.list(new LambdaQueryWrapper<AttendanceLeaveType>()
|
||||
.eq(AttendanceLeaveType::getDeleteMark, 0)
|
||||
.like(StringUtil.isNotEmpty(keyword), AttendanceLeaveType::getName, keyword)
|
||||
.orderByAsc(AttendanceLeaveType::getCreatorTime));
|
||||
return ActionResult.success(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增/修改假期类型
|
||||
* @param attendanceLeaveType 假期类型
|
||||
*/
|
||||
@PostMapping("/type")
|
||||
public ActionResult<Void> typeSaveOrUpdate(@RequestBody AttendanceLeaveType attendanceLeaveType) {
|
||||
attendanceLeaveTypeService.typeSaveOrUpdate(attendanceLeaveType);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除假期类型
|
||||
* @param id 假期类型Id
|
||||
*/
|
||||
@DeleteMapping("/type/{id}")
|
||||
public ActionResult<Void> deleteType(@PathVariable("id") String id) {
|
||||
attendanceLeaveTypeService.deleteType(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jnpf.attendance.service.AttendanceGroupService;
|
||||
import jnpf.attendance.service.AttendanceLineSchedulingConfigService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.entity.AttendanceGroup;
|
||||
import jnpf.entity.attendance.FtbAttendanceLineSchedulingConfig;
|
||||
import jnpf.permission.V2PositionApi;
|
||||
import jnpf.permission.dto.v2.position.QueryBasePositionBatchDTO;
|
||||
import jnpf.permission.vo.v2.position.PositionBaseInfoVO;
|
||||
import jnpf.util.StringUtil;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 划线排班配置控制器
|
||||
*
|
||||
* @author ahua
|
||||
* @version 2.1
|
||||
* @copyright 引迈信息技术有限公司(https://www.jnpfsoft.com)
|
||||
* @date 2025-12-30
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/arranging/line/scheduling/config")
|
||||
public class AttendanceLineSchedulingConfigController {
|
||||
|
||||
@Resource
|
||||
private AttendanceLineSchedulingConfigService attendanceLineSchedulingConfigService;
|
||||
|
||||
@Resource
|
||||
private V2PositionApi v2PositionApi;
|
||||
|
||||
@Resource
|
||||
private AttendanceGroupService attendanceGroupService;
|
||||
|
||||
/**
|
||||
* 根据考勤组ID获取划线排班配置详情
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @return 划线排班配置详情
|
||||
*/
|
||||
@GetMapping("detail")
|
||||
public ActionResult<FtbAttendanceLineSchedulingConfig> detail(@RequestParam(value = "groupId") String groupId) {
|
||||
FtbAttendanceLineSchedulingConfig config = attendanceLineSchedulingConfigService.getByGroupId(groupId);
|
||||
return ActionResult.success(config);
|
||||
}
|
||||
/**
|
||||
* 划线排班未排班通知
|
||||
*
|
||||
* @param tenantId 租户id
|
||||
* @return 划线排班配置详情
|
||||
*/
|
||||
@GetMapping("noticeLineScheduling")
|
||||
public ActionResult noticeLineScheduling(@RequestParam(value = "tenantId") String tenantId) {
|
||||
attendanceLineSchedulingConfigService.noticeLineScheduling(tenantId);
|
||||
return ActionResult.success();
|
||||
}
|
||||
/**
|
||||
* 保存或更新划线排班配置
|
||||
*
|
||||
* @param config 划线排班配置
|
||||
* @return 保存结果
|
||||
*/
|
||||
@PostMapping("saveOrUpdate")
|
||||
public ActionResult saveOrUpdate(@RequestBody FtbAttendanceLineSchedulingConfig config) {
|
||||
boolean result = attendanceLineSchedulingConfigService.saveOrUpdateLineSchedulingConfig(config);
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据考勤组ID获取岗位基础信息列表
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @return 岗位基础信息列表
|
||||
*/
|
||||
@Operation(summary = "[列表]根据考勤组ID获取岗位基础信息列表")
|
||||
@GetMapping("/position/base/list")
|
||||
public ActionResult<List<PositionBaseInfoVO>> listPositionBaseInfo(@RequestParam(value = "groupId") String groupId) {
|
||||
// 验证groupId
|
||||
if (StringUtil.isBlank(groupId)) {
|
||||
return ActionResult.fail("考勤组ID不能为空");
|
||||
}
|
||||
|
||||
// 查询AttendanceGroup
|
||||
AttendanceGroup attendanceGroup = attendanceGroupService.queryByGroupId(groupId);
|
||||
if (attendanceGroup == null) {
|
||||
return ActionResult.fail("未找到指定的考勤组");
|
||||
}
|
||||
|
||||
// 获取orgId
|
||||
String orgId = attendanceGroup.getOrgId();
|
||||
if (StringUtil.isBlank(orgId)) {
|
||||
return ActionResult.fail("考勤组未绑定组织");
|
||||
}
|
||||
|
||||
// 创建DTO并设置参数
|
||||
QueryBasePositionBatchDTO dto = new QueryBasePositionBatchDTO();
|
||||
dto.setOrganizeIds(Collections.singletonList(orgId));
|
||||
|
||||
// 调用Feign客户端获取岗位基础信息
|
||||
return v2PositionApi.listPositionBaseInfo(dto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import jnpf.attendance.service.AttendanceLocationSettingService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.AttendanceLocationSettingDto;
|
||||
import jnpf.model.attendance.dto.SaveForStoreDto;
|
||||
import jnpf.model.attendance.vo.AttendanceGroupVo;
|
||||
import jnpf.model.attendance.vo.AttendanceLocationSettingVo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤组-考勤点配置表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2023-11-29
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/location/setting")
|
||||
public class AttendanceLocationSettingController {
|
||||
@Autowired
|
||||
private AttendanceLocationSettingService attendanceLocationSettingService;
|
||||
|
||||
/**
|
||||
* 根据考勤组ID和类型查询考勤地点设置列表。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @param type 类型(用于筛选设置)
|
||||
* @return 考勤地点设置视图对象列表
|
||||
*/
|
||||
@GetMapping
|
||||
public ActionResult<List<AttendanceLocationSettingVo>> findList(@RequestParam String groupId, @RequestParam Integer type) {
|
||||
return ActionResult.success(attendanceLocationSettingService.findList(groupId, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据门店信息保存考勤点数据
|
||||
* @param saveForStore
|
||||
*/
|
||||
@PostMapping("saveForStore")
|
||||
public ActionResult saveForStore(@RequestBody SaveForStoreDto saveForStore){
|
||||
attendanceLocationSettingService.saveForStore(saveForStore);
|
||||
return ActionResult.success();
|
||||
}
|
||||
/**
|
||||
* 根据门店id集合删除考勤点信息
|
||||
* @param saveForStore
|
||||
*/
|
||||
@DeleteMapping("delForStore")
|
||||
public ActionResult delForStore(@RequestBody SaveForStoreDto saveForStore){
|
||||
attendanceLocationSettingService.delForStore(saveForStore);
|
||||
return ActionResult.success();
|
||||
}
|
||||
/**
|
||||
* 获取当前考勤组考勤点关联门店id
|
||||
* @param groupId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("getStoreIds")
|
||||
public ActionResult<List<String>> getStoreIds(@RequestParam String groupId){
|
||||
return ActionResult.success(attendanceLocationSettingService.getStoreIds(groupId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取启用的考勤组信息。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @return 启用的考勤组视图对象列表
|
||||
*/
|
||||
@GetMapping("getEnableGroups")
|
||||
public ActionResult<List<AttendanceGroupVo>> getEnableGroups(@RequestParam String groupId) {
|
||||
return ActionResult.success(attendanceLocationSettingService.getEnableGroup(groupId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存考勤地点设置信息。
|
||||
*
|
||||
* @param dto 考勤地点设置数据传输对象
|
||||
* @throws HandleException 处理异常
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult save(@RequestBody AttendanceLocationSettingDto dto) throws HandleException {
|
||||
attendanceLocationSettingService.save(dto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定的考勤地点设置信息。
|
||||
*
|
||||
* @param id 考勤地点设置ID
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@DeleteMapping("{id}")
|
||||
public ActionResult del(@PathVariable String id) {
|
||||
attendanceLocationSettingService.del(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改考勤地点设置的启用状态。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @param type 类型(用于区分设置类型)
|
||||
* @param enable 启用状态(0禁用,1启用)
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PutMapping("changeStatus")
|
||||
public ActionResult changeStatus(@RequestParam String groupId, @RequestParam Integer type, @RequestParam Integer enable) {
|
||||
attendanceLocationSettingService.changeStatus(groupId, type, enable);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.attendance.service.AttendanceMachineManageService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.dto.PageDto;
|
||||
import jnpf.model.attendance.dto.MachineDto;
|
||||
import jnpf.model.attendance.dto.MachineQueryDto;
|
||||
import jnpf.model.attendance.dto.MachineUpdateDto;
|
||||
import jnpf.model.attendance.vo.AttendanceMachineManageVo;
|
||||
import jnpf.model.attendance.vo.MachineScopeVo;
|
||||
import jnpf.model.attendance.vo.attendance.GroupMiniVo;
|
||||
import jnpf.model.attendance.vo.attendance.GroupUserMiniVo;
|
||||
import jnpf.model.attendance.vo.attendance.LogMiniVo;
|
||||
import jnpf.util.FtbUtil;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤机管理
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2024-09-10
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/machineManage")
|
||||
public class AttendanceMachineManageController {
|
||||
|
||||
@Resource
|
||||
private AttendanceMachineManageService attendanceMachineManageService;
|
||||
|
||||
/**
|
||||
* 考勤机管理 - 考勤组列表
|
||||
* @param machineId 考勤机id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/group/list")
|
||||
public Object getGroupList(@RequestParam(required = false) String machineId) {
|
||||
|
||||
List<GroupMiniVo> list = attendanceMachineManageService.getGroupList(machineId);
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 考勤机管理 - 考勤机列表
|
||||
* @param queryDto 查询条件
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/machine/list")
|
||||
public Object getMachineList(MachineQueryDto queryDto) {
|
||||
|
||||
PageListVO<AttendanceMachineManageVo> page = attendanceMachineManageService.getMachineList(queryDto);
|
||||
return ActionResult.page(page.getList(), page.getPagination());
|
||||
}
|
||||
|
||||
/**
|
||||
* 考勤机管理 - 查询考勤机更新信息
|
||||
* @param id 考勤机id
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.MachineScopeVo>
|
||||
*/
|
||||
@GetMapping(value = "/update-detail/{id}")
|
||||
public ActionResult<MachineScopeVo> getUpdateDetail(@PathVariable(value = "id") String id) {
|
||||
|
||||
MachineScopeVo machineScope = attendanceMachineManageService.getUpdateDetail(id);
|
||||
return ActionResult.success(machineScope);
|
||||
}
|
||||
|
||||
/**
|
||||
* 考勤机管理 - 添加考勤机
|
||||
* @param machineDto 考勤机信息
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PostMapping(value = "/machine")
|
||||
public Object addMachine(@RequestBody @Valid MachineDto machineDto) throws Exception {
|
||||
|
||||
attendanceMachineManageService.addMachine(machineDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 考勤机管理 - 编辑考勤机
|
||||
* @param id 考勤机id
|
||||
* @param machineUpdateDto 考勤机信息
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PutMapping(value = "/machine/{id}")
|
||||
public Object updateMachine(@PathVariable(value = "id") String id, @RequestBody @Valid MachineUpdateDto machineUpdateDto) throws Exception {
|
||||
|
||||
attendanceMachineManageService.updateMachine(id, machineUpdateDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 考勤机管理 - 移除
|
||||
* @param id 考勤机id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@DeleteMapping(value = "/machine/{id}")
|
||||
public Object deleteMachine(@PathVariable(value = "id") String id) throws Exception {
|
||||
|
||||
attendanceMachineManageService.deleteMachine(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 考勤机管理 - 考勤组成员列表
|
||||
* @param groupId 考勤组id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/group/user/{groupId}")
|
||||
public Object getGroupUserList(@PathVariable(value = "groupId") String groupId) {
|
||||
|
||||
List<GroupUserMiniVo> list = attendanceMachineManageService.getGroupUserList(groupId);
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/group/user")
|
||||
public Object getGroupUserList2(@RequestParam(value = "groupId") String groupId) {
|
||||
|
||||
List<GroupUserMiniVo> list = attendanceMachineManageService.getGroupUserList(groupId);
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步考勤机成员
|
||||
* @param id 考勤机id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PutMapping("/sync/{id}")
|
||||
public Object syncMachineMemberData(@PathVariable(value = "id") String id) {
|
||||
|
||||
List<GroupUserMiniVo> list = attendanceMachineManageService.syncMachineMemberData(id);
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 考勤机管理 - 人脸库
|
||||
* @param id 考勤机id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/member/list/{id}")
|
||||
public Object getMachineMemberList(@PathVariable(value = "id") String id) {
|
||||
|
||||
List<GroupUserMiniVo> list = attendanceMachineManageService.getMachineMemberList(id);
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询考勤机打卡记录(查往前3个月的数据)
|
||||
* @param id 考勤机id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/record/list/{id}")
|
||||
public ActionResult<PageListVO<LogMiniVo>> getLogList(@PathVariable(value = "id") String id, PageDto pageQuery) {
|
||||
|
||||
PageInfo<LogMiniVo> page = attendanceMachineManageService.getLogList(id, pageQuery);
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jnpf.attendance.service.AttendanceNoticeService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.model.attendance.dto.NoticeContentInfoDto;
|
||||
import jnpf.model.attendance.vo.NoticeConfirmListVo;
|
||||
import jnpf.model.attendance.vo.NoticeContentInfoVo;
|
||||
import jnpf.util.CustomTenantUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import javax.websocket.server.PathParam;
|
||||
|
||||
/**
|
||||
* 考勤消息通知
|
||||
*
|
||||
* @author shitou
|
||||
* @email shitou@niujiekeji.com
|
||||
* @date 2024-08-08 10:49:41
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/attendance/notice")
|
||||
public class AttendanceNoticeController {
|
||||
@Resource
|
||||
private CustomTenantUtil customTenantUtil;
|
||||
@Autowired
|
||||
private AttendanceNoticeService attendanceNoticeService;
|
||||
|
||||
|
||||
@Operation(summary = "内容详情")
|
||||
@GetMapping(value = "/getContentInfo")
|
||||
public ActionResult<NoticeContentInfoVo> getContentInfo(@Valid NoticeContentInfoDto req) {
|
||||
try {
|
||||
log.info("内容详情,入参=>{}", JSONObject.toJSON(req));
|
||||
long st = System.currentTimeMillis();
|
||||
NoticeContentInfoVo data = attendanceNoticeService.getContentInfo(req);
|
||||
long ent = System.currentTimeMillis();
|
||||
log.info("内容详情,耗时=>{}", ent - st + " 毫秒");
|
||||
return ActionResult.success(data);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return ActionResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤通知-确认")
|
||||
@PostMapping(value = "/confirm/{id}")
|
||||
public ActionResult noticeConfirm(@PathVariable("id") String id) {
|
||||
attendanceNoticeService.noticeConfirm(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤通知-确认列表")
|
||||
@GetMapping(value = "confirmList/{id}")
|
||||
public ActionResult<NoticeConfirmListVo> getNoticeConfirmList(@PathVariable("id") String id) {
|
||||
return ActionResult.success(attendanceNoticeService.getNoticeConfirmList(id));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import jnpf.attendance.service.AttendancePermissionDictService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.entity.PermissionDict;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.SavePermissionDto;
|
||||
import jnpf.model.attendance.vo.PermissionDictVo;
|
||||
import jnpf.util.ParamUtil;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 权限字典管理
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/dict")
|
||||
public class AttendancePermissionDictController {
|
||||
|
||||
@Resource
|
||||
private AttendancePermissionDictService attendancePermissionDictService;
|
||||
|
||||
/**
|
||||
* 保存权限字典信息
|
||||
* @param savePermissionDto
|
||||
* @return ActionResult<Void>
|
||||
* @throws Exception
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult<Void> save(@RequestBody SavePermissionDto savePermissionDto) throws Exception {
|
||||
ParamUtil.checkParam(savePermissionDto);
|
||||
attendancePermissionDictService.save(savePermissionDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限字典查询列表
|
||||
* @param moduleType
|
||||
* @return ActionResult<List<PermissionDictVo>>
|
||||
*/
|
||||
@GetMapping
|
||||
public ActionResult<List<PermissionDictVo>> query(Integer moduleType) {
|
||||
List<PermissionDictVo> result = attendancePermissionDictService.queryPermissionDictList(moduleType);
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id删除权限字典
|
||||
* @param id 权限字典id
|
||||
* @return ActionResult<Void>
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public ActionResult<Void> delete(@PathVariable String id) {
|
||||
attendancePermissionDictService.delete(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限详情
|
||||
* @param id
|
||||
* @return ActionResult<PermissionDict>
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public ActionResult<PermissionDict> detail(@PathVariable String id) {
|
||||
PermissionDict permissionDict = attendancePermissionDictService.detail(id);
|
||||
return ActionResult.success(permissionDict);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import jnpf.attendance.service.AttendanceQuickTemplateService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.model.attendance.dto.FixedClassGroupDto;
|
||||
import jnpf.model.attendance.dto.QuickTemDto;
|
||||
import jnpf.model.attendance.dto.QuickTemplateDto;
|
||||
import jnpf.model.attendance.vo.AttendanceQuickTemplateVo;
|
||||
import jnpf.model.attendance.vo.attendance.QuickTemVo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤配置-快速模板 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2023-11-28
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/quick/template")
|
||||
public class AttendanceQuickTemplateController {
|
||||
|
||||
@Autowired
|
||||
private AttendanceQuickTemplateService attendanceQuickTemplateService;
|
||||
|
||||
/**
|
||||
* 根据考勤组ID查询快速模板列表。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @return 快速模板视图对象列表
|
||||
*/
|
||||
@GetMapping
|
||||
public ActionResult<List<AttendanceQuickTemplateVo>> findList(@RequestParam String groupId) {
|
||||
List<AttendanceQuickTemplateVo> list = attendanceQuickTemplateService.findList(groupId);
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据快速模板ID查询单个快速模板。
|
||||
*
|
||||
* @param id 快速模板ID
|
||||
* @return 快速模板视图对象
|
||||
*/
|
||||
@GetMapping("{id}")
|
||||
public ActionResult<AttendanceQuickTemplateVo> findOne(@PathVariable String id) {
|
||||
return ActionResult.success(attendanceQuickTemplateService.findOne(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存快速模板信息。
|
||||
*
|
||||
* @param quickTemplateDto 快速模板数据传输对象
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult save(@RequestBody QuickTemplateDto quickTemplateDto) {
|
||||
attendanceQuickTemplateService.save(quickTemplateDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定的快速模板信息。
|
||||
*
|
||||
* @param id 快速模板ID
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@DeleteMapping("{id}")
|
||||
public ActionResult del(@PathVariable String id) {
|
||||
attendanceQuickTemplateService.del(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 新版考勤快速排班模板
|
||||
* @param dto 快速排班信息
|
||||
*/
|
||||
@PostMapping("/new")
|
||||
public ActionResult saveNew(@RequestBody @Valid QuickTemDto dto) {
|
||||
attendanceQuickTemplateService.saveOrUpdateNew(dto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 新版考勤快速排班列表
|
||||
* @param groupId 考勤组Id
|
||||
*/
|
||||
@GetMapping("/new")
|
||||
public ActionResult<List<QuickTemVo>> findNewList(@RequestParam String groupId) {
|
||||
List<QuickTemVo> list = attendanceQuickTemplateService.findNewList(groupId);
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.attendance.service.AttendanceShiftNameSettingService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.FixedClassChangeStatusDto;
|
||||
import jnpf.model.attendance.dto.FixedClassGroupDto;
|
||||
import jnpf.model.attendance.dto.ShiftNameDto;
|
||||
import jnpf.model.attendance.dto.ShiftNameQueryDto;
|
||||
import jnpf.model.attendance.vo.attendance.ShiftNameListVo;
|
||||
import jnpf.model.attendance.vo.attendance.ShiftNameVo;
|
||||
import jnpf.util.FtbUtil;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
|
||||
/**
|
||||
* 考勤组配置-考勤班制 前端控制器
|
||||
* @Author huanglinpan
|
||||
* @Date 2024/5/9 10:01
|
||||
* @Version 1.0 (版本号)
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shifts/shiftName")
|
||||
public class AttendanceShiftNameSettingController {
|
||||
|
||||
@Resource
|
||||
private AttendanceShiftNameSettingService attendanceShiftNameSettingService;
|
||||
|
||||
/**
|
||||
* 新增/修改班次名称
|
||||
* @param dto 班次名称信息
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult save(@RequestBody @Valid ShiftNameDto dto) throws HandleException {
|
||||
return attendanceShiftNameSettingService.save(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 起停班次
|
||||
* @param statusDto 班次状态修改dto
|
||||
*/
|
||||
@PutMapping("/changeStatus")
|
||||
public ActionResult changeStatus(@RequestBody FixedClassChangeStatusDto statusDto) {
|
||||
return attendanceShiftNameSettingService.changeStatus(statusDto.getShiftNameId(), statusDto.getEnable(), statusDto.getUpdateShift());
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除班次
|
||||
* @param shiftNameId 班次名称Id
|
||||
*/
|
||||
@DeleteMapping("/{shiftNameId}")
|
||||
public ActionResult delete(@PathVariable("shiftNameId") String shiftNameId) {
|
||||
return attendanceShiftNameSettingService.delete(shiftNameId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取班次详情
|
||||
* @param shiftNameId 班次名称Id
|
||||
*/
|
||||
@GetMapping("{shiftNameId}")
|
||||
public ActionResult<ShiftNameVo> getDetail(@PathVariable("shiftNameId") String shiftNameId) {
|
||||
return ActionResult.success(attendanceShiftNameSettingService.getDetail(shiftNameId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 班次列表
|
||||
* @param queryDto 查询条件
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public ActionResult<PageListVO<ShiftNameListVo>> getList(@Valid ShiftNameQueryDto queryDto) throws HandleException {
|
||||
PageInfo<ShiftNameListVo> list = attendanceShiftNameSettingService.getList(queryDto);
|
||||
return ActionResult.page(list.getList(), FtbUtil.getPagination(list));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存考勤组固定排班
|
||||
* @param dto 固定排班对象
|
||||
*/
|
||||
@PutMapping("/fixedClass")
|
||||
public ActionResult saveOrUpdateFixedClass(@RequestBody @Valid FixedClassGroupDto dto) {
|
||||
return attendanceShiftNameSettingService.saveOrUpdateFixedClass(dto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import jnpf.attendance.service.AttendanceShiftSettingService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.AttendanceShiftDto;
|
||||
import jnpf.model.attendance.vo.AttendanceShiftSettingVo;
|
||||
import jnpf.model.attendance.vo.ShiftPeriodVo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤组配置-考勤配置 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2023-11-22
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shifts/setting")
|
||||
public class AttendanceShiftSettingController {
|
||||
@Autowired
|
||||
private AttendanceShiftSettingService attendanceShiftSettingService;
|
||||
|
||||
/**
|
||||
* 根据考勤组ID查询班次设置。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @return 班次设置视图对象
|
||||
*/
|
||||
@GetMapping("{groupId}")
|
||||
public ActionResult<AttendanceShiftSettingVo> findByGroupId(@PathVariable("groupId") String groupId) {
|
||||
return ActionResult.success(attendanceShiftSettingService.findByGroupId(groupId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存班次设置信息。
|
||||
*
|
||||
* @param dto 班次设置数据传输对象
|
||||
* @throws HandleException 处理异常
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult save(@RequestBody AttendanceShiftDto dto) throws HandleException {
|
||||
attendanceShiftSettingService.save(dto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定的班次周期。
|
||||
*
|
||||
* @param periodId 班次周期ID
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@DeleteMapping("/period/{periodId}")
|
||||
public ActionResult delPeriod(@PathVariable("periodId") String periodId) {
|
||||
attendanceShiftSettingService.delPeriod(periodId);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改班次设置的启用状态。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @param enable 启用状态(0禁用,1启用)
|
||||
* @return 处理结果视图对象
|
||||
*/
|
||||
@PutMapping("changeStatus")
|
||||
public ActionResult changeStatus(@RequestParam String groupId, @RequestParam Integer enable) {
|
||||
attendanceShiftSettingService.changeStatus(groupId, enable, null);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据考勤组ID获取班次时段列表。
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @return 班次周期视图对象列表
|
||||
*/
|
||||
@GetMapping("/period/list")
|
||||
public ActionResult<List<ShiftPeriodVo>> periodList(@RequestParam("groupId") String groupId) {
|
||||
return ActionResult.success(attendanceShiftSettingService.periodList(groupId));
|
||||
}
|
||||
/**
|
||||
* 自我排班的班次列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/self/period/list")
|
||||
public ActionResult<List<ShiftPeriodVo>> periodListForSelfScheduling() {
|
||||
return ActionResult.success(attendanceShiftSettingService.periodListForSelfScheduling());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import jnpf.attendance.AttendanceSimulateDataApi;
|
||||
import jnpf.attendance.service.AttenceMachineService;
|
||||
import jnpf.attendance.service.AttendanceUserService;
|
||||
import jnpf.attendance.service.UserFaceService;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.entity.AttendanceGroupUser;
|
||||
import jnpf.entity.attendance.AttendanceMachineManage;
|
||||
import jnpf.util.NoDataSourceBind;
|
||||
import jnpf.util.UserProvider;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 考勤打卡控制器
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2023-11-21
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/simulateData")
|
||||
public class AttendanceSimulatedDataController implements AttendanceSimulateDataApi {
|
||||
|
||||
@Resource
|
||||
private AttenceMachineService attendanceClockInService;
|
||||
@Autowired
|
||||
private AttendanceUserService attendanceUserService;
|
||||
@Autowired
|
||||
private UserFaceService userFaceService;
|
||||
|
||||
/**
|
||||
* 打卡
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/clockIn")
|
||||
@NoDataSourceBind
|
||||
public void clockIn(@RequestParam(value = "tenantId") String tenantId) throws Exception {
|
||||
Assert.notNull(tenantId, "租户ID不能为空");
|
||||
TenantDataSourceUtil.switchTenant(tenantId);
|
||||
List<AttendanceGroupUser> attendanceGroupUsers = attendanceUserService.queryByUsersAndGroupFilterSecondment(new Date(), new Date(), null, null);
|
||||
UserProvider.getUser().setTenantId(tenantId);
|
||||
Map<String, List<AttendanceMachineManage>> userFaceList = userFaceService.getUserFaceList(attendanceGroupUsers.stream().map(AttendanceGroupUser::getUserId).distinct().collect(Collectors.toList()), tenantId);
|
||||
attendanceGroupUsers.forEach(attendanceGroupUser -> {
|
||||
try {
|
||||
List<AttendanceMachineManage> attendanceMachineManages = userFaceList.get(attendanceGroupUser.getUserId());
|
||||
if(CollUtil.isEmpty(attendanceMachineManages)){
|
||||
return;
|
||||
}
|
||||
AttendanceMachineManage attendanceMachineManage = attendanceMachineManages.stream().findFirst().orElse(null);
|
||||
if(Objects.isNull(attendanceMachineManage)){
|
||||
return;
|
||||
}
|
||||
attendanceClockInService.clockIn(attendanceMachineManage.getMac(), attendanceGroupUser.getUserId(), tenantId);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import jnpf.attendance.service.AttendanceApprovalSettingService;
|
||||
import jnpf.attendance.service.AttendanceSuperAdminService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.model.attendance.dto.*;
|
||||
import jnpf.model.attendance.vo.AttendanceManagerDetailVo;
|
||||
import jnpf.model.attendance.vo.AttendanceUserVo;
|
||||
import jnpf.model.attendance.vo.CurUserPermissionVo;
|
||||
import jnpf.model.attendance.vo.permission.ActionPermissionVo;
|
||||
import jnpf.model.attendance.vo.permission.ApprovalSettingVo;
|
||||
import jnpf.model.attendance.vo.permission.AttendanceTeamSetVo;
|
||||
import jnpf.model.attendance.vo.permission.app.ManagerPermissionVo;
|
||||
import jnpf.model.authority.vo.role.FtbPermissionPositionMenuVO;
|
||||
import jnpf.util.ParamUtil;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* APP全局设置
|
||||
* @author yier
|
||||
* @Time 2023-11-23
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/permission")
|
||||
public class AttendanceSuperAdminController {
|
||||
|
||||
@Resource
|
||||
private AttendanceSuperAdminService attendanceSuperAdminService;
|
||||
@Resource
|
||||
private AttendanceApprovalSettingService attendanceApprovalSettingService;
|
||||
|
||||
|
||||
/**
|
||||
* 添加考勤组超级管理员
|
||||
* @param saveSuperAdminDto 保存信息
|
||||
* @return Void
|
||||
* @throws Exception 抛出异常
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult<Void> add(@RequestBody SaveSuperAdminDto saveSuperAdminDto) throws Exception {
|
||||
ParamUtil.checkParam(saveSuperAdminDto);
|
||||
attendanceSuperAdminService.add(saveSuperAdminDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除超级管理员
|
||||
* @param userIds 用户id
|
||||
* @return ActionResult<Void>
|
||||
*/
|
||||
@DeleteMapping
|
||||
public ActionResult<Void> delete(@RequestParam List<String> userIds) {
|
||||
attendanceSuperAdminService.delete(userIds);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考勤超级管理员
|
||||
* @return ActionResult<List<UserEntity>>
|
||||
*/
|
||||
@GetMapping
|
||||
public ActionResult<List<AttendanceUserVo>> getSuperAdmin(String name) {
|
||||
return ActionResult.success(attendanceSuperAdminService.querySuperAdmin(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加考勤组管理员
|
||||
* @param saveGroupAdmin
|
||||
* @return ActionResult<Void>
|
||||
*/
|
||||
@PostMapping("/addGroupAdmin")
|
||||
public ActionResult<Void> addGroupAdmin(@RequestBody SaveGroupAdmin saveGroupAdmin) throws Exception {
|
||||
ParamUtil.checkParam(saveGroupAdmin);
|
||||
attendanceSuperAdminService.addGroupAdmin(saveGroupAdmin);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加考勤组管理员
|
||||
* @param groupAdminList
|
||||
* @return ActionResult<Void>
|
||||
*/
|
||||
@PostMapping("/batchAddGroupAdmin")
|
||||
public ActionResult<Void> batchAddGroupAdmin(@RequestBody BatchSaveGroupAdmin groupAdminList) throws Exception {
|
||||
ParamUtil.checkParam(groupAdminList);
|
||||
attendanceSuperAdminService.batchAddGroupAdmin(groupAdminList);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改考勤组管理员权限
|
||||
* @param saveGroupAdmin
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@PutMapping("/updateGroupAdmin")
|
||||
public ActionResult<Void> updateGroupAdmin(@RequestBody SaveGroupAdmin saveGroupAdmin) throws Exception {
|
||||
ParamUtil.checkParam(saveGroupAdmin);
|
||||
attendanceSuperAdminService.updateGroupAdmin(saveGroupAdmin);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除考勤组管理员
|
||||
* @param saveGroupAdmin
|
||||
* @return ActionResult<Void>
|
||||
*/
|
||||
@DeleteMapping("/deleteGroupAdmin")
|
||||
public ActionResult<Void> deleteGroupAdmin(@RequestBody SaveGroupAdmin saveGroupAdmin) {
|
||||
attendanceSuperAdminService.deleteGroupAdmin(saveGroupAdmin);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询考勤组管理员列表
|
||||
* @param groupId 考勤组id
|
||||
* @return ActionResult<List<AttendanceGroupAdminVo>>
|
||||
*/
|
||||
@GetMapping("/listGroupAdmin")
|
||||
public ActionResult<Map<String, Object>> listGroupAdmin(String groupId) {
|
||||
Map<String, Object> result = attendanceSuperAdminService.listGroupAdmin(groupId);
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录用户权限
|
||||
*/
|
||||
@GetMapping("/getCurPermission")
|
||||
public ActionResult<CurUserPermissionVo> getCurPermission(String groupId) {
|
||||
CurUserPermissionVo curUserPermissionVo = attendanceSuperAdminService.getByUserId(groupId);
|
||||
return ActionResult.success(curUserPermissionVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改审批设置
|
||||
* @param attendanceApprovalSettingDto
|
||||
* @return ActionResult<Void>
|
||||
*/
|
||||
@PostMapping("/updateApprovalSetting")
|
||||
public ActionResult<Void> updateApprovalSetting(@RequestBody AttendanceApprovalSettingDto attendanceApprovalSettingDto) {
|
||||
attendanceApprovalSettingService.update(attendanceApprovalSettingDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员权限详情
|
||||
* @param groupId
|
||||
* @param userId
|
||||
* @return ActionResult<List<PermissionDictVo>>
|
||||
*/
|
||||
@GetMapping("/adminDetail")
|
||||
public ActionResult<AttendanceManagerDetailVo> adminDetail(String groupId, String userId) {
|
||||
AttendanceManagerDetailVo dictVos = attendanceSuperAdminService.adminDetail(groupId, userId);
|
||||
return ActionResult.success(dictVos);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有查看权限
|
||||
* @return ActionResult
|
||||
*/
|
||||
@GetMapping("/isView")
|
||||
public ActionResult<Boolean> isView(String groupId) {
|
||||
Boolean viewPermission = attendanceSuperAdminService.isViewPermission(groupId);
|
||||
return ActionResult.success(viewPermission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取操作权限
|
||||
* @return ActionResult<ActionPermissionVo>
|
||||
*/
|
||||
@GetMapping("/actionPermission")
|
||||
public ActionResult<ActionPermissionVo> actionPermission(String groupId) {
|
||||
ActionPermissionVo actionPermission = attendanceSuperAdminService.getActionPermission(groupId);
|
||||
return ActionResult.success(actionPermission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有全局设置权限
|
||||
* @return ActionResult<Boolean>
|
||||
*/
|
||||
@GetMapping("/isGlobal")
|
||||
public ActionResult<Boolean> isGlobal() {
|
||||
Boolean globalSetting = attendanceSuperAdminService.isGlobalSetting();
|
||||
return ActionResult.success(globalSetting);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是考勤组管理员
|
||||
* @return ActionResult<Boolean>
|
||||
*/
|
||||
@GetMapping("/isManager")
|
||||
public ActionResult<ManagerPermissionVo> isManager() {
|
||||
ManagerPermissionVo manager = attendanceSuperAdminService.isManager();
|
||||
return ActionResult.success(manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考勤组审批设置
|
||||
* @return ActionResult<ApprovalSettingVo>
|
||||
*/
|
||||
@GetMapping("/getGroupApprovalPermission")
|
||||
public ActionResult<ApprovalSettingVo> getGroupApprovalPermission(@RequestParam("groupId") String groupId,
|
||||
@RequestParam("type") Integer type) {
|
||||
ApprovalSettingVo approvalSettingInfo = attendanceSuperAdminService.getApprovalSettingInfo(groupId, type);
|
||||
return ActionResult.success(approvalSettingInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户id获取所属权限集合
|
||||
* @param userIds 用户id
|
||||
* @return FtbPermissionPositionMenuInnerVO
|
||||
*/
|
||||
@PostMapping("/queryPermissionListByUserIds")
|
||||
public ActionResult<List<FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO>> queryPermissionListByUserIds(@RequestBody List<String> userIds) {
|
||||
List<FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO> voList = attendanceSuperAdminService.queryPermissionListByUserIds(userIds);
|
||||
return ActionResult.success(voList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考勤组团队设置
|
||||
* @return ActionResult<AttendanceTeamSetVo>
|
||||
*/
|
||||
@GetMapping("/getTeamSet")
|
||||
public ActionResult<AttendanceTeamSetVo> getTeamSet(@Valid GroupFilterDto dto) {
|
||||
return ActionResult.success(attendanceSuperAdminService.getTeamSet(dto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 考勤组月报通知开启/关闭
|
||||
* @return ActionResult<Boolean>
|
||||
*/
|
||||
@PutMapping("/setMonthNotice")
|
||||
public ActionResult<Boolean> setMonthNotice(@Valid @RequestBody GroupFilterDto dto) {
|
||||
return ActionResult.success(attendanceSuperAdminService.setMonthNotice(dto));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import jnpf.attendance.service.AttendanceUserBalanceService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.AttendanceUserBalanceDto;
|
||||
import jnpf.model.attendance.dto.AttendanceUserBalanceListQueryDto;
|
||||
import jnpf.model.attendance.vo.attendance.AttendanceUserBalanceListVo;
|
||||
import jnpf.model.attendance.vo.attendance.AttendanceUserBalanceVo;
|
||||
import jnpf.model.attendance.vo.attendance.AttendanceUserTitleVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
|
||||
/**
|
||||
* 用户余额
|
||||
* @author 盼盼
|
||||
* @create 2025-09-18
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/user-balance")
|
||||
@Slf4j
|
||||
public class AttendanceUserBalanceController {
|
||||
|
||||
@Autowired
|
||||
private AttendanceUserBalanceService attendanceUserBalanceService;
|
||||
|
||||
/**
|
||||
* 获取考勤余额管理列表
|
||||
* @param queryDto 余额名称模糊查询非必传
|
||||
*/
|
||||
@PostMapping("/list")
|
||||
public ActionResult<AttendanceUserBalanceListVo> list(@RequestBody @Valid AttendanceUserBalanceListQueryDto queryDto) throws HandleException {
|
||||
AttendanceUserBalanceListVo vo = attendanceUserBalanceService.list(queryDto);
|
||||
return ActionResult.success(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑、批量编辑余额
|
||||
* @param userBalanceDto 余额
|
||||
*/
|
||||
@PutMapping()
|
||||
public ActionResult<Void> updateUserBalance(@RequestBody AttendanceUserBalanceDto userBalanceDto) {
|
||||
attendanceUserBalanceService.updateUserBalance(userBalanceDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取余额详情
|
||||
* @param userBalanceDto 用户Id及类型Id(类型Id没有默认查调休)
|
||||
*/
|
||||
@GetMapping("/detail")
|
||||
public ActionResult<AttendanceUserBalanceVo> getDetail(AttendanceUserBalanceDto userBalanceDto) {
|
||||
return ActionResult.success(attendanceUserBalanceService.getDetail(userBalanceDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取余额详情页-顶部用户相关及动态假期表头
|
||||
* @param userBalanceDto 用户Id及类型Id(类型Id没有默认查调休)
|
||||
*/
|
||||
@GetMapping("/title")
|
||||
public ActionResult<AttendanceUserTitleVo> getTitle(AttendanceUserBalanceDto userBalanceDto) {
|
||||
return ActionResult.success(attendanceUserBalanceService.getTitle(userBalanceDto));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import jnpf.attendance.service.AttendanceUserSettingService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.enums.attendance.UserSettingEnum;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.AppUserSettingQueryDto;
|
||||
import jnpf.model.attendance.dto.AttendanceAppUserSettingDto;
|
||||
import jnpf.model.attendance.vo.UserSettingVo;
|
||||
import jnpf.util.UserProvider;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* app用户个人及考勤组设置
|
||||
* @Author huanglinpan
|
||||
* @Date 2024/8/8 10:53
|
||||
* @Version 1.0 (版本号)
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/app")
|
||||
@Slf4j
|
||||
public class AttendanceUserSettingController {
|
||||
|
||||
@Resource
|
||||
private AttendanceUserSettingService attendanceUserSettingService;
|
||||
@Resource
|
||||
private UserProvider userProvider;
|
||||
|
||||
/**
|
||||
* 修改设置
|
||||
* @param attendanceAppUserSettingDto 设置信息
|
||||
*/
|
||||
@PutMapping("/setting")
|
||||
public ActionResult saveOrUpdate(@RequestBody AttendanceAppUserSettingDto attendanceAppUserSettingDto) {
|
||||
attendanceUserSettingService.saveOrUpdate(attendanceAppUserSettingDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量保存设置
|
||||
* @param attendanceAppUserSettingDto 保存的对象
|
||||
*/
|
||||
@PutMapping("/saveOrUpdateList")
|
||||
public ActionResult saveOrUpdateList(@RequestBody List<AttendanceAppUserSettingDto> attendanceAppUserSettingDto) {
|
||||
attendanceUserSettingService.saveOrUpdateList(attendanceAppUserSettingDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设置列表
|
||||
* @param appUserSettingQueryDto 查询信息
|
||||
*/
|
||||
@GetMapping("/setting")
|
||||
public ActionResult<List<UserSettingVo>> getList(AppUserSettingQueryDto appUserSettingQueryDto) {
|
||||
return ActionResult.success(attendanceUserSettingService.getList(appUserSettingQueryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户上下班极速打卡配置
|
||||
*/
|
||||
@GetMapping("/userSetting")
|
||||
public ActionResult<List<UserSettingVo>> getUserSettingList() {
|
||||
return ActionResult.success(attendanceUserSettingService.getSettingList(CollUtil.newArrayList(userProvider.get().getUserId()),1, Stream.of(UserSettingEnum.ATTENDANCE_SETTING_START_SPEED_CHECK.getCode(),
|
||||
UserSettingEnum.ATTENDANCE_SETTING_END_SPEED_CHECK.getCode())
|
||||
.collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
/*****************************************考勤V1.9************************************************/
|
||||
|
||||
/**
|
||||
* v1.9查询设置列表
|
||||
*
|
||||
* 因考虑兼容,导致原本的优化接口变为赋值接口并优化逻辑
|
||||
* @param appUserSettingQueryDto 查询信息
|
||||
*/
|
||||
@GetMapping("/settingNew")
|
||||
public ActionResult<List<UserSettingVo>> getListNew(AppUserSettingQueryDto appUserSettingQueryDto) {
|
||||
return ActionResult.success(attendanceUserSettingService.getListNew(appUserSettingQueryDto));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import jnpf.util.CustomTenantUtil;
|
||||
import jnpf.util.NoDataSourceBind;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 英泰斯达考勤机控制器
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2024-03-28
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping(value = "/ffi")
|
||||
public class FfiMachineController {
|
||||
|
||||
@Autowired
|
||||
private CustomTenantUtil customTenantUtil;
|
||||
|
||||
/**
|
||||
* 设备录入自定义编号判断
|
||||
* @return java.util.Map<java.lang.String,java.lang.Object>
|
||||
*/
|
||||
@PostMapping(consumes = "application/octet-stream")
|
||||
@NoDataSourceBind
|
||||
public Map<String, Object> addFace(HttpServletRequest request) {
|
||||
|
||||
String requestCode = request.getHeader("request_code");
|
||||
String devId = request.getHeader("dev_id");
|
||||
String contentLength = request.getHeader("Content-Length");
|
||||
log.error("requestCode: {}, devId: {}, contentLength: {}", requestCode, devId, contentLength);
|
||||
int contentLength2 = request.getContentLength();
|
||||
log.error("contentLength2: {}", contentLength2);
|
||||
// 获取请求体的ServletInputStream
|
||||
String body;
|
||||
try {
|
||||
// 读取二进制流(这里需要自己实现)
|
||||
ServletInputStream inputStream = request.getInputStream();
|
||||
byte[] buffer = new byte[contentLength2];
|
||||
int bytesRead = 0;
|
||||
while (bytesRead < contentLength2) {
|
||||
int bytes = inputStream.read(buffer, bytesRead, contentLength2 - bytesRead);
|
||||
if (bytes == -1) {
|
||||
break;
|
||||
}
|
||||
bytesRead += bytes;
|
||||
}
|
||||
log.error("buffer bytes: {}", Arrays.toString(buffer));
|
||||
body = getJsonBlock(buffer);
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
return null;
|
||||
}
|
||||
log.error("body: {}", body);
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("Result", 0);
|
||||
map.put("Msg", "进入方法...");
|
||||
return map;
|
||||
}
|
||||
|
||||
private String getJsonBlock(byte[] buffer) {
|
||||
|
||||
String str = "";
|
||||
if (buffer.length < 4) {
|
||||
return str;
|
||||
}
|
||||
int lenText = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||
if (lenText > buffer.length - 4 || lenText == 0) {
|
||||
return str;
|
||||
}
|
||||
str = new String(buffer, 4, lenText, StandardCharsets.UTF_8);
|
||||
if (buffer[4 + lenText - 1] == 0) {
|
||||
str = new String(buffer, 4, lenText - 1, StandardCharsets.UTF_8);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jnpf.attendance.service.InitializationService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.UserInfo;
|
||||
import jnpf.config.ConfigValueUtil;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.exception.ApproveException;
|
||||
import jnpf.exception.LoginException;
|
||||
import jnpf.util.NoDataSourceBind;
|
||||
import jnpf.util.StringUtil;
|
||||
import jnpf.util.UserProvider;
|
||||
import jnpf.util.data.DataSourceContextHolder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 初始化控制器
|
||||
* @Author huanglinpan
|
||||
* @Date 2024/7/1 9:14
|
||||
* @Version 1.0 (版本号)
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/config")
|
||||
@Tag(name = "初始化", description = "initialization")
|
||||
public class InitializationController {
|
||||
|
||||
|
||||
@Autowired
|
||||
private ConfigValueUtil configValueUtil;
|
||||
|
||||
|
||||
@Resource
|
||||
private InitializationService initializationService;
|
||||
|
||||
/**
|
||||
* 初始化存休 有效期考勤v1.3版本
|
||||
*/
|
||||
@GetMapping(value = "/storageRest")
|
||||
@Deprecated
|
||||
public ActionResult storageRest() {
|
||||
Integer i = initializationService.storageRest();
|
||||
|
||||
return ActionResult.success("初始化成功"+i+"条数据");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import jnpf.attendance.annotation.Machine;
|
||||
import jnpf.attendance.service.AttenceMachineService;
|
||||
import jnpf.attendance.service.IsPerfMachineService;
|
||||
import jnpf.attendance.service.MachineStrategy;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.UserInfo;
|
||||
import jnpf.enums.attendance.ActionEnum;
|
||||
import jnpf.enums.attendance.MachineEnum;
|
||||
import jnpf.model.attendance.dto.SecondCheckDto;
|
||||
import jnpf.permission.model.user.PartUserInfoVo;
|
||||
import jnpf.util.ConstantUtil;
|
||||
import jnpf.util.CustomTenantUtil;
|
||||
import jnpf.util.NoDataSourceBind;
|
||||
import jnpf.util.RedisUtil;
|
||||
import jnpf.util.TenantUtil;
|
||||
import jnpf.util.attendance.MachineStrategyFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 开架易控制器
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2024-04-01
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
public class IsPerfMachineController {
|
||||
|
||||
@Resource
|
||||
private IsPerfMachineService isPerfMachineService;
|
||||
|
||||
@Resource
|
||||
private AttenceMachineService attenceMachineService;
|
||||
|
||||
@Resource
|
||||
private MachineStrategyFactory machineStrategyFactory;
|
||||
|
||||
@Autowired
|
||||
private CustomTenantUtil tenantUtil;
|
||||
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@GetMapping(value = "/main")
|
||||
public Object welcome() {
|
||||
|
||||
// 初始化netty服务器, 设备登录在 应用设置--其他设置--通信设置 填入服务器 ip:port
|
||||
isPerfMachineService.welcome();
|
||||
return ActionResult.success("netty绑定成功");
|
||||
}
|
||||
|
||||
@PostMapping(value = "/callback")
|
||||
@NoDataSourceBind
|
||||
public Object callback(@RequestBody Map<String, Object> params) {
|
||||
|
||||
log.error("callback init ...");
|
||||
/*String userNo = params.get("userId").toString();
|
||||
log.info("callback in : {}", params.toString());
|
||||
JSONObject json = new JSONObject(params.get("extra"));
|
||||
String tenantId = json.get("tenantId").toString();
|
||||
String userId = json.get("userId").toString();
|
||||
tenantUtil.checkOutTenant(tenantId, userId);
|
||||
String sn = params.get("mac").toString();
|
||||
String b = attenceMachineService.clockIn(sn, userId, tenantId);
|
||||
// log.error(b);
|
||||
json.clear();
|
||||
// 将结果保存到redis 0: 打卡失败, 1: 正常, 2: 迟到, 3: 早退
|
||||
redisUtil.insert(ConstantUtil.MACHINE_KEY + sn + "-" + userNo, "locked", 5L);*/
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("code", 1);
|
||||
map.put("flag", 1);
|
||||
map.put("tips", "");
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开架易 - 二次校验
|
||||
* @param params 二次校验dto
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PostMapping(value = "/kips/secondCheck")
|
||||
@NoDataSourceBind
|
||||
@Machine(dealAction = ActionEnum.DA_KA, factory = MachineEnum.KAI_JIA_YI)
|
||||
public Object getClockInResult(@RequestBody Map<String, Object> params) {
|
||||
|
||||
int code = 0;
|
||||
int flag = 0;
|
||||
log.error("callback in : {}", params.toString());
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
// 解析入参
|
||||
String userNo = params.get("vipID").toString();
|
||||
JSONObject json = new JSONObject(params.get("extra"));
|
||||
String tenantId = json.get("tenantId").toString();
|
||||
String userId = json.get("userId").toString();
|
||||
String sn = params.get("mac").toString();
|
||||
// 防止重复提交, 查看redis是否还在限制打卡
|
||||
String key = ConstantUtil.MACHINE_KEY + sn + "-" + userNo;
|
||||
if (redisUtil.exists(key)) {
|
||||
map.put("code", code);
|
||||
map.put("flag", flag);
|
||||
map.put("tips", "");
|
||||
return map;
|
||||
}
|
||||
tenantUtil.checkOutTenant(tenantId, userId);
|
||||
String b = attenceMachineService.clockIn(sn, userId, tenantId);
|
||||
json.clear();
|
||||
// 防重复提交
|
||||
redisUtil.insert(key, "locked", 5L);
|
||||
String tips = "";
|
||||
switch (b) {
|
||||
case "0":
|
||||
tips = "打卡失败";
|
||||
break;
|
||||
case "1":
|
||||
tips = "打卡成功";
|
||||
break;
|
||||
case "2":
|
||||
tips = "迟到";
|
||||
break;
|
||||
case "3":
|
||||
tips = "早退";
|
||||
break;
|
||||
default:
|
||||
tips = b;
|
||||
break;
|
||||
}
|
||||
map.put("code", code);
|
||||
map.put("flag", flag);
|
||||
map.put("tips", tips);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 版本升级
|
||||
* @param params 参数
|
||||
*/
|
||||
@PostMapping(value = "/updateApp")
|
||||
public void updateApp(@RequestBody Map<String, Object> params) {
|
||||
|
||||
isPerfMachineService.updateApp(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看netty所有考勤机在线用户
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@GetMapping(value = "/allOnlineClient")
|
||||
public Object getAllOnlineClient() {
|
||||
|
||||
List<String> list = isPerfMachineService.getAllOnlineClient();
|
||||
return ActionResult.success(list);
|
||||
}
|
||||
|
||||
@GetMapping("/kyj/sendMqtt/{type}")
|
||||
@NoDataSourceBind
|
||||
public String kyjSendMqtt(@PathVariable(value = "type") Integer type) {
|
||||
|
||||
tenantUtil.checkOutTenant("ftb_dev");
|
||||
MachineEnum machineEnum = MachineEnum.getMachineEnum(MachineEnum.KAI_JIA_YI.getValue());
|
||||
MachineStrategy machineStrategy = machineStrategyFactory.getMachineStrategy(machineEnum);
|
||||
UserInfo userInfo = new UserInfo();
|
||||
userInfo.setTenantId("ftb_dev");
|
||||
PartUserInfoVo user = new PartUserInfoVo();
|
||||
user.setRealName("小鄢");
|
||||
user.setUserId("471608060058616325");
|
||||
user.setUserNo(123);
|
||||
user.setGender(1);
|
||||
String sn = "B48F62EEAC7D";
|
||||
if (type == 1) {
|
||||
machineStrategy.addUserToMachine(userInfo, user, sn);
|
||||
} else {
|
||||
machineStrategy.deleteUserList(userInfo, Stream.of(user.getUserNo().toString()).collect(Collectors.toList()), sn);
|
||||
}
|
||||
return "发送结束";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import jnpf.attendance.service.AttenceMachineService;
|
||||
import jnpf.model.attendance.vo.attendance.UserTenantVo;
|
||||
import jnpf.permission.UserApi;
|
||||
import jnpf.permission.V2UserApi;
|
||||
import jnpf.permission.model.user.UserNoInfoVo;
|
||||
import jnpf.permission.vo.v2.user.UserBoundVO;
|
||||
import jnpf.util.Base64Util;
|
||||
import jnpf.util.CustomTenantUtil;
|
||||
import jnpf.util.NoDataSourceBind;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 科密考勤机
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2025-08-22
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping(value = "/kemi")
|
||||
public class KeMiController {
|
||||
|
||||
@Resource
|
||||
private CustomTenantUtil customTenantUtil;
|
||||
@Resource
|
||||
private AttenceMachineService attenceMachineService;
|
||||
@Autowired
|
||||
private Base64Util base64Util;
|
||||
@Autowired
|
||||
private V2UserApi v2UserApi;
|
||||
|
||||
@NoDataSourceBind
|
||||
@PostMapping(value = "/{tenantId}")
|
||||
public ResponseEntity<String> messageFromMachine(@PathVariable(value = "tenantId") String tenantId, @RequestBody Map<String, Object> body, HttpServletRequest request) {
|
||||
|
||||
customTenantUtil.checkOutTenant(tenantId);
|
||||
// log.error("科密推送 - {}", JSONUtil.toJsonStr(body));
|
||||
// 获取命令内容
|
||||
String requestCode = request.getHeader("request_code");
|
||||
String transId = request.getHeader("trans_id");
|
||||
String devId = request.getHeader("dev_id");
|
||||
String token = request.getHeader("token");
|
||||
String userId = body.get("userId").toString();
|
||||
if (requestCode.equals("realtime_glog")) {
|
||||
// 实时打卡记录推送
|
||||
if (StringUtil.isNotEmpty(userId)) {
|
||||
List<UserBoundVO> list = v2UserApi.userListAndCopy(List.of(userId), null, tenantId);
|
||||
String userName = "";
|
||||
if (null != list && !list.isEmpty()) {
|
||||
userName = list.get(0).getUserName();
|
||||
}
|
||||
UserTenantVo userTenant = new UserTenantVo(userId, userId, userName, tenantId, devId);
|
||||
attenceMachineService.KeMiClockIn(userTenant, devId, tenantId);
|
||||
} else {
|
||||
log.error("科密: 陌生人打卡, {}", userId);
|
||||
}
|
||||
} else if (requestCode.equals("realtime_enroll_data")) {
|
||||
// 实时登记数据传输
|
||||
Object photo = body.get("photo");
|
||||
if (null != photo) {
|
||||
String photoUrl = base64Util.convertAndUpload(body.get("photo").toString());
|
||||
attenceMachineService.updateKeMiPhoto(userId, photoUrl, tenantId);
|
||||
} else {
|
||||
log.error("未获取到base64图片, 用户id: {}", userId);
|
||||
}
|
||||
}
|
||||
return ResponseEntity.ok()
|
||||
.headers(header -> {
|
||||
header.add("response_code", "OK");
|
||||
header.add("trans_id", transId);
|
||||
header.add("token", token);
|
||||
})
|
||||
.contentType(MediaType.APPLICATION_JSON).body(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.attendance.service.OvertimeRuleService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.model.attendance.dto.OvertimeRuleDto;
|
||||
import jnpf.model.attendance.dto.OvertimeRuleQueryDto;
|
||||
import jnpf.model.attendance.vo.attendance.OvertimeRulePageVo;
|
||||
import jnpf.model.attendance.vo.attendance.OvertimeRuleVo;
|
||||
import jnpf.util.DateDetail;
|
||||
import jnpf.util.FtbUtil;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 加班规则
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2025-09-17
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/overtime-rule")
|
||||
public class OvertimeRuleController {
|
||||
|
||||
@Resource
|
||||
private OvertimeRuleService overtimeRuleService;
|
||||
|
||||
/**
|
||||
* 新增加班规则
|
||||
* @param overtimeRuleDto 加班规则dto
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PostMapping
|
||||
public Object addOvertimeRule(@RequestBody @Valid OvertimeRuleDto overtimeRuleDto) throws Exception {
|
||||
|
||||
overtimeRuleService.addOvertimeRule(overtimeRuleDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑加班规则
|
||||
* @param id 加班规则id
|
||||
* @param overtimeRuleDto 加班规则dto
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PutMapping(value = "/{id}")
|
||||
public Object updateOvertimeRule(@PathVariable(value = "id") String id, @RequestBody @Valid OvertimeRuleDto overtimeRuleDto) throws Exception {
|
||||
|
||||
overtimeRuleService.updateOvertimeRule(id, overtimeRuleDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除加班规则
|
||||
* @param id 加班规则id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@DeleteMapping(value = "/{id}")
|
||||
public Object deleteOvertimeRule(@PathVariable(value = "id") String id) {
|
||||
|
||||
overtimeRuleService.deleteOvertimeRule(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用/启用加班规则
|
||||
* @param id 加班规则id
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PutMapping(value = "/enable/{id}")
|
||||
public Object updateEnableStatus(@PathVariable(value = "id") String id) throws Exception {
|
||||
|
||||
overtimeRuleService.updateEnableStatus(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询加班规则详情
|
||||
* @param id 加班规则id
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.attendance.OvertimeRuleVo>
|
||||
*/
|
||||
@GetMapping(value = "/detail/{id}")
|
||||
public ActionResult<OvertimeRuleVo> getDetail(@PathVariable(value = "id") String id) {
|
||||
|
||||
OvertimeRuleVo vo = overtimeRuleService.getDetail(id);
|
||||
return ActionResult.success(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询加班规则列表(分页)
|
||||
* @param queryDto 查询条件
|
||||
* @return jnpf.base.ActionResult<jnpf.base.vo.PageListVO<jnpf.model.attendance.vo.attendance.OvertimeRulePageVo>>
|
||||
*/
|
||||
@GetMapping(value = "/page")
|
||||
public ActionResult<PageListVO<OvertimeRulePageVo>> getPage(OvertimeRuleQueryDto queryDto) {
|
||||
|
||||
PageInfo<OvertimeRulePageVo> page = overtimeRuleService.getPage(queryDto);
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户加班规则
|
||||
* @param userId 用户id
|
||||
* @param queryDate 查询日期(yyyy-MM-dd)
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.attendance.OvertimeRuleVo>
|
||||
*/
|
||||
@GetMapping(value = "/user")
|
||||
public ActionResult<OvertimeRuleVo> getUserOvertimeRule(@RequestParam String userId, @RequestParam String queryDate) {
|
||||
|
||||
OvertimeRuleVo effectDetail = overtimeRuleService.getEffectDetail(userId, null, DateDetail.getStr2Date(queryDate));
|
||||
return ActionResult.success(effectDetail);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.attendance.service.PublicHolidayRulesService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.model.attendance.dto.AttendancePublicHolidayRulesDto;
|
||||
import jnpf.model.attendance.vo.attendance.AttendancePublicHolidayRulesVo;
|
||||
import jnpf.model.common.PageDto;
|
||||
import jnpf.util.FtbUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
/**
|
||||
* 考勤公休规则
|
||||
* @author panpan
|
||||
* @version V2.0
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/public-holiday")
|
||||
@Slf4j
|
||||
public class PublicHolidayRulesController {
|
||||
|
||||
@Autowired
|
||||
private PublicHolidayRulesService publicHolidayRulesService;
|
||||
|
||||
/**
|
||||
* 获取考勤公休规则列表
|
||||
* @param iText 规则名称模糊查询 非必传
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public ActionResult<PageListVO<AttendancePublicHolidayRulesVo>> list(@RequestParam(value = "iText", required = false) String iText, PageDto pageDto) {
|
||||
PageInfo<AttendancePublicHolidayRulesVo> vo = publicHolidayRulesService.list(iText,pageDto);
|
||||
return ActionResult.page(vo.getList(), FtbUtil.getPagination(vo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增公休规则
|
||||
* @param publicHolidayRulesDto 公休规则
|
||||
*/
|
||||
@PostMapping()
|
||||
public ActionResult<Void> add(@RequestBody AttendancePublicHolidayRulesDto publicHolidayRulesDto) throws Exception {
|
||||
publicHolidayRulesService.add(publicHolidayRulesDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改公休规则
|
||||
* @param publicHolidayRulesDto 公休规则
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
public ActionResult<Void> put(@PathVariable("id") String id, @RequestBody AttendancePublicHolidayRulesDto publicHolidayRulesDto) throws Exception{
|
||||
publicHolidayRulesDto.setId(id);
|
||||
publicHolidayRulesService.update(publicHolidayRulesDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公休规则详情
|
||||
* @param id 公休规则 ID
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public ActionResult<AttendancePublicHolidayRulesVo> detail(@PathVariable("id") String id) {
|
||||
return ActionResult.success(publicHolidayRulesService.selectOne(id));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除公休规则
|
||||
* @param id 公休规则 ID
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public ActionResult<Void> delete(@PathVariable("id") String id) {
|
||||
publicHolidayRulesService.delete(id);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用、停用公休规则
|
||||
* @param publicHolidayRulesDto 公休规则
|
||||
*/
|
||||
@PutMapping("/updateState")
|
||||
public ActionResult<Void> updateState( @RequestBody AttendancePublicHolidayRulesDto publicHolidayRulesDto) {
|
||||
publicHolidayRulesService.updateState(publicHolidayRulesDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import jnpf.attendance.service.AttenceMachineService;
|
||||
import jnpf.attendance.service.AttendanceUserFaceService;
|
||||
import jnpf.attendance.service.MachineStrategy;
|
||||
import jnpf.attendance.service.RV1109MachineService;
|
||||
import jnpf.base.UserInfo;
|
||||
import jnpf.config.MqttConfiguration;
|
||||
import jnpf.enums.attendance.MachineEnum;
|
||||
import jnpf.model.attendance.vo.UserFaceVo;
|
||||
import jnpf.permission.entity.UserEntity;
|
||||
import jnpf.permission.model.user.PartUserInfoVo;
|
||||
import jnpf.util.*;
|
||||
import jnpf.util.attendance.MachineStrategyFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* RV1109考勤机控制器
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2024-04-09
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping
|
||||
public class RV1109MachineController {
|
||||
|
||||
@Autowired
|
||||
private CustomTenantUtil tenantUtil;
|
||||
|
||||
@Autowired
|
||||
private RV1109MachineService rv1109MachineService;
|
||||
|
||||
@Autowired
|
||||
private AttendanceUserFaceService attendanceUserFaceService;
|
||||
|
||||
@Autowired
|
||||
private AttenceMachineService attenceMachineService;
|
||||
|
||||
@Autowired
|
||||
private MqttConfiguration mqttConfiguration;
|
||||
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Resource
|
||||
private MachineStrategyFactory machineStrategyFactory;
|
||||
|
||||
/**
|
||||
* 设备登录
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PostMapping(value = "/device/login")
|
||||
@NoDataSourceBind
|
||||
public Object deviceLogin(@RequestBody Map<String, Object> params) {
|
||||
|
||||
String devSno = params.get("dev_sno").toString();
|
||||
String token = redisUtil.getHashValues(ConstantUtil.ATTENDANCE_DEVICE, devSno);
|
||||
if (StringUtils.isEmpty(token)) {
|
||||
token = UUID.randomUUID().toString();
|
||||
redisUtil.insertHash(ConstantUtil.ATTENDANCE_DEVICE, devSno, token);
|
||||
}
|
||||
JSONObject json1 = new JSONObject();
|
||||
json1.set("code", 0);
|
||||
json1.set("dev_sno", devSno);
|
||||
json1.set("msg", "登陆成功");
|
||||
json1.set("success", true);
|
||||
json1.set("token", token);
|
||||
JSONObject json2 = new JSONObject();
|
||||
String broker = mqttConfiguration.getHost();
|
||||
String[] split = broker.split(":");
|
||||
String host = split[1].substring(2);
|
||||
Integer port = Integer.parseInt(split[2]);
|
||||
json2.set("host", host);
|
||||
json2.set("keepalive", 60);
|
||||
json2.set("login", mqttConfiguration.getUsername());
|
||||
json2.set("password", mqttConfiguration.getPassword());
|
||||
json2.set("port", port);
|
||||
json2.set("qos", mqttConfiguration.getQos());
|
||||
json2.set("topic", devSno);
|
||||
json1.set("mqinfo", json2);
|
||||
return json1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设备同步成员
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PostMapping(value = "/device/sync_person")
|
||||
@NoDataSourceBind
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object deviceSyncPerson(@RequestBody Map<String, Object> params) {
|
||||
|
||||
// 获取租户信息
|
||||
Map<String, Object> pathParamMap = (Map<String, Object>) params.get("path_params");
|
||||
JSONArray array = JSONUtil.parseArray(pathParamMap.get("person_list"));
|
||||
String userIdStr = array.get(0).toString();
|
||||
String tenantId = userIdStr.split("@")[0];
|
||||
String userId = userIdStr.split("@")[1];
|
||||
tenantUtil.checkOutTenant(tenantId, userId);
|
||||
JSONObject json = new JSONObject();
|
||||
json.set("code", 0);
|
||||
json.set("msg", "OK");
|
||||
json.set("success", true);
|
||||
json.set("person_list", getJsonArray(userId, tenantId));
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回结果至设备
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PostMapping(value = "/device/notify")
|
||||
@NoDataSourceBind
|
||||
public Object deviceNotify(@RequestBody Map<String, Object> params) {
|
||||
|
||||
// 获取租户信息
|
||||
boolean b = (boolean) params.get("success");
|
||||
JSONObject json = new JSONObject();
|
||||
if (b) {
|
||||
json.set("code", 0);
|
||||
json.set("msg", "OK");
|
||||
json.set("success", true);
|
||||
} else {
|
||||
json.set("code", 0);
|
||||
json.set("msg", "NOT OK");
|
||||
json.set("success", false);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
private JSONArray getJsonArray(String userId, String tenantId) {
|
||||
|
||||
JSONArray array = new JSONArray();
|
||||
UserEntity user = rv1109MachineService.getUserInfoById(userId, tenantId);
|
||||
if (null == user) {
|
||||
log.error("用户不存在, 用户ID:{}", userId);
|
||||
return array;
|
||||
}
|
||||
// 查询人脸
|
||||
UserFaceVo userFace = attendanceUserFaceService.getUserFace(user.getId());
|
||||
if (null == userFace) {
|
||||
log.error("人脸数据不存在, 用户ID:{}", userId);
|
||||
return array;
|
||||
}
|
||||
JSONObject json = new JSONObject();
|
||||
json.set("person_id", tenantId + "@" + user.getId());
|
||||
json.set("person_name", user.getRealName());
|
||||
json.set("person_type", "4");
|
||||
json.set("sex", null == user.getGender() ? 0 : user.getGender());
|
||||
JSONArray picArray = new JSONArray();
|
||||
picArray.add(userFace.getFaceData());
|
||||
json.set("templateImgUrl", picArray);
|
||||
json.set("qr", "");
|
||||
json.set("id_card", "");
|
||||
json.set("birthday", null == user.getBirthday() ? "" : DateDetail.getDate2Str(user.getBirthday(), DateDetail.DF));
|
||||
array.add(json);
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录上传
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PostMapping(value = "/record/upload/online")
|
||||
@NoDataSourceBind
|
||||
public Object recordUploadOnline(@RequestBody Map<String, Object> params) {
|
||||
|
||||
// 获取租户信息
|
||||
String personIdStr = params.get("person_id").toString();
|
||||
String tenantId = personIdStr.split("@")[0];
|
||||
String userId = personIdStr.split("@")[1];
|
||||
tenantUtil.checkOutTenant(tenantId, userId);
|
||||
// 获取设备号
|
||||
String sn = params.get("dev_sno").toString();
|
||||
// 获取对比结果
|
||||
int captureStatus = Integer.parseInt(params.get("capture_status").toString());
|
||||
if (ConstantUtil.NUM_TRUE == captureStatus) {
|
||||
// 对比通过
|
||||
String b = attenceMachineService.clockIn(sn, userId, tenantId);
|
||||
if (StringUtils.isNotEmpty(b)) {
|
||||
log.error("打卡失败");
|
||||
}
|
||||
}
|
||||
JSONObject json = new JSONObject();
|
||||
json.set("code", 0);
|
||||
json.set("msg", "OK");
|
||||
json.set("success", true);
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试方法
|
||||
* @return java.lang.String
|
||||
*/
|
||||
@GetMapping("/sendMqtt/{type}")
|
||||
@NoDataSourceBind
|
||||
public String sendMqtt(@PathVariable(value = "type") String type) {
|
||||
|
||||
MachineEnum machineEnum = MachineEnum.getMachineEnum(MachineEnum.YU_QUE.getValue());
|
||||
MachineStrategy machineStrategy = machineStrategyFactory.getMachineStrategy(machineEnum);
|
||||
UserInfo userInfo = new UserInfo();
|
||||
userInfo.setTenantId("ftb_dev");
|
||||
PartUserInfoVo user = new PartUserInfoVo();
|
||||
user.setUserId("471608060058616325");
|
||||
String sn = "0A:0C:E1:43:B0:37";
|
||||
if (type.equals("add")) {
|
||||
machineStrategy.addUserToMachine(userInfo, user, sn);
|
||||
}
|
||||
if (type.equals("delete")) {
|
||||
machineStrategy.deleteUserList(userInfo, Stream.of(user.getUserId()).collect(Collectors.toList()), sn);
|
||||
}
|
||||
return "发送结束";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jnpf.attendance.service.ScheduleGroupRuleConfigService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.model.attendance.dto.scheduling.ScheduleGroupRuleConfigDto;
|
||||
import jnpf.model.attendance.vo.scheduling.ScheduleGroupRuleConfigVo;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 智能排班:考勤组维度「排班规则配置」查询与保存(仅固定排班核心参数 + 划线排班参数)。
|
||||
* 控制器只负责打印接口入参与耗时(JNPF 日志规范)。
|
||||
*
|
||||
* @author xiaofeng
|
||||
* @since 2026-05-13
|
||||
*/
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RestController
|
||||
@RequestMapping("/attendance/schedule")
|
||||
@Tag(name = "排班规则配置", description = "考勤组固定排班与划线排班参数 GET/POST")
|
||||
public class ScheduleGroupRuleConfigController {
|
||||
|
||||
@Resource
|
||||
private ScheduleGroupRuleConfigService scheduleGroupRuleConfigService;
|
||||
|
||||
/**
|
||||
* 获取排班规则配置。无表记录时各子块返回与表 DEFAULT 一致的默认结构。
|
||||
*
|
||||
* @param groupId 考勤组 ID
|
||||
* @return 配置
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Operation(summary = "获取排班规则配置")
|
||||
@GetMapping("/getRuleConfig")
|
||||
public ActionResult<ScheduleGroupRuleConfigVo> getRuleConfig(
|
||||
@RequestParam("groupId") @NotBlank(message = "考勤组ID不能为空") String groupId) {
|
||||
log.info("获取排班规则配置,入参=>{}", groupId);
|
||||
long st = System.currentTimeMillis();
|
||||
ScheduleGroupRuleConfigVo data = scheduleGroupRuleConfigService.getRuleConfig(groupId);
|
||||
log.info("获取排班规则配置,耗时=>{} 毫秒", System.currentTimeMillis() - st);
|
||||
return ActionResult.success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存排班规则配置。请求体根与各子块为 DTO;GET/POST 成功响应根与各子块均为 VO(JSON 字段名不变)。
|
||||
* 服务端在事务内 upsert 固定排班与划线排班参数表。
|
||||
*
|
||||
* @param dto 配置({@code groupId}、{@code fixedScheduling}、{@code lineScheduling} 必填)
|
||||
* @return 保存后的配置
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Operation(summary = "保存排班规则配置")
|
||||
@PostMapping("/saveRuleConfig")
|
||||
public ActionResult<ScheduleGroupRuleConfigVo> saveRuleConfig(
|
||||
@RequestBody @Valid ScheduleGroupRuleConfigDto dto) {
|
||||
log.info("保存排班规则配置,入参=>{}", JSONObject.toJSON(dto));
|
||||
long st = System.currentTimeMillis();
|
||||
ScheduleGroupRuleConfigVo data = scheduleGroupRuleConfigService.saveRuleConfig(dto.getGroupId(), dto);
|
||||
log.info("保存排班规则配置,耗时=>{} 毫秒", System.currentTimeMillis() - st);
|
||||
return ActionResult.success(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jnpf.attendance.service.SmartPreScheduleService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.exception.QueryException;
|
||||
import jnpf.model.attendance.dto.scheduling.PreScheduleTableQueryDto;
|
||||
import jnpf.model.attendance.vo.scheduling.PreScheduleTableVo;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* AI 智能排班确认:预排班主表生成与提交保存接口层。
|
||||
*
|
||||
* @author xiaofeng
|
||||
* @create 2026-05-13
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/attendance/smartSchedule")
|
||||
@Tag(name = "智能排班预排班", description = "预排班主表生成与整包保存")
|
||||
public class SmartPreScheduleController {
|
||||
|
||||
@Resource
|
||||
private SmartPreScheduleService smartPreScheduleService;
|
||||
|
||||
/**
|
||||
* 预排班生成主表:返回 rows,每行含 posts、stations 预览。
|
||||
*
|
||||
* @param dto 日期范围、按日预估营业额、人效目标、考勤组
|
||||
* @return 主表数据
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Operation(summary = "预排班功能")
|
||||
@PostMapping("/preScheduling")
|
||||
public ActionResult<PreScheduleTableVo> buildTable(@RequestBody @Valid PreScheduleTableQueryDto dto) {
|
||||
log.error("预排班生成主表,入参=>{}", JSONObject.toJSON(dto));
|
||||
long startMs = System.currentTimeMillis();
|
||||
PreScheduleTableVo data = smartPreScheduleService.buildPreScheduleTable(dto);
|
||||
log.error("预排班生成主表,耗时=>{}毫秒", System.currentTimeMillis() - startMs);
|
||||
ActionResult<PreScheduleTableVo> result = ActionResult.success(data);
|
||||
if (data != null && StringUtil.isNotBlank(data.getMsg())) {
|
||||
result.setMsg(data.getMsg());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预排班主表提交保存:按 rows 过滤 Redis 中 byEmployee 并写回,返回 redisKeySuffix。
|
||||
*
|
||||
* @param vo groupId + rows
|
||||
* @return redisKeySuffix(考勤组:日期区间,不含租户)
|
||||
*/
|
||||
@Operation(summary = "预排班主表提交保存")
|
||||
@PostMapping("/saveSchedul")
|
||||
public ActionResult<String> saveTable(@RequestBody @Valid PreScheduleTableVo vo)
|
||||
throws HandleException, QueryException {
|
||||
log.error("预排班主表提交保存,入参=>{}", JSONObject.toJSON(vo));
|
||||
long startMs = System.currentTimeMillis();
|
||||
String redisKeySuffix = smartPreScheduleService.savePreScheduleTable(vo);
|
||||
log.error("预排班主表提交保存,耗时=>{}毫秒", System.currentTimeMillis() - startMs);
|
||||
return ActionResult.success(redisKeySuffix);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jnpf.attendance.service.UserConfigService;
|
||||
import jnpf.base.ActionResult;
|
||||
|
||||
|
||||
import jnpf.model.attendance.vo.attendance.GroupShiftTimeVo;
|
||||
import jnpf.model.attendance.vo.attendance.UserConfigVo;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author huanglinpan
|
||||
* @Date 2024/6/24 11:23
|
||||
* @Version 1.0 (版本号)
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/config")
|
||||
@Tag(name = "APP/后台 - 用户配置", description = "group")
|
||||
public class UserConfigController {
|
||||
|
||||
@Resource
|
||||
private UserConfigService userConfigService;
|
||||
|
||||
/**
|
||||
* 获取用户app考勤配置
|
||||
*/
|
||||
@GetMapping("/userConfig")
|
||||
public ActionResult<UserConfigVo> getUserConfig() {
|
||||
|
||||
return ActionResult.success(userConfigService.getUserConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户APP考勤配置
|
||||
*/
|
||||
@PutMapping("/userConfig")
|
||||
public ActionResult updateUserConfig(@RequestBody UserConfigVo userConfigVo) {
|
||||
userConfigService.updateUserConfig(userConfigVo);
|
||||
return ActionResult.success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.attendance.service.UserFaceService;
|
||||
import jnpf.attendance.service.UserFaceTxService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.exception.LoginException;
|
||||
import jnpf.exception.QueryException;
|
||||
import jnpf.model.attendance.dto.FaceChangeQueryDto;
|
||||
import jnpf.model.attendance.dto.FaceQueryDto;
|
||||
import jnpf.model.attendance.dto.UserDto;
|
||||
import jnpf.model.attendance.dto.UserFaceDto;
|
||||
import jnpf.model.attendance.vo.ChangeLogVo;
|
||||
import jnpf.model.attendance.vo.FaceMiniVo;
|
||||
import jnpf.model.attendance.vo.UserFaceDetailVo;
|
||||
import jnpf.model.attendance.vo.UserFaceVo;
|
||||
import jnpf.model.common.PageDto;
|
||||
import jnpf.util.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 人脸识别
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2025-04-08
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping(value = "/attendance/user-face")
|
||||
public class UserFaceController {
|
||||
|
||||
@Resource
|
||||
private UserFaceService userFaceService;
|
||||
@Resource
|
||||
private UserFaceTxService userFaceTxService;
|
||||
@Resource
|
||||
private UserProvider userProvider;
|
||||
|
||||
/**
|
||||
* 下发用户人脸至考勤机
|
||||
* @param userId 用户id列表
|
||||
* @return jnpf.base.ActionResult<java.lang.Object>
|
||||
*/
|
||||
@PutMapping(value = "/sync")
|
||||
public ActionResult<Object> syncUserFaceToMachine(@RequestParam String userId) throws Exception {
|
||||
|
||||
Integer result = userFaceTxService.syncUserFaceToMachine(userId);
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 人脸对比
|
||||
* @param file 人脸图片
|
||||
* @return jnpf.base.ActionResult<java.lang.Boolean>
|
||||
*/
|
||||
@PostMapping(value = "/compare")
|
||||
public ActionResult<Boolean> getPhotoCheck(@RequestPart MultipartFile file) throws Exception {
|
||||
|
||||
if (!isImageFile(file)) {
|
||||
return ActionResult.fail("请上传图片文件进行比对");
|
||||
}
|
||||
Boolean result = userFaceService.getPhotoCheck(file, userProvider.get());
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 人脸对比2
|
||||
* @return jnpf.base.ActionResult<java.lang.Boolean>
|
||||
*/
|
||||
@PostMapping(value = "/compare-sec")
|
||||
public ActionResult<Boolean> getPhotoCheck2() throws Exception {
|
||||
|
||||
List<MultipartFile> list = UpUtil.getFileAll();
|
||||
MultipartFile file = list.get(0);
|
||||
if (!isImageFile(file)) {
|
||||
return ActionResult.fail("请上传图片文件进行比对");
|
||||
}
|
||||
Boolean result = userFaceService.getPhotoCheck(file, userProvider.get());
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
private boolean isImageFile(MultipartFile file) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
String contentType = file.getContentType();
|
||||
return contentType != null && ConstantUtil.IMAGE_CONTENT_TYPES.contains(contentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 录入人脸
|
||||
* @param userId 用户id
|
||||
* @return jnpf.base.ActionResult<java.lang.Object>
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult<Object> addUserFace(@RequestPart("file") MultipartFile file, @RequestPart("userId") String userId) throws Exception {
|
||||
|
||||
if (!isImageFile(file)) {
|
||||
return ActionResult.fail("文件格式错误!");
|
||||
}
|
||||
Integer result = userFaceTxService.uploadUserFace(file, new UserDto(userId), userProvider.get());
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 录入人脸 - add
|
||||
* @param userId 用户id
|
||||
* @return jnpf.base.ActionResult<java.lang.Object>
|
||||
*/
|
||||
@PostMapping(value = "/add/{userId}")
|
||||
public ActionResult<Object> addUserFace2(@PathVariable("userId") String userId) throws Exception {
|
||||
|
||||
List<MultipartFile> list = UpUtil.getFileAll();
|
||||
MultipartFile file = list.get(0);
|
||||
if (!isImageFile(file)) {
|
||||
return ActionResult.fail("文件格式错误!");
|
||||
}
|
||||
Integer result = userFaceTxService.uploadUserFace(file, new UserDto(userId), userProvider.get());
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空人脸
|
||||
* @param userId 用户id
|
||||
* @return jnpf.base.ActionResult<java.lang.Object>
|
||||
*/
|
||||
@DeleteMapping(value = "/{userId}")
|
||||
public ActionResult<Object> deleteUserFace(@PathVariable(value = "userId") String userId) throws Exception {
|
||||
|
||||
userFaceService.deleteUserFace(userId, userProvider.get());
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看人脸
|
||||
* @param userId 用户id
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.UserFaceVo>
|
||||
*/
|
||||
@GetMapping(value = "/{userId}")
|
||||
public ActionResult<UserFaceVo> getUserFace(@PathVariable(value = "userId") String userId) {
|
||||
|
||||
UserFaceVo userFace = userFaceService.getUserFace(userId);
|
||||
return ActionResult.success(userFace);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看人脸详情
|
||||
* @param id 人脸记录id
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.UserFaceVo>
|
||||
*/
|
||||
@GetMapping(value = "/detail/{id}")
|
||||
public ActionResult<UserFaceVo> getUserFaceDetail(@PathVariable(value = "id") String id) {
|
||||
|
||||
UserFaceVo userFace = userFaceService.getUserFaceDetail(id);
|
||||
return ActionResult.success(userFace);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户人脸信息
|
||||
* @param userId 用户id
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.vo.UserFaceVo>
|
||||
*/
|
||||
@GetMapping(value = "/info/{userId}")
|
||||
public ActionResult<FaceMiniVo> getUserFaceInfo(@PathVariable(value = "userId") String userId) {
|
||||
|
||||
FaceMiniVo userFace = userFaceService.getUserFaceInfo(userId);
|
||||
return ActionResult.success(userFace);
|
||||
}
|
||||
|
||||
/**
|
||||
* 变动记录(分页)
|
||||
* @param queryDto 查询条件
|
||||
* @return jnpf.base.ActionResult<jnpf.base.vo.PageListVO<jnpf.model.attendance.vo.ChangeLogVo>>
|
||||
*/
|
||||
@GetMapping(value = "/change-log/page")
|
||||
public ActionResult<PageListVO<ChangeLogVo>> getChangeLog(FaceChangeQueryDto queryDto) {
|
||||
|
||||
PageInfo<ChangeLogVo> page = userFaceService.getChangeLogPage(queryDto);
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* 人脸记录(分页)
|
||||
* @param queryDto 查询条件
|
||||
* @return jnpf.base.ActionResult<jnpf.base.vo.PageListVO<jnpf.model.attendance.vo.UserFaceDetailVo>>
|
||||
*/
|
||||
@PostMapping(value = "/page")
|
||||
public ActionResult<PageListVO<UserFaceDetailVo>> getUserFacePage(@RequestBody @Valid FaceQueryDto queryDto) throws QueryException {
|
||||
|
||||
if (StringUtil.isEmpty(queryDto.getGroupId()) && StringUtil.isEmpty(queryDto.getTeamId())) {
|
||||
throw new QueryException("请选择考勤组或班组");
|
||||
}
|
||||
PageInfo<UserFaceDetailVo> page = userFaceService.getUserFacePage(queryDto);
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户是否上传人脸
|
||||
* @param userId 用户id
|
||||
* @return jnpf.base.ActionResult<java.lang.Boolean>
|
||||
*/
|
||||
@GetMapping(value = "/check/{userId}")
|
||||
public ActionResult<Boolean> hasUserFace(@PathVariable(value = "userId") String userId) {
|
||||
|
||||
Boolean b = userFaceService.hasUserFace(userId);
|
||||
return ActionResult.success(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* V1.8.2初始化人脸缩略图
|
||||
* @param tenantId 租户id
|
||||
*/
|
||||
@NoDataSourceBind
|
||||
@GetMapping(value = "/initializationFace")
|
||||
public ActionResult<Boolean> initializationFace(@RequestParam("tenantId") String tenantId) {
|
||||
try {
|
||||
TenantDataSourceUtil.switchTenant(tenantId);
|
||||
} catch (LoginException e) {
|
||||
throw new RuntimeException("切换租户失败");
|
||||
}
|
||||
userFaceService.initializationFace(tenantId);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.attendance.service.UsualPhoneService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.model.attendance.dto.CancelPhoneDto;
|
||||
import jnpf.model.attendance.dto.UsualPhoneQueryDto;
|
||||
import jnpf.model.attendance.dto.UsualPhoneSettingDto;
|
||||
import jnpf.model.attendance.vo.attendance.UsualPhonePageVo;
|
||||
import jnpf.util.FtbUtil;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 常用设备管理
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2025-09-17
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/user-phone")
|
||||
public class UserPhoneController {
|
||||
|
||||
@Resource
|
||||
private UsualPhoneService usualPhoneService;
|
||||
|
||||
/**
|
||||
* 批量取消绑定
|
||||
* @param cancelPhoneDto 取消绑定参数
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PutMapping(value = "/cancel")
|
||||
public Object cancelPhoneBatch(@RequestBody @Valid CancelPhoneDto cancelPhoneDto) {
|
||||
|
||||
usualPhoneService.cancelPhoneBatch(cancelPhoneDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新常用手机设置
|
||||
* @param usualPhoneSettingDto 常用手机设置dto
|
||||
* @return java.lang.Object
|
||||
*/
|
||||
@PutMapping(value = "/setting")
|
||||
public Object updateUsualPhoneSetting(@RequestBody @Valid UsualPhoneSettingDto usualPhoneSettingDto) {
|
||||
|
||||
usualPhoneService.updateUsualPhoneSetting(usualPhoneSettingDto);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询常用手机列表(分页)
|
||||
* @param queryDto 查询条件
|
||||
* @return jnpf.base.ActionResult<jnpf.base.vo.PageListVO<jnpf.model.attendance.vo.attendance.UsualPhonePageVo>>
|
||||
*/
|
||||
@GetMapping(value = "/page")
|
||||
public ActionResult<PageListVO<UsualPhonePageVo>> getUsualPhonePage(UsualPhoneQueryDto queryDto) {
|
||||
|
||||
PageInfo<UsualPhonePageVo> page = usualPhoneService.getUsualPhonePage(queryDto);
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查常用设备是否异常
|
||||
* @param phoneName 手机名称
|
||||
* @return jnpf.base.ActionResult<java.lang.Boolean>
|
||||
*/
|
||||
@GetMapping(value = "/abnormal")
|
||||
public ActionResult<Boolean> checkUsualPhone(@RequestParam(value = "phoneName") String phoneName, @RequestParam(value = "phoneCode") String phoneCode) {
|
||||
|
||||
Boolean flag = usualPhoneService.checkUsualPhone(phoneName, phoneCode);
|
||||
return ActionResult.success(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询常用手机配置
|
||||
* @return jnpf.base.ActionResult<jnpf.model.attendance.dto.UsualPhoneSettingDto>
|
||||
*/
|
||||
@GetMapping(value = "/usual-phone/setting")
|
||||
public ActionResult<UsualPhoneSettingDto> getUsualPhoneSetting() {
|
||||
|
||||
UsualPhoneSettingDto dto = usualPhoneService.getUsualPhoneSetting();
|
||||
return ActionResult.success(dto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,489 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.fantaibao.permission.annotation.FtbCheckPermission;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jnpf.attendance.FtbStatisticsApi;
|
||||
import jnpf.attendance.dto.*;
|
||||
import jnpf.attendance.service.AttendanceCustomizeTableService;
|
||||
import jnpf.attendance.service.AttendanceDayStatisticsService;
|
||||
import jnpf.attendance.service.AttendanceSealSettingService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.constants.MessageTopicConstants;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.enums.attendance.TriggerSceneEnum;
|
||||
import jnpf.exception.LoginException;
|
||||
import jnpf.model.attendance.dto.*;
|
||||
import jnpf.model.attendance.event.StatisticsBatchClearDto;
|
||||
import jnpf.model.attendance.event.StatisticsSingleDto;
|
||||
import jnpf.model.attendance.vo.attendance.*;
|
||||
import jnpf.model.personnels.vo.analysis.PersonnelDataAnalysisListVO;
|
||||
import jnpf.personnels.utils.PersonnelDataAnalysisUtil;
|
||||
import jnpf.util.FtbUtil;
|
||||
import jnpf.util.NoDataSourceBind;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 考勤统计WEB
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping(value = "/attendance/statistics")
|
||||
public class WebStatisticsController implements FtbStatisticsApi {
|
||||
@Resource
|
||||
private RocketMQTemplate rocketMqTemplate;
|
||||
@Resource
|
||||
private AttendanceDayStatisticsService dayStaService;
|
||||
@Autowired
|
||||
private AttendanceCustomizeTableService tableService;
|
||||
@Resource
|
||||
private AttendanceSealSettingService sealSettingService;
|
||||
|
||||
@Override
|
||||
@Operation(summary = "用户日统计数据初始化")
|
||||
@GetMapping(value = "/userDayStatisticsInit")
|
||||
public ActionResult<Boolean> userDayStatisticsInit(@RequestParam(value = "tenantId") String tenantId) {
|
||||
return ActionResult.success(dayStaService.handleDataForJob(tenantId));
|
||||
}
|
||||
|
||||
@Operation(summary = "日度统计-汇总")
|
||||
@PostMapping("/dayStatistics")
|
||||
public ActionResult<List<DayStatisticsDataVo>> dayStatistics(@Valid @RequestBody DayStatisticsDataDto req) {
|
||||
return ActionResult.success(dayStaService.getDayStatisticsData(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "日度统计-分页列表")
|
||||
@PostMapping(value = "/dayPageList")
|
||||
public ActionResult<PageListVO<DayStatisticsPageListVo>> dayPageList(@Valid @RequestBody DayStatisticsPageListDto req) {
|
||||
PageInfo<DayStatisticsPageListVo> page = dayStaService.getDayPageList(req);
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
|
||||
@Operation(summary = "日度统计-导出")
|
||||
@PostMapping(value = "/dayDataExport")
|
||||
public ActionResult<Boolean> dayDataExport(@Valid @RequestBody DayStatisticsExportDto req) {
|
||||
dayStaService.dayDataExport(req);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "月度统计-汇总")
|
||||
@PostMapping("/monthStatistics")
|
||||
public ActionResult<List<DayStatisticsDataVo>> monthStatistics(@Valid @RequestBody MouthStatisticsDataDto req) {
|
||||
return ActionResult.success(dayStaService.getMonthStatisticsData(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "月度统计-分页列表")
|
||||
@PostMapping(value = "/monthPageList")
|
||||
public ActionResult<PageListVO<MonthStatisticsPageListVo>> monthPageList(@Valid @RequestBody MonthStatisticsPageListDto req) throws Exception {
|
||||
PageInfo<MonthStatisticsPageListVo> page = dayStaService.getMonthPageList(req);
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
|
||||
@Operation(summary = "月度统计-导出")
|
||||
@PostMapping(value = "/monthDataExport")
|
||||
public ActionResult<Boolean> monthDataExport(@Valid @RequestBody MonthStatisticsExportDto req) {
|
||||
dayStaService.monthDataExport(req);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "个人考勤日报通知")
|
||||
@GetMapping(value = "/dayStatisticsNotice")
|
||||
public ActionResult<Boolean> dayStatisticsNotice(@RequestParam(value = "tenantId") String tenantId) {
|
||||
return ActionResult.success(dayStaService.dayStatisticsNotice(tenantId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "个人统计月报通知")
|
||||
@GetMapping(value = "/monthStatisticsNotice")
|
||||
public ActionResult<Boolean> monthStatisticsNotice(@RequestParam(value = "tenantId") String tenantId) {
|
||||
return ActionResult.success(dayStaService.monthStatisticsNotice(tenantId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "连续未排班通知")
|
||||
@GetMapping(value = "/consentUnscheduledNotice")
|
||||
public void consentUnscheduledNotice(@RequestParam(value = "tenantId") String tenantId) {
|
||||
dayStaService.consentUnscheduledNotice(tenantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "团队统计月报通知")
|
||||
@GetMapping(value = "/teamMonthStatisticsNotice")
|
||||
public ActionResult<Boolean> teamMonthStatisticsNotice(@RequestParam(value = "tenantId") String tenantId) {
|
||||
return ActionResult.success(dayStaService.teamMonthStatisticsNotice(tenantId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "计算考勤组平均工时(实际出勤工时)")
|
||||
@PostMapping(value = "/countAttendanceAvgHours")
|
||||
public List<AttendanceCountAvgHoursVo> countAttendanceAvgHours(@Valid @RequestBody AttendanceCountAvgHoursDto dto) {
|
||||
return dayStaService.countAttendanceAvgHours(dto);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "获取多考勤组月度统计数据")
|
||||
@PostMapping(value = "/getAttendanceAvgHoursDetails")
|
||||
public ActionResult<MonthStatsDetailsVo> getAttendanceAvgHoursDetails(@Valid @RequestBody MonthStatsDetailsDto dto) {
|
||||
MonthStatsDetailsVo result = dayStaService.getAttendanceAvgHoursDetails(dto);
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "获取多考勤组月度人均工时折线图")
|
||||
@PostMapping(value = "/getAttendanceMonthPerCapita")
|
||||
public ActionResult<List<MonthStatsPerCapitaVo>> getAttendanceMonthPerCapita(@Valid @RequestBody MonthStatsDetailsDto dto) {
|
||||
return ActionResult.success(dayStaService.getAttendanceMonthPerCapita(dto));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "获取多考勤组月度日常情况")
|
||||
@PostMapping(value = "/getAttendanceDailySituation")
|
||||
public ActionResult<List<MonthStatsDailySituationVo>> getAttendanceDailySituation(@Valid @RequestBody MonthStatsDetailsDto dto) {
|
||||
return ActionResult.success(dayStaService.getAttendanceDailySituation(dto));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "获取多考勤组月度考勤工时排行")
|
||||
@PostMapping(value = "/getAttendanceHoursRanking")
|
||||
public ActionResult<List<MonthStatsHoursRankingVo>> getAttendanceHoursRanking(@Valid @RequestBody MonthStatsDetailsDto dto) {
|
||||
return ActionResult.success(dayStaService.getAttendanceHoursRanking(dto));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "获取多考勤组月度全勤情况")
|
||||
@PostMapping(value = "/getAttendanceFullSituation")
|
||||
public ActionResult<List<MonthStatsFullSituationVo>> getAttendanceFullSituation(@Valid @RequestBody MonthStatsDetailsDto dto) {
|
||||
return ActionResult.success(dayStaService.getAttendanceFullSituation(dto));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "获取多考勤组月度异常情况")
|
||||
@PostMapping(value = "/getAttendanceAbnormalCondition")
|
||||
public ActionResult<MonthStatsAbnormalConditionVo> getAttendanceAbnormalCondition(@Valid @RequestBody MonthStatsDetailsDto dto) {
|
||||
return ActionResult.success(dayStaService.getAttendanceAbnormalCondition(dto));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "获取多考勤组月度加班情况")
|
||||
@PostMapping(value = "/getAttendanceOvertimeSituation")
|
||||
public ActionResult<List<MonthStatsOvertimeSituationVo>> getAttendanceOvertimeSituation(@Valid @RequestBody MonthStatsDetailsDto dto) {
|
||||
return ActionResult.success(dayStaService.getAttendanceOvertimeSituation(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤封账-自动封账设置详情")
|
||||
@GetMapping(value = "/getAutoSealSettingInfo")
|
||||
public ActionResult<MonthAutoSealSettingVo> getAutoSealSettingInfo() {
|
||||
return ActionResult.success(sealSettingService.getAutoSealSettingInfo());
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤封账-自动封账设置")
|
||||
@PutMapping(value = "/autoSealSetting")
|
||||
public ActionResult<Boolean> autoSealSetting(@Valid @RequestBody MonthAutoSealSettingDto dto) {
|
||||
return ActionResult.success(sealSettingService.autoSealSetting(dto));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "考勤封账-自动封账定时器")
|
||||
@PutMapping(value = "/autoSealTimer")
|
||||
public ActionResult<Boolean> autoSealTimer(@RequestParam(value = "tenantId") String tenantId) {
|
||||
return ActionResult.success(sealSettingService.autoSealTimer(tenantId));
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤封账-分页列表")
|
||||
@PostMapping(value = "/sealPageList")
|
||||
public ActionResult<PageListVO<MonthSealPageListVo>> sealPageList(@Valid @RequestBody MonthSealPageListDto dto) {
|
||||
PageInfo<MonthSealPageListVo> page = dayStaService.sealPageList(dto);
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤封账-批量|单个封账")
|
||||
@PutMapping(value = "/sealSubmit")
|
||||
public ActionResult<Boolean> sealSubmit(@Valid @RequestBody MonthSealSubmitDto dto) {
|
||||
return ActionResult.success(dayStaService.sealSubmit(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤封账-解封")
|
||||
@PutMapping(value = "/unSealSubmit")
|
||||
public ActionResult<Boolean> unSealSubmit(@Valid @RequestBody MonthUnSealSubmitDto dto) {
|
||||
return ActionResult.success(dayStaService.unSealSubmit(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "批量查询用户是否封账")
|
||||
@PostMapping(value = "/selectUserIsSeal")
|
||||
public ActionResult<Map<String, Boolean>> selectUserIsSeal(@Valid @RequestBody MonthSealSubmitDto dto) {
|
||||
return ActionResult.success(dayStaService.selectUserIsSeal(dto.getUserIdList(), dto.getMonth()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "薪酬考勤数据支持(薪酬)")
|
||||
@PostMapping(value = "/salaryAttendanceSupport")
|
||||
public Map<String, SalaryAttendanceSupportVo> salaryAttendanceSupport(@Valid @RequestBody SalaryAttendanceSupportDto dto) {
|
||||
return dayStaService.salaryAttendanceSupport(dto);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "考勤统计数据日度列表表头(薪酬)")
|
||||
@PostMapping(value = "/attendanceDayStaTable")
|
||||
public List<AttendanceCustomizeTableVo> attendanceDayStaTable() {
|
||||
return tableService.findList(null, null, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "考勤统计数据日度列表(薪酬)")
|
||||
@PostMapping(value = "/attendanceDayStaList")
|
||||
public List<DayStatisticsPageListVo> attendanceDayStaList(@Valid @RequestBody SalaryAttendanceSupportDto dto) {
|
||||
return dayStaService.attendanceStaList(dto);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "获取日出勤信息")
|
||||
@NoDataSourceBind
|
||||
@PostMapping(value = "/getAttendanceDayStaList")
|
||||
public List<DayStatisticsVo> getAttendanceDayStaList(@Valid @RequestBody DayStatisticsDto dto) {
|
||||
//切换成租户库
|
||||
try {
|
||||
TenantDataSourceUtil.switchTenant(dto.getTenantId());
|
||||
} catch (LoginException e) {
|
||||
throw new RuntimeException("切换租户失败");
|
||||
}
|
||||
return dayStaService.getAttendanceDayStaList(dto);
|
||||
}
|
||||
|
||||
@NoDataSourceBind
|
||||
@Operation(summary = "模拟统计数据消息推送")
|
||||
@GetMapping("/mockStatisticsPush")
|
||||
public ActionResult<Boolean> mockStatisticsPush(@RequestParam("tenantId") String tenantId,
|
||||
@RequestParam("groupId") String groupId,
|
||||
@RequestParam("userId") String userId,
|
||||
@RequestParam("day") String day) {
|
||||
StatisticsSingleDto courseEventDTO = StatisticsSingleDto.builder()
|
||||
.tenantId(tenantId)
|
||||
.groupId(groupId)
|
||||
.userId(userId)
|
||||
.triggerSceneEnum(TriggerSceneEnum.MANUAL_TRIGGER)
|
||||
.day(DateUtil.parse(day))
|
||||
.build();
|
||||
Message<StatisticsSingleDto> message = MessageBuilder.withPayload(courseEventDTO).build();
|
||||
rocketMqTemplate.syncSend(MessageTopicConstants.ATTENDANCE_STATISTICS_SINGLE_TOPIC, message, 3000L, 2);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
@NoDataSourceBind
|
||||
@Operation(summary = "日统计触发")
|
||||
@GetMapping("/dayStatisticsTriggered")
|
||||
public ActionResult<Boolean> dayStatisticsTriggered(@RequestParam("tenantId") String tenantId,
|
||||
@RequestParam("groupId") String groupId,
|
||||
@RequestParam("userId") String userId,
|
||||
@RequestParam("day") String day) throws LoginException {
|
||||
StatisticsSingleDto courseEventDTO = StatisticsSingleDto.builder()
|
||||
.tenantId(tenantId)
|
||||
.groupId(groupId)
|
||||
.userId(userId)
|
||||
.day(DateUtil.parse(day))
|
||||
.triggerSceneEnum(TriggerSceneEnum.MANUAL_TRIGGER)
|
||||
.build();
|
||||
dayStaService.statisticDataChange(courseEventDTO);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
@NoDataSourceBind
|
||||
@Operation(summary = "日统计数据清除")
|
||||
@GetMapping("/dayStatisticsClear")
|
||||
public ActionResult<Boolean> dayStatisticsClear(@RequestParam("tenantId") String tenantId,
|
||||
@RequestParam("groupId") String groupId,
|
||||
@RequestParam("userId") List<String> userList,
|
||||
@RequestParam("day") String day,
|
||||
@RequestParam("startDay") String startDay) {
|
||||
StatisticsBatchClearDto courseEventDTO = StatisticsBatchClearDto.builder()
|
||||
.tenantId(tenantId)
|
||||
.groupId(groupId)
|
||||
.userIdList(userList)
|
||||
.day(DateUtil.parse(day))
|
||||
.startDay(DateUtil.parse(startDay))
|
||||
.build();
|
||||
dayStaService.batchStatisticDataClear(courseEventDTO);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
@NoDataSourceBind
|
||||
@Operation(summary = "重新生成日统计数据")
|
||||
@GetMapping(value = "/regenerateDayData")
|
||||
public ActionResult<Boolean> regenerateDayData(@RequestParam("tenantId") String tenantId,
|
||||
@RequestParam("start") Date start) {
|
||||
dayStaService.regenerateDayData(tenantId, start);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
@NoDataSourceBind
|
||||
@Operation(summary = "处理历史数据")
|
||||
@GetMapping(value = "/processHistoricalData")
|
||||
public ActionResult<Boolean> processHistoricalData(@RequestParam("tenantId") String tenantId,
|
||||
@RequestParam("start") Date start,
|
||||
@RequestParam("end") Date end) {
|
||||
dayStaService.processHistoricalData(tenantId, start, end);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "获取各维度出勤人数")
|
||||
@PostMapping(value = "/getDimensionsAttendanceCountMap")
|
||||
public Map<String, List<DateDimensionsRangeVo>> getDimensionsAttendanceCountMap(@Valid @RequestBody DimensionsAttendanceCountDto dto) {
|
||||
return dayStaService.getDimensionsAttendanceCountMap(dto);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "获取各维度出勤人数(天维度)")
|
||||
@PostMapping(value = "/getDimensionsAttendanceDayCountMap")
|
||||
public Map<String, Map<Date, Integer>> getDimensionsAttendanceDayCountMap(@Valid @RequestBody DimensionsAttendanceDayCountDto dto) {
|
||||
return dayStaService.getDimensionsAttendanceDayCountMap(dto);
|
||||
}
|
||||
|
||||
@Operation(summary = "日度计薪统计-分页列表")
|
||||
@PostMapping(value = "/dayPayrollPageList")
|
||||
public ActionResult<PageListVO<DayPayrollStatisticsPageListVo>> dayPayrollPageList(@Valid @RequestBody DayPayrollStatisticsPageListDto req) {
|
||||
PageInfo<DayPayrollStatisticsPageListVo> page = dayStaService.getDayPayrollPageList(req);
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
|
||||
@Operation(summary = "月度计薪统计-分页列表")
|
||||
@PostMapping(value = "/monthPayrollPageList")
|
||||
public ActionResult<PageListVO<MonthPayrollStatisticsPageListVo>> monthPayrollPageList(@Valid @RequestBody MonthPayrollStatisticsPageListDto req) throws Exception {
|
||||
PageInfo<MonthPayrollStatisticsPageListVo> page = dayStaService.getMonthPayrollPageList(req);
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤平均工时趋势-分页列表")
|
||||
@PostMapping(value = "/averageWorkHoursTrend/pageList")
|
||||
public ActionResult<PersonnelDataAnalysisListVO> averageWorkHoursTrendPageList(@Valid @RequestBody PersonnelApiInfoPageListDto dto) {
|
||||
PageListVO<AverageTrendPageListVo> result = dayStaService.averageWorkHoursTrendPageList(dto);
|
||||
return ActionResult.success(PersonnelDataAnalysisUtil.encapsulatePageData(result, AverageTrendPageListVo.class));
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤平均工时趋势-导出")
|
||||
@PostMapping(value = "/averageWorkHoursTrend/export")
|
||||
public void averageWorkHoursTrendExport(HttpServletResponse response, @Valid @RequestBody PersonnelApiInfoPageListDto pageDto) throws Exception {
|
||||
dayStaService.averageWorkHoursTrendExport(response, pageDto);
|
||||
}
|
||||
|
||||
@Operation(summary = "人均工时趋势-分页列表")
|
||||
@PostMapping(value = "/personWorkHoursTrend/pageList")
|
||||
public ActionResult<PersonnelDataAnalysisListVO> personWorkHoursTrendPageList(@Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) {
|
||||
PageListVO<PersonnelTrendPageListVo> result = dayStaService.personWorkHoursTrendPageList(pageDto);
|
||||
return ActionResult.success(PersonnelDataAnalysisUtil.encapsulatePageData(result, PersonnelTrendPageListVo.class));
|
||||
}
|
||||
|
||||
@Operation(summary = "人均工时趋势-导出")
|
||||
@PostMapping(value = "/personWorkHoursTrend/export")
|
||||
public void personWorkHoursTrendExport(HttpServletResponse response, @Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) throws Exception {
|
||||
dayStaService.personWorkHoursTrendExport(response, pageDto);
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤组日常情况-分页列表")
|
||||
@PostMapping(value = "/dailySituation/pageList")
|
||||
public ActionResult<PersonnelDataAnalysisListVO> dailySituationPageList(@Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) {
|
||||
PageListVO<DailySituationPageListVo> result = dayStaService.dailySituationPageList(pageDto);
|
||||
return ActionResult.success(PersonnelDataAnalysisUtil.encapsulatePageData(result, DailySituationPageListVo.class));
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤组日常情况-导出")
|
||||
@PostMapping(value = "/dailySituation/export")
|
||||
public void dailySituationExport(HttpServletResponse response, @Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) throws Exception {
|
||||
dayStaService.dailySituationExport(response, pageDto);
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤工时排行-分页列表")
|
||||
@PostMapping(value = "/workHoursRanking/pageList")
|
||||
public ActionResult<PersonnelDataAnalysisListVO> workHoursRankingPageList(@Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) {
|
||||
PageListVO<WorkHoursRankingPageListVo> result = dayStaService.workHoursRankingPageList(pageDto);
|
||||
return ActionResult.success(PersonnelDataAnalysisUtil.encapsulatePageData(result, WorkHoursRankingPageListVo.class));
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤工时排行-导出")
|
||||
@PostMapping(value = "/workHoursRanking/export")
|
||||
public void workHoursRankingExport(HttpServletResponse response, @Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) throws Exception {
|
||||
dayStaService.workHoursRankingExport(response, pageDto);
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤组全勤情况-分页列表")
|
||||
@PostMapping(value = "/fullAttendanceStatus/pageList")
|
||||
public ActionResult<PersonnelDataAnalysisListVO> fullAttendanceStatusPageList(@Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) {
|
||||
PageListVO<FullAttendanceStatusPageListVo> result = dayStaService.fullAttendanceStatusPageList(pageDto);
|
||||
return ActionResult.success(PersonnelDataAnalysisUtil.encapsulatePageData(result, FullAttendanceStatusPageListVo.class));
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤组全勤情况-导出")
|
||||
@PostMapping(value = "/fullAttendanceStatus/export")
|
||||
public void fullAttendanceStatusExport(HttpServletResponse response, @Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) throws Exception {
|
||||
dayStaService.fullAttendanceStatusExport(response, pageDto);
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤异常情况-分页列表")
|
||||
@PostMapping(value = "/exceptionSituation/pageList")
|
||||
public ActionResult<PersonnelDataAnalysisListVO> exceptionSituationPageList(@Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) {
|
||||
PageListVO<ExceptionSituationPageListVo> result = dayStaService.exceptionSituationPageList(pageDto);
|
||||
return ActionResult.success(PersonnelDataAnalysisUtil.encapsulatePageData(result, ExceptionSituationPageListVo.class));
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤异常情况-导出")
|
||||
@PostMapping(value = "/exceptionSituation/export")
|
||||
public void exceptionSituationExport(HttpServletResponse response, @Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) throws Exception {
|
||||
dayStaService.exceptionSituationExport(response, pageDto);
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤组加班情况-分页列表")
|
||||
@PostMapping(value = "/overtimeSituation/pageList")
|
||||
public ActionResult<PersonnelDataAnalysisListVO> overtimeSituationPageList(@Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) {
|
||||
PageListVO<OvertimeSituationPageListVo> result = dayStaService.overtimeSituationPageList(pageDto);
|
||||
return ActionResult.success(PersonnelDataAnalysisUtil.encapsulatePageData(result, OvertimeSituationPageListVo.class));
|
||||
}
|
||||
|
||||
@Operation(summary = "考勤组加班情况-导出")
|
||||
@PostMapping(value = "/overtimeSituation/export")
|
||||
public void overtimeSituationExport(HttpServletResponse response, @Valid @RequestBody PersonnelApiInfoSinglePageListDto pageDto) throws Exception {
|
||||
dayStaService.overtimeSituationExport(response, pageDto);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询用户考勤统计信息")
|
||||
@PostMapping(value = "/queryUserStatisticsInfo")
|
||||
@FtbCheckPermission("attendance_2.0.statistics.monthlyStatistics")
|
||||
public ActionResult<QueryStatisticsInfoVo> queryUserStatisticsInfo(@Valid @RequestBody QueryStatisticsInfoDto dto) {
|
||||
return ActionResult.success(dayStaService.queryUserStatisticsInfo(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询考勤组的考勤情况")
|
||||
@PostMapping(value = "/queryGroupStatistics")
|
||||
@FtbCheckPermission("attendance_2.0.statistics.monthlyStatistics")
|
||||
public ActionResult<QueryGroupStatisticsVo> queryGroupStatistics(@Valid @RequestBody QueryGroupStatisticsDto dto) {
|
||||
return ActionResult.success(dayStaService.queryGroupStatistics(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询用户的加班情况")
|
||||
@PostMapping(value = "/queryUserOvertime")
|
||||
@FtbCheckPermission("attendance_2.0.statistics.monthlyStatistics")
|
||||
public ActionResult<QueryUserOvertimeVo> queryUserOvertime(@Valid @RequestBody QueryStatisticsInfoDto dto) {
|
||||
return ActionResult.success(dayStaService.queryUserOvertime(dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询用户的上班情况")
|
||||
@PostMapping(value = "/queryUserWorkSituation")
|
||||
public ActionResult<Map<String, UserWorkSituationVo>> queryUserWorkSituation(@Valid @RequestBody UserWorkSituationDto dto) {
|
||||
return ActionResult.success(dayStaService.queryUserWorkSituation(dto));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package jnpf.attendance.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.attendance.service.WorkstationService;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.base.vo.PageListVO;
|
||||
import jnpf.model.attendance.dto.WorkstationQueryDto;
|
||||
import jnpf.model.attendance.dto.WorkstationSaveDto;
|
||||
import jnpf.model.attendance.dto.WorkstationUserAddDto;
|
||||
import jnpf.model.attendance.dto.WorkstationUserRemoveDto;
|
||||
import jnpf.model.attendance.vo.WorkstationDetailVo;
|
||||
import jnpf.model.attendance.vo.WorkstationVo;
|
||||
import jnpf.model.attendance.vo.WorkstationWithUsersVo;
|
||||
import jnpf.util.FtbUtil;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤工作站控制器
|
||||
*
|
||||
* @author AI Generated
|
||||
* @create 2026-05-11
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/attendance/workstation")
|
||||
public class WorkstationController {
|
||||
|
||||
@Resource
|
||||
private WorkstationService workstationService;
|
||||
|
||||
/**
|
||||
* 查询工作站列表(分页)
|
||||
*
|
||||
* @param dto 查询条件(含分页参数 currentPage/pageSize)
|
||||
* @return 工作站分页列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public ActionResult<PageListVO<WorkstationVo>> list(WorkstationQueryDto dto) {
|
||||
PageInfo<WorkstationVo> page = workstationService.listWorkstations(dto);
|
||||
return ActionResult.page(page.getList(), FtbUtil.getPagination(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增工作站
|
||||
*
|
||||
* @param dto 工作站保存DTO
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PostMapping
|
||||
public ActionResult<Void> add(@RequestBody @Valid WorkstationSaveDto dto) {
|
||||
workstationService.saveWorkstation(dto);
|
||||
return ActionResult.success("新增成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑工作站
|
||||
*
|
||||
* @param id 工作站ID
|
||||
* @param dto 工作站保存DTO
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
public ActionResult<Void> update(@PathVariable String id, @RequestBody @Valid WorkstationSaveDto dto) {
|
||||
workstationService.updateWorkstation(id, dto);
|
||||
return ActionResult.success("编辑成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除工作站
|
||||
*
|
||||
* @param id 工作站ID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public ActionResult<Void> delete(@PathVariable String id) {
|
||||
workstationService.deleteWorkstation(id);
|
||||
return ActionResult.success("删除成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加人员
|
||||
*
|
||||
* @param dto 添加人员DTO
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PostMapping("/users/add")
|
||||
public ActionResult<Void> addUsers(@RequestBody @Valid WorkstationUserAddDto dto) {
|
||||
workstationService.addUsers(dto);
|
||||
return ActionResult.success("添加成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除人员
|
||||
*
|
||||
* @param dto 删除人员DTO
|
||||
* @return 操作结果
|
||||
*/
|
||||
@DeleteMapping("/users/remove")
|
||||
public ActionResult<Void> removeUser(@RequestBody @Valid WorkstationUserRemoveDto dto) {
|
||||
workstationService.removeUser(dto);
|
||||
return ActionResult.success("删除成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询工作站详情
|
||||
*
|
||||
* @param id 工作站ID
|
||||
* @return 工作站详情
|
||||
*/
|
||||
@GetMapping("/{id}/detail")
|
||||
public ActionResult<WorkstationDetailVo> detail(
|
||||
@PathVariable String id) {
|
||||
return ActionResult.success(workstationService.getDetail(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按考勤组查询工作站及其归属员工(含在组日、划线排班权限)
|
||||
*
|
||||
* @param groupId 考勤组ID
|
||||
* @param startTime 查询开始日期(含),yyyy-MM-dd
|
||||
* @param endTime 查询结束日期(含),yyyy-MM-dd;同时作为成员快照截止日
|
||||
*/
|
||||
@GetMapping("/by-group/{groupId}")
|
||||
public ActionResult<List<WorkstationWithUsersVo>> listByGroupId(
|
||||
@PathVariable String groupId,
|
||||
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime,
|
||||
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date endTime) {
|
||||
return ActionResult.success(workstationService.listWorkstationsByGroupId(groupId, startTime, endTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置工作站人员:恢复为岗位默认归属人员,清除另加入的额外人员
|
||||
*
|
||||
* @param id 工作站ID
|
||||
*/
|
||||
@PostMapping("/{id}/reset")
|
||||
public ActionResult<Void> reset(@PathVariable String id) {
|
||||
workstationService.resetWorkstationUsers(id);
|
||||
return ActionResult.success("重置成功");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package jnpf.attendance.entity;
|
||||
|
||||
import jnpf.entity.AttendanceGroup;
|
||||
import jnpf.entity.AttendanceGroupUser;
|
||||
import jnpf.entity.attendance.AttendanceBaseSetting;
|
||||
import jnpf.entity.attendance.AttendanceFestivalRules;
|
||||
import jnpf.model.attendance.vo.AttendanceShiftSettingVo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class FixedHandleDTO {
|
||||
private List<String> groupIds;
|
||||
private Date start;
|
||||
private Date end;
|
||||
private List<AttendanceGroup> attendanceGroupVos;
|
||||
private List<AttendanceGroupUser> users;
|
||||
private Map<String, AttendanceBaseSetting> enableBaseSetting;
|
||||
private Map<String, AttendanceShiftSettingVo> shiftSettingMap;
|
||||
private Map<String, List<AttendanceFestivalRules>> festivalMap;
|
||||
private String tenantId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package jnpf.attendance.event;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import jnpf.attendance.service.AttendanceClockInService;
|
||||
import jnpf.base.UserInfo;
|
||||
import jnpf.constants.MessageTopicConstants;
|
||||
import jnpf.constants.RedisConstant;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.model.attendance.vo.UserDayVo;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.compress.utils.Lists;
|
||||
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
|
||||
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
|
||||
import org.apache.rocketmq.spring.annotation.ConsumeMode;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static jnpf.constants.RedisConstant.ATTENDANCE_NOTIFICATION_CLOCK_USER;
|
||||
|
||||
/**
|
||||
* 考勤统计-单条消息监听,监听生成用户日统计消息
|
||||
* @author 石头
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = MessageTopicConstants.ATTENDANCE_NOTIFICATION_CLOCK_TOPIC,
|
||||
consumerGroup = MessageTopicConstants.ATTENDANCE_NOTIFICATION_CLOCK_CONSUMER_GROUP,
|
||||
consumeMode = ConsumeMode.CONCURRENTLY,
|
||||
maxReconsumeTimes = 5)
|
||||
public class NotificationClockMQListener implements RocketMQListener<List<UserDayVo>>, RocketMQPushConsumerLifecycleListener {
|
||||
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
@Autowired
|
||||
private AttendanceClockInService attendanceClockInService;
|
||||
|
||||
@Override
|
||||
public void onMessage(List<UserDayVo> userDayList) {
|
||||
if (CollUtil.isEmpty(userDayList)) {
|
||||
return;
|
||||
}
|
||||
log.error("接受到排班通知打卡消息,{}", JSONObject.toJSONString(userDayList));
|
||||
UserDayVo userDayVo1 = userDayList.get(0);
|
||||
Assert.isFalse(StringUtil.isEmpty(userDayVo1.getTenantId()), "排班通知打卡tenantId不能为空");
|
||||
List<RLock> locks = Lists.newArrayList();
|
||||
try {
|
||||
for (UserDayVo userDayVo : userDayList) {
|
||||
String lockKey = String.format(ATTENDANCE_NOTIFICATION_CLOCK_USER, userDayVo.getUserId(), userDayVo.getDay());
|
||||
RLock lock = redissonClient.getLock(lockKey);
|
||||
RLock lock1 = redissonClient.getLock(String.format(RedisConstant.ATTENDANCE_USER_SET_SCHEDULES, userDayVo.getTenantId(), userDayVo.getUserId(), userDayVo.getUserId()));
|
||||
// 立即尝试获取锁(不等待),失败直接抛异常
|
||||
if (lock.isLocked() || lock1.isLocked() || !lock.tryLock(5, 60, TimeUnit.SECONDS)) {
|
||||
throw new RuntimeException(userDayVo.getUserId() + "通知打卡获取锁失败");
|
||||
}
|
||||
locks.add(lock);
|
||||
}
|
||||
TenantDataSourceUtil.switchTenant(userDayVo1.getTenantId());
|
||||
UserInfo user = new UserInfo();
|
||||
user.setUserId(userDayVo1.getUserId());
|
||||
user.setTenantId(userDayVo1.getTenantId());
|
||||
// 执行业务(异常直接向上抛出)
|
||||
attendanceClockInService.changeAttendanceRuleBatch(userDayList, user);
|
||||
|
||||
} catch (Exception ex) {
|
||||
log.error("处理排班通知打卡消息失败,触发重试,消息 {} ", JSONObject.toJSONString(userDayList), ex);
|
||||
throw new RuntimeException("处理排班通知打卡消息失败,触发重试", ex);
|
||||
} finally {
|
||||
// 安全释放:仅当前线程持有时释放,异常仅记录不抛出
|
||||
locks.forEach(lock -> {
|
||||
if (lock != null && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareStart(DefaultMQPushConsumer consumer) {
|
||||
// 优化消费参数 每次拉取的消息数量
|
||||
consumer.setPullBatchSize(32);
|
||||
// 设置消费间隔,避免过于频繁拉取
|
||||
consumer.setPullInterval(200);
|
||||
// 设置消费超时时间(分钟)
|
||||
consumer.setConsumeTimeout(10);
|
||||
// 设置消费起始位置(从上次消费的位置继续)
|
||||
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
|
||||
// 调整消费线程池最小线程数
|
||||
consumer.setConsumeThreadMin(10);
|
||||
// 调整消费线程池最大线程数
|
||||
consumer.setConsumeThreadMax(20);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package jnpf.attendance.event;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import jnpf.attendance.service.AttendanceUserService;
|
||||
import jnpf.constants.MessageTopicConstants;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.message.model.permission.PermissionRelationOrganizeUserListDTO;
|
||||
import jnpf.model.attendance.model.OrganizeUserConsumerDTO;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static jnpf.constants.RedisConstant.GROUP_JOIN_USERS_KEY;
|
||||
import static jnpf.constants.RedisConstant.GROUP_ONBOARDING_KEY;
|
||||
|
||||
/**
|
||||
* 入职请求信息
|
||||
*/
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = MessageTopicConstants.PERSONNEL_ONBOARDING_TOPIC,
|
||||
consumerGroup = MessageTopicConstants.ONBOARDING_GROUP,
|
||||
replyTimeout = 600000,
|
||||
maxReconsumeTimes = 3,
|
||||
nameServer = "${spring.cloud.stream.rocketmq.binder.name-server}"
|
||||
)
|
||||
@Slf4j
|
||||
public class OnboardingConsumerMQListener implements RocketMQListener<String> {
|
||||
@Autowired
|
||||
private AttendanceUserService attendanceUserService;
|
||||
@Autowired
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
if (StringUtil.isEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
log.error("接收入职/变动请求信息{}", message);
|
||||
OrganizeUserConsumerDTO messageList = JSON.parseObject(message, OrganizeUserConsumerDTO.class);
|
||||
if (StringUtil.equals(messageList.getBeforeOrgId(), messageList.getOrganizeId())) {
|
||||
return;
|
||||
}
|
||||
RLock lock = null;
|
||||
try {
|
||||
String key = String.format(GROUP_JOIN_USERS_KEY, messageList.getUserId());
|
||||
lock = redissonClient.getLock(key);
|
||||
if (!lock.tryLock(5, 10, TimeUnit.SECONDS)) {
|
||||
log.error("接收组织人员添加通知,目前用户【{}】正在被变更!", messageList.getUserId());
|
||||
throw new RuntimeException(String.format("接收组织人员添加通知,目前用户【%s】正在被变更,触发重试", messageList.getUserId()));
|
||||
}
|
||||
PermissionRelationOrganizeUserListDTO permissionRelationOrganizeUserListDTO = new PermissionRelationOrganizeUserListDTO();
|
||||
permissionRelationOrganizeUserListDTO.setUserId(messageList.getUserId());
|
||||
permissionRelationOrganizeUserListDTO.setOldOrganizeId(messageList.getBeforeOrgId());
|
||||
permissionRelationOrganizeUserListDTO.setOrganizeId(messageList.getOrganizeId());
|
||||
permissionRelationOrganizeUserListDTO.setEntryDate(messageList.getEntryDate());
|
||||
permissionRelationOrganizeUserListDTO.setTenantId(messageList.getTenantId());
|
||||
TenantDataSourceUtil.switchTenant(messageList.getTenantId());
|
||||
if (StringUtil.isNotEmpty(messageList.getBeforeOrgId())) {
|
||||
attendanceUserService.removeUsers(List.of(permissionRelationOrganizeUserListDTO), false);
|
||||
}
|
||||
attendanceUserService.addUsers(List.of(permissionRelationOrganizeUserListDTO), true);
|
||||
} catch (Exception e) {
|
||||
log.error("消息解析异常: message={}", message, e);
|
||||
throw new RuntimeException(e.getMessage());
|
||||
} finally{
|
||||
if (Objects.nonNull(lock) && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package jnpf.attendance.event;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import jnpf.attendance.service.AttendanceUserService;
|
||||
import jnpf.constants.MessageTopicConstants;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.message.model.permission.PermissionRelationOrganizeUserListDTO;
|
||||
import jnpf.model.attendance.model.TurnoverConsumerModel;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 终止入职信息
|
||||
*/
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = MessageTopicConstants.PERSONNEL_SECONDMENT_FAIL_TOPIC,
|
||||
consumerGroup = MessageTopicConstants.ONBOARDING_FAIL_GROUP,
|
||||
replyTimeout = 600000,
|
||||
maxReconsumeTimes = 3,
|
||||
nameServer = "${spring.cloud.stream.rocketmq.binder.name-server}"
|
||||
)
|
||||
@Slf4j
|
||||
public class OnboardingFailConsumerMQListener implements RocketMQListener<String> {
|
||||
@Autowired
|
||||
private AttendanceUserService attendanceUserService;
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
if (StringUtil.isEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
log.error("接受终止入职信息{}", message);
|
||||
try {
|
||||
TurnoverConsumerModel messageList = JSON.parseObject(message, TurnoverConsumerModel.class);
|
||||
if (Objects.isNull(messageList)) {
|
||||
return;
|
||||
}
|
||||
TenantDataSourceUtil.switchTenant(messageList.getTenantId());
|
||||
PermissionRelationOrganizeUserListDTO permissionRelationOrganizeUserListDTO = new PermissionRelationOrganizeUserListDTO();
|
||||
permissionRelationOrganizeUserListDTO.setOldOrganizeId(messageList.getCurrOrgId());
|
||||
permissionRelationOrganizeUserListDTO.setUserId(messageList.getUserId());
|
||||
//删
|
||||
attendanceUserService.removeUsers(List.of(permissionRelationOrganizeUserListDTO),false);
|
||||
} catch (Exception e) {
|
||||
log.error("消息解析异常: message={}", message, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package jnpf.attendance.event;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import jnpf.attendance.service.AttendanceGroupService;
|
||||
import jnpf.constants.MessageTopicConstants;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.message.enums.permission.v2.OperationTypeMessageEnums;
|
||||
import jnpf.message.model.permission.v2.OrganizeUpdateMessageDTO;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 组织变更消费者
|
||||
*/
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = MessageTopicConstants.PERMISSION_TOPIC,
|
||||
consumerGroup = MessageTopicConstants.JNPF_GROUP,
|
||||
selectorExpression = MessageTopicConstants.TAG_ORGANIZE,
|
||||
replyTimeout = 600000,
|
||||
maxReconsumeTimes = 3,
|
||||
nameServer = "${spring.cloud.stream.rocketmq.binder.name-server}"
|
||||
)
|
||||
@Slf4j
|
||||
public class OrganizeConsumerMQListener implements RocketMQListener<String> {
|
||||
@Autowired
|
||||
private AttendanceGroupService attendanceGroupService;
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
if (StringUtil.isEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
log.error("接受组织变更信息{}", message);
|
||||
try {
|
||||
List<OrganizeUpdateMessageDTO> messageList = JSON.parseArray(message, OrganizeUpdateMessageDTO.class);
|
||||
if (CollUtil.isEmpty(messageList) || StringUtil.isEmpty(messageList.get(0).getId())) {
|
||||
return;
|
||||
}
|
||||
TenantDataSourceUtil.switchTenant(messageList.get(0).getTenantId());
|
||||
List<OrganizeUpdateMessageDTO> collect = messageList.stream().filter(vo -> Objects.equals(vo.getOperationTypeEnum(), OperationTypeMessageEnums.ADD) || Objects.equals(vo.getOperationTypeEnum(), OperationTypeMessageEnums.UPDATE)).collect(Collectors.toList());
|
||||
attendanceGroupService.batchSaveGroupByOrgIds(collect.get(0).getTenantId(), collect.stream().map(OrganizeUpdateMessageDTO::getId).collect(Collectors.toList()));
|
||||
} catch (Exception e) {
|
||||
log.error("消息解析异常: message={}", message, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package jnpf.attendance.event;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import jnpf.attendance.service.AttendanceUserService;
|
||||
import jnpf.constants.MessageTopicConstants;
|
||||
import jnpf.message.model.permission.PermissionRelationOrganizeUserListDTO;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 组织下人员变更
|
||||
*/
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = MessageTopicConstants.PERMISSION_TOPIC,
|
||||
consumerGroup = MessageTopicConstants.JNPF_USER_GROUP,
|
||||
selectorExpression = MessageTopicConstants.ORGANIZE_RELATION_USER,
|
||||
replyTimeout = 600000,
|
||||
maxReconsumeTimes = 3,
|
||||
nameServer = "${spring.cloud.stream.rocketmq.binder.name-server}"
|
||||
)
|
||||
@Slf4j
|
||||
public class OrganizeUserConsumerMQListener implements RocketMQListener<String> {
|
||||
@Autowired
|
||||
private AttendanceUserService attendanceUserService;
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
if (StringUtil.isEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
log.error("接受组织下人员(批量入职/批量删除/预入职/离职)变更信息{}", message);
|
||||
try {
|
||||
List<PermissionRelationOrganizeUserListDTO> messageList = JSON.parseArray(message, PermissionRelationOrganizeUserListDTO.class);
|
||||
if (CollUtil.isEmpty(messageList) || StringUtil.isEmpty(messageList.get(0).getUserId())) {
|
||||
log.error("接受组织下人员无效数据过滤{}", message);
|
||||
return;
|
||||
}
|
||||
//增删改
|
||||
attendanceUserService.orgUpdateHandle(messageList);
|
||||
} catch (Exception e) {
|
||||
log.error("消息解析异常: message={}", message, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package jnpf.attendance.event;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import jnpf.attendance.service.AttendanceDailyRuleService;
|
||||
import jnpf.attendance.service.AttendanceGroupService;
|
||||
import jnpf.constants.MessageTopicConstants;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.exception.ApproveException;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.attendance.dto.AttendanceSecondedDto;
|
||||
import jnpf.model.personnels.dto.secondment.msg.SecondmentMsgUserInfo;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 借调申请消息
|
||||
*/
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = MessageTopicConstants.PERSONNEL_SECONDMENT_TOPIC,
|
||||
consumerGroup = MessageTopicConstants.SECONDMENT_GROUP,
|
||||
replyTimeout = 600000,
|
||||
nameServer = "${spring.cloud.stream.rocketmq.binder.name-server}"
|
||||
)
|
||||
@Slf4j
|
||||
public class SecondmentConsumerMQListener implements RocketMQListener<String> {
|
||||
@Resource
|
||||
private AttendanceDailyRuleService attendanceDailyRuleService;
|
||||
@Autowired
|
||||
private AttendanceGroupService attendanceGroupService;
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
if (StringUtil.isEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
log.error("接受借调申请信息{}", message);
|
||||
try {
|
||||
SecondmentMsgUserInfo messageList = JSONUtil.toBean(message, SecondmentMsgUserInfo.class);
|
||||
if (Objects.isNull(messageList)) {
|
||||
return;
|
||||
}
|
||||
if (StringUtil.equals(messageList.getOriginalOrganizationId(), messageList.getSecondedOrganizationId())) {
|
||||
return;
|
||||
}
|
||||
AttendanceSecondedDto bean = new AttendanceSecondedDto();
|
||||
bean.setBackTime(messageList.getSecondmentEndTime());
|
||||
bean.setDepartureTime(messageList.getSecondmentStartTime());
|
||||
bean.setStartTime(messageList.getSecondmentStartTime());
|
||||
bean.setEndTime(messageList.getSecondmentEndTime());
|
||||
bean.setUserIds(List.of(messageList.getUserId()));
|
||||
TenantDataSourceUtil.switchTenant(messageList.getTenantId());
|
||||
Map<String, String> org2grouopMap = attendanceGroupService.batchSaveGroupByOrgIds(messageList.getTenantId(), CollUtil.newArrayList(messageList.getOriginalOrganizationId(), messageList.getSecondedOrganizationId()));
|
||||
if (!org2grouopMap.containsKey(messageList.getOriginalOrganizationId()) || !org2grouopMap.containsKey(messageList.getSecondedOrganizationId())) {
|
||||
throw new ApproveException("组织不存在");
|
||||
}
|
||||
bean.setSelfGroupId(org2grouopMap.get(messageList.getOriginalOrganizationId()));
|
||||
bean.setGroupId(org2grouopMap.get(messageList.getSecondedOrganizationId()));
|
||||
try {
|
||||
attendanceGroupService.secondedStart(bean);
|
||||
} catch (HandleException e) {
|
||||
throw new ApproveException(e.getMessage());
|
||||
}
|
||||
//修改用户排班
|
||||
try {
|
||||
attendanceDailyRuleService.secondmentDailyRuleHandle(bean.getUserIds(), bean.getSelfGroupId(), bean.getGroupId(), bean.getStartTime(), bean.getEndTime(), bean.getDepartureTime(), bean.getBackTime(), messageList.getTenantId());
|
||||
} catch (HandleException e) {
|
||||
throw new ApproveException(e.getMessage());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("消息解析异常: message={}", message, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package jnpf.attendance.event;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jnpf.attendance.service.AttendanceDailyRuleService;
|
||||
import jnpf.attendance.service.AttendanceGroupService;
|
||||
import jnpf.attendance.service.AttendanceUserService;
|
||||
import jnpf.constants.MessageTopicConstants;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.entity.AttendanceGroup;
|
||||
import jnpf.entity.AttendanceGroupUser;
|
||||
import jnpf.model.attendance.vo.SecondmentDateVo;
|
||||
import jnpf.model.personnels.dto.secondment.msg.SecondmentMsgUserInfo;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.compress.utils.Lists;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 借调撤销消息
|
||||
*/
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = MessageTopicConstants.SECONDMENT_WITHDRAWAL_OUTPUT,
|
||||
consumerGroup = MessageTopicConstants.SECONDMENT_WITHDRAWAL_GROUP,
|
||||
replyTimeout = 600000,
|
||||
nameServer = "${spring.cloud.stream.rocketmq.binder.name-server}"
|
||||
)
|
||||
@Slf4j
|
||||
public class SecondmentWithdrawalConsumerMQListener implements RocketMQListener<String> {
|
||||
@Resource
|
||||
private AttendanceDailyRuleService attendanceDailyRuleService;
|
||||
@Autowired
|
||||
private AttendanceUserService attendanceUserService;
|
||||
@Autowired
|
||||
private AttendanceGroupService attendanceGroupService;
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
if (StringUtil.isEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
log.error("接受借调撤回信息{}", message);
|
||||
try {
|
||||
SecondmentMsgUserInfo messageList = JSONUtil.toBean(message, SecondmentMsgUserInfo.class);
|
||||
if (Objects.isNull(messageList)) {
|
||||
return;
|
||||
}
|
||||
TenantDataSourceUtil.switchTenant(messageList.getTenantId());
|
||||
//存在排班的借调撤回不执行
|
||||
Assert.isFalse(attendanceDailyRuleService.hasRuleByUserIdAndTime(messageList.getUserId(), messageList.getSecondmentStartTime(), messageList.getSecondmentEndTime()), "存在排班的借调撤回不执行");
|
||||
List<AttendanceGroup> byOrgId = attendanceGroupService.getByOrgIds(List.of(messageList.getOriginalOrganizationId(), messageList.getSecondedOrganizationId()));
|
||||
Map<String, String> group2orgMap = byOrgId.stream().collect(Collectors.toMap(AttendanceGroup::getId, AttendanceGroup::getOrgId));
|
||||
List<AttendanceGroupUser> userList = attendanceUserService.list(new LambdaQueryWrapper<AttendanceGroupUser>()
|
||||
.in(AttendanceGroupUser::getGroupId, byOrgId.stream().map(AttendanceGroup::getId).collect(Collectors.toList()))
|
||||
.eq(AttendanceGroupUser::getUserId, messageList.getUserId())
|
||||
);
|
||||
//删除借调组数据
|
||||
for (AttendanceGroupUser next : userList) {
|
||||
String orgId = group2orgMap.get(next.getGroupId());
|
||||
List<SecondmentDateVo> list = StringUtil.isEmpty(next.getTimeJson()) ? Lists.newArrayList() : JSONUtil.toList(next.getTimeJson(), SecondmentDateVo.class);
|
||||
if (list.stream().noneMatch(item -> item.getStartTime().compareTo(messageList.getSecondmentStartTime()) == 0)) {
|
||||
continue;
|
||||
}
|
||||
//如果是借调组或者被借调组,则根据借调时间范围找到timeJSON中指定时段并清除
|
||||
list.removeIf(item -> item.getStartTime().compareTo(messageList.getSecondmentStartTime()) == 0);
|
||||
if (CollUtil.isNotEmpty(list) || Objects.equals(next.getType(),1)) {
|
||||
next.setTimeJson(JSONUtil.toJsonStr(list));
|
||||
attendanceUserService.updateById(next);
|
||||
continue;
|
||||
}
|
||||
//当借调组的timeJson为空时,则删除该用户信息
|
||||
if (StringUtil.equals(orgId, messageList.getSecondedOrganizationId())) {
|
||||
attendanceUserService.removeById(next);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("消息解析异常: message={}", message, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package jnpf.attendance.event;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import jnpf.attendance.service.AttendanceDayStatisticsService;
|
||||
import jnpf.constants.MessageTopicConstants;
|
||||
import jnpf.model.attendance.event.StatisticsBatchClearDto;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
|
||||
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
|
||||
import org.apache.rocketmq.spring.annotation.ConsumeMode;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 批量清除日统计消息监听,监听批量清除日统计消息
|
||||
* @author 石头
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(topic = MessageTopicConstants.ATTENDANCE_STATISTICS_BATCH_CLEAR_TOPIC,
|
||||
consumerGroup = MessageTopicConstants.ATTENDANCE_STATISTICS_BATCH_CLEAR_CONSUMER_GROUP,
|
||||
consumeMode = ConsumeMode.CONCURRENTLY,
|
||||
maxReconsumeTimes = 10)
|
||||
public class StatisticsBatchClearMQListener implements RocketMQListener<StatisticsBatchClearDto>, RocketMQPushConsumerLifecycleListener {
|
||||
@Resource
|
||||
private AttendanceDayStatisticsService attendanceDayStatisticsService;
|
||||
|
||||
@Override
|
||||
public void onMessage(StatisticsBatchClearDto batchClearDto) {
|
||||
if (Objects.isNull(batchClearDto)) {
|
||||
log.warn("接收到空消息,忽略处理");
|
||||
return;
|
||||
}
|
||||
log.info("接受到一条批量清除日统计消息,{}", JSONObject.toJSONString(batchClearDto));
|
||||
if (CollUtil.isEmpty(batchClearDto.getUserIdList()) || StringUtil.isEmpty(batchClearDto.getTenantId()) ||
|
||||
StringUtil.isEmpty(batchClearDto.getGroupId()) || (Objects.isNull(batchClearDto.getDay()) && Objects.isNull(batchClearDto.getStartDay()))){
|
||||
log.error("消费批量清除日统计消息失败:消息格式无效,内容: {}", JSONObject.toJSONString(batchClearDto));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
attendanceDayStatisticsService.batchStatisticDataClear(batchClearDto);
|
||||
} catch (Exception ex) {
|
||||
log.error("消费批量清除日统计消息消费失败,触发重试,消息 {}, 错误:{} ", JSONObject.toJSONString(batchClearDto), ExceptionUtil.stacktraceToString(ex));
|
||||
throw new RuntimeException("消费批量清除日统计消息消费失败,触发重试", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareStart(DefaultMQPushConsumer consumer) {
|
||||
// 优化消费参数 每次拉取的消息数量
|
||||
consumer.setPullBatchSize(32);
|
||||
// 设置消费间隔,避免过于频繁拉取
|
||||
consumer.setPullInterval(200);
|
||||
// 设置消费超时时间(分钟)
|
||||
consumer.setConsumeTimeout(10);
|
||||
// 设置消费起始位置(从上次消费的位置继续)
|
||||
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
|
||||
// 调整消费线程池最小线程数
|
||||
consumer.setConsumeThreadMin(10);
|
||||
// 调整消费线程池最大线程数
|
||||
consumer.setConsumeThreadMax(20);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package jnpf.attendance.event;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import jnpf.attendance.service.AttendanceDayStatisticsService;
|
||||
import jnpf.constants.MessageTopicConstants;
|
||||
import jnpf.database.model.TenantVO;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.enums.attendance.StatisticsEnumUtil;
|
||||
import jnpf.model.attendance.event.StatisticsSingleHistoryDto;
|
||||
import jnpf.util.DateUtil;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
|
||||
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
|
||||
import org.apache.rocketmq.spring.annotation.ConsumeMode;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 考勤统计-单条消息监听,监听生成历史数据处理
|
||||
* @author 石头
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = MessageTopicConstants.ATTENDANCE_STATISTICS_SINGLE_HISTORY_TOPIC,
|
||||
consumerGroup = MessageTopicConstants.ATTENDANCE_STATISTICS_SINGLE_HISTORY_CONSUMER_GROUP,
|
||||
consumeMode = ConsumeMode.CONCURRENTLY,
|
||||
maxReconsumeTimes = 5)
|
||||
public class StatisticsSingleHistoryMQListener implements RocketMQListener<StatisticsSingleHistoryDto>, RocketMQPushConsumerLifecycleListener {
|
||||
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
@Resource
|
||||
private AttendanceDayStatisticsService attendanceDayStatisticsService;
|
||||
|
||||
@Override
|
||||
public void onMessage(StatisticsSingleHistoryDto singleDto) {
|
||||
if (Objects.isNull(singleDto)) {
|
||||
log.warn("接收到空消息,忽略处理");
|
||||
return;
|
||||
}
|
||||
log.info("接受到一条历史数据处理消息,{}", JSONObject.toJSONString(singleDto));
|
||||
// 校验必要字段
|
||||
if (ObjectUtil.isNull(singleDto) || StringUtil.isEmpty(singleDto.getUserId()) ||
|
||||
StringUtil.isEmpty(singleDto.getTenantId()) || StringUtil.isEmpty(singleDto.getGroupId()) ||
|
||||
ObjectUtil.isNull(singleDto.getDay())) {
|
||||
log.error("生成历史数据处理消费失败:消息格式无效,内容: {}", JSONObject.toJSONString(singleDto));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String lockKey = String.format(StatisticsEnumUtil.AttendanceClockEnum.DAY_STATISTICS.getKey(), singleDto.getTenantId(), singleDto.getGroupId(),
|
||||
singleDto.getUserId(), DateUtil.daFormat(singleDto.getDay()));
|
||||
RLock lock = redissonClient.getLock(lockKey);
|
||||
try {
|
||||
// 立即尝试获取锁(不等待),失败直接抛异常
|
||||
if (!lock.tryLock(5, 20, TimeUnit.SECONDS)) {
|
||||
throw new RuntimeException("获取锁失败");
|
||||
}
|
||||
// 租户不为空就需要切库
|
||||
TenantVO tenantVO = TenantDataSourceUtil.switchTenant(singleDto.getTenantId());
|
||||
log.error("切换tenant对象{}", JSON.toJSONString(tenantVO));
|
||||
attendanceDayStatisticsService.statisticDataChangeHistory(singleDto);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("获取锁时线程被中断: " + lockKey, e);
|
||||
} finally {
|
||||
// 安全释放:仅当前线程持有时释放,异常仅记录不抛出
|
||||
if (lock.isHeldByCurrentThread() && lock.isHeldByThread(Thread.currentThread().getId())) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.info("处理历史数据处理失败,触发重试,消息 {}, 错误:{} ", JSONObject.toJSONString(singleDto), ex.getMessage());
|
||||
throw new RuntimeException("处理历史数据处理失败,触发重试", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareStart(DefaultMQPushConsumer consumer) {
|
||||
// 优化消费参数 每次拉取的消息数量
|
||||
consumer.setPullBatchSize(32);
|
||||
// 设置消费间隔,避免过于频繁拉取
|
||||
consumer.setPullInterval(200);
|
||||
// 设置消费超时时间(分钟)
|
||||
consumer.setConsumeTimeout(10);
|
||||
// 设置消费起始位置(从上次消费的位置继续)
|
||||
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
|
||||
// 调整消费线程池最小线程数
|
||||
consumer.setConsumeThreadMin(10);
|
||||
// 调整消费线程池最大线程数
|
||||
consumer.setConsumeThreadMax(20);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package jnpf.attendance.event;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import jnpf.attendance.service.AttendanceDayStatisticsService;
|
||||
import jnpf.constants.MessageTopicConstants;
|
||||
import jnpf.database.model.TenantVO;
|
||||
import jnpf.database.util.TenantDataSourceUtil;
|
||||
import jnpf.enums.attendance.StatisticsEnumUtil;
|
||||
import jnpf.model.attendance.event.StatisticsSingleDto;
|
||||
import jnpf.util.DateUtil;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
|
||||
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
|
||||
import org.apache.rocketmq.spring.annotation.ConsumeMode;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 考勤统计-单条消息监听,监听生成用户日统计消息
|
||||
* @author 石头
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = MessageTopicConstants.ATTENDANCE_STATISTICS_SINGLE_TOPIC,
|
||||
consumerGroup = MessageTopicConstants.ATTENDANCE_STATISTICS_SINGLE_CONSUMER_GROUP,
|
||||
consumeMode = ConsumeMode.CONCURRENTLY,
|
||||
maxReconsumeTimes = 5)
|
||||
public class StatisticsSingleMQListener implements RocketMQListener<StatisticsSingleDto>, RocketMQPushConsumerLifecycleListener {
|
||||
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
@Resource
|
||||
private AttendanceDayStatisticsService attendanceDayStatisticsService;
|
||||
|
||||
@Override
|
||||
public void onMessage(StatisticsSingleDto singleDto) {
|
||||
if (Objects.isNull(singleDto)) {
|
||||
log.warn("接收到空消息,忽略处理");
|
||||
return;
|
||||
}
|
||||
log.error("接受到一条生成用户日统计消息,{}", JSONObject.toJSONString(singleDto));
|
||||
// 校验必要字段
|
||||
if (ObjectUtil.isNull(singleDto) || StringUtil.isEmpty(singleDto.getUserId()) ||
|
||||
StringUtil.isEmpty(singleDto.getTenantId()) || StringUtil.isEmpty(singleDto.getGroupId()) ||
|
||||
ObjectUtil.isNull(singleDto.getDay())) {
|
||||
log.error("生成用户日统计消息消费失败:消息格式无效,内容: {}", JSONObject.toJSONString(singleDto));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String lockKey = String.format(StatisticsEnumUtil.AttendanceClockEnum.DAY_STATISTICS.getKey(), singleDto.getTenantId(),
|
||||
singleDto.getGroupId(), singleDto.getUserId(), DateUtil.daFormat(singleDto.getDay()));
|
||||
RLock lock = redissonClient.getLock(lockKey);
|
||||
try {
|
||||
if (!lock.tryLock(5, 20, TimeUnit.SECONDS)) {
|
||||
throw new RuntimeException("获取锁失败");
|
||||
}
|
||||
// 租户不为空就需要切库
|
||||
TenantVO tenantVO = TenantDataSourceUtil.switchTenant(singleDto.getTenantId());
|
||||
log.error("切换tenant对象{}", JSON.toJSONString(tenantVO));
|
||||
attendanceDayStatisticsService.statisticDataChange(singleDto);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("获取锁时线程被中断: " + lockKey, e);
|
||||
} finally {
|
||||
// 安全释放:仅当前线程持有时释放,异常仅记录不抛出
|
||||
if (lock.isHeldByCurrentThread() && lock.isHeldByThread(Thread.currentThread().getId())) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("处理用户日统计消息失败,触发重试,消息 {}, 错误:{} ", JSONObject.toJSONString(singleDto), ex.getMessage());
|
||||
throw new RuntimeException("处理用户日统计消息失败,触发重试", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareStart(DefaultMQPushConsumer consumer) {
|
||||
// 优化消费参数 每次拉取的消息数量
|
||||
consumer.setPullBatchSize(32);
|
||||
// 设置消费间隔,避免过于频繁拉取
|
||||
consumer.setPullInterval(200);
|
||||
// 设置消费超时时间(分钟)
|
||||
consumer.setConsumeTimeout(10);
|
||||
// 设置消费起始位置(从上次消费的位置继续)
|
||||
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
|
||||
// 调整消费线程池最小线程数
|
||||
consumer.setConsumeThreadMin(10);
|
||||
// 调整消费线程池最大线程数
|
||||
consumer.setConsumeThreadMax(20);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package jnpf.attendance.excel;
|
||||
|
||||
import com.alibaba.excel.write.handler.CellWriteHandler;
|
||||
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤本导出单元格合并处理器
|
||||
* 使用CellWriteHandler在数据写入过程中执行合并,避免与表头合并冲突
|
||||
*
|
||||
* @author Generated
|
||||
* @date 2026-04-29
|
||||
*/
|
||||
@Slf4j
|
||||
public class AttendanceBookMergeHandler implements CellWriteHandler {
|
||||
|
||||
/**
|
||||
* 需要合并的单元格范围列表(数据行索引,不包含表头)
|
||||
*/
|
||||
private final List<CellRangeAddress> mergeCells;
|
||||
|
||||
/**
|
||||
* 表头行数(用于偏移数据行索引)
|
||||
*/
|
||||
private final int headerRowCount;
|
||||
|
||||
/**
|
||||
* 预期数据总行数(用于判断是否是最后一行)
|
||||
*/
|
||||
private final int expectedDataRowCount;
|
||||
|
||||
/**
|
||||
* 额外表头行数(标题行+说明行)
|
||||
*/
|
||||
private final int extraHeaderRows;
|
||||
|
||||
/**
|
||||
* 总列数(用于合并标题和说明行)
|
||||
*/
|
||||
private final int totalColumns;
|
||||
|
||||
/**
|
||||
* 是否已执行合并
|
||||
*/
|
||||
private boolean merged = false;
|
||||
|
||||
public AttendanceBookMergeHandler(List<CellRangeAddress> mergeCells, int headerRowCount, int expectedDataRowCount, int totalColumns) {
|
||||
this.mergeCells = mergeCells;
|
||||
this.headerRowCount = headerRowCount;
|
||||
this.expectedDataRowCount = expectedDataRowCount;
|
||||
this.extraHeaderRows = 0; // 使用3层表头,不需要额外行
|
||||
this.totalColumns = totalColumns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCellDispose(CellWriteHandlerContext context) {
|
||||
// 只在未合并且是数据行(非表头)时才执行合并
|
||||
if (!merged && mergeCells != null && !mergeCells.isEmpty()) {
|
||||
Integer rowIndex = context.getRowIndex();
|
||||
Boolean isHead = context.getHead();
|
||||
|
||||
// 跳过表头行
|
||||
if (isHead != null && isHead) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 在写入最后一行数据后执行合并
|
||||
if (rowIndex != null && rowIndex >= headerRowCount + expectedDataRowCount - 1) {
|
||||
Sheet sheet = context.getWriteSheetHolder().getSheet();
|
||||
|
||||
try {
|
||||
int mergedCount = 0;
|
||||
|
||||
// 合并数据区域(使用3层表头,偏移量为headerRowCount)
|
||||
for (CellRangeAddress address : mergeCells) {
|
||||
int offset = headerRowCount; // 3层表头
|
||||
CellRangeAddress adjustedAddress = new CellRangeAddress(
|
||||
address.getFirstRow() + offset,
|
||||
address.getLastRow() + offset,
|
||||
address.getFirstColumn(),
|
||||
address.getLastColumn()
|
||||
);
|
||||
|
||||
// 检查是否与现有合并区域冲突
|
||||
if (!hasConflict(sheet, adjustedAddress)) {
|
||||
sheet.addMergedRegion(adjustedAddress);
|
||||
mergedCount++;
|
||||
} else {
|
||||
log.warn("跳过冲突的合并区域: {}", adjustedAddress);
|
||||
}
|
||||
}
|
||||
merged = true;
|
||||
log.info("考勤本导出单元格合并完成,成功合并 {} 个区域,表头行数: {}, 数据行数: {}",
|
||||
mergedCount, headerRowCount, expectedDataRowCount);
|
||||
} catch (Exception e) {
|
||||
log.error("考勤本导出单元格合并失败: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查合并区域是否与现有合并区域冲突
|
||||
*/
|
||||
private boolean hasConflict(Sheet sheet, CellRangeAddress newAddress) {
|
||||
int numMergedRegions = sheet.getNumMergedRegions();
|
||||
for (int i = 0; i < numMergedRegions; i++) {
|
||||
CellRangeAddress existing = sheet.getMergedRegion(i);
|
||||
if (isOverlap(newAddress, existing)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查两个合并区域是否重叠
|
||||
*/
|
||||
private boolean isOverlap(CellRangeAddress addr1, CellRangeAddress addr2) {
|
||||
return !(addr1.getLastRow() < addr2.getFirstRow() ||
|
||||
addr1.getFirstRow() > addr2.getLastRow() ||
|
||||
addr1.getLastColumn() < addr2.getFirstColumn() ||
|
||||
addr1.getFirstColumn() > addr2.getLastColumn());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package jnpf.attendance.excel;
|
||||
|
||||
import com.alibaba.excel.write.handler.CellWriteHandler;
|
||||
import com.alibaba.excel.write.handler.RowWriteHandler;
|
||||
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
|
||||
/**
|
||||
* 组合写入处理器
|
||||
* 用于同时应用多个Handler(样式Handler + 合并Handler)
|
||||
*
|
||||
* @author Generated
|
||||
* @date 2026-04-29
|
||||
*/
|
||||
@Slf4j
|
||||
public class CompositeWriteHandler implements RowWriteHandler, CellWriteHandler {
|
||||
|
||||
private final RowWriteHandler rowHandler;
|
||||
private final CellWriteHandler cellHandler;
|
||||
|
||||
public CompositeWriteHandler(RowWriteHandler rowHandler, CellWriteHandler cellHandler) {
|
||||
this.rowHandler = rowHandler;
|
||||
this.cellHandler = cellHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
|
||||
// 执行样式Handler
|
||||
if (rowHandler != null) {
|
||||
try {
|
||||
rowHandler.afterRowDispose(writeSheetHolder, writeTableHolder, row, relativeRowIndex, isHead);
|
||||
} catch (Exception e) {
|
||||
log.error("RowHandler执行失败: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCellDispose(CellWriteHandlerContext context) {
|
||||
// 执行单元格Handler(包含合并逻辑)
|
||||
if (cellHandler != null) {
|
||||
try {
|
||||
cellHandler.afterCellDispose(context);
|
||||
} catch (Exception e) {
|
||||
log.error("CellHandler执行失败: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
package jnpf.attendance.excel;
|
||||
|
||||
import com.alibaba.excel.write.handler.RowWriteHandler;
|
||||
import com.alibaba.excel.write.handler.SheetWriteHandler;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
||||
import org.apache.poi.xssf.usermodel.XSSFColor;
|
||||
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
||||
|
||||
|
||||
public class HeadStyleHandler implements RowWriteHandler, SheetWriteHandler {
|
||||
@Override
|
||||
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
|
||||
Sheet sheet = writeSheetHolder.getSheet();
|
||||
XSSFCellStyle contextCellStyle = getContextCellStyle(sheet);
|
||||
int rowNum = row.getRowNum();
|
||||
Workbook workbook = sheet.getWorkbook();
|
||||
Font font = workbook.createFont();
|
||||
font.setFontHeight((short) (20 * 18));
|
||||
font.setColor(IndexedColors.WHITE.getIndex());
|
||||
for (Cell cell : row) {
|
||||
if (isHead) {
|
||||
if (textSetRedFont(cell)) {
|
||||
contextCellStyle.setAlignment(HorizontalAlignment.LEFT);
|
||||
cell.setCellStyle(contextCellStyle);
|
||||
continue;
|
||||
}
|
||||
// 3层表头结构:
|
||||
// rowNum == 0: 标题行(蓝色背景,白色字体)
|
||||
// rowNum == 1: 说明行(黑色字体,左对齐,无背景)
|
||||
// rowNum == 2: 表头行(黑色字体,大小11,无背景)
|
||||
if (rowNum == 0) {
|
||||
// 标题行:蓝色背景,白色字体
|
||||
contextCellStyle.setFont(font);
|
||||
contextCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
contextCellStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(48, 84, 150), null));
|
||||
} else if (rowNum == 1) {
|
||||
// 说明行:黑色字体,左对齐,无背景
|
||||
Font noteFont = workbook.createFont();
|
||||
noteFont.setFontHeight((short) (20 * 11));
|
||||
noteFont.setColor(IndexedColors.BLACK.getIndex());
|
||||
contextCellStyle.setFont(noteFont);
|
||||
contextCellStyle.setAlignment(HorizontalAlignment.LEFT);
|
||||
contextCellStyle.setFillPattern(FillPatternType.NO_FILL);
|
||||
contextCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
|
||||
} else if (rowNum == 2) {
|
||||
// 表头行:黑色字体,大小11,无背景
|
||||
Font headerFont = workbook.createFont();
|
||||
headerFont.setFontHeight((short) (20 * 11));
|
||||
headerFont.setColor(IndexedColors.BLACK.getIndex());
|
||||
contextCellStyle.setFont(headerFont);
|
||||
contextCellStyle.setFillPattern(FillPatternType.NO_FILL);
|
||||
contextCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
|
||||
}
|
||||
}
|
||||
cell.setCellStyle(contextCellStyle);
|
||||
}
|
||||
|
||||
// 实现自动行高调整,使用手动计算方式避免兼容性问题
|
||||
calculateAndSetRowHeight(row);
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动计算并设置行高
|
||||
* @param row 行对象
|
||||
*/
|
||||
private void calculateAndSetRowHeight(Row row) {
|
||||
float defaultRowHeight = 30.0f; // 默认行高
|
||||
float maxCellHeight = defaultRowHeight;
|
||||
|
||||
// 遍历行中的每个单元格,根据内容计算所需高度
|
||||
for (Cell cell : row) {
|
||||
String cellValue = getCellValueAsString(cell);
|
||||
if (cellValue != null) {
|
||||
// 计算基于内容的行高
|
||||
float cellHeight = calculateCellHeight(cellValue);
|
||||
if (cellHeight > maxCellHeight) {
|
||||
maxCellHeight = cellHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置行高,确保不低于默认行高
|
||||
row.setHeightInPoints(Math.max(maxCellHeight, defaultRowHeight));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据单元格内容和列宽计算所需行高
|
||||
* @param content 单元格内容
|
||||
* @return 计算的行高
|
||||
*/
|
||||
private float calculateCellHeight(String content) {
|
||||
if (content == null || content.isEmpty()) {
|
||||
return 19.0f;
|
||||
}
|
||||
// 计算需要的行数
|
||||
String[] lines = content.split("\n");
|
||||
int lineCount = lines.length;
|
||||
|
||||
|
||||
// 每行大约15点高度
|
||||
return lineCount * 19;
|
||||
}
|
||||
|
||||
public Boolean textSetRedFont(Cell cell) {
|
||||
String cellValue = getCellValueAsString(cell);
|
||||
if (cellValue != null && cellValue.contains("[RED]")) {
|
||||
Workbook workbook = cell.getSheet().getWorkbook();
|
||||
// 创建红色字体
|
||||
Font redFont = workbook.createFont();
|
||||
redFont.setColor(IndexedColors.RED.getIndex());
|
||||
redFont.setFontHeight((short) (20 * 14));
|
||||
redFont.setBold(true);
|
||||
// 创建正常字体
|
||||
Font normalFont = workbook.createFont();
|
||||
normalFont.setColor(IndexedColors.BLACK.getIndex());
|
||||
normalFont.setFontHeight((short) (20 * 12));
|
||||
// 移除 [RED] 标记并保留原始内容
|
||||
String cleanValue = cellValue.replace("[RED]", "");
|
||||
XSSFRichTextString richText = new XSSFRichTextString(cleanValue);
|
||||
// 分割文本为行
|
||||
String[] lines = cleanValue.split("\n");
|
||||
int currentIndex = 0;
|
||||
for (String line : lines) {
|
||||
// 检查当前行是否包含 [RED] 标记
|
||||
if (cellValue.contains("[RED]"+ line)) {
|
||||
richText.applyFont(currentIndex, currentIndex + line.length(), redFont);
|
||||
} else {
|
||||
richText.applyFont(currentIndex, currentIndex + line.length(), normalFont);
|
||||
}
|
||||
currentIndex += line.length() + 1; // +1 for \n
|
||||
}
|
||||
|
||||
cell.setCellValue(richText);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全地获取单元格的字符串值
|
||||
*
|
||||
* @param cell 单元格对象
|
||||
* @return 单元格的字符串表示
|
||||
*/
|
||||
private String getCellValueAsString(Cell cell) {
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
switch (cell.getCellType()) {
|
||||
case STRING:
|
||||
return cell.getStringCellValue();
|
||||
case NUMERIC:
|
||||
if (DateUtil.isCellDateFormatted(cell)) {
|
||||
return cell.getDateCellValue().toString();
|
||||
} else {
|
||||
// 数值转字符串
|
||||
return String.valueOf(cell.getNumericCellValue());
|
||||
}
|
||||
case BOOLEAN:
|
||||
return String.valueOf(cell.getBooleanCellValue());
|
||||
case FORMULA:
|
||||
// 尝试获取公式结果
|
||||
try {
|
||||
return cell.getStringCellValue();
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
return String.valueOf(cell.getNumericCellValue());
|
||||
} catch (Exception ex) {
|
||||
return cell.getCellFormula();
|
||||
}
|
||||
}
|
||||
case BLANK:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 如果出现异常,返回空字符串而不是抛出异常
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private XSSFCellStyle getContextCellStyle(Sheet sheet) {
|
||||
Workbook workbook = sheet.getWorkbook();
|
||||
Font font = workbook.createFont();
|
||||
font.setBold(false);
|
||||
font.setFontName("宋体");
|
||||
font.setFontHeight((short) (20 * 11));
|
||||
XSSFCellStyle headCellStyle = (XSSFCellStyle) workbook.createCellStyle();
|
||||
//居中
|
||||
headCellStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
headCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
|
||||
//设置表头高度
|
||||
//上下居中
|
||||
headCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
headCellStyle.setFont(font);
|
||||
// 设置自动换行;
|
||||
headCellStyle.setWrapText(true);
|
||||
return headCellStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
|
||||
// 不需要实现
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
|
||||
// 在所有数据写入完成后,设置表头列宽自适应
|
||||
Sheet sheet = writeSheetHolder.getSheet();
|
||||
autoSizeHeaderColumns(sheet, 3); // 前3行是表头
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置表头列宽自适应
|
||||
*/
|
||||
private void autoSizeHeaderColumns(Sheet sheet, int headerRowCount) {
|
||||
if (sheet.getRow(0) == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 遍历所有列
|
||||
for (int col = 0; col < sheet.getRow(0).getLastCellNum(); col++) {
|
||||
// 遍历表头行,找到最长的内容
|
||||
int maxWidth = 0;
|
||||
for (int row = 0; row < headerRowCount; row++) {
|
||||
Row headerRow = sheet.getRow(row);
|
||||
if (headerRow != null) {
|
||||
Cell cell = headerRow.getCell(col);
|
||||
if (cell != null) {
|
||||
String content = cell.getStringCellValue();
|
||||
if (content != null && !content.isEmpty()) {
|
||||
// 中文字符算2个单位,英文算1个单位
|
||||
int width = content.replaceAll("[\u4e00-\u9fa5]", "**").length();
|
||||
maxWidth = Math.max(maxWidth, width);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 设置列宽,额外增加2个字符的边距
|
||||
if (maxWidth > 0) {
|
||||
sheet.setColumnWidth(col, (maxWidth + 2) * 256);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package jnpf.attendance.excel.listener;
|
||||
|
||||
|
||||
import com.alibaba.excel.converters.Converter;
|
||||
import com.alibaba.excel.converters.ReadConverterContext;
|
||||
import com.alibaba.excel.converters.WriteConverterContext;
|
||||
import com.alibaba.excel.enums.CellDataTypeEnum;
|
||||
import com.alibaba.excel.metadata.data.WriteCellData;
|
||||
|
||||
public class CustomStringStringConverter implements Converter<String> {
|
||||
@Override
|
||||
public Class<?> supportJavaTypeKey() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellDataTypeEnum supportExcelTypeKey() {
|
||||
return CellDataTypeEnum.STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* 这里读的时候会调用
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String convertToJavaData(ReadConverterContext<?> context) {
|
||||
return context.getReadCellData().getStringValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 这里是写的时候会调用 不用管
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public WriteCellData<?> convertToExcelData(WriteConverterContext<String> context) {
|
||||
return new WriteCellData<>(context.getValue());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package jnpf.attendance.excel.listener;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import jnpf.attendance.service.impl.AttendanceDailyRuleServiceImpl;
|
||||
import jnpf.entity.attendance.FtbAttendanceDailyRule;
|
||||
import jnpf.entity.attendance.FtbAttendanceLineSchedulingConfig;
|
||||
import jnpf.enums.attendance.AttendanceTypeEnum;
|
||||
import jnpf.enums.attendance.ScheduleImportEnum;
|
||||
import jnpf.model.attendance.model.ScheduleImportFailModel;
|
||||
import jnpf.permission.model.user.PartUserInfoVo;
|
||||
import jnpf.util.DateDetail;
|
||||
import jnpf.util.StringUtil;
|
||||
import jnpf.util.attendance.DailyRuleUtil;
|
||||
import jnpf.util.attendance.RuleExcelImportUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
|
||||
@Slf4j
|
||||
public class LineSchedulesDataListener extends AnalysisEventListener<Map<Integer, String>> {
|
||||
|
||||
/**
|
||||
* 缓存的数据
|
||||
*/
|
||||
private final List<FtbAttendanceDailyRule> cachedDataList;
|
||||
private final List<ScheduleImportFailModel> failList;
|
||||
private final FtbAttendanceLineSchedulingConfig lineSchedulingConfig;
|
||||
private final Date month;
|
||||
private final String groupId;
|
||||
private final List<String> heads;
|
||||
|
||||
private final Map<String, PartUserInfoVo> userMap;
|
||||
private final Map<String, Integer> selfGroupMap;
|
||||
|
||||
private int headRow = 0;
|
||||
|
||||
public LineSchedulesDataListener(String groupId, List<FtbAttendanceDailyRule> cachedDataList, List<ScheduleImportFailModel> failList, List<String> heads, Date month, Map<String, PartUserInfoVo> userMap, FtbAttendanceLineSchedulingConfig lineSchedulingConfig, Map<String, Integer> selfGroupMap) {
|
||||
this.cachedDataList = cachedDataList;
|
||||
this.failList = failList;
|
||||
this.heads = heads;
|
||||
this.month = month;
|
||||
this.groupId = groupId;
|
||||
this.userMap = userMap;
|
||||
this.lineSchedulingConfig = lineSchedulingConfig;
|
||||
this.selfGroupMap = selfGroupMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
|
||||
// 处理表头数据
|
||||
// headMap的key是列索引,value是表头名称
|
||||
headRow++;
|
||||
if (context.readRowHolder().getRowIndex() < 2) {
|
||||
return;
|
||||
}
|
||||
Assert.isFalse(heads.size() != headMap.size() ||
|
||||
!CollectionUtils.isEqualCollection(heads, headMap.values()), ScheduleImportEnum.IMPORT_ERROR_FORMAT_WRONG.getMessage());
|
||||
Assert.isFalse(Objects.isNull(lineSchedulingConfig), ScheduleImportEnum.IMPORT_ERROR_FORMAT_WRONG.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(Map<Integer, String> data, AnalysisContext context) {
|
||||
Assert.isFalse(headRow != 3, ScheduleImportEnum.IMPORT_ERROR_FORMAT_WRONG.getMessage());
|
||||
// 处理每一行数据
|
||||
// data的key是列索引,value是单元格值
|
||||
//用户人员信息校验
|
||||
String userName = data.get(0);
|
||||
String phone = data.get(1);
|
||||
//划线排班人员校验
|
||||
if (RuleExcelImportUtil.addFail(StringUtil.isEmpty(userName) || StringUtil.isEmpty(phone), ScheduleImportEnum.IMPORT_ERROR_UNIDENTIFIED_MEMBER, userName, failList)) {
|
||||
return;
|
||||
}
|
||||
PartUserInfoVo userEntity = userMap.get(phone);
|
||||
if (RuleExcelImportUtil.addFail(Objects.isNull(userEntity), ScheduleImportEnum.IMPORT_ERROR_MEMBER_NOT_IN_GROUP, userName, failList)) {
|
||||
return;
|
||||
}
|
||||
if (RuleExcelImportUtil.addFail(!userEntity.getRealName().equals(userName), ScheduleImportEnum.IMPORT_ERROR_UNIDENTIFIED_MEMBER, userName, failList)) {
|
||||
return;
|
||||
}
|
||||
if (RuleExcelImportUtil.addFail(cachedDataList.stream().anyMatch(vo -> vo.getUserId().equals(userEntity.getUserId())), ScheduleImportEnum.IMPORT_ERROR_DUPLICATE_MEMBERS, userEntity.getRealName(), failList)) {
|
||||
return;
|
||||
}
|
||||
Integer selfGroup = selfGroupMap.get(userEntity.getUserId());
|
||||
if (RuleExcelImportUtil.addFail(Objects.isNull(selfGroup), ScheduleImportEnum.IMPORT_ERROR_MEMBER_NOT_IN_GROUP, userName, failList)) {
|
||||
return;
|
||||
}
|
||||
DateTime today = DateUtil.beginOfDay(new Date());
|
||||
//班次信息校验
|
||||
List<FtbAttendanceDailyRule> cachedDayDataList = CollUtil.newArrayList();
|
||||
data.forEach((index, periodSrt) -> {
|
||||
if (index < 2 || heads.size() < index - 1) {
|
||||
return;
|
||||
}
|
||||
String head = heads.get(index);
|
||||
String dayIndex = head.split("\n")[1];
|
||||
DateTime day = DateUtil.offsetDay(month, Integer.parseInt(dayIndex) - 1);
|
||||
if (day.isBefore(today)) {
|
||||
return;
|
||||
}
|
||||
Date startTime = DateDetail.getDateByPoint(day, lineSchedulingConfig.getStartTime(), lineSchedulingConfig.getStartType());
|
||||
Date endTime = DateUtil.offsetHour(DateDetail.getDateByPoint(day, lineSchedulingConfig.getEndTime(), lineSchedulingConfig.getEndType()), 1);
|
||||
if (StringUtil.isEmpty(periodSrt)) {
|
||||
FtbAttendanceDailyRule ftbAttendanceDailyRule = AttendanceDailyRuleServiceImpl.buildLineSchedulesRule(groupId, selfGroup, day, day, day, userEntity.getUserId(), lineSchedulingConfig);
|
||||
ftbAttendanceDailyRule.setAttendanceType(AttendanceTypeEnum.CLEAR.getCode());
|
||||
cachedDataList.add(ftbAttendanceDailyRule);
|
||||
return;
|
||||
}
|
||||
cachedDayDataList.clear();
|
||||
String[] periodArr = periodSrt.split("\\|");
|
||||
for (String period : periodArr) {
|
||||
if (StringUtil.isEmpty(period)) {
|
||||
continue;
|
||||
}
|
||||
String[] dateArr = period.trim().split("-");
|
||||
try {
|
||||
Date start = DateDetail.getDateByPoint(day, dateArr[0], 1);
|
||||
Date end = DateDetail.getDateByPoint(day, dateArr[1], 1);
|
||||
if (start.after(end)) {
|
||||
end = DateUtil.offsetDay(end, 1);
|
||||
}
|
||||
Date ceilStart = new Date(start.getTime());
|
||||
DailyRuleUtil.ceilToHalfHour(start);
|
||||
Date ceilEnd = new Date(end.getTime());
|
||||
DailyRuleUtil.ceilToHalfHour(end);
|
||||
if (ceilStart.compareTo(start) != 0 || ceilEnd.compareTo(end) != 0) {
|
||||
RuleExcelImportUtil.addFail(true, ScheduleImportEnum.IMPORT_ERROR_PERIOD_INVALID, userEntity.getRealName(), failList);
|
||||
return;
|
||||
}
|
||||
if (start.before(startTime) || end.after(endTime)) {
|
||||
RuleExcelImportUtil.addFail(true, ScheduleImportEnum.IMPORT_ERROR_OVERDUE_TIME_INVALID, userEntity.getRealName(), failList);
|
||||
return;
|
||||
}
|
||||
cachedDayDataList.add(AttendanceDailyRuleServiceImpl.buildLineSchedulesRule(groupId, selfGroup, day, start, end, userEntity.getUserId(), lineSchedulingConfig));
|
||||
} catch (Exception e) {
|
||||
RuleExcelImportUtil.addFail(true, ScheduleImportEnum.IMPORT_ERROR_PERIOD_INVALID, userEntity.getRealName(), failList);
|
||||
return;
|
||||
}
|
||||
}
|
||||
cachedDataList.addAll(DailyRuleUtil.mergeRules(cachedDayDataList));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||
// 所有数据解析完成后的操作
|
||||
log.error("所有数据解析完成");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package jnpf.attendance.excel.listener;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import jnpf.enums.attendance.AttendanceTypeEnum;
|
||||
import jnpf.enums.attendance.ScheduleImportEnum;
|
||||
import jnpf.model.attendance.model.ScheduleImportFailModel;
|
||||
import jnpf.model.attendance.vo.*;
|
||||
import jnpf.model.attendance.vo.attendance.ShiftNameVo;
|
||||
import jnpf.permission.model.user.PartUserInfoVo;
|
||||
import jnpf.util.StringUtil;
|
||||
import jnpf.util.attendance.RuleExcelImportUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.compress.utils.Lists;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
|
||||
@Slf4j
|
||||
public class SchedulesDataListener extends AnalysisEventListener<Map<Integer, String>> {
|
||||
|
||||
/**
|
||||
* 缓存的数据
|
||||
*/
|
||||
private final List<SchedulesV2Vo> cachedDataList;
|
||||
private final List<ScheduleImportFailModel> failList;
|
||||
|
||||
private final Date month;
|
||||
|
||||
private final List<String> heads;
|
||||
|
||||
private final Map<String, ShiftNameVo> shiftMap;
|
||||
private final Map<String, PartUserInfoVo> userMap;
|
||||
|
||||
private static final String format = "yyyy-MM-dd";
|
||||
|
||||
private int headRow = 0;
|
||||
|
||||
public SchedulesDataListener(List<SchedulesV2Vo> cachedDataList, List<ScheduleImportFailModel> failList, List<String> heads, Date month, Map<String, ShiftNameVo> shiftMap, Map<String, PartUserInfoVo> userMap) {
|
||||
this.cachedDataList = cachedDataList;
|
||||
this.failList = failList;
|
||||
this.heads = heads;
|
||||
this.month = month;
|
||||
this.shiftMap = shiftMap;
|
||||
this.userMap = userMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
|
||||
// 处理表头数据
|
||||
// headMap的key是列索引,value是表头名称
|
||||
headRow++;
|
||||
if (context.readRowHolder().getRowIndex() < 2) {
|
||||
return;
|
||||
}
|
||||
Assert.isFalse(heads.size() != headMap.size() ||
|
||||
!CollectionUtils.isEqualCollection(heads, headMap.values()), ScheduleImportEnum.IMPORT_ERROR_FORMAT_WRONG.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(Map<Integer, String> data, AnalysisContext context) {
|
||||
Assert.isFalse(headRow != 3, ScheduleImportEnum.IMPORT_ERROR_FORMAT_WRONG.getMessage());
|
||||
// 处理每一行数据
|
||||
// data的key是列索引,value是单元格值
|
||||
//用户人员信息校验
|
||||
String userName = data.get(0);
|
||||
String phone = data.get(1);
|
||||
if (RuleExcelImportUtil.addFail(StringUtil.isEmpty(userName) || StringUtil.isEmpty(phone), ScheduleImportEnum.IMPORT_ERROR_UNIDENTIFIED_MEMBER, userName, failList)) {
|
||||
return;
|
||||
}
|
||||
PartUserInfoVo userEntity = userMap.get(phone);
|
||||
if (RuleExcelImportUtil.addFail(Objects.isNull(userEntity), ScheduleImportEnum.IMPORT_ERROR_MEMBER_NOT_IN_GROUP, userName, failList)) {
|
||||
return;
|
||||
}
|
||||
if (RuleExcelImportUtil.addFail(!userEntity.getRealName().equals(userName), ScheduleImportEnum.IMPORT_ERROR_UNIDENTIFIED_MEMBER, userName, failList)) {
|
||||
return;
|
||||
}
|
||||
if (RuleExcelImportUtil.addFail(cachedDataList.stream().anyMatch(vo -> vo.getUserId().equals(userEntity.getUserId())), ScheduleImportEnum.IMPORT_ERROR_DUPLICATE_MEMBERS, userEntity.getRealName(), failList)) {
|
||||
return;
|
||||
}
|
||||
LinkedHashMap<String, SchedulesDayVo> schedulesDaySetDto = new LinkedHashMap<>();
|
||||
cachedDataList.add(SchedulesV2Vo.builder()
|
||||
.userId(userEntity.getUserId())
|
||||
.mobilePhone(userEntity.getMobilePhone())
|
||||
.realName(userEntity.getRealName())
|
||||
.val(schedulesDaySetDto)
|
||||
.build());
|
||||
//班次信息校验
|
||||
data.forEach((index, shiftNameSrt) -> {
|
||||
if (index < 3 || heads.size() < index - 1) {
|
||||
return;
|
||||
}
|
||||
String head = heads.get(index);
|
||||
String dayIndex = head.split("\n")[1];
|
||||
DateTime day = DateUtil.offsetDay(month, Integer.parseInt(dayIndex) - 1);
|
||||
String dayStr = DateUtil.format(day, format);
|
||||
if (StringUtil.isEmpty(shiftNameSrt)) {
|
||||
//清空
|
||||
schedulesDaySetDto.put(dayStr, SchedulesDayVo.builder().itemVos(List.of(SchedulesItemVo.builder().type(0).build())).build());
|
||||
return;
|
||||
}
|
||||
String[] shiftNameArr = shiftNameSrt.split("\\|");
|
||||
int length = shiftNameArr.length;
|
||||
ArrayList<SchedulesItemVo> list = Lists.newArrayList();
|
||||
schedulesDaySetDto.put(dayStr, SchedulesDayVo.builder().itemVos(list).build());
|
||||
for (int i = 0; i < shiftNameArr.length; i++) {
|
||||
//上午半天是否为休
|
||||
boolean isAMOff = list.stream().anyMatch(vo -> Objects.equals(vo.getType(), 1) || Objects.equals(vo.getType(), 3) || Objects.equals(vo.getType(), 4));
|
||||
String shiftName = shiftNameArr[i];
|
||||
//判断班次类型
|
||||
ShiftNameVo shiftPeriodVo = shiftMap.get(shiftName);
|
||||
if (Objects.nonNull(shiftPeriodVo)) {
|
||||
//是否为全天班
|
||||
if (length > 1 && Arrays.stream(shiftNameArr).noneMatch(vo -> StringUtil.equals(vo, AttendanceTypeEnum.REST.getMsg()))) {
|
||||
RuleExcelImportUtil.addFail(true, ScheduleImportEnum.IMPORT_ERROR_SHIFT_NAME_INVALID, userEntity.getRealName(), failList);
|
||||
return;
|
||||
}
|
||||
//是否为全天班设置了两次
|
||||
List<SchedulesItemVo> collect = list.stream().filter(vo -> Objects.equals(vo.getShiftId(), shiftPeriodVo.getId())).peek(vo -> vo.setSchedulesType(0)).collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(collect)) {
|
||||
continue;
|
||||
}
|
||||
list.add(SchedulesItemVo.builder()
|
||||
.schedulesType(length < 2 ? 0 : i + 1)
|
||||
.type(2)
|
||||
.sort(length < 2 ? 0 : i + 1)
|
||||
.shiftId(shiftPeriodVo.getId())
|
||||
.name(shiftPeriodVo.getName())
|
||||
.shortName(shiftPeriodVo.getShortName())
|
||||
.colour(shiftPeriodVo.getColour())
|
||||
.build());
|
||||
continue;
|
||||
}
|
||||
//秀
|
||||
if (!isAMOff && StringUtil.equals(shiftName, AttendanceTypeEnum.REST.getMsg())) {
|
||||
list.add(SchedulesItemVo.builder()
|
||||
.schedulesType(length < 2 ? 0 : i + 1)
|
||||
.type(1)
|
||||
.build());
|
||||
continue;
|
||||
}
|
||||
if (!isAMOff && StringUtil.equals(shiftName, AttendanceTypeEnum.DEDUCTION_HOLIDAYS.getMsg())) {
|
||||
list.add(SchedulesItemVo.builder()
|
||||
.schedulesType(length < 2 ? 0 : i + 1)
|
||||
.type(3)
|
||||
.build());
|
||||
continue;
|
||||
}
|
||||
if (!isAMOff && StringUtil.equals(shiftName, AttendanceTypeEnum.EXCHANGE_HOLIDAYS.getMsg())) {
|
||||
list.add(SchedulesItemVo.builder()
|
||||
.schedulesType(length < 2 ? 0 : i + 1)
|
||||
.type(4)
|
||||
.build());
|
||||
continue;
|
||||
}
|
||||
RuleExcelImportUtil.addFail(true, ScheduleImportEnum.IMPORT_ERROR_SHIFT_NAME_INVALID, userEntity.getRealName(), failList);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||
// 所有数据解析完成后的操作
|
||||
log.error("所有数据解析完成");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package jnpf.attendance.handler;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class JsonToListTypeHandler extends BaseTypeHandler<List<Object>> {
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, List<Object> parameter, JdbcType jdbcType) throws SQLException {
|
||||
ps.setString(i, toJson(parameter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
List<Object> list = parseJson(rs.getString(columnName));
|
||||
if(CollUtil.isEmpty(list)){
|
||||
return null;
|
||||
}
|
||||
// 删除掉为空的数据
|
||||
list.removeIf(Objects::isNull);
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
List<Object> list = parseJson(rs.getString(columnIndex));
|
||||
if(CollUtil.isEmpty(list)){
|
||||
return null;
|
||||
}
|
||||
// 删除掉为空的数据
|
||||
list.removeIf(Objects::isNull);
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
List<Object> list = parseJson(cs.getString(columnIndex));
|
||||
if(CollUtil.isEmpty(list)){
|
||||
return null;
|
||||
}
|
||||
// 删除掉为空的数据
|
||||
list.removeIf(Objects::isNull);
|
||||
return list;
|
||||
}
|
||||
|
||||
private String toJson(List<Object> list) {
|
||||
try {
|
||||
return OBJECT_MAPPER.writeValueAsString(list);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Object> parseJson(String json) {
|
||||
try {
|
||||
if (json == null || json.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
List<Object> result = OBJECT_MAPPER.readValue(json,
|
||||
OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, Object.class)
|
||||
);
|
||||
return result.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.flatMap(item -> {
|
||||
if (item instanceof List) {
|
||||
List<?> itemList = (List<?>) item;
|
||||
return itemList.stream().filter(Objects::nonNull);
|
||||
} else {
|
||||
return java.util.stream.Stream.of(item);
|
||||
}
|
||||
}).collect(java.util.stream.Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("JSON解析失败: " + json, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.ApiCallLog;
|
||||
|
||||
/**
|
||||
* 接口调用记录Mapper
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2026-01-28
|
||||
*/
|
||||
public interface ApiCallLogMapper extends SuperMapper<ApiCallLog> {
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.model.attendance.vo.attendance.ClockRecordVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤ai Mapper
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2026-05-07
|
||||
*/
|
||||
public interface AttendanceAIMapper {
|
||||
|
||||
/**
|
||||
* 查询打卡记录列表
|
||||
* @param userId 用户id
|
||||
* @param queryDate 查询日期
|
||||
* @return java.util.List<jnpf.model.attendance.vo.attendance.ClockRecordVo>
|
||||
*/
|
||||
List<ClockRecordVo> getClockRecordList(@Param("userId") String userId, @Param("queryDate") String queryDate);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import jnpf.entity.AttendanceApprovalSetting;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤审批设置表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author Auto-generator
|
||||
* @since 2023-11-21
|
||||
*/
|
||||
public interface AttendanceApprovalSettingMapper extends BaseMapper<AttendanceApprovalSetting> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.model.attendance.vo.OvertimeVouchersVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* describe
|
||||
* 考勤审批相关
|
||||
* @author HuangLinPan
|
||||
* @date 2023/11/22
|
||||
*/
|
||||
public interface AttendanceApproveMapper {
|
||||
|
||||
|
||||
/**
|
||||
* 查前天的加班出勤规则找这些出勤规则对应的加班结果表数据
|
||||
* @param date 日期
|
||||
* @return java.util.List<jnpf.model.attendance.vo.OvertimeVouchersVo>
|
||||
* @author hlp
|
||||
*/
|
||||
List<OvertimeVouchersVo> getOvertimeVouchersList(@Param("date") Date date);
|
||||
|
||||
/**
|
||||
* 校验是否重复发放加班劵
|
||||
* @param ruleId 排班Id
|
||||
* @param code 类型 : 1.节日 2.假日 3.加班(调休)
|
||||
*/
|
||||
Integer getOvertimeByRuleId(@Param("ruleId") String ruleId, @Param("code") Integer code);
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
|
||||
import jnpf.entity.attendance.AttendanceBalanceRecordEntity;
|
||||
import jnpf.entity.attendance.AttendanceStorageRest;
|
||||
import jnpf.model.attendance.model.*;
|
||||
import jnpf.model.attendance.vo.AttendanceBalanceRecordVo;
|
||||
import jnpf.model.attendance.vo.UserBalanceVo;
|
||||
import jnpf.model.attendance.vo.VacationVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface AttendanceBalanceRecordMapper {
|
||||
|
||||
/**
|
||||
* 余额管理列表
|
||||
*
|
||||
* @param balanceQueryDto 查询参数
|
||||
* @return java.util.List<jnpf.model.attendance.vo.UserBalanceVo>
|
||||
* @author hlp
|
||||
*/
|
||||
// @Deprecated
|
||||
// List<UserBalanceVo> getBalanceList(@Param("balanceQueryDto") BalanceQueryDto balanceQueryDto, @Param("balanceSort") String balanceSort, @Param("paidBalanceSort") String paidBalanceSort, @Param("unpaidBalanceSort") String unpaidBalanceSort, @Param("adventBalance") String adventBalance);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 新增假期节假日劵
|
||||
*
|
||||
* @param id 主键id
|
||||
* @param userId 用户
|
||||
* @param holidayName 节假日名称
|
||||
* @param dayNum 总额
|
||||
* @param expiresTime 过期时间
|
||||
* @param unit 单位 : 1 :小时 2: 天
|
||||
* @param grantWay 发放方式 0.自动发放 1.手动发放
|
||||
* @param createUserId 创建人
|
||||
* @param paid 是否带薪(1带薪 2非带薪)
|
||||
* @param type 类型 : 1.节日 2.假日 3.加班
|
||||
* @param objectId 关联id和Type联合使用 节日时是节日id 假日是是假日id 加班时是加班id
|
||||
* @author hlp
|
||||
*/
|
||||
// @Deprecated
|
||||
// void grantBalance(@Param("id") String id, @Param("userId") String userId, @Param("holidayName") String holidayName, @Param("dayNum") BigDecimal dayNum, @Param("expiresTime") Date expiresTime, @Param("unit") Integer unit, @Param("grantWay") Integer grantWay, @Param("createUserId") String createUserId, @Param("paid") Integer paid, @Param("type") Integer type, @Param("objectId") String objectId);
|
||||
|
||||
/**
|
||||
* 余额记录列表
|
||||
*
|
||||
* @param balanceQueryDto 参数
|
||||
* @return java.util.List<jnpf.model.attendance.vo.AttendanceBalanceRecordVo>
|
||||
* @author hlp
|
||||
*/
|
||||
// @Deprecated
|
||||
// List<AttendanceBalanceRecordVo> getUserBalance(@Param("balanceQueryDto") BalanceQueryDto balanceQueryDto);
|
||||
|
||||
/**
|
||||
* 成员余额记录列表
|
||||
*
|
||||
* @param balanceQueryDto 参数
|
||||
* @return java.util.List<jnpf.model.attendance.vo.AttendanceBalanceRecordVo>
|
||||
* @author hlp
|
||||
*/
|
||||
// @Deprecated
|
||||
// List<AttendanceBalanceRecordVo> getUserBalanceDetail(@Param("balanceQueryDto") BalanceQueryDto balanceQueryDto);
|
||||
|
||||
/**
|
||||
* 修改指定劵的状态
|
||||
*
|
||||
* @param id 劵的id
|
||||
* @param state 状态 0 正常 1 过期 2已停用
|
||||
* @author hlp
|
||||
*/
|
||||
// @Deprecated
|
||||
// void updateBalanceState(@Param("id") String id, @Param("state") Integer state, @Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 获取用户余额
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return jnpf.model.attendance.vo.UserBalanceVo
|
||||
* @author hlp
|
||||
*/
|
||||
@Deprecated
|
||||
UserBalanceVo getBalanceByUserId(@Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 过期劵
|
||||
*
|
||||
* @author hlp
|
||||
*/
|
||||
void invalidationCoupons(@Param("ids") List<String> ids);
|
||||
|
||||
/**
|
||||
* 获取节日信息
|
||||
*
|
||||
* @param balanceId 节日id
|
||||
* @return jnpf.model.attendance.vo.VacationVo
|
||||
* @author hlp
|
||||
*/
|
||||
VacationVo getFestivalSetting(@Param("balanceId") String balanceId);
|
||||
|
||||
/**
|
||||
* 获取假日配置信息
|
||||
*
|
||||
* @param balanceId 假日id
|
||||
* @return jnpf.model.attendance.vo.VacationVo
|
||||
* @author hlp
|
||||
*/
|
||||
VacationVo getHolidaySetting(@Param("balanceId") String balanceId);
|
||||
|
||||
/**
|
||||
* 获取用户的劵过期的排前面
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @param paid 是否带薪(1带薪 2非带薪)
|
||||
* @return java.util.List<jnpf.model.attendance.vo.AttendanceBalanceRecordVo>
|
||||
* @author hlp
|
||||
*/
|
||||
@Deprecated
|
||||
List<AttendanceBalanceRecordVo> getBalanceRecordByUserId(@Param("userId") String userId, @Param("paid") List<Integer> paid);
|
||||
|
||||
/**
|
||||
* 修改劵的使用情况
|
||||
*
|
||||
* @param id 主键id
|
||||
* @param balance 余额
|
||||
* @param over 是否使用完 0未使用完 1使用完
|
||||
* @author hlp
|
||||
*/
|
||||
void updateBalance(@Param("id") String id, @Param("balance") BigDecimal balance, @Param("over") Integer over);
|
||||
|
||||
/**
|
||||
* 获取用户指定类型假的余额总数
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @param paid 是否带薪(1带薪 2非带薪)
|
||||
* @return java.math.BigDecimal
|
||||
* @author hlp
|
||||
*/
|
||||
// BigDecimal getBalanceRecordCountByUserId(@Param("userId") String userId, @Param("paid") Integer paid);
|
||||
|
||||
|
||||
/**
|
||||
* 通过劵的id获取劵的详情
|
||||
*
|
||||
* @param balanceIds 劵的id
|
||||
* @return java.util.List<jnpf.model.attendance.vo.AttendanceBalanceRecordVo>
|
||||
* @author hlp
|
||||
*/
|
||||
List<AttendanceBalanceRecordVo> getBalanceDetailList(@Param("balanceIds") List<String> balanceIds);
|
||||
|
||||
/**
|
||||
* 验证出勤规则id有无发加班劵
|
||||
*
|
||||
* @param ruleId 出勤规则id
|
||||
* @return java.lang.Integer
|
||||
* @author hlp
|
||||
*/
|
||||
Integer getBalanceByRuleId(@Param("ruleId") String ruleId);
|
||||
|
||||
/**
|
||||
* 批量获取用户余额
|
||||
*
|
||||
* @param userIds 用户ids
|
||||
*/
|
||||
List<UserBalanceVo> getBalanceByUserIds(@Param("userIds") List<String> userIds);
|
||||
|
||||
/**
|
||||
* 根据申请id集合批量获取用户余额
|
||||
*
|
||||
* @param applyIds 申请id集合
|
||||
*/
|
||||
List<BalanceRecord> getBalanceByApplyIds(@Param("applyIds") List<String> applyIds);
|
||||
|
||||
/**
|
||||
* 获取用户余额
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<AttendanceStorageRest> getStraightBalanceList();
|
||||
|
||||
|
||||
/**
|
||||
* 删除当月存休
|
||||
*/
|
||||
void deleteByYearMonth(@Param("lastMonthDate") String lastMonthDate);
|
||||
|
||||
/**
|
||||
* 查询用户加班存休天数以及剩余天数
|
||||
*
|
||||
* @param userIds 用户id集合
|
||||
*/
|
||||
List<OvertimeBalanceModel> getOvertimeBalanceInfo(@Param("startDate") Date startDate, @Param("endDate") Date endDate,
|
||||
@Param("userIds") List<String> userIds);
|
||||
|
||||
/**
|
||||
* 查询用户存休剩余天数
|
||||
*
|
||||
* @param userIds 用户id集合
|
||||
*/
|
||||
List<SurplusDaysModel> getSurplusDaysInfo(@Param("userIds") List<String> userIds);
|
||||
|
||||
/**
|
||||
* 查询用户节假日加班天数
|
||||
*
|
||||
* @param userIds 用户id集合
|
||||
*/
|
||||
List<OvertimeHolidaysInfoModel> getOvertimeHolidaysInfo(@Param("startDate") Date startDate, @Param("endDate") Date endDate,
|
||||
@Param("userIds") List<String> userIds);
|
||||
/**
|
||||
* 查询查询用户各个请假类型余额天数
|
||||
*
|
||||
* @param userIds 用户id集合
|
||||
*/
|
||||
List<LeaveBalanceInfoModel> getLeaveBalanceInfo(@Param("startDate") Date startDate, @Param("endDate") Date endDate,
|
||||
@Param("userIds") List<String> userIds);
|
||||
|
||||
/**
|
||||
* 查询查询用户各个请假审批数据
|
||||
*
|
||||
* @param userIds 用户id集合
|
||||
*/
|
||||
List<LeaveApprovalModel> getLeaveApprovalInfo(@Param("leaveIds") List<String> leaveIds,
|
||||
@Param("userIds") List<String> userIds);
|
||||
|
||||
List<AttendanceBalanceRecordEntity> selectInvalidationCoupons();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import jnpf.entity.attendance.AttendanceBalanceUseRecord;
|
||||
import jnpf.model.doclibrary.vo.UseDetailVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface AttendanceBalanceUseRecordMapper extends BaseMapper<AttendanceBalanceUseRecord> {
|
||||
|
||||
/**
|
||||
* 获取用户劵的使用劵详情
|
||||
* @param id 劵的Id
|
||||
*/
|
||||
List<UseDetailVo> getUserBalanceDetail(String id);
|
||||
|
||||
/**
|
||||
* 新增劵使用记录
|
||||
* @param id 主键id
|
||||
* @param balanceId 余额劵id
|
||||
* @param quota 使用额度
|
||||
* @param unit 单位 : 1 :小时 2: 天
|
||||
* @param userType 使用方式 0: 审批 ,1:排班
|
||||
* @param objectId 关联id和useType联合使用
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param lock 锁定: 1锁定 2已消费
|
||||
* @author hlp
|
||||
*/
|
||||
void addOne(@Param("id") String id, @Param("balanceId") String balanceId, @Param("quota") BigDecimal quota, @Param("unit") Integer unit, @Param("userType") Integer userType, @Param("objectId") String objectId, @Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("lock") Integer lock);
|
||||
|
||||
/**
|
||||
* 查出本次排班相关的所有消费记录
|
||||
* @param id 关联id和useType联合使用
|
||||
* @param userType 使用方式 0: 审批 ,1:排班
|
||||
* @return java.util.List<jnpf.model.doclibrary.vo.UseDetailVo>
|
||||
* @author hlp
|
||||
*/
|
||||
List<UseDetailVo> getUserBalanceListByObjectId(@Param("id") String id, @Param("userType") Integer userType);
|
||||
|
||||
/**
|
||||
* 根据劵的使用记录id删除记录
|
||||
* @param userBalanceList 劵的使用记录id
|
||||
* @author hlp
|
||||
*/
|
||||
void deleteByIds(@Param("userBalanceList") List<UseDetailVo> userBalanceList);
|
||||
|
||||
/**
|
||||
* 批量新增劵使用记录
|
||||
* @param useRecordList 劵使用记录
|
||||
* @author hlp
|
||||
*/
|
||||
void addBatch(@Param("useRecordList") List<AttendanceBalanceUseRecord> useRecordList);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.AttendanceBaseSetting;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤基础设置表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2023-11-29
|
||||
*/
|
||||
public interface AttendanceBaseSettingMapper extends SuperMapper<AttendanceBaseSetting> {
|
||||
|
||||
/**
|
||||
* 获取出勤换算
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
Integer getAttendanceRatio(String userId);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.AttendanceBookConfigEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 考勤本配置Mapper
|
||||
*
|
||||
* @author Generated
|
||||
* @create 2026-04-15
|
||||
*/
|
||||
@Mapper
|
||||
public interface AttendanceBookConfigMapper extends SuperMapper<AttendanceBookConfigEntity>{
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import jnpf.entity.attendance.AttendanceBookOperationLogEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 考勤本操作日志Mapper
|
||||
*
|
||||
* @author Generated
|
||||
* @create 2026-04-15
|
||||
*/
|
||||
@Mapper
|
||||
public interface AttendanceBookOperationLogMapper extends BaseMapper<AttendanceBookOperationLogEntity> {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import jnpf.entity.attendance.AttendanceBookRecordEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 考勤本记录表Mapper
|
||||
*
|
||||
* @author Generated
|
||||
* @create 2026-04-15
|
||||
*/
|
||||
@Mapper
|
||||
@Component
|
||||
public interface AttendanceBookRecordMapper extends BaseMapper<AttendanceBookRecordEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
|
||||
public interface AttendanceCardReplacementApproveMapper {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.FtbAttendanceClockIn;
|
||||
import jnpf.model.attendance.model.ClockClassRecord;
|
||||
import jnpf.model.attendance.vo.*;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 打卡mapper
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2023-11-21
|
||||
*/
|
||||
public interface AttendanceClockInMapper extends SuperMapper<FtbAttendanceClockIn> {
|
||||
|
||||
/**
|
||||
* 查询用户出勤结果
|
||||
* @param list 用户id
|
||||
* @return java.util.List<jnpf.model.attendance.vo.ClockInVo>
|
||||
*/
|
||||
List<ClockInVo> getClockInResultByRule(@Param("list") List<RuleUserVo> list);
|
||||
|
||||
/**
|
||||
* 查询用户出勤结果
|
||||
* @param ruleIdList 出勤规则ids
|
||||
* @return java.util.List<jnpf.model.attendance.vo.ClockInVo>
|
||||
*/
|
||||
List<ClockInVo> getClockInResultByRuleList(@Param("list") List<String> ruleIdList);
|
||||
|
||||
/**
|
||||
* 查询时间段内的补卡次数
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param userId 用户id
|
||||
* @param groupId 考勤组id
|
||||
* @return int
|
||||
*/
|
||||
int getRepairCount(@Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("userId") String userId, @Param("groupId") String groupId);
|
||||
|
||||
/**
|
||||
* 查询考勤组本月异常打卡记录
|
||||
* @param userId 用户id
|
||||
* @param groupId 考勤组id
|
||||
* @param monthBeginDate 月初
|
||||
* @param monthEndDate 月末
|
||||
* @param absenceType 能否补缺勤卡(1: 是, 0: 否)
|
||||
* @param queryTypeList 补卡类型(1: 迟到, 2: 早退, 3: 缺卡)
|
||||
* @return java.util.List<jnpf.model.attendance.vo.AbnormalClockInVo>
|
||||
*/
|
||||
List<AbnormalClockInVo> getAbnormalClockInList(@Param("userId") String userId, @Param("groupId") String groupId,
|
||||
@Param("monthBeginDate") Date monthBeginDate, @Param("monthEndDate") Date monthEndDate,
|
||||
@Param("absenceType") Integer absenceType, @Param("list") List<Integer> queryTypeList);
|
||||
|
||||
/**
|
||||
* 更新为缺勤
|
||||
* @param ruleId 出勤规则id
|
||||
* @param userId 用户id
|
||||
* @param handleUser 上次操作人
|
||||
* @return int
|
||||
*/
|
||||
int updateToAbsence(@Param("ruleId") String ruleId, @Param("userId") String userId, @Param("handleUser") String handleUser);
|
||||
|
||||
/**
|
||||
* 更新为不缺勤
|
||||
* @param ruleId 出勤规则id
|
||||
* @param userId 用户id
|
||||
* @param handleUser 上次操作人
|
||||
* @return int
|
||||
*/
|
||||
int updateToUnAbsence(@Param("ruleId") String ruleId, @Param("userId") String userId, @Param("handleUser") String handleUser);
|
||||
|
||||
/***
|
||||
* 查询当日所有打卡记录
|
||||
* @param userId 用户id
|
||||
* @param queryDate 日期
|
||||
* @return java.util.List<jnpf.model.attendance.vo.DailyClockInVo>
|
||||
*/
|
||||
List<DailyClockInVo> getListByRuleAndDate(@Param("userId") String userId, @Param("queryDate") String queryDate);
|
||||
|
||||
/***
|
||||
* 查询当日所有打卡记录
|
||||
* @param userId 用户id
|
||||
* @param queryDate 日期
|
||||
* @return java.util.List<jnpf.model.attendance.vo.DailyClockInVo>
|
||||
*/
|
||||
List<ClockClassRecord> getClockInByStatistics(@Param("userId") String userId, @Param("queryDate") Date queryDate);
|
||||
|
||||
/**
|
||||
* 批量查询所有打卡记录
|
||||
* @param userIds 用户id集合
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
*/
|
||||
List<ClockClassRecord> getClockInList(@Param("userIds") List<String> userIds, @Param("start") String start, @Param("end") String end);
|
||||
|
||||
/**
|
||||
* 查询打卡记录[批量]
|
||||
* @param userDayList 用户日期列表
|
||||
* @param approvalStatus 审批状态
|
||||
* @return java.util.List<jnpf.entity.attendance.FtbAttendanceClockIn>
|
||||
*/
|
||||
List<FtbAttendanceClockIn> selectListBatch(@Param("list") List<UserDayVo> userDayList, @Param("approvalStatus") Integer approvalStatus);
|
||||
|
||||
/**
|
||||
* 删除审批中的打卡记录
|
||||
* @param userDayList 用户日期列表
|
||||
* @param passApproval 审批状态
|
||||
*/
|
||||
void deleteBatchByUserDay(@Param("list") List<UserDayVo> userDayList, @Param("passApproval") Integer passApproval);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.AttendanceClockInPic;
|
||||
|
||||
/**
|
||||
* 外勤打卡图片mapper
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2023-11-21
|
||||
*/
|
||||
public interface AttendanceClockInPicMapper extends SuperMapper<AttendanceClockInPic> {
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.AttendanceClockInResult;
|
||||
import jnpf.model.attendance.vo.ChangeInfoVo;
|
||||
import jnpf.model.attendance.vo.ConditionVo;
|
||||
import jnpf.model.attendance.vo.RuleDayVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 打卡结果mapper
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2023-11-27
|
||||
*/
|
||||
public interface AttendanceClockInResultMapper extends SuperMapper<AttendanceClockInResult> {
|
||||
|
||||
/**
|
||||
* 根据出勤规则删除用户的打卡结果
|
||||
* @param userId 用户id
|
||||
* @param updateUserId 操作人
|
||||
* @return int
|
||||
*/
|
||||
int deleteRecordByRule(@Param("userId") String userId, @Param("updateUserId") String updateUserId);
|
||||
|
||||
/**
|
||||
* 根据出勤规则删除用户的打卡结果[批量]
|
||||
* @param userIds 用户id列表
|
||||
* @param updateUserId 操作人
|
||||
* @return int
|
||||
*/
|
||||
int deleteRecordByRuleBatch(@Param("list") List<String> userIds, @Param("updateUserId") String updateUserId);
|
||||
|
||||
/**
|
||||
* 根据条件查询用户打卡记录
|
||||
* @param dateStr 日期
|
||||
* @return java.util.List<jnpf.entity.attendance.AttendanceClockInResult>
|
||||
*/
|
||||
List<AttendanceClockInResult> selectUserClockInHistory(String dateStr);
|
||||
|
||||
|
||||
/**
|
||||
* 根据考勤组id,用户id及时间范围查询打卡结果记录
|
||||
*/
|
||||
List<ChangeInfoVo> selectUserClockInResult(@Param("groupId") String groupId, @Param("userId") String userId, @Param("start") Date start, @Param("end") Date end);
|
||||
/**
|
||||
* 批量更新记录为删除
|
||||
* @param delList 删除列表
|
||||
* @return int
|
||||
*/
|
||||
int updateBatchToDel(@Param("list") List<String> delList);
|
||||
|
||||
/**
|
||||
* 更新申请信息为空
|
||||
* @param clockInId 打卡id
|
||||
* @param applyId 审批id
|
||||
* @return int
|
||||
*/
|
||||
int updateReplyToNull(@Param("clockInId") String clockInId, @Param("applyId") String applyId);
|
||||
|
||||
/**
|
||||
* 判断是否缺勤
|
||||
* @param ruleId 出勤规则
|
||||
* @param userId 用户id
|
||||
* @return int
|
||||
*/
|
||||
int countAbsence(@Param("ruleId") String ruleId, @Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 更新审批为空
|
||||
* @param id 结果id
|
||||
* @param dealUser 处理人
|
||||
* @return int
|
||||
*/
|
||||
int updateResultReplyToNull(@Param("id") String id, @Param("dealUser") String dealUser);
|
||||
|
||||
/**
|
||||
* 查询已存在的打卡结果
|
||||
* @param list 打卡结果列表
|
||||
* @param containsType 包含打卡类型(上/下班) 1: 是, 0: 否
|
||||
* @return java.util.List<jnpf.entity.attendance.AttendanceClockInResult>
|
||||
*/
|
||||
List<AttendanceClockInResult> selectExistRecord(@Param("list") List<AttendanceClockInResult> list, @Param("containsType") Integer containsType);
|
||||
|
||||
/**
|
||||
* 根据出勤规则删除打卡结果
|
||||
* @param list 出勤规则列表
|
||||
* @param updateUserId 更新用户id
|
||||
* @return int
|
||||
*/
|
||||
int updateToDelByRule(@Param("list") List<String> list, @Param("updateUserId") String updateUserId);
|
||||
|
||||
/**
|
||||
* 查询跨天的打卡id
|
||||
* @param ruleIds 出勤规则ids
|
||||
* @param day 日期
|
||||
* @return java.util.List<java.lang.String>
|
||||
*/
|
||||
List<String> getCrossDayClockInIdList(@Param("list") List<String> ruleIds, @Param("day") Date day);
|
||||
/**
|
||||
* 查询跨天的打卡id[批量]
|
||||
* @param ruleDayList 规则日期列表
|
||||
* @return java.util.List<java.lang.String>
|
||||
*/
|
||||
List<String> getCrossDayClockInIdListBatch(@Param("list") List<RuleDayVo> ruleDayList);
|
||||
|
||||
/**
|
||||
* 查询打卡结果是否在审批中
|
||||
* @param clockInResultId 打卡结果id
|
||||
* @return int
|
||||
*/
|
||||
int getReplyingCount(String clockInResultId);
|
||||
|
||||
/**
|
||||
* 更新缺勤为正常
|
||||
* @param id 结果id
|
||||
* @return int
|
||||
*/
|
||||
int updateAbsenceToNormal(String id);
|
||||
/**
|
||||
* 更新为缺勤
|
||||
* @param id 结果id
|
||||
* @return int
|
||||
*/
|
||||
int updateToAbsence(String id);
|
||||
|
||||
/**
|
||||
* 根据用户和日期查询打卡结果
|
||||
* @param userId 用户id
|
||||
* @param date 日期
|
||||
* @return java.util.List<java.lang.String>
|
||||
*/
|
||||
List<String> getByUserAndDay(@Param("userId") String userId, @Param("date") Date date);
|
||||
|
||||
/**
|
||||
* 根据出勤规则删除打卡结果
|
||||
* @param ruleIdList 出勤规则列表
|
||||
* @return int
|
||||
*/
|
||||
int removeClockInResultByRule(@Param("list") List<String> ruleIdList);
|
||||
|
||||
/**
|
||||
* 获取用户打卡天数
|
||||
*/
|
||||
Integer getClockInDayNum(String userId);
|
||||
|
||||
/**
|
||||
* 获取用户迟到次数
|
||||
*/
|
||||
Integer getLateClockInNum(@Param("dayRuleIds") List<String> dayRuleIds);
|
||||
|
||||
/**
|
||||
* 查询补卡审批中次数
|
||||
* @param userId 用户id
|
||||
* @param groupId 考勤组id
|
||||
* @return int
|
||||
*/
|
||||
int selectRepairApplyCount(@Param("userId") String userId, @Param("groupId") String groupId, @Param("beginDate") String beginDate, @Param("endDate") String endDate);
|
||||
|
||||
/**
|
||||
* 根据打卡ids查询打卡结果
|
||||
* @param clockInIds 打卡ids
|
||||
* @return java.util.List<jnpf.entity.attendance.AttendanceClockInResult>
|
||||
*/
|
||||
List<AttendanceClockInResult> selectBatchByClockInIds(@Param("list") List<String> clockInIds);
|
||||
|
||||
/**
|
||||
* 变更打卡结果绑定的rule
|
||||
* @param resultId 打卡结果id
|
||||
* @param ruleId 出勤规则id
|
||||
*/
|
||||
void updateResultRelation(@Param("resultId") String resultId, @Param("ruleId") String ruleId);
|
||||
|
||||
/**
|
||||
* 查询需要更新为缺勤的打卡结果
|
||||
* @param conditionList 缺勤条件
|
||||
* @return java.util.List<jnpf.model.attendance.vo.ConditionVo>
|
||||
*/
|
||||
List<ConditionVo> selectRuleIdsForAbsence(@Param("list") List<ConditionVo> conditionList);
|
||||
|
||||
/**
|
||||
* 更新为缺勤[批量]
|
||||
* @param updateResultIds 打卡结果ids
|
||||
*/
|
||||
void updateToAbsenceBatch(@Param("list") List<String> updateResultIds);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.AttendanceCloudAlbum;
|
||||
|
||||
/**
|
||||
* @Description: 考勤云相册表
|
||||
* @Author: shiTou(他是小石头)
|
||||
* @Date: 2024-10-30 10:26
|
||||
*/
|
||||
public interface AttendanceCloudAlbumMapper extends SuperMapper<AttendanceCloudAlbum> {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.AttendanceConfirmDetails;
|
||||
|
||||
/**
|
||||
* 考勤确认详情
|
||||
*
|
||||
* @author shitou
|
||||
* @email shitou@niujiekeji.com
|
||||
* @date 2024-11-07 09:33:43
|
||||
*/
|
||||
public interface AttendanceConfirmDetailsMapper extends SuperMapper<AttendanceConfirmDetails> {
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.AttendanceConfirm;
|
||||
import jnpf.model.attendance.vo.attendance.ConfirmListQueryVo;
|
||||
import jnpf.model.attendance.vo.attendance.ConfirmStatisticsVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤确认
|
||||
*
|
||||
* @author shitou
|
||||
* @email shitou@niujiekeji.com
|
||||
* @date 2024-11-07 09:33:43
|
||||
*/
|
||||
public interface AttendanceConfirmMapper extends SuperMapper<AttendanceConfirm> {
|
||||
/**
|
||||
* 考勤确认聚合统计
|
||||
*
|
||||
* @param userIds 用户ID集合
|
||||
* @param year 考勤年份
|
||||
* @param month 月份
|
||||
* @return 考勤确认聚合统计
|
||||
*/
|
||||
ConfirmStatisticsVo getStatistics(@Param("userIds") List<String> userIds, @Param("year") int year, @Param("month") int month,@Param("type") Integer type);
|
||||
|
||||
/**
|
||||
* 考勤确认列表查询
|
||||
*
|
||||
* @param userIds 用户ID集合
|
||||
* @param year 考勤年份
|
||||
* @param month 月份
|
||||
* @param type 数据类型
|
||||
* @return 考勤确认列表
|
||||
*/
|
||||
List<ConfirmListQueryVo> getPageList(@Param("userIds") List<String> userIds, @Param("year") int year, @Param("month") int month, @Param("type") Integer type);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.AttendanceConfirmSetting;
|
||||
|
||||
/**
|
||||
* 考勤确认设置
|
||||
*
|
||||
* @author shitou
|
||||
* @email shitou@niujiekeji.com
|
||||
* @date 2024-11-07 09:33:43
|
||||
*/
|
||||
public interface AttendanceConfirmSettingMapper extends SuperMapper<AttendanceConfirmSetting> {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.entity.AttendanceCustomizeTable;
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤-自定义报表设置 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2024-09-03
|
||||
*/
|
||||
public interface AttendanceCustomizeTableMapper extends SuperMapper<AttendanceCustomizeTable> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.FtbAttendanceDailyRule;
|
||||
import jnpf.model.attendance.vo.*;
|
||||
import jnpf.model.attendance.vo.attendance.YesterdayRuleVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤组-每日出勤规则 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2023-11-22
|
||||
*/
|
||||
public interface AttendanceDailyRuleMapper extends SuperMapper<FtbAttendanceDailyRule> {
|
||||
|
||||
/**
|
||||
* 查询昨天和今天的出勤规则
|
||||
* @param currentDate 当前日期
|
||||
* @param userId 用户id
|
||||
* @return java.util.List<jnpf.entity.attendance.FtbAttendanceDailyRule>
|
||||
*/
|
||||
List<FtbAttendanceDailyRule> getRuleClockTimeContainsToday(@Param("currentDate") Date currentDate, @Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 查询指定日期的最后一个出勤规则
|
||||
* @param currentDate 当前日期
|
||||
* @param userId 用户id
|
||||
* @return jnpf.entity.attendance.FtbAttendanceDailyRule
|
||||
*/
|
||||
FtbAttendanceDailyRule getLastDailyRule(@Param("currentDate") Date currentDate, @Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 查询ruleId的上一个或下一个(班/加班)出勤
|
||||
* @param ruleId 出勤id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param userId 用户id
|
||||
* @param queryType 查询类型(previous/next)
|
||||
* @return jnpf.entity.attendance.FtbAttendanceDailyRule
|
||||
*/
|
||||
FtbAttendanceDailyRule getPreviousOrNextRule(@Param("ruleId") String ruleId, @Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("userId") String userId, @Param("queryType") String queryType);
|
||||
|
||||
/**
|
||||
* 获取指定日期的排班
|
||||
* @param startDay 指定日期 2023-11-11
|
||||
* @return java.util.List<jnpf.model.attendance.vo.ClassesDetailVo>
|
||||
* @author hlp
|
||||
*/
|
||||
List<ClassesDetailVo> getShiftByDay(@Param("startDay") String startDay, @Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 查询所有下班缺卡时间是今天的出勤规则(普班)
|
||||
* @param today 今天
|
||||
* @param yesterday 昨天
|
||||
* @param userId 用户id
|
||||
* @return java.util.List<jnpf.entity.attendance.FtbAttendanceDailyRule>
|
||||
*/
|
||||
List<FtbAttendanceDailyRule> getRuleListByDate(@Param("today") Date today, @Param("yesterday") Date yesterday, @Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 查询指定日期最后一个班次是加班的出勤记录
|
||||
* @param date 日期
|
||||
* @param userId 用户id
|
||||
* @return java.util.List<jnpf.entity.attendance.FtbAttendanceDailyRule>
|
||||
*/
|
||||
List<FtbAttendanceDailyRule> getOverTimeRuleListByDate(@Param("date") Date date, @Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 获取用户时间段内排班信息
|
||||
* @param userId 用户id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return java.lang.Integer
|
||||
* @author hlp
|
||||
*/
|
||||
Integer getUserShift(@Param("userId") String userId, @Param("startTime") Date startTime, @Param("endTime") Date endTime);
|
||||
|
||||
/**
|
||||
* 查询所有工作时间是queryDate的出勤规则
|
||||
* @param queryDate 日期
|
||||
* @return java.util.List<jnpf.entity.attendance.FtbAttendanceDailyRule>
|
||||
*/
|
||||
List<FtbAttendanceDailyRule> getListWorkTimeInToday(@Param("queryDate") Date queryDate);
|
||||
|
||||
/**
|
||||
* 查询上班/下班时间在时间范围内的出勤规则
|
||||
* @param beginDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return java.util.List<jnpf.entity.attendance.FtbAttendanceDailyRule>
|
||||
*/
|
||||
List<FtbAttendanceDailyRule> getListByWorkTime(@Param("beginDate") Date beginDate, @Param("endDate") Date endDate);
|
||||
|
||||
/**
|
||||
* 查询一个月的打卡记录(缺勤次数统计)
|
||||
* @return java.util.List<jnpf.model.attendance.vo.MonthRecordVo>
|
||||
*/
|
||||
List<MonthRecordVo> selectMonthRecord();
|
||||
|
||||
/**
|
||||
* 查询存在的出勤规则
|
||||
* @param ruleIdList 出勤规则id列表
|
||||
* @return java.util.List<java.lang.String>
|
||||
*/
|
||||
List<String> getExistRuleId(@Param("list") List<String> ruleIdList);
|
||||
|
||||
/**
|
||||
* 获取排班用户数
|
||||
* @param userIds 用户Ids
|
||||
* @param groupIds 考勤组Ids
|
||||
* @return int
|
||||
*/
|
||||
Integer getGroupUserNum(@Param("userIds") List<String> userIds, @Param("groupIds") List<String> groupIds);
|
||||
/**
|
||||
* 查询今日班次
|
||||
* @param userId 用户Id
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return java.util.List<YesterdayRuleVo>
|
||||
*/
|
||||
List<YesterdayRuleVo> getYesterdayRule(@Param("userId") String userId,@Param("startDate") Date startDate,@Param("endDate") Date endDate);
|
||||
/**
|
||||
* 获取排班用户数
|
||||
* @param groupUserIds 用户Ids
|
||||
* @param groupIds 考勤组Ids
|
||||
* @return java.util.List<java.lang.String>
|
||||
*/
|
||||
List<String> getDayRule(@Param("groupUserIds") List<String> groupUserIds, @Param("groupIds") List<String> groupIds);
|
||||
|
||||
/**
|
||||
* 批量查询[当日+前一日]出勤规则
|
||||
* @param userDayList 用户日期列表
|
||||
* @return java.util.List<jnpf.entity.attendance.FtbAttendanceDailyRule>
|
||||
*/
|
||||
List<FtbAttendanceDailyRule> getDailyRuleListBatch(@Param("list") List<UserDayVo> userDayList);
|
||||
|
||||
/**
|
||||
* 获取用户已使用的公休数
|
||||
* @param yearMonth 年月 格式yyyy-MM
|
||||
* @param userIds 用户Ids
|
||||
* @return java.util.Map<java.lang.String, java.math.BigDecimal>
|
||||
*/
|
||||
List<KeyValueVo> getUserPublicHoliday(@Param("yearMonth") String yearMonth, @Param("userIds") List<String> userIds);
|
||||
|
||||
/**
|
||||
* 查询每个出勤规则的下一个出勤规则
|
||||
* @param dayRuleIds 出勤规则ids
|
||||
* @param dayStr 日期
|
||||
* @return java.util.List<jnpf.model.attendance.vo.NextRuleVo>
|
||||
*/
|
||||
List<NextRuleVo> getNextRulePartInfo(@Param("list") List<String> dayRuleIds, @Param("dayStr") String dayStr);
|
||||
|
||||
/**
|
||||
* 获取指定日期的出勤规则
|
||||
* @param finalStartDate 开始日期
|
||||
* @param finalEndDate 结束日期
|
||||
* @return 排班列表
|
||||
*/
|
||||
List<CreateDayStatistics> getDayRuleByMonth(@Param("startDate") LocalDate finalStartDate, @Param("endDate") LocalDate finalEndDate);
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import jnpf.attendance.dto.AttendanceCountAvgHoursVo;
|
||||
import jnpf.attendance.dto.DateDimensionsRangeDto;
|
||||
import jnpf.entity.attendance.AttendanceDayStatistics;
|
||||
import jnpf.model.attendance.dto.*;
|
||||
import jnpf.model.attendance.vo.attendance.*;
|
||||
import jnpf.model.common.DateRangeDto;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤日度统计表
|
||||
*
|
||||
* @author shitou
|
||||
* @email shitou@niujiekeji.com
|
||||
* @date 2024-06-24 09:33:43
|
||||
*/
|
||||
@Mapper
|
||||
@Component
|
||||
public interface AttendanceDayStatisticsMapper extends BaseMapper<AttendanceDayStatistics> {
|
||||
/**
|
||||
* 查询日统计数据
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 日统计数据
|
||||
*/
|
||||
StatisticsDataQueryVo getDayStatisticsDataQuery(@Param("req") StatisticsDataQueryDto queryDto);
|
||||
|
||||
/**
|
||||
* 查询日统计分页数据
|
||||
*
|
||||
* @param req 筛选条件
|
||||
* @return 分页数据
|
||||
*/
|
||||
List<DayStatisticsQueryVo> getDayPageList(@Param("req") DayStatisticsDataPageListQueryDto req);
|
||||
|
||||
/**
|
||||
* 查询计薪日统计分页数据
|
||||
*
|
||||
* @param req 筛选条件
|
||||
* @return 分页数据
|
||||
*/
|
||||
List<DayPayrollStatisticsQueryVo> getDayPayrollPageList(@Param("req") DayStatisticsDataPageListQueryDto req);
|
||||
|
||||
/**
|
||||
* 查询月统计数据
|
||||
*
|
||||
* @param queryDto 日欺范围
|
||||
* @param isGroupBy 是否按照考勤组分组
|
||||
* @return 月统计数据
|
||||
*/
|
||||
StatisticsDataQueryVo getMonthStatisticsDataQuery(@Param("req") StatisticsDataQueryDto queryDto, @Param("isGroupBy") Boolean isGroupBy);
|
||||
|
||||
/**
|
||||
* 查询月统计分页数据
|
||||
*
|
||||
* @param req 筛选条件
|
||||
* @return 分页数据
|
||||
*/
|
||||
List<MonthStatisticsQueryVo> getMonthPageList(@Param("req") MonthStatisticsDataQueryDto req);
|
||||
|
||||
/**
|
||||
* 查询计薪月统计分页数据
|
||||
*
|
||||
* @param req 筛选条件
|
||||
* @return 分页数据
|
||||
*/
|
||||
List<MonthPayrollStatisticsQueryVo> getMonthPayrollPageList(@Param("req") MonthStatisticsDataQueryDto req);
|
||||
|
||||
/**
|
||||
* 查询需要提醒的日统计数据
|
||||
*
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 日统计数据
|
||||
*/
|
||||
List<DayStatisticsNoticeQueryVo> getDayStatisticsNotice(@Param("startDate") String startDate, @Param("endDate") String endDate);
|
||||
|
||||
/**
|
||||
* 查询需要提醒的月统计数据
|
||||
*
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 月统计数据
|
||||
*/
|
||||
List<MonthStatisticsNoticeQueryVo> getMonthStatisticsNotice(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 查询需要提醒的团队统计数据
|
||||
*
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 团队统计数据
|
||||
*/
|
||||
List<TeamMonthStatisticsNoticeQueryVo> getStemMonthStatisticsNotice(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 获取考勤组每月的平均工时
|
||||
*
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 每月的平均工时
|
||||
*/
|
||||
List<AttendanceCountAvgHoursVo> getAvgHours(@Param("groupIds") List<String> groupIds, @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 获取多考勤组月度统计数据
|
||||
*
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 月度统计数据
|
||||
*/
|
||||
MonthStatsDetailsQueryVo getAttendanceAvgHoursDetails(@Param("groupIds") List<String> groupIds, @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 获取多考勤组月度人均工时折线图
|
||||
*
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 人均工时折线图
|
||||
*/
|
||||
List<MonthStatsPerCapitaQueryVo> getAttendanceMonthPerCapita(@Param("groupIds") List<String> groupIds, @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 获取多考勤组月度日常情况
|
||||
*
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 月度日常情况
|
||||
*/
|
||||
MonthStatsDailySituationQueryVo getAttendanceDailySituation(@Param("groupIds") List<String> groupIds, @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 获取多考勤组月度考勤工时排行
|
||||
*
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 考勤工时排行
|
||||
*/
|
||||
List<MonthStatsHoursRankingQueryVo> getAttendanceHoursRanking(@Param("groupIds") List<String> groupIds, @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 获取多考勤组月度全勤情况
|
||||
*
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 全勤情况
|
||||
*/
|
||||
List<MonthStatsFullSituationQueryVo> getAttendanceFullSituation(@Param("groupIds") List<String> groupIds, @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 获取多考勤组月度异常情况
|
||||
*
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 异常情况
|
||||
*/
|
||||
MonthStatsAbnormalConditionQueryVo getAttendanceAbnormalCondition(@Param("groupIds") List<String> groupIds, @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 获取多考勤组月度加班情况
|
||||
*
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 加班情况
|
||||
*/
|
||||
List<MonthStatsOvertimeSituationQueryVo> getAttendanceOvertimeSituation(@Param("groupIds") List<String> groupIds, @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 获取当月考勤确认数据
|
||||
*
|
||||
* @param userIds 用户ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 考勤组月度加班情况
|
||||
*/
|
||||
List<MonthStatisticsQueryVo> getConfirmDetailsInfoByMonth(@Param("userIds") List<String> userIds, @Param("startDate") Date startDate, @Param("endDate") Date endDate);
|
||||
|
||||
/**
|
||||
* 批量查询用户在指定月份是否封账
|
||||
*
|
||||
* @param userIdList 用户ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 是否封账
|
||||
*/
|
||||
List<SealUserInfoDataVo> selectUserIsSeal(@Param("userIdList") List<String> userIdList,
|
||||
@Param("startDate") String startDate,
|
||||
@Param("endDate") String endDate);
|
||||
|
||||
/**
|
||||
* 按天查询用户在日期范围内的封存日期列表(仅返回已封存的日期)
|
||||
* 用于跨月查询场景下按天判断每个用户每一天是否被封存
|
||||
*
|
||||
* @param userIdList 用户ID集合
|
||||
* @param startDate 开始时间(含)
|
||||
* @param endDate 结束时间(含)
|
||||
* @return 用户按天封存记录
|
||||
*/
|
||||
List<UserDailySealVo> selectUserDailySeal(@Param("userIdList") List<String> userIdList,
|
||||
@Param("startDate") String startDate,
|
||||
@Param("endDate") String endDate);
|
||||
|
||||
/**
|
||||
* 考勤封账-分页列表
|
||||
*
|
||||
* @param queryDto 考勤封账分页列表参数
|
||||
* @param seal 封账状态
|
||||
* @return 考勤封账分页列表结果
|
||||
*/
|
||||
List<MonthSealPageListVo> sealPageList(@Param("req") StatisticsDataQueryDto queryDto, @Param("seal") Integer seal);
|
||||
|
||||
/**
|
||||
* 薪酬考勤数据支持
|
||||
*
|
||||
* @param dto 薪酬考勤数据支持参数
|
||||
* @return 薪酬考勤数据支持结果
|
||||
*/
|
||||
List<SalaryAttendanceSupportQuery> salaryAttendanceSupport(@Param("req") SalaryAttendanceSupportDto dto);
|
||||
|
||||
/**
|
||||
* 获取考勤组维度考勤数据
|
||||
*
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param dimensions 维度范围
|
||||
* @return 考勤组维度考勤数据
|
||||
*/
|
||||
List<AttendanceDimensionVo> getDimensionsAttendanceCountList(@Param("groupIds") List<String> groupIds,
|
||||
@Param("dimensions") List<DateDimensionsRangeDto> dimensions);
|
||||
|
||||
/**
|
||||
* 获取考勤组维度考勤数据-日维度
|
||||
*
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 考勤组维度考勤数据
|
||||
*/
|
||||
List<AttendanceDimensionDayVo> getDimensionsAttendanceDayCountList(@Param("groupIds") List<String> groupIds,
|
||||
@Param("startDate") Date startDate,
|
||||
@Param("endDate") Date endDate);
|
||||
|
||||
/**
|
||||
* 考勤平均工时趋势-分页列表
|
||||
* @param page 分页参数
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 考勤平均工时趋势-分页列表结果
|
||||
*/
|
||||
Page<AverageTrendPageListVo> averageWorkHoursTrendPageList(@Param("page") Page<AverageTrendPageListVo> page,
|
||||
@Param("groupIds") List<String> groupIds,
|
||||
@Param("startDate") LocalDate startDate,
|
||||
@Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 考勤人均工时趋势-分页列表
|
||||
* @param page 分页参数
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 考勤人均工时趋势-分页列表结果
|
||||
*/
|
||||
Page<PersonnelTrendPageListVo> personWorkHoursTrendPageList(@Param("page") Page<PersonnelTrendPageListVo> page,
|
||||
@Param("groupIds") List<String> groupIds,
|
||||
@Param("startDate") LocalDate startDate,
|
||||
@Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 考勤日常情况-分页列表
|
||||
* @param page 分页参数
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 日常情况-分页列表结果
|
||||
*/
|
||||
Page<DailySituationPageListVo> dailySituationPageList(@Param("page") Page<DailySituationPageListVo> page,
|
||||
@Param("groupIds") List<String> groupIds,
|
||||
@Param("startDate") LocalDate startDate,
|
||||
@Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 考勤工时排名-分页列表
|
||||
* @param page 分页参数
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 考勤组工时排名-分页列表结果
|
||||
*/
|
||||
Page<WorkHoursRankingPageListVo> workHoursRankingPageList(@Param("page") Page<WorkHoursRankingPageListVo> page,
|
||||
@Param("groupIds") List<String> groupIds,
|
||||
@Param("startDate") LocalDate startDate,
|
||||
@Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 考勤全勤情况-分页列表
|
||||
* @param page 分页参数
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 全勤情况-分页列表结果
|
||||
*/
|
||||
Page<FullAttendanceStatusPageListVo> fullAttendanceStatusPageList(@Param("page") Page<FullAttendanceStatusPageListVo> page,
|
||||
@Param("groupIds") List<String> groupIds,
|
||||
@Param("startDate") LocalDate startDate,
|
||||
@Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 考勤异常情况-分页列表
|
||||
* @param page 分页参数
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 异常情况-分页列表结果
|
||||
*/
|
||||
Page<ExceptionSituationPageListVo> exceptionSituationPageList(@Param("page") Page<ExceptionSituationPageListVo> page,
|
||||
@Param("groupIds") List<String> groupIds,
|
||||
@Param("startDate") LocalDate startDate,
|
||||
@Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 考勤加班情况-分页列表
|
||||
* @param page 分页参数
|
||||
* @param groupIds 考勤组ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 加班情况-分页列表结果
|
||||
*/
|
||||
Page<OvertimeSituationPageListVo> overtimeSituationPageList(@Param("page") Page<OvertimeSituationPageListVo> page,
|
||||
@Param("groupIds") List<String> groupIds,
|
||||
@Param("startDate") LocalDate startDate,
|
||||
@Param("endDate") LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 查询用户考勤统计信息
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param dateRangeDto 时间范围
|
||||
* @return 用户考勤统计信息
|
||||
*/
|
||||
DayStatisticsQueryDbVo queryUserStatisticsInfo(@Param("userId") String userId, @Param("dateRangeDto") DateRangeDto dateRangeDto);
|
||||
|
||||
/**
|
||||
* 查询用户加班详情
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param dateRangeDto 时间范围
|
||||
* @return 用户加班详情
|
||||
*/
|
||||
List<QueryUserOvertimeDetailsDbVo> queryUserOvertime(@Param("userId") String userId, @Param("dateRangeDto") DateRangeDto dateRangeDto);
|
||||
|
||||
/**
|
||||
* 查询用户工作状况统计信息
|
||||
*
|
||||
* @param userIds 用户ID集合
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 用户工作状况统计信息
|
||||
*/
|
||||
List<UserWorkSituationDbVo> queryUserWorkSituation(@Param("userIds") List<String> userIds,
|
||||
@Param("startDate") LocalDate startDate,
|
||||
@Param("endDate") LocalDate endDate);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.AttendanceFestivalRules;
|
||||
import jnpf.model.attendance.dto.FestivalRulesQueryDto;
|
||||
import jnpf.model.attendance.vo.attendance.AttendanceFestivalRulesVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
@Component
|
||||
public interface AttendanceFestivalRulesMapper extends SuperMapper<AttendanceFestivalRules> {
|
||||
/**
|
||||
* 列表
|
||||
* @param queryDto 查询参数
|
||||
* @return 列表
|
||||
*/
|
||||
List<AttendanceFestivalRulesVo> getPageList(@Param("queryDto") FestivalRulesQueryDto queryDto);
|
||||
|
||||
/**
|
||||
* 添加
|
||||
* @param id 主键
|
||||
* @param state 状态 1是 0否
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
void updateState(@Param("id") String id, @Param("state") Integer state, @Param("userId") String userId);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.entity.attendance.AttendanceFestivalSettingEntity;
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤配置-节日配置 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2023-11-29
|
||||
*/
|
||||
public interface AttendanceFestivalSettingMapper extends SuperMapper<AttendanceFestivalSettingEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.entity.attendance.AttendanceFieldPersonnel;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author huanglinpan
|
||||
* @Date 2025/2/17 16:03
|
||||
* @Version 1.0 (版本号)
|
||||
*/
|
||||
public interface AttendanceFieldPersonnelMapper {
|
||||
|
||||
/** 根据考勤组Id删除绑定的外勤人员 */
|
||||
void deleteByGroupId(@Param("groupId") String groupId);
|
||||
|
||||
/** 批量新增考勤组可外勤人员 */
|
||||
void insertList(@Param("fieldPersonnelList") List<AttendanceFieldPersonnel> fieldPersonnelList);
|
||||
|
||||
/**
|
||||
* 根据考勤组Id获取外勤人员Id列表
|
||||
* @param groupId 考勤组Id
|
||||
*/
|
||||
List<String> getUserIdsByGroupId(@Param("groupId") String groupId);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
|
||||
public interface AttendanceFieldpersonnelApproveMapper {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.attendance.AttendanceFixedClassEntity;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* @Author huanglinpan
|
||||
* @Date 2024/5/9 15:14
|
||||
* @Version 1.0 (版本号)
|
||||
*/
|
||||
public interface AttendanceFixedClassMapper extends SuperMapper<AttendanceFixedClassEntity>{
|
||||
|
||||
/**
|
||||
* 校验该班次有无在固定排班使用
|
||||
* @param shiftNameId 班次Id
|
||||
*/
|
||||
Integer getUseBYShiftNameId(@Param("shiftNameId") String shiftNameId);
|
||||
|
||||
/**
|
||||
* 校验该班次有无在排班使用
|
||||
* @param shiftNameId 班次Id
|
||||
*/
|
||||
Integer getRuleUseBYShiftNameId(@Param("shiftNameId") String shiftNameId);
|
||||
/**
|
||||
* 校验该班次有无在快速排班使用
|
||||
* @param shiftNameId 班次Id
|
||||
*/
|
||||
Integer getQuickUseBYShiftNameId(@Param("shiftNameId") String shiftNameId);
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.attendance.dto.AttendanceUserGroupVo;
|
||||
import jnpf.attendance.dto.AttendanceUserListGroupVO;
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.AttendanceGroup;
|
||||
import jnpf.model.attendance.dto.AttendanceGroupOrgDto;
|
||||
import jnpf.model.attendance.dto.GroupQueryDto;
|
||||
import jnpf.model.attendance.vo.AttendanceGroupVo;
|
||||
import jnpf.model.attendance.vo.GroupNodeVo;
|
||||
import jnpf.model.attendance.vo.attendance.GroupMiniVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤组mapper
|
||||
*
|
||||
* @author yanwenfu
|
||||
* @create 2023-11-21
|
||||
*/
|
||||
public interface AttendanceGroupMapper extends SuperMapper<AttendanceGroup> {
|
||||
/**
|
||||
* 查询用户管理的考勤组列表(考勤组名称模糊搜索)
|
||||
*/
|
||||
List<AttendanceGroup> queryManagerGroupList(@Param("userId") String userId, @Param("keyword") String keyword);
|
||||
/**
|
||||
* 查询用户管理的考勤组列表
|
||||
*/
|
||||
List<AttendanceGroupVo> queryGroupList(@Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 查询考勤组名称
|
||||
*
|
||||
* @param groupId 考勤组id
|
||||
* @return java.lang.String
|
||||
*/
|
||||
String getGroupName(String groupId);
|
||||
|
||||
/**
|
||||
* 获取指定考勤组信息
|
||||
*
|
||||
* @param groupId 考勤组id
|
||||
* @return jnpf.entity.AttendanceGroup
|
||||
* @author hlp
|
||||
*/
|
||||
AttendanceGroup getGroupDetail(String groupId);
|
||||
|
||||
/**
|
||||
* 批量获取考勤组信息
|
||||
*
|
||||
* @param list 考勤组ids
|
||||
* @return java.util.List<jnpf.entity.AttendanceGroup>
|
||||
* @author hlp
|
||||
*/
|
||||
List<AttendanceGroup> getGroupDetailList(@Param("list") List<String> list);
|
||||
|
||||
/**
|
||||
* 查询被删除的考勤组
|
||||
*
|
||||
* @param groupIdList 考勤组列表
|
||||
* @return java.util.List<java.lang.String>
|
||||
*/
|
||||
List<String> selectDelIds(@Param("list") List<String> groupIdList);
|
||||
|
||||
/**
|
||||
* 获取所有考勤组
|
||||
*
|
||||
* @param groupQueryDto 考勤组查询条件
|
||||
* @return java.util.List<jnpf.entity.AttendanceGroup>
|
||||
*/
|
||||
List<AttendanceGroupVo> getAllGroupList(@Param("groupQueryDto") GroupQueryDto groupQueryDto, @Param("userId") String userId, @Param("permissionType") Integer permissionType);
|
||||
|
||||
/**
|
||||
* 通过组织Id找到组织下的考勤组
|
||||
*
|
||||
* @param orgId 组织Id
|
||||
*/
|
||||
List<AttendanceGroupVo> groupListByOrgId(@Param("orgId") String orgId);
|
||||
|
||||
/**
|
||||
* 通过考勤组Id获取绑定的组织
|
||||
*
|
||||
* @param groupId 组织Id
|
||||
*/
|
||||
AttendanceGroupVo getGroupBindingOrg(@Param("groupId") String groupId);
|
||||
|
||||
/**
|
||||
* 绑定考勤组的组织
|
||||
*
|
||||
* @param attendanceGroupOrgDto 考勤组和组织信息
|
||||
*/
|
||||
void updateGroupOrg(@Param("attendanceGroupOrgDto") AttendanceGroupOrgDto attendanceGroupOrgDto);
|
||||
|
||||
/**
|
||||
* 获取用户考勤组
|
||||
*
|
||||
* @param userIds 用户ids
|
||||
*/
|
||||
List<AttendanceUserGroupVo> getAttendanceUserGroup(@Param("userIds") List<String> userIds);
|
||||
|
||||
/**
|
||||
* 查询考勤组锁定日期
|
||||
* @param groupId 考勤组id
|
||||
* @return java.util.Date
|
||||
*/
|
||||
Date getGroupLockDate(String groupId);
|
||||
|
||||
/**
|
||||
* 查询父级考勤组id
|
||||
* @param groupId 考勤组id
|
||||
* @return java.lang.String
|
||||
*/
|
||||
String getParentGroupId(String groupId);
|
||||
|
||||
/**
|
||||
* 查询本级及子级考勤组
|
||||
* @param groupId 考勤组id
|
||||
* @return java.util.List<jnpf.model.attendance.vo.GroupNodeVo>
|
||||
*/
|
||||
List<GroupNodeVo> getSelfAndChildrenGroup(String groupId);
|
||||
|
||||
/**
|
||||
* 获取多用户的考勤组信息,包含多级考勤组名称
|
||||
* @param userIds 用户ids
|
||||
* @return 包含多级考勤组名称的考勤信息
|
||||
*/
|
||||
List<AttendanceUserListGroupVO> getAttendanceUserListGroupVO(@Param("userIds") List<String> userIds);
|
||||
|
||||
/**
|
||||
* 查询所有考勤组(层级排序)
|
||||
* @return java.util.List<jnpf.model.attendance.vo.attendance.GroupMiniVo>
|
||||
*/
|
||||
List<GroupMiniVo> getAllGroupByLevel(@Param("list") List<String> groupIds);
|
||||
|
||||
/**
|
||||
* 查询用户是否拥有指定考勤组的指定权限
|
||||
* @param userId 用户
|
||||
* @param groupId 考勤组
|
||||
* @param permissionCode 指定权限
|
||||
*/
|
||||
Integer appointPermissionByGroupId(@Param("userId") String userId, @Param("groupId") String groupId, @Param("permissionCode") String permissionCode, @Param("type") Integer type);
|
||||
|
||||
/**
|
||||
* 获取组织下的考勤组
|
||||
* @param groupQueryDto 考勤组查询条件
|
||||
* @return List<AttendanceGroupVo>
|
||||
*/
|
||||
List<AttendanceGroupVo> getGroupListByOrgId(@Param("groupQueryDto") GroupQueryDto groupQueryDto, @Param("orgIds") List<String> orgIds);
|
||||
|
||||
/**
|
||||
* 根据考勤组ID列表查询考勤组信息
|
||||
*
|
||||
* @param groupIds 考勤组ID列表
|
||||
* @return 考勤组信息列表
|
||||
*/
|
||||
List<AttendanceGroupVo> getGroupListByIds(@Param("groupIds") List<String> groupIds);
|
||||
|
||||
/**
|
||||
* 查询组织id
|
||||
* @param groupId 考勤组id
|
||||
* @return java.lang.String
|
||||
*/
|
||||
String getOrgId(String groupId);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.entity.AttendanceGroupUser;
|
||||
import jnpf.model.attendance.dto.GroupUserQueryDto;
|
||||
import jnpf.model.attendance.vo.AttendanceGroupUserVo;
|
||||
import jnpf.model.attendance.vo.MiniGroupVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤组成员管理表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author Auto-generator
|
||||
* @since 2023-11-21
|
||||
*/
|
||||
public interface AttendanceGroupUserMapper extends SuperMapper<AttendanceGroupUser> {
|
||||
/**
|
||||
* 获取考勤组用户生存周期记录
|
||||
* @param groupId 考勤组名称
|
||||
*/
|
||||
List<AttendanceGroupUserVo> viewGroupUserList(@Param("groupId") String groupId, @Param("name") String name);
|
||||
|
||||
/**
|
||||
* 查询系统用户列表
|
||||
* @param orgId
|
||||
* @param name
|
||||
* @return List<AttendanceGroupUserVo>
|
||||
*/
|
||||
List<AttendanceGroupUserVo> querySysUsers(@Param("orgId") String orgId, @Param("name") String name);
|
||||
|
||||
/**
|
||||
* 获取用户所有产生的考勤组集合
|
||||
* @param userId 用户id
|
||||
* @return java.util.List<jnpf.model.attendance.vo.AttendanceGroupUserVo>
|
||||
* @author hlp
|
||||
*/
|
||||
List<AttendanceGroupUserVo> getUserGroupList(@Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 查询考勤组用户信息列表
|
||||
* @param groupIds 考勤组ids
|
||||
* @param userId 用户id
|
||||
* @return java.util.List<jnpf.model.attendance.vo.MiniGroupVo>
|
||||
*/
|
||||
List<MiniGroupVo> getGroupUserList(@Param("list") Set<String> groupIds, @Param("userId") String userId, @Param("delStatus") Integer delStatus);
|
||||
|
||||
/**
|
||||
* 查询自己的考勤组id
|
||||
* @param userId 用户id
|
||||
* @return java.lang.String
|
||||
*/
|
||||
String getSelfGroup(String userId);
|
||||
|
||||
/**
|
||||
* 批量修改考勤组用户
|
||||
* @param groupUserIds 考勤用户关系主键id
|
||||
* @param type 1.本组 2.借调 3.移除
|
||||
*/
|
||||
void batchUpdateGroupUser(@Param("groupUserIds") List<String> groupUserIds, @Param("type") Integer type);
|
||||
|
||||
// List<AttendanceGroupUserVo> viewGroupUserListInGroupIds(@Param("groupId") List<String> groupIds);
|
||||
|
||||
/**
|
||||
* 根据用户ids查询考勤组用户信息
|
||||
* @param userIds 用户ids
|
||||
* @param type 1.本组 2.借调 3.离组
|
||||
* @return List<AttendanceGroupUserVo>
|
||||
*/
|
||||
List<AttendanceGroupUserVo> getGroupInUserIds(@Param("userIds") List<String> userIds, @Param("type") Integer type);
|
||||
|
||||
/**
|
||||
* 查询考勤组成员(不含借调)
|
||||
* @param groupIdList 考勤组ids
|
||||
* @return java.util.List<java.lang.String>
|
||||
*/
|
||||
List<String> getGroupUserListByIds(@Param("list") List<String> groupIdList);
|
||||
|
||||
/**
|
||||
* 查询考勤组成员
|
||||
* @param groupIds 查询条件考勤组集合
|
||||
* @return
|
||||
*/
|
||||
List<AttendanceGroupUserVo> getUsersByGroupIds(@Param("groupIds") List<String> groupIds);
|
||||
|
||||
/**
|
||||
* 获取考勤组成员id
|
||||
* @param groupIds 查询条件考勤组集合
|
||||
* @return java.util.List<java.lang.String>
|
||||
*/
|
||||
List<String> getGroupUserIds(@Param("groupIds") List<String> groupIds);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
import jnpf.entity.attendance.AttendanceHolidaySettingEntity;
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 考勤配置-假日设置 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author ahua
|
||||
* @since 2023-11-29
|
||||
*/
|
||||
public interface AttendanceHolidaySettingMapper extends SuperMapper<AttendanceHolidaySettingEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
package jnpf.attendance.mapper;
|
||||
|
||||
|
||||
import jnpf.model.attendance.model.LeaveSituationData;
|
||||
import jnpf.model.attendance.vo.*;
|
||||
import jnpf.model.attendance.vo.attendance.BusinessTripVo;
|
||||
import jnpf.model.attendance.vo.attendance.GoOutVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface AttendanceLeaveApproveMapper {
|
||||
|
||||
/**
|
||||
* 获取请假申请详情
|
||||
* @param id 审批的唯一id
|
||||
* @return jnpf.model.attendance.vo.AttendanceLeaveApproveVo
|
||||
* @author hlp
|
||||
*/
|
||||
AttendanceLeaveApproveVo getLeaveDetailById(@Param("id") String id);
|
||||
|
||||
/**
|
||||
* 获取请假申请详情
|
||||
* @param groupId 考勤组id
|
||||
* @param userId 用户id
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return java.util.List<jnpf.model.attendance.model.LeaveSituationData>
|
||||
*/
|
||||
List<LeaveSituationData> getUserLeaveList(@Param("groupId") String groupId, @Param("userId") String userId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);
|
||||
|
||||
/**
|
||||
* 获取请假申请详情
|
||||
* @param applyIds 审批id集合
|
||||
* @return java.util.List<jnpf.model.attendance.model.LeaveSituationData>
|
||||
*/
|
||||
List<LeaveSituationData> getUserLeaveListByApplyIds(@Param("applyIds") List<String> applyIds);
|
||||
|
||||
/**
|
||||
* 修改请假审批信息
|
||||
* @param id 审批的唯一id
|
||||
* @param dayNum 未抵扣时间(单位 : 天)
|
||||
* @param applicationDurationSecond 请假时长秒
|
||||
* @param undeductedTimeSecond 未抵扣时长秒
|
||||
* @param leaveName 请假名称
|
||||
* @param applicationDuration 请假时长
|
||||
* @param applicationDurationDay 半天、天时的请假时长
|
||||
* @param notDeductedDay 半天、天时的未抵扣时长
|
||||
* @param start 命中的开始时间
|
||||
* @param end 命中的结束时间
|
||||
* @param leaveDurationJson 请假时长Json
|
||||
* @param leaveConsumptionDetailJson 请假消耗详情Json 2.0 新增
|
||||
* @author hlp
|
||||
*/
|
||||
void updateLeaveApprove(@Param("id") String id, @Param("dayNum") BigDecimal dayNum, @Param("applicationDuration") BigDecimal applicationDuration, @Param("leaveName") String leaveName, @Param("applicationDurationSecond") Integer applicationDurationSecond, @Param("undeductedTimeSecond") Integer undeductedTimeSecond, @Param("userId") String userId, @Param("userName") String userName, @Param("applicationDurationDay") BigDecimal applicationDurationDay, @Param("notDeductedDay") BigDecimal notDeductedDay, @Param("start") Date start, @Param("end") Date end, @Param("leaveDurationJson") String leaveDurationJson, @Param("leaveConsumptionDetailJson") String leaveConsumptionDetailJson);
|
||||
|
||||
/**
|
||||
* 获取用户该类型的请假有多少未抵扣余额
|
||||
* @param userId 用户id
|
||||
* @param leaveTypeId 请假类型id
|
||||
* @return java.math.BigDecimal
|
||||
* @author hlp
|
||||
*/
|
||||
BigDecimal getUserUnDeductedTime(@Param("userId") String userId, @Param("leaveTypeId") String leaveTypeId);
|
||||
|
||||
/**
|
||||
* 获取用户时间段内审核中和审核通过的请假审批列表
|
||||
* @param userId 用户id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return java.util.List<jnpf.model.attendance.vo.AttendanceLeaveApproveVo>
|
||||
* @author hlp
|
||||
*/
|
||||
List<AttendanceLeaveApproveVo> getUserLeaveByTimeSlot(@Param("userId") String userId, @Param("startTime") Date startTime, @Param("endTime") Date endTime);
|
||||
|
||||
/**
|
||||
* 获取用户时间段内审核通过的请假审批列表
|
||||
* @param userId 用户id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return java.util.List<jnpf.model.attendance.vo.AttendanceLeaveApproveVo>
|
||||
* @author hlp
|
||||
*/
|
||||
List<AttendanceLeaveApproveVo> getUserPassLeaveByTime(@Param("userId") String userId, @Param("startTime") Date startTime, @Param("endTime") Date endTime);
|
||||
|
||||
/**
|
||||
*批量获取用户时间段内审核通过的请假审批列表
|
||||
* @param userIds 用户id集合
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return java.util.List<jnpf.model.attendance.vo.AttendanceLeaveApproveVo>
|
||||
* @author hlp
|
||||
*/
|
||||
List<LeaveStaVo> getBatchLeaveByUserIds(@Param("userIds") List<String> userIds, @Param("startTime") Date startTime, @Param("endTime") Date endTime);
|
||||
|
||||
/**
|
||||
* 通过id获取加班详情
|
||||
* @param id 审批的唯一id
|
||||
* @author hlp
|
||||
*/
|
||||
AttendanceWorkOverTimeVo getWorkOverTime(@Param("id") String id);
|
||||
|
||||
/**
|
||||
* 修改加班审批的审批状态
|
||||
* @param id 加班主键id
|
||||
* @author hlp
|
||||
*/
|
||||
void updateWorkOverTimeApprove(@Param("id") String id, @Param("status") Integer status, @Param("userId") String userId, @Param("userName") String userName, @Param("json") String json);
|
||||
|
||||
/**
|
||||
* 获取待审批的借调审批详情
|
||||
* @param id 审批的唯一id
|
||||
* @author hlp
|
||||
*/
|
||||
AttendanceSelfApproveVo getSelfApprove(@Param("id") String id);
|
||||
|
||||
/**
|
||||
* 获取借调用户集合
|
||||
* @param id 借调审批主键id
|
||||
* @return java.util.List<java.lang.String>
|
||||
* @author hlp
|
||||
*/
|
||||
List<String> getUserList(@Param("id") String id);
|
||||
|
||||
/**
|
||||
* 修改借调审批为通过
|
||||
* @param id 主键id
|
||||
* @author hlp
|
||||
*/
|
||||
void updateSelfApprove(@Param("id") String id, @Param("departureTime") Date departureTime, @Param("backTime") Date backTime, @Param("status") Integer status, @Param("userId") String userId, @Param("userName") String userName);
|
||||
|
||||
/**
|
||||
* 将对应审批变为未通过
|
||||
* @param id F_UniqueId 审批的唯一id
|
||||
* @author hlp
|
||||
*/
|
||||
void updateLeaveApproveStatus(@Param("id") String id, @Param("status") Integer status, @Param("userId") String userId, @Param("userName") String userName);
|
||||
|
||||
/**
|
||||
* 获取用户时间段内加班申请数量
|
||||
* @param userId 用户id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return java.lang.Integer
|
||||
* @author hlp
|
||||
*/
|
||||
Integer getUserWorkByTimeSlot(@Param("userId") String userId, @Param("startTime") Date startTime, @Param("endTime") Date endTime);
|
||||
|
||||
/**
|
||||
* 获取用户时间段内加班申请数量
|
||||
* @param userId 用户id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return java.lang.Integer
|
||||
* @author hlp
|
||||
*/
|
||||
Integer getUserPassWorkByTime(@Param("userId") String userId, @Param("startTime") Date startTime, @Param("endTime") Date endTime);
|
||||
|
||||
/**
|
||||
* 修改外出审批状态
|
||||
* @param applyId 主键Id
|
||||
* @param status 是否审核通过 0.待审核 1.通过 2.未通过
|
||||
*/
|
||||
void updateGoOutApprove(@Param("applyId") String applyId, @Param("status") Integer status, @Param("userId") String userId, @Param("userName") String userName);
|
||||
|
||||
/**
|
||||
* 获取外出审批详情
|
||||
* @param applyId 主键Id
|
||||
*/
|
||||
GoOutVo getGoOut(@Param("applyId") String applyId);
|
||||
|
||||
/**
|
||||
* 获取出差审批详情
|
||||
* @param applyId 主键Id
|
||||
*/
|
||||
BusinessTripVo getBusinessTrip(@Param("applyId") String applyId);
|
||||
|
||||
/**
|
||||
* 修改出差审批状态
|
||||
* @param applyId 主键Id
|
||||
* @param status 是否审核通过 0.待审核 1.通过 2.未通过
|
||||
*/
|
||||
void updateBusinessTripApprove(@Param("applyId") String applyId, @Param("status") Integer status, @Param("userId") String userId, @Param("userName") String userName);
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的加班申请列表
|
||||
* @param userId 用户
|
||||
* @param queryDate 日期
|
||||
*/
|
||||
List<DailyApprovalVo> getApplyWorkOverTimeList(@Param("userId") String userId, @Param("queryDate") String queryDate, @Param("currentGroupId") String currentGroupId, @Param("code") Integer code);
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的申请中的加班申请列表
|
||||
* @param userId 用户
|
||||
* @param queryDate 日期
|
||||
*/
|
||||
List<DailyApprovalVo> getApplyingWorkOverTimeList(@Param("userId") String userId, @Param("queryDate") String queryDate);
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的外出申请列表
|
||||
* @param userId 用户
|
||||
* @param queryDate 日期
|
||||
*/
|
||||
List<DailyApprovalVo> getApplyGoOutList(@Param("userId") String userId, @Param("queryDate") String queryDate, @Param("currentGroupId") String currentGroupId, @Param("code") Integer code);
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的申请中的外出申请列表
|
||||
* @param userId 用户
|
||||
* @param queryDate 日期
|
||||
*/
|
||||
List<DailyApprovalVo> getApplyingGoOutList(@Param("userId") String userId, @Param("queryDate") String queryDate);
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的请假申请列表
|
||||
* @param userId 用户
|
||||
* @param queryDate 日期
|
||||
*/
|
||||
List<DailyApprovalVo> getApplyLeaveList(@Param("userId") String userId, @Param("queryDate") String queryDate, @Param("currentGroupId") String currentGroupId, @Param("code") Integer code);
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的申请中的请假申请列表
|
||||
* @param userId 用户
|
||||
* @param queryDate 日期
|
||||
*/
|
||||
List<DailyApprovalVo> getApplyingLeaveList(@Param("userId") String userId, @Param("queryDate") String queryDate);
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的借调申请列表
|
||||
* @param userId 用户
|
||||
* @param queryDate 日期
|
||||
*/
|
||||
List<DailyApprovalVo> getApplySelfList(@Param("userId") String userId, @Param("queryDate") String queryDate, @Param("currentGroupId") String currentGroupId, @Param("code") Integer code);
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的出差申请列表
|
||||
* @param userId 用户
|
||||
* @param queryDate 日期
|
||||
*/
|
||||
List<DailyApprovalVo> getApplyBusinessTripList(@Param("userId") String userId, @Param("queryDate") String queryDate, @Param("currentGroupId") String currentGroupId, @Param("code") Integer code);
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的申请中的出差申请列表
|
||||
* @param userId 用户
|
||||
* @param queryDate 日期
|
||||
*/
|
||||
List<DailyApprovalVo> getApplyingBusinessTripList(@Param("userId") String userId, @Param("queryDate") String queryDate);
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的外出申请数量
|
||||
* @param userId 用户Id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
*/
|
||||
Integer getUserGoOutByTimeSlot(@Param("userId") String userId, @Param("startTime") Date startTime, @Param("endTime") Date endTime);
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的出差申请数量
|
||||
* @param userId 用户Id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
*/
|
||||
Integer getUserBusinessTripByTimeSlot(@Param("userId") String userId, @Param("startTime") Date startTime, @Param("endTime") Date endTime);
|
||||
|
||||
/**
|
||||
* 获取已审批的借调记录
|
||||
* @author hlp
|
||||
*/
|
||||
List<AttendanceSelfApproveVo> getSelfApproveList(@Param("startTime") String startTime, @Param("endTime") String endTime);
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的出差申请数量除开本次申请
|
||||
* @param userId 用户Id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
*/
|
||||
Integer getBusinessTripForOa(@Param("userId") String userId, @Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("taskId") String taskId);
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的外出申请数量除开本次申请 小时
|
||||
* @param userId 用户Id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
*/
|
||||
Integer getUserGoOutForOa(@Param("userId") String userId, @Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("taskId") String taskId);
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户时间段内加班申请数量
|
||||
* @param userId 用户id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return java.lang.Integer
|
||||
* @author hlp
|
||||
*/
|
||||
Integer getUserWorkByTimeSlotForOa(@Param("userId") String userId, @Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("taskId") String taskId);
|
||||
|
||||
/**
|
||||
* 获取指定用户指定日期的外出申请数量除开本次申请 天
|
||||
* @param userId 用户Id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
*/
|
||||
Integer getUserGoOutForDay(@Param("userId") String userId, @Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("taskId") String taskId);
|
||||
|
||||
/**
|
||||
* 获取用户集合在指定日期范围的借调申请中的用户集合
|
||||
* @param userIds 用户Id
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param taskId 任务Id
|
||||
*/
|
||||
List<String> checkSelfApprove(@Param("userIds") List<String> userIds, @Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("taskId") String taskId);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user