钉钉处理

This commit is contained in:
andy 2026-03-27 10:23:28 +08:00
parent cb1d56c751
commit 8eb0a5a58f
42 changed files with 780 additions and 169 deletions

View File

@ -120,5 +120,9 @@ public class RzAttendance extends BaseEntity {
private Date startTime;
@TableField(exist = false)
private Date endTime;
/***
* 补卡扣款
*/
private BigDecimal debiting;
}

View File

@ -67,7 +67,7 @@ public interface IRzAttendanceService extends IService<RzAttendance>
public void dingDing(String dingUserId, String bizId);
void addRzOverTime(String result, SysStaff sysStaff, DingShiftGroup dingsShiftGroup, String checkType, Date formatWorkDate, Date formatUserCheckTime, String timeResult, String remark );
void addRzOverTime(String result, SysStaff sysStaff, DingShiftGroup dingsShiftGroup, String checkType, Date formatWorkDate, Date formatUserCheckTime, String timeResult, String remark, Double debiting);
public RzAttendance queryNowDayAttendanceByStatisticalIdAndDate(Long staffId, Date date);
}

View File

@ -141,11 +141,6 @@ public class RzAttendanceDetailServiceImpl extends ServiceImpl<RzAttendanceDetai
data.setIcon(timeLine.icon);
});
return result;
//
// return getBaseMapper().selectListByAttendanceId(new LambdaQueryWrapper<RzAttendanceDetail>().eq(RzAttendanceDetail::getAttendanceId, attId)
// .select(RzAttendanceDetail::getButtonType, RzAttendanceDetail::getPhoto, RzAttendanceDetail::getDateTime,RzAttendanceDetail::getDelFlag)).stream().map(data ->{
// return new RzAttendanceDetailTimeLineVO(data.getButtonType(), data.getPhoto(), DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",data.getDateTime()), data.getDelFlag());
// }).collect(Collectors.toList());
}
SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd");

View File

@ -16,10 +16,7 @@ import com.evo.attendance.service.RzAttendanceDetailService;
import com.evo.common.annotation.DataScope;
import com.evo.common.core.domain.AjaxResult;
import com.evo.common.core.domain.entity.SysDept;
import com.evo.common.utils.Collections;
import com.evo.common.utils.DateUtils;
import com.evo.common.utils.SecurityUtils;
import com.evo.common.utils.StringUtils;
import com.evo.common.utils.*;
import com.evo.ding.DingUtils;
import com.evo.ding.domain.DingShift;
import com.evo.ding.domain.DingShiftGroup;
@ -563,7 +560,7 @@ public class RzAttendanceServiceImpl extends ServiceImpl<RzAttendanceMapper, RzA
Date formatWorkDate = Date.from(Instant.ofEpochMilli(workDate));
Date formatUserCheckTime = Date.from(Instant.ofEpochMilli(userCheckTime));
DingShiftGroup dingsShiftGroup = dingsShiftGroupMapper.selectByGroupIdAndTypeAndCheckTime(groupId, checkType, formatPlanCheckTime);
addRzOverTime(result, sysStaff, dingsShiftGroup, checkType, formatWorkDate, formatUserCheckTime, timeResult, null);
addRzOverTime(result, sysStaff, dingsShiftGroup, checkType, formatWorkDate, formatUserCheckTime, timeResult, null, 0d);
/* DingShiftGroup dingsShiftGroup = dingsShiftGroupMapper.selectByGroupIdAndTypeAndCheckTime(groupId, checkType, formatPlanCheckTime);
if(dingsShiftGroup != null){
@ -647,7 +644,7 @@ public class RzAttendanceServiceImpl extends ServiceImpl<RzAttendanceMapper, RzA
}
@Override
public void addRzOverTime(String result, SysStaff sysStaff, DingShiftGroup dingsShiftGroup, String checkType, Date formatWorkDate, Date formatUserCheckTime, String timeResult, String remark){
public void addRzOverTime(String result, SysStaff sysStaff, DingShiftGroup dingsShiftGroup, String checkType, Date formatWorkDate, Date formatUserCheckTime, String timeResult, String remark, Double debiting){
if(dingsShiftGroup != null){
//通过打卡类型, classId, 和排班打卡时间, 获取工作时长
//通过班次id拿到工作时长
@ -685,15 +682,16 @@ public class RzAttendanceServiceImpl extends ServiceImpl<RzAttendanceMapper, RzA
}else if(dingsShift.getWorkHour() == 8 && attendance.getWorkSum().intValue() >= 8 && attendance.getWorkStartTime() != null && attendance.getWorkStartTime().getHours() >= 12 && attendance.getWorkStartTime().getHours() < 21){
attendance.setMiddleShiftNumber(1);
}
//记录补卡扣款
attendance.setDebiting(DataUtils.findDefaultValue(attendance.getDebiting(), DataUtils.DEFAULT_VALUE).add(new BigDecimal(DataUtils.findDefaultValue(debiting, 0d))));
getBaseMapper().updateRzAttendance(attendance);
//检查是否开启加班
if(dingsShift.getOvertimeWork()){
//使用排班下班时间作为加班开始时间
rzOverTimeService.overTimeCard(sysStaff, DateUtils.parseDate(DateUtils.parseDateToStr("yyyy-MM-dd", formatWorkDate)+" "+ dingsShiftGroup.getCheckTime()));
//员工打卡时间作为加班下班时间
rzOverTimeService.overTimeOffDutyCard(sysStaff, formatUserCheckTime, "/");
}
//检查是否开启加班, 所有的加班调整为, 扫脸打卡
// if(dingsShift.getOvertimeWork()){
// //使用排班下班时间作为加班开始时间
// rzOverTimeService.overTimeCard(sysStaff, DateUtils.parseDate(DateUtils.parseDateToStr("yyyy-MM-dd", formatWorkDate)+" "+ dingsShiftGroup.getCheckTime()));
// //员工打卡时间作为加班下班时间
// rzOverTimeService.overTimeOffDutyCard(sysStaff, formatUserCheckTime, "/");
// }
}else{
log.info("钉钉回调打卡信息=====>>>>> {}", result);
}

View File

@ -4,6 +4,7 @@ import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evo.common.constant.CacheConstants;
import com.evo.common.utils.DateUtils;
import com.evo.common.utils.SecurityUtils;
import com.evo.equipment.constant.Constants;
@ -103,6 +104,7 @@ public class RzSysParamServiceImpl extends ServiceImpl<RzSysParamMapper, RzSysPa
@Override
@Cacheable(cacheNames = Constants.SYS_RUNNING_PARAMS, key = "#code")
public RzSysParam getRzSysParam(String name, String code, String defVal, String des){
RzSysParam param = getRzSysParam(code);
if(ObjectUtils.isEmpty(param)){

View File

@ -133,4 +133,9 @@ public class Constants
public static final BigDecimal DAY_WORK_HOUR = new BigDecimal(8);
public static final String SOURCE_PT = "1";
public static final String SOURCE_DING = "2";
}

View File

@ -76,6 +76,17 @@ public class ParamUtils {
return Double.valueOf(param.getParamValue());
}
/***
* 获取补卡单次扣款
* @return
*/
public static Double getDebiting(){
RzSysParam param= paramService.getRzSysParam("补卡单次扣款", "recharge_card_debiting","2","单次补卡扣款");
return Double.valueOf(param.getParamValue());
}
/***
* 获取餐厅的开放时间
* @return
@ -302,14 +313,13 @@ public class ParamUtils {
return false;
}
//检查格式, 如果格式不匹配, 输出日志, 直接返回true
if(!Pattern.compile("").matcher(checkDate).matches()){
if(!Pattern.compile("^\\d{4}-\\d{2}-\\d{2}$").matcher(checkDate).matches()){
log.error("当前检查日期{}, 不符合检查规则", checkDate);
return false;
}
//检查是否为假期
return getHoliddayList(Integer.valueOf(checkDate.substring(0,4)), 0).contains(checkDate);
}
/***
* 获取假期范围 0 全部 1法休 2 公休
* @param year

View File

@ -77,32 +77,6 @@ public class DingUtils {
return token;
}
// public static String getDeptList(Long deptId){
// try {
// DingTalkClient client = new DefaultDingTalkClient(DingBase.getUrl()+"v2/department/listsub");
// OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();
// req.setDeptId(deptId);
// req.setLanguage("zh_CN");
// OapiV2DepartmentListsubResponse rsp = client.execute(req, getAccessToken());
// return rsp.getBody();
// } catch (Exception e) {
// e.printStackTrace();
// }
// return "";
// }
//
// public static String getUserList(Long deptId){
// try {
// DingTalkClient client = new DefaultDingTalkClient(DingBase.getUrl()+"user/listid");
// OapiUserListidRequest req = new OapiUserListidRequest();
// req.setDeptId(deptId);
// OapiUserListidResponse rsp = client.execute(req, getAccessToken());
// return rsp.getBody();
// } catch (Exception e) {
// e.printStackTrace();
// }
// return "";
// }
//根据手机号获取用户id
public static String getUserIdByPhoto(String photo){
try {
@ -123,7 +97,7 @@ public class DingUtils {
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getUrl()+"v2/user/get");
OapiV2UserGetRequest req = new OapiV2UserGetRequest();
req.setUserid(userId);
OapiV2UserGetResponse rsp = client.execute(req, "");
OapiV2UserGetResponse rsp = client.execute(req, getAccessToken());
return rsp.getBody();
} catch (Exception e) {
e.printStackTrace();
@ -147,6 +121,34 @@ public class DingUtils {
return "";
}
public static OapiAttendanceShiftQueryResponse.TopShiftVo getShiftDetail(Long id){
try {
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getBaseUrl()+"topapi/attendance/shift/query");
OapiAttendanceShiftQueryRequest req = new OapiAttendanceShiftQueryRequest();
req.setOpUserId("03491015494921375480");
req.setShiftId(id);
OapiAttendanceShiftQueryResponse rsp = client.execute(req, getAccessToken());
return rsp.getResult();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static OapiAttendanceGroupQueryResponse.TopSimpleGroupVO getGroupDetail(Long id){
try {
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getBaseUrl()+"topapi/attendance/group/query");
OapiAttendanceGroupQueryRequest req = new OapiAttendanceGroupQueryRequest();
req.setOpUserId("03491015494921375480");
req.setGroupId(id);
OapiAttendanceGroupQueryResponse rsp = client.execute(req, getAccessToken());
return rsp.getResult();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/***
* 获取考勤组信息
*

View File

@ -25,9 +25,9 @@ public class DingShift implements Serializable {
public String dingId;
/** 工作时长 */
public Integer workHour;
/** 是否加班 */
public Boolean overtimeWork;
/** 扣减时长 */
public Double deductionHour;
/** 上班基准时间节点 */
public String onDutyCheckTime;
/** 下班基准时间节点 */
public String offDutyCheckTime;
}

View File

@ -1,5 +1,6 @@
package com.evo.ding.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
@ -26,4 +27,9 @@ public class DingShiftGroup implements Serializable {
/** type 打卡类型 */
public String checkTime;
@TableField(exist = false)
private String shiftName;
@TableField(exist = false)
private String groupName;
}

View File

@ -0,0 +1,19 @@
package com.evo.ding.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.evo.ding.domain.DingGroup;
import com.evo.ding.domain.DingShift;
import org.apache.ibatis.annotations.Param;
/**
* DingGroupMapper
*
* @author andy.shi
* @ClassName:DingsShiftGroupMapper
* @date: 2026年03月05日 14:47
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
*/
public interface DingGroupMapper extends BaseMapper<DingGroup> {
public DingGroup selectByDingId(@Param("dingId") String dingId);
}

View File

@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.evo.ding.domain.DingShiftGroup;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* DingsShiftGroupMapper
*
@ -14,6 +16,9 @@ import org.apache.ibatis.annotations.Param;
*/
public interface DingShiftGroupMapper extends BaseMapper<DingShiftGroup> {
DingShiftGroup selectByGroupIdAndTypeAndCheckTime(@Param("groupId") String groupId, @Param("type") String type, @Param("checkTime") String checkTime);
int updateCheckTimeByShiftIdAndType(@Param("shiftId")String shiftId, @Param("type")String type, @Param("checkTime")String checkTime);
List<DingShiftGroup> selectList(DingShiftGroup dingShiftGroup);
}

View File

@ -2,9 +2,12 @@ package com.evo.ding.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.evo.ding.domain.DingShift;
import com.evo.system.domain.SysStaff;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* DingsShiftGroupMapper
*
@ -16,4 +19,6 @@ import org.apache.ibatis.annotations.Select;
public interface DingShiftMapper extends BaseMapper<DingShift> {
public DingShift selectByDingId(@Param("dingId") String dingId);
public List<DingShift> selectList(DingShift dingShift);
}

View File

@ -9,6 +9,7 @@ import com.evo.system.domain.SysStaff;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.util.List;
/**
@ -27,16 +28,29 @@ public interface AttendanceApproveStatusChangeExchangeProcessor extends DingBasi
String APPROVE_TYPE_LEAVE = "LEAVE";
//加班
String APPROVE_TYPE_OVERTIME = "OVERTIME";
//请假
String APPROVE_TYPE_OUT = "OUT";
//撤销
String BIZ_ACTION_REVOKE = "REVOKE";
boolean accept(String approveType, String result, String status);
void exchange(GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json);
void exchange(String processInstanceId, GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json);
default JSONObject getExtValue(GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json, String componentType) {
List<GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues> formComponentValueList = json.getFormComponentValues();
GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues formComponentValue = formComponentValueList.stream().filter(data -> componentType.equals(data.getComponentType())).findAny().orElse(null);
GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues formComponentValue = formComponentValueList.stream().filter(data -> componentType.equals(data.getComponentType())).findAny().orElse(null);
if(formComponentValue != null){
return JSON.parseObject(formComponentValue.getExtValue());
return JSON.parseObject(formComponentValue.getExtValue());
}
throw new RuntimeException("未查询到相关审批信息, 审批类型为:"+componentType+"; 参数信息为: "+ json.toString());
}
default JSONArray getValue(GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json, String componentType) {
List<GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues> formComponentValueList = json.getFormComponentValues();
GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues formComponentValue = formComponentValueList.stream().filter(data -> componentType.equals(data.getComponentType())).findAny().orElse(null);
if(formComponentValue != null){
return JSON.parseArray(formComponentValue.getValue());
}
throw new RuntimeException("未查询到相关审批信息, 审批类型为:"+componentType+"; 参数信息为: "+ json.toString());
}

View File

@ -38,52 +38,82 @@ public class ApproveStatusLeaveExchangeProcessor implements AttendanceApproveSta
}
@Override
public void exchange(GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json) {
public void exchange(String processInstanceId, GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json) {
try {
SysStaff sysStaff = getSysStaffByDingUserId(json.getOriginatorUserId());
JSONObject extValueJson = getExtValue(json, "DDHolidayField");
//解析假期类型
JSONObject extension = JSON.parseObject(extValueJson.getString("extension"));
//查询假期类型
String tag = extension.getString("tag");
SysDictData sysDictData = sysDictDataService.selectDictDataListByType("holidays_type").stream().filter(data-> StringUtils.equals(data.getDictLabel(),tag)).findFirst().orElse(null);
if(sysDictData != null){
//假期类型的code
Long dictCode = sysDictData.getDictCode();
JSONArray detailList = extValueJson.getJSONArray("detailList");
Date beginTime = null;
Date endTime = null;
//如果大于1 证明是多天请假, 需要排序
if(detailList.size() > 1){
detailList.sort((a,b)->{
return ((JSONObject) a).getLong("workDate").compareTo(((JSONObject) b).getLong("workDate"));
});
//获取第一天
beginTime = new Date(detailList.getJSONObject(0).getJSONObject("approveInfo").getLong("fromTime"));
//获取最后一天
endTime = new Date(detailList.getJSONObject(detailList.size()-1).getJSONObject("approveInfo").getLong("toTime"));
}else{
//只请一天假
JSONObject approveInfo = detailList.getJSONObject(0).getJSONObject("approveInfo");
beginTime = new Date(approveInfo.getLong("fromTime"));
//获取最后一天
endTime = new Date(approveInfo.getLong("toTime"));
}
RzLeave rzLeave = getIRzLeaveService().selectRzLeaveByUserId(sysStaff.getUserId());
RzLeaveDetail rzLeaveDetail = new RzLeaveDetail();
rzLeaveDetail.setName(sysStaff.getName());
rzLeaveDetail.setLeaveStartTime(beginTime);
rzLeaveDetail.setLeaveEndTime(endTime);
rzLeaveDetail.setLeaveId(rzLeave.getId());
rzLeaveDetail.setType(dictCode);
rzLeaveDetail.setLeaveHour(extValueJson.getInteger("durationInHour"));
rzLeaveDetail.setRemarks("钉钉"+tag);
getIRzLeaveDetailService().insertRzLeaveDetail(rzLeaveDetail);
//如果是撤销, 执行撤销
if(BIZ_ACTION_REVOKE.equals(json.getBizAction())){
revoke(processInstanceId);
}else{
leave(processInstanceId, getSysStaffByDingUserId(json.getOriginatorUserId()), json);
}
} catch (Exception e) {
log.error("执行钉钉 -[请假审批]-回调出现异常, 异常原因为:{}", e.getMessage());
log.error("执行钉钉 -["+(BIZ_ACTION_REVOKE.equals(json.getBizAction()) ? "撤销" : "请假")+"审批]-回调出现异常, 异常原因为:{}", e.getMessage());
e.printStackTrace();
}
}
/***
* 撤销假期
* @param processInstanceId 钉钉审批单详情
*/
public void revoke(String processInstanceId){
RzLeaveDetail rzLeaveDetail = getIRzLeaveDetailService().selectRzLeaveDetailByProcessInstanceId(processInstanceId);
if(rzLeaveDetail != null){
getIRzLeaveDetailService().deleteRzLeaveDetailById(rzLeaveDetail.getId());
}
}
/***
* 请假
* @param processInstanceId 钉钉审批单详情
* @param sysStaff 平台用户
* @param json 请求数据信息
*/
public void leave(String processInstanceId, SysStaff sysStaff, GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json) {
JSONObject extValueJson = getExtValue(json, "DDHolidayField");
//解析假期类型
JSONObject extension = JSON.parseObject(extValueJson.getString("extension"));
//查询假期类型
String tag = extension.getString("tag");
SysDictData sysDictData = sysDictDataService.selectDictDataListByType("holidays_type").stream().filter(data-> StringUtils.equals(data.getDictLabel(),tag)).findFirst().orElse(null);
if(sysDictData != null){
//假期类型的code
Long dictCode = sysDictData.getDictCode();
JSONArray detailList = extValueJson.getJSONArray("detailList");
Date beginTime = null;
Date endTime = null;
//如果大于1 证明是多天请假, 需要排序
if(detailList.size() > 1){
detailList.sort((a,b)->{
return ((JSONObject) a).getLong("workDate").compareTo(((JSONObject) b).getLong("workDate"));
});
//获取第一天
beginTime = new Date(detailList.getJSONObject(0).getJSONObject("approveInfo").getLong("fromTime"));
//获取最后一天
endTime = new Date(detailList.getJSONObject(detailList.size()-1).getJSONObject("approveInfo").getLong("toTime"));
}else{
//只请一天假
JSONObject approveInfo = detailList.getJSONObject(0).getJSONObject("approveInfo");
beginTime = new Date(approveInfo.getLong("fromTime"));
//获取最后一天
endTime = new Date(approveInfo.getLong("toTime"));
}
RzLeave rzLeave = getIRzLeaveService().selectRzLeaveByUserId(sysStaff.getUserId());
RzLeaveDetail rzLeaveDetail = new RzLeaveDetail();
rzLeaveDetail.setName(sysStaff.getName());
rzLeaveDetail.setLeaveStartTime(beginTime);
rzLeaveDetail.setLeaveEndTime(endTime);
rzLeaveDetail.setLeaveId(rzLeave.getId());
rzLeaveDetail.setType(dictCode);
rzLeaveDetail.setLeaveHour(extValueJson.getInteger("durationInHour"));
rzLeaveDetail.setRemarks("钉钉"+tag);
rzLeaveDetail.setProcessInstanceId(processInstanceId);
getIRzLeaveDetailService().insertRzLeaveDetail(rzLeaveDetail);
}
}
}

View File

@ -0,0 +1,127 @@
package com.evo.ding.processor.approveStatus.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.evo.attendance.domain.RzAttendance;
import com.evo.attendance.domain.RzAttendanceDetail;
import com.evo.attendance.mapper.RzAttendanceMapper;
import com.evo.attendance.service.IRzAttendanceService;
import com.evo.attendance.service.RzAttendanceDetailService;
import com.evo.common.core.domain.entity.SysDictData;
import com.evo.common.utils.ParamUtils;
import com.evo.common.utils.StringUtils;
import com.evo.ding.processor.approveStatus.AttendanceApproveStatusChangeExchangeProcessor;
import com.evo.personnelMatters.domain.RzLeave;
import com.evo.personnelMatters.domain.RzLeaveDetail;
import com.evo.system.domain.SysStaff;
import com.evo.system.service.ISysDictDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.Date;
/**
* 出差事件处理 ApproveStatusOutExchangeProcessor
*
* @author andy.shi
* @ClassName:ApproveStatusLeaveExchangeProcessor
* @date: 2026年03月12日 13:32
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
*/
@Slf4j
@Service
public class ApproveStatusOutExchangeProcessor implements AttendanceApproveStatusChangeExchangeProcessor {
@Resource
private RzAttendanceMapper rzAttendanceMapper;
@Resource
private RzAttendanceDetailService rzAttendanceDetailService;
@Override
public boolean accept(String approveType, String result, String status) {
return APPROVE_TYPE_OUT.equals(approveType.toUpperCase()) && APPROVE_STATUS.equals(status.toUpperCase()) && APPROVE_RESULT.equals(result.toUpperCase());
}
@Override
public void exchange(String processInstanceId, GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json) {
try {
rzAttendance(json, BIZ_ACTION_REVOKE.equals(json.getBizAction()));
} catch (Exception e) {
log.error("执行钉钉 -[出差审批]-回调出现异常, 异常原因为:{}", e.getMessage());
e.printStackTrace();
}
}
/***
*
* @param json 审批单数据
* @param isRevoke 是否为撤回
*/
public void rzAttendance(GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json, Boolean isRevoke){
SysStaff sysStaff = getSysStaffByDingUserId(json.getOriginatorUserId());
//出差
JSONArray valueJson = getValue(json, "TableField");
JSONObject jsonObject = valueJson.getJSONObject(0);
JSONArray rowValue = jsonObject.getJSONArray("rowValue");
for (int i = 0; i < rowValue.size(); i++) {
JSONObject rowValueObject = rowValue.getJSONObject(i);
if ("duration".equals(rowValueObject.getString("bizAlias"))) {
JSONObject extendValue = rowValueObject.getJSONObject("extendValue");
JSONArray detailList = extendValue.getJSONArray("detailList");
for (int j = 0; j < detailList.size(); j++) {
JSONObject detailObject = detailList.getJSONObject(j);
Date formatWorkDate = Date.from(Instant.ofEpochMilli(detailObject.getLong("workDate")));
//检查是否为假期, 如果为假期, 不做记录, 只记录不是假期的数据, 假期的外出, 需要提交加班审批
if (!ParamUtils.checkHoliday(formatWorkDate)) {
JSONObject classInfo = detailObject.getJSONObject("classInfo");
JSONObject section = classInfo.getJSONArray("sections").getJSONObject(0);
Long startTime = section.getLong("startTime");
Long endTime = section.getLong("endTime");
Integer durationInHour = detailObject.getJSONObject("approveInfo").getInteger("durationInHour");
Date formatStartTime = Date.from(Instant.ofEpochMilli(startTime));
Date formatEndTime = Date.from(Instant.ofEpochMilli(endTime));
//通过workDate 获取哪一天的卡
RzAttendance attendance = rzAttendanceMapper.queryNowDayAttendanceByStatisticalIdAndDate(sysStaff.getUserId(), formatStartTime);
if(isRevoke){
//清除打卡记录
rzAttendanceDetailService.remove(new LambdaQueryWrapper<RzAttendanceDetail>().eq(RzAttendanceDetail::getAttendanceId, attendance.getId()));
//重置打卡信息
attendance.setRules("");
attendance.setWorkStartTime(null);
attendance.setWorkEndTime(null);
attendance.setWorkSum(BigDecimal.valueOf(0));
attendance.setNightNumber(0);
attendance.setMiddleShiftNumber(0);
}else{
//生成打卡记录
rzAttendanceDetailService.addDetail(attendance, "上班卡", "/", formatStartTime, "出差自动打卡", "");
rzAttendanceDetailService.addDetail(attendance, "下班卡", "/", formatEndTime, "出差自动打卡", "");
//上班
attendance.setRules("上班卡");
attendance.setWorkStartTime(formatStartTime);
attendance.setWorkEndTime(formatEndTime);
attendance.setWorkSum(BigDecimal.valueOf(durationInHour));
if (attendance.getWorkSum().intValue() >= 12 && attendance.getWorkStartTime() != null && attendance.getWorkStartTime().getHours() > 12) {
attendance.setNightNumber(1);
} else if (attendance.getWorkSum().intValue() >= 8 && attendance.getWorkStartTime() != null && attendance.getWorkStartTime().getHours() >= 12 && attendance.getWorkStartTime().getHours() < 21) {
attendance.setMiddleShiftNumber(1);
}
}
rzAttendanceMapper.updateRzAttendance(attendance);
}
}
break;
}
}
}
}

View File

@ -53,12 +53,13 @@ public class ApproveStatusOvertimeExchangeProcessor implements AttendanceApprove
@Override
public boolean accept(String approveType, String result, String status) {
return APPROVE_TYPE_OVERTIME.equals(approveType.toUpperCase()) && APPROVE_STATUS.equals(status.toUpperCase()) && APPROVE_RESULT.equals(result.toUpperCase());
//加班不在对接
return false; //APPROVE_TYPE_OVERTIME.equals(approveType.toUpperCase()) && APPROVE_STATUS.equals(status.toUpperCase()) && APPROVE_RESULT.equals(result.toUpperCase());
}
@Override
@Transactional
public void exchange(GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult result) {
public void exchange(String processInstanceId, GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult result) {
try {
SysStaff sysStaff = getSysStaffByDingUserId(result.getOriginatorUserId());
List<GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues> formComponentValueList = result.getFormComponentValues();

View File

@ -23,6 +23,12 @@ public interface DingCallBackExchangeProcessor {
static final String EVENT_TYPE_INSTANCE_CHANGE = "bpms_instance_change";
//请假加班出差外出状态变更事件
static final String EVENT_TYPE_APPROVE_STATUS_CHANGE = "attendance_approve_status_change";
//班制调整
static final String EVENT_TYPE_ATTEND_SHIFT_CHANGE = "attend_shift_change";
//考勤组调整
static final String EVENT_TYPE_ATTEND_GROUP_CHANGE = "attend_group_change";
boolean accept(String eventType);

View File

@ -41,7 +41,7 @@ public class DingCallBackApproveStatusChangeExchangeProcessor implements DingCal
GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult result = DingUtils.getProcessInstanceInfo(processInstanceId);
for (AttendanceApproveStatusChangeExchangeProcessor processor : approveStatusChangeExchangeProcessorList) {
if (processor.accept(json.getString("approveType"), result.getResult(), result.getStatus())) {
processor.exchange(result);
processor.exchange(processInstanceId, result);
}
}
}

View File

@ -0,0 +1,113 @@
package com.evo.ding.processor.callback.impl;
import com.alibaba.fastjson2.JSONObject;
import com.dingtalk.api.response.OapiAttendanceGroupQueryResponse;
import com.dingtalk.api.response.OapiAttendanceShiftQueryResponse;
import com.evo.common.utils.Collections;
import com.evo.common.utils.DateUtils;
import com.evo.ding.DingUtils;
import com.evo.ding.domain.DingGroup;
import com.evo.ding.domain.DingShift;
import com.evo.ding.domain.DingShiftGroup;
import com.evo.ding.processor.callback.DingCallBackExchangeProcessor;
import com.evo.ding.service.DingGroupService;
import com.evo.ding.service.DingShiftGroupService;
import com.evo.ding.service.DingShiftService;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 考勤组信息调整 DingCallBackGroupChangeExchangeProcessor
* @author andy.shi
* @ClassName:DingCallBackCheckRecordExchangeProcessor
* @date: 2026年03月12日 9:02
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
*/
@Slf4j
@Service
public class DingCallBackGroupChangeExchangeProcessor implements DingCallBackExchangeProcessor {
@Autowired
DingGroupService dingGroupService;
@Autowired
DingShiftService dingShiftService;
@Autowired
DingShiftGroupService dingShiftGroupService;
@Override
public boolean accept(String eventType) {
return EVENT_TYPE_ATTEND_GROUP_CHANGE.equals(eventType);
}
@Override
public void exchange(JSONObject json) {
log.info("钉钉 班制调整回调========================>>>{}", json.toString());
OapiAttendanceGroupQueryResponse.TopSimpleGroupVO groupDetail = DingUtils.getGroupDetail(json.getLong("id"));
if(groupDetail != null){
String groupDingId = String.valueOf(groupDetail.getId());
DingGroup dingGroup = dingGroupService.selectByDingId(groupDingId);
if(dingGroup == null){
dingGroup = new DingGroup();
}
dingGroup.setName(groupDetail.getName());
dingGroup.setDingId(groupDingId);
dingGroupService.saveOrUpdate(dingGroup);
//获取现在所有的数据
List<DingShiftGroup> dingShiftGroupList = dingShiftGroupService.selectListByGroupId(groupDingId);
//如果返回为空, 旧数据不为空, 直接清除
if(Collections.isEmpty(groupDetail.getShiftIds()) && Collections.isNotEmpty(dingShiftGroupList)){
dingShiftGroupService.removeByIds(dingShiftGroupList);
}else if(Collections.isNotEmpty(groupDetail.getShiftIds()) && Collections.isEmpty(dingShiftGroupList)){
//更新绑定信息
for (Long shiftId : groupDetail.getShiftIds()) {
crateDingShiftGroup(groupDingId, String.valueOf(shiftId));
}
}else if(Collections.isNotEmpty(groupDetail.getShiftIds()) && Collections.isNotEmpty(dingShiftGroupList)){
Map<String, List<DingShiftGroup>> map = dingShiftGroupList.stream().collect(Collectors.groupingBy(DingShiftGroup::getShiftId));
for (Long shiftId : groupDetail.getShiftIds()) {
String strShiftId = String.valueOf(shiftId);
if(map.containsKey(strShiftId)){
DingShift dingShift = dingShiftService.selectByDingId(strShiftId);
for (DingShiftGroup dingShiftGroup : map.get(strShiftId)){
dingShiftGroup.setCheckTime(("OnDuty".equals(dingShiftGroup.getType()) ? dingShift.getOnDutyCheckTime() : dingShift.getOffDutyCheckTime()));
dingShiftGroupService.updateById(dingShiftGroup);
}
map.remove(strShiftId);
}else{
crateDingShiftGroup(groupDingId, String.valueOf(shiftId));
}
}
//如果还存在, 需要删除
if(Collections.isNotEmpty(map)){
dingShiftGroupService.removeByIds(map.values().stream().filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList()));
}
}
}
}
public void crateDingShiftGroup(String groupId, String shiftId){
DingShift dingShift = dingShiftService.selectByDingId(shiftId);
//直接更新上班, 下班
for (int i = 0; i < 2; i++) {
DingShiftGroup dingShiftGroup = new DingShiftGroup();
dingShiftGroup.setGroupId(groupId);
dingShiftGroup.setShiftId(String.valueOf(shiftId));
dingShiftGroup.setType(i == 0 ? "OnDuty" : "OffDuty");
if(dingShift != null){
dingShiftGroup.setCheckTime(i == 0 ? dingShift.getOnDutyCheckTime() : dingShift.getOffDutyCheckTime());
}
dingShiftGroupService.save(dingShiftGroup);
}
}
}

View File

@ -0,0 +1,69 @@
package com.evo.ding.processor.callback.impl;
import com.alibaba.fastjson2.JSONObject;
import com.dingtalk.api.response.OapiAttendanceShiftQueryResponse;
import com.evo.common.utils.DateUtils;
import com.evo.ding.DingUtils;
import com.evo.ding.domain.DingShift;
import com.evo.ding.processor.callback.DingCallBackExchangeProcessor;
import com.evo.ding.service.DingShiftGroupService;
import com.evo.ding.service.DingShiftService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 班制信息调整 DingCallBackShiftChangeExchangeProcessor
* @author andy.shi
* @ClassName:DingCallBackCheckRecordExchangeProcessor
* @date: 2026年03月12日 9:02
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
*/
@Slf4j
@Service
public class DingCallBackShiftChangeExchangeProcessor implements DingCallBackExchangeProcessor {
@Autowired
DingShiftService dingShiftService;
@Autowired
DingShiftGroupService dingShiftGroupService;
@Override
public boolean accept(String eventType) {
return EVENT_TYPE_ATTEND_SHIFT_CHANGE.equals(eventType);
}
@Override
public void exchange(JSONObject json) {
log.info("钉钉 班制调整回调========================>>>{}", json.toString());
OapiAttendanceShiftQueryResponse.TopShiftVo shiftDetail = DingUtils.getShiftDetail(json.getLong("id"));
if(shiftDetail != null){
String shiftDingId = String.valueOf(shiftDetail.getId());
DingShift dingShift = dingShiftService.selectByDingId(shiftDingId);
//获取工作时长
OapiAttendanceShiftQueryResponse.TopShiftSettingVo topShiftSettingVo = shiftDetail.getShiftSetting();
OapiAttendanceShiftQueryResponse.TopSectionVo topSectionVo = shiftDetail.getSections().get(0);
OapiAttendanceShiftQueryResponse.TopPunchVo newOnDutyTopPunchVo = topSectionVo.getPunches().stream().filter(data -> data.getCheckType().equals("OnDuty")).findAny().orElse(null);
OapiAttendanceShiftQueryResponse.TopPunchVo newOffDutyTopPunchVo = topSectionVo.getPunches().stream().filter(data -> data.getCheckType().equals("OffDuty")).findAny().orElse(null);
//如果不存在班制, 创建新的班制
if(dingShift == null){
//如果本地不存在, 直接创建新的
dingShift = new DingShift();
dingShift.setName(shiftDetail.getName());
dingShift.setDingId(shiftDingId);
}
dingShift.setWorkHour(new BigDecimal(topShiftSettingVo.getWorkTimeMinutes()).divide(new BigDecimal(60), 2, java.math.BigDecimal.ROUND_HALF_UP).intValue());
dingShift.setOnDutyCheckTime(DateUtils.parseDateToStr("HH:mm:ss",newOnDutyTopPunchVo.getCheckTime()));
dingShift.setOffDutyCheckTime(DateUtils.parseDateToStr("HH:mm:ss",newOffDutyTopPunchVo.getCheckTime()));
//通过三目判定, 如果id为空, 则走保存,如果存在id 则更新
if((dingShift.getId() == null ? dingShiftService.save(dingShift) : dingShiftService.updateById(dingShift))){
dingShiftGroupService.updateCheckTimeByShiftIdAndType(shiftDingId, newOnDutyTopPunchVo.getCheckType(), dingShift.getOnDutyCheckTime());
dingShiftGroupService.updateCheckTimeByShiftIdAndType(shiftDingId, newOffDutyTopPunchVo.getCheckType(), dingShift.getOffDutyCheckTime());
}
}
}
}

View File

@ -37,8 +37,7 @@ public class DingCallBackUserAddOrgExchangeProcessor implements DingCallBackExch
JSONArray dataList = json.getJSONArray("userId");
if(dataList!= null && dataList.size() > 0){
dataList.forEach(data->{
DingUtils.getUserInfoByUserId(String.valueOf(data));
sysStaffService.sysStaffLeaveByDingUserId(String.valueOf(data));
sysStaffService.insertSysStaffByDingDing(DingUtils.getUserInfoByUserId(String.valueOf(data)));
});
}
}

View File

@ -3,6 +3,7 @@ package com.evo.ding.processor.instance.impl;
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
import com.evo.common.utils.DateUtils;
import com.evo.common.utils.ParamUtils;
import com.evo.common.utils.StringUtils;
import com.evo.ding.DingUtils;
import com.evo.ding.domain.DingShiftGroup;
@ -62,7 +63,7 @@ public class InstanceChangeRechargeCardExchangeProcessor implements InstanceChan
dingsShiftGroup = getDingShiftGroupService().selectByGroupIdAndTypeAndCheckTime(planResultObject.getString("group_id"), checkType, formatPlanCheckTime);
Date date= DateUtils.parseDate(bkTime, "yyyy-MM-dd HH:mm");
//生成补卡记录信息
getIRzAttendanceService().addRzOverTime(json.toString(), sysStaff, dingsShiftGroup, checkType, date, date, "/", "钉钉补卡-"+bkYi);
getIRzAttendanceService().addRzOverTime(json.toString(), sysStaff, dingsShiftGroup, checkType, date, date, "/", "钉钉补卡-"+bkYi, ParamUtils.getDebiting());
}
}
} catch (ParseException e) {

View File

@ -0,0 +1,18 @@
package com.evo.ding.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.evo.ding.domain.DingGroup;
import com.evo.ding.domain.DingShift;
/**
* DingsShiftService
*
* @author andy.shi
* @ClassName:DingsShiftService
* @date: 2026年03月11日 15:55
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
*/
public interface DingGroupService extends IService<DingGroup> {
public DingGroup selectByDingId(String dingId);
}

View File

@ -1,8 +1,11 @@
package com.evo.ding.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.evo.ding.domain.DingShift;
import com.evo.ding.domain.DingShiftGroup;
import java.util.List;
/**
* DingShiftGroupService
*
@ -14,4 +17,10 @@ import com.evo.ding.domain.DingShiftGroup;
public interface DingShiftGroupService extends IService<DingShiftGroup> {
DingShiftGroup selectByGroupIdAndTypeAndCheckTime(String groupId, String type, String checkTime);
int updateCheckTimeByShiftIdAndType(String shiftId, String type, String checkTime);
List<DingShiftGroup> selectListByGroupId(String groupId);
public List<DingShiftGroup> selectList(DingShiftGroup dingShiftGroup);
}

View File

@ -2,6 +2,9 @@ package com.evo.ding.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.evo.ding.domain.DingShift;
import com.evo.system.domain.SysStaff;
import java.util.List;
/**
* DingsShiftService
@ -14,4 +17,6 @@ import com.evo.ding.domain.DingShift;
public interface DingShiftService extends IService<DingShift> {
public DingShift selectByDingId(String dingId);
public List<DingShift> selectList(DingShift dingShift);
}

View File

@ -0,0 +1,26 @@
package com.evo.ding.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evo.ding.domain.DingGroup;
import com.evo.ding.domain.DingShift;
import com.evo.ding.mapper.DingGroupMapper;
import com.evo.ding.mapper.DingShiftMapper;
import com.evo.ding.service.DingGroupService;
import com.evo.ding.service.DingShiftService;
import org.springframework.stereotype.Service;
/**
* DingShiftGroupServiceImpl
*
* @author andy.shi
* @ClassName:DingShiftGroupServiceImpl
* @date: 2026年03月11日 15:49
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
*/
@Service
public class DingGroupServiceImpl extends ServiceImpl<DingGroupMapper, DingGroup> implements DingGroupService {
@Override
public DingGroup selectByDingId(String dingId) {
return getBaseMapper().selectByDingId(dingId);
}
}

View File

@ -1,11 +1,14 @@
package com.evo.ding.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evo.ding.domain.DingShiftGroup;
import com.evo.ding.mapper.DingShiftGroupMapper;
import com.evo.ding.service.DingShiftGroupService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* DingShiftGroupServiceImpl
*
@ -20,4 +23,19 @@ public class DingShiftGroupServiceImpl extends ServiceImpl<DingShiftGroupMapper,
public DingShiftGroup selectByGroupIdAndTypeAndCheckTime(String groupId, String type, String checkTime) {
return getBaseMapper().selectByGroupIdAndTypeAndCheckTime(groupId, type, checkTime);
}
@Override
public int updateCheckTimeByShiftIdAndType(String shiftId, String type, String checkTime) {
return getBaseMapper().updateCheckTimeByShiftIdAndType(shiftId, type, checkTime);
}
@Override
public List<DingShiftGroup> selectListByGroupId(String groupId) {
return list(new LambdaQueryWrapper<DingShiftGroup>().eq(DingShiftGroup::getGroupId, groupId));
}
@Override
public List<DingShiftGroup> selectList(DingShiftGroup dingShiftGroup) {
return getBaseMapper().selectList(dingShiftGroup);
}
}

View File

@ -9,6 +9,8 @@ import com.evo.ding.service.DingShiftGroupService;
import com.evo.ding.service.DingShiftService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* DingShiftGroupServiceImpl
*
@ -23,4 +25,9 @@ public class DingShiftServiceImpl extends ServiceImpl<DingShiftMapper, DingShift
public DingShift selectByDingId(String dingId) {
return getBaseMapper().selectByDingId(dingId);
}
@Override
public List<DingShift> selectList(DingShift dingShift) {
return getBaseMapper().selectList(dingShift);
}
}

View File

@ -49,7 +49,8 @@ public class RzLeaveDetail extends BaseEntity
private String remarks;
private String delFlag;
//钉钉审批id
private String processInstanceId;
/***
* 扩展字段
*/

View File

@ -1,6 +1,7 @@
package com.evo.personnelMatters.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.evo.personnelMatters.domain.RzLeave;
import com.evo.personnelMatters.domain.RzLeaveDetail;
import org.apache.ibatis.annotations.Param;
@ -84,4 +85,5 @@ public interface RzLeaveDetailMapper extends BaseMapper<RzLeaveDetail>
*/
Long selectLeaveHourByUserIdAndDateAndType(@Param("userId") Long userId,@Param("date") Date date, @Param("type") Long type);
RzLeaveDetail selectRzLeaveDetailByProcessInstanceId(@Param("processInstanceId") String processInstanceId);
}

View File

@ -1,6 +1,7 @@
package com.evo.personnelMatters.service;
import com.evo.common.core.domain.AjaxResult;
import com.evo.personnelMatters.domain.RzLeave;
import com.evo.personnelMatters.domain.RzLeaveDetail;
import java.util.List;
@ -52,4 +53,6 @@ public interface IRzLeaveDetailService
public AjaxResult deleteRzLeaveDetailById(Long id);
public RzLeaveDetail calculationLeaveHour(RzLeaveDetail rzLeaveDetail);
public RzLeaveDetail selectRzLeaveDetailByProcessInstanceId(String processInstanceId);
}

View File

@ -394,6 +394,11 @@ public class RzLeaveDetailServiceImpl extends ServiceImpl<RzLeaveDetailMapper, R
return rzLeaveDetail;
}
@Override
public RzLeaveDetail selectRzLeaveDetailByProcessInstanceId(String processInstanceId) {
return getBaseMapper().selectRzLeaveDetailByProcessInstanceId(processInstanceId);
}
public RzLeaveDetail leaveHour(RzLeaveDetail rzLeaveDetail) {
if(rzLeaveDetail.getType() == null || rzLeaveDetail.getLeaveStartTime() == null){
return rzLeaveDetail;

View File

@ -0,0 +1,55 @@
package com.evo.system.controller;
import com.evo.common.core.controller.BaseController;
import com.evo.common.core.page.TableDataInfo;
import com.evo.ding.domain.DingShift;
import com.evo.ding.domain.DingShiftGroup;
import com.evo.ding.service.DingShiftGroupService;
import com.evo.ding.service.DingShiftService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* ShiftController
*
* @author andy.shi
* @ClassName:ShiftContriller
* @date: 2026年03月27日 9:18
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
*/
@RestController
@RequestMapping("/system/shift")
public class ShiftController extends BaseController {
@Resource
private DingShiftService dingShiftService;
@Resource
private DingShiftGroupService dingShiftGroupService;
/**
* 查询班次信息
*/
@PreAuthorize("@ss.hasPermi('system:shift:list')")
@GetMapping("/list")
public TableDataInfo list(DingShift dingShift){
startPage();
List<DingShift> list = dingShiftService.selectList(dingShift);
return getDataTable(list);
}
/**
* 查询考勤组信息
*/
@GetMapping("/group/list")
public TableDataInfo list(DingShiftGroup dingShiftGroup){
startPage();
List<DingShiftGroup> list = dingShiftGroupService.selectList(dingShiftGroup);
return getDataTable(list);
}
}

View File

@ -216,6 +216,8 @@ public class SysStaff extends BaseEntity
private String extended;
private String dingUserId;
//数据来源 1 平台, 2 钉钉
private String source;
public List<Long> getSubsidyList() {
if(Collections.isEmpty(subsidyList) && StringUtils.isNotEmpty(subsidys)){

View File

@ -45,7 +45,7 @@ public interface ISysStaffService extends IService<SysStaff>
* @param result 员工管理
* @return 结果
*/
public void insertSysStaffByDingDing(String result);
public void insertSysStaffByDingDing(String dingUserInfo);
/**
* 修改员工管理
*

View File

@ -150,7 +150,7 @@ public class SysStaffServiceImpl extends ServiceImpl<SysStaffMapper, SysStaff> i
sysStaff.setCreateTime(DateUtils.getNowDate());
sysStaff.setCreateBy(SecurityUtils.getUsername());
sysStaff.setDelFlag(Constants.DELETE_FLAG_0);
sysStaff.setSource(Constants.SOURCE_PT);
if(CollectionUtils.isNotEmpty(sysStaff.getSubsidyList())){
sysStaff.setSubsidys(sysStaff.getSubsidyList().stream().map(String::valueOf).collect(Collectors.joining(",")));
}
@ -182,66 +182,56 @@ public class SysStaffServiceImpl extends ServiceImpl<SysStaffMapper, SysStaff> i
}
@Override
public void insertSysStaffByDingDing(String result) {
public void insertSysStaffByDingDing(String dingUserInfo) {
JSONObject dingResult = JSONObject.parseObject(result);
dingResult.getJSONObject("result");
JSONObject dingResult = JSONObject.parseObject(dingUserInfo);
JSONObject result = dingResult.getJSONObject("result");
String mobile = result.getString("mobile");
String name = result.getString("name");
//钉钉推送, 只能通过名称+手机号核查是否存在. 如果录入过, 改为重新入职
SysStaff sysStaff = getOne(new LambdaQueryWrapper<SysStaff>().eq(SysStaff::getPhone, mobile).eq(SysStaff::getName,name), false);
if(sysStaff != null){
//如果用户不为空, 并且状态为离职
if(sysStaff.getStatus().equals("-1")){
//重新做员工入职
if(StringUtils.isEmpty(sysStaff.getDingUserId())){
sysStaff.setDingUserId(result.getString("userid"));
getBaseMapper().updateById(sysStaff);
}
//做员工重新入职
reEmployment(sysStaff.getUserId());
}
//不为空, 还不是离职. 不做处理, 当前员工已经存在
log.info("当前员工信息已经存在, 无法再次入库, 钉钉返回员工信息为{}", dingUserInfo);
return;
}
// //根据省份证号查询是否已经录入
// SysStaff p_staff = getBaseMapper().queryysStaffByIdCard(sysStaff.getIdCard());
// if(StringUtils.isNotNull(p_staff)){
// return AjaxResult.error("此人录入过!!");
// }
// //判断是否是领导是反写部门信息
// if("".equals(sysStaff.getIsLeader())){
// //根据ID查询部门信息
// SysDept sysDept = deptMapper.selectDeptById(sysStaff.getDeptId());
// sysDept.setPhone(sysStaff.getPhone());
// sysDept.setLeader(sysStaff.getName());
// int i = deptMapper.updateDept(sysDept);
// if(i < 1){
// return AjaxResult.error("更新部门负责人失败");
// }
// }
// //根据省份证确定性别和年龄
// sysStaff.setAge(Long.parseLong(new SimpleDateFormat("yyyy").format(new Date())) - Long.parseLong(sysStaff.getIdCard().substring(6,10)));
// //性别
// sysStaff.setSex((Integer.parseInt(sysStaff.getIdCard().substring(16,17)) % 2 == 0) ? "1" : "0");
// //员工编码
// sysStaff.setCode(getCodeByCompanyName());
// sysStaff.setSeniority(0l);
// sysStaff.setStatus(Constants.JOB_STATIS_0);
// sysStaff.setCreateTime(DateUtils.getNowDate());
// sysStaff.setCreateBy(SecurityUtils.getUsername());
// sysStaff.setDelFlag(Constants.DELETE_FLAG_0);
//
// if(CollectionUtils.isNotEmpty(sysStaff.getSubsidyList())){
// sysStaff.setSubsidys(sysStaff.getSubsidyList().stream().map(String::valueOf).collect(Collectors.joining(",")));
// }
// //打卡位置改为多选
// if(CollectionUtils.isNotEmpty(sysStaff.getTimeClockList())){
// sysStaff.setTimeClock(sysStaff.getTimeClockList().stream().collect(Collectors.joining(",")));
// }
// //新增员工信息到金蝶
// if(StringUtils.isNotEmpty(sysStaff.getJobCode())){
// sysStaff.setExtended(KingdeeRequestUtils.employeeSave(Collections.asMap("userName", sysStaff.getName(), "userCode", sysStaff.getCode(), "jobCode", sysStaff.getJobCode().split("_")[0],"deptCode", sysStaff.getJobCode().split("_")[1])));
// }else if(StringUtils.isEmpty(sysStaff.getJobCode())){
// sysStaff.setExtended(KingdeeRequestUtils.employeeSaveEmptyJob(Collections.asMap("userName", sysStaff.getName(), "userCode", sysStaff.getCode())));
// }
//
// int i = getBaseMapper().insertSysStaff(sysStaff);
// if(i < 1){
// return AjaxResult.error("员工添加失败");
// }
// //员工详情
// createStaffDetail(sysStaff);
// //打卡统计打卡详情
// rzAttendanceStatisticalService.createRzAttendance(sysStaff, Collections.emptyList(), null);
// //处理餐饮信息
// rzRestaurantStatisticsService.createRestaurantStatistics(sysStaff, DateUtils.getNowDate());
// //处理考勤机相关信息
// initCheckDevice(sysStaff);
//创建新的用户
sysStaff = new SysStaff();
sysStaff.setName(name);
sysStaff.setPhone(mobile);
sysStaff.setDingUserId(dingResult.getString("userid"));
//员工编码
sysStaff.setCode(getCodeByCompanyName());
sysStaff.setSeniority(0l);
sysStaff.setStatus(Constants.JOB_STATIS_0);
sysStaff.setCreateTime(DateUtils.getNowDate());
sysStaff.setCreateBy(SecurityUtils.getUsername());
sysStaff.setDelFlag(Constants.DELETE_FLAG_0);
sysStaff.setSource(Constants.SOURCE_DING);
int i = getBaseMapper().insertSysStaff(sysStaff);
if(i < 1){
log.error("员工添加失败, 钉钉数据:{}",dingUserInfo);
return;
}
//员工详情
createStaffDetail(sysStaff);
//打卡统计打卡详情
rzAttendanceStatisticalService.createRzAttendance(sysStaff, Collections.emptyList(), null);
//处理餐饮信息
rzRestaurantStatisticsService.createRestaurantStatistics(sysStaff, DateUtils.getNowDate());
}
private void initCheckDevice(SysStaff sysStaff){
@ -301,6 +291,13 @@ public class SysStaffServiceImpl extends ServiceImpl<SysStaffMapper, SysStaff> i
public AjaxResult updateSysStaff(SysStaff sysStaff)
{
if(StringUtils.isNotEmpty(sysStaff.getSource()) && sysStaff.getSource().equals(Constants.SOURCE_DING) && StringUtils.isEmpty(sysStaff.getSex())){
//根据省份证确定性别和年龄
sysStaff.setAge(Long.parseLong(new SimpleDateFormat("yyyy").format(new Date())) - Long.parseLong(sysStaff.getIdCard().substring(6,10)));
//性别
sysStaff.setSex((Integer.parseInt(sysStaff.getIdCard().substring(16,17)) % 2 == 0) ? "1" : "0");
}
if(CollectionUtils.isNotEmpty(sysStaff.getSubsidyList())){
sysStaff.setSubsidys(sysStaff.getSubsidyList().stream().map(String::valueOf).collect(Collectors.joining(",")));
}

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.evo.ding.mapper.DingGroupMapper">
<resultMap type="DingGroup" id="DingGroupResult">
<result property="id" column="id" />
<result property="name" column="name" />
<result property="dingId" column="ding_Id" />
<result property="groupKey" column="group_key" />
</resultMap>
<sql id="selectVo">
select id, name, ding_Id, group_key from ding_group
</sql>
<select id="selectByDingId" resultMap="DingGroupResult">
<include refid="selectVo"/>
where ding_id = #{dingId}
</select>
</mapper>

View File

@ -26,6 +26,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where group_id =#{groupId} and type = #{type} and check_time = #{checkTime}
</select>
<update id="updateCheckTimeByShiftIdAndType">
update ding_shift_group set check_time = #{checkTime} where shift_id=#{shiftId} and type = #{type}
</update>
<select id="selectList" parameterType="com.evo.ding.domain.DingShiftGroup" resultMap="DingShiftGroupResult">
select
dsg.id, dsg.group_id, dsg.shift_id, dsg.type, dsg.check_time,
ds.name as shiftName,
dg.name as groupName
from ding_shift_group dsg
left join ding_shift ds on ds.ding_id = dsg.shift_id
left join ding_group dg on dg.ding_id = dsg.group_id
<where>
dsg.shift_id = #{shiftId}
</where>
</select>
<!-- <select id="selectEqButtonList" parameterType="EqButton" resultMap="EqButtonResult">-->
<!-- <include refid="selectEqButtonVo"/>-->

View File

@ -9,12 +9,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="name" column="name" />
<result property="dingId" column="ding_Id" />
<result property="workHour" column="work_Hour" />
<result property="overtimeWork" column="overtime_Work" />
<result property="deductionHour" column="deduction_Hour" />
</resultMap>
<sql id="selectVo">
select id, name, ding_Id, work_Hour, overtime_Work, deduction_Hour from ding_shift
select id, name, ding_Id, work_Hour, on_duty_check_time, off_duty_check_time from ding_shift
</sql>
<select id="selectByDingId" resultMap="DingShiftResult">
@ -23,6 +21,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="selectList" parameterType="com.evo.ding.domain.DingShift" resultMap="DingShiftResult">
<include refid="selectVo"/>
<where>
<if test="name != null and name != ''"> name like concat('%', #{name}, '%')</if>
</where>
</select>
<!-- <select id="selectEqButtonList" parameterType="EqButton" resultMap="EqButtonResult">-->
<!-- <include refid="selectEqButtonVo"/>-->
<!-- <where>-->

View File

@ -125,7 +125,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where ld.del_flag = '0' and ld.type = #{type} and l.user_id=#{userId} and JSON_EXTRACT(extension,CONCAT('$.',CONCAT("month",DATE_FORMAT(#{date},'%m'))))=DATE_FORMAT(#{date},'%Y-%m')
</select>
<select id="selectRzLeaveDetailByProcessInstanceId" resultMap="RzLeaveDetailResult">
<include refid="selectRzLeaveDetailVo"/>
where del_flag = '0' and process_instance_id = #{processInstanceId} limit 1
</select>
</mapper>

View File

@ -51,6 +51,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="timeClock" column="time_clock" />
<result property="extended" column="extended" />
<result property="dingUserId" column="ding_user_id" />
<result property="source" column="source" />
</resultMap>
<sql id="selectSysStaffVo">
@ -59,7 +60,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
quit_date, contract_start, contract_end, contract_type, social_type, seniority, is_overtime_pay,
zs_flag, secrecy, injury, insurance, introducer, clock_in, status,
wages_ratio_date, remarks, del_flag, create_by, create_time, update_by,
update_time, image_url,time_clock,subsidys, job_code, extended, openid, ding_user_id
update_time, image_url,time_clock,subsidys, job_code, extended, openid, ding_user_id, source
from sys_staff
</sql>
@ -149,6 +150,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="jobCode != null">job_code,</if>
<if test="extended != null and extended != ''">extended,</if>
<if test="openid != null">openid,</if>
<if test="source != null">source,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
@ -199,6 +201,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="jobCode != null">#{jobCode},</if>
<if test="extended != null and extended != ''">#{extended},</if>
<if test="openid != null">#{openid},</if>
<if test="source != null">#{source},</if>
</trim>
</insert>