对接钉钉考勤

总结:

应用场景:公司ERP里看到钉钉的考勤记录

一共建了4个实体 ,如果只有单个公司又想简化的话可以只建实体2和4

  1. 公司ID和公司密匙表(我需要涉及多个公司)
  2. 钉钉用户与ERP系统用户的对照表
  3. 钉钉的考勤记录
  4. 系统的考勤记录

其中踩了个坑,通过接口传入userIdList 获取考勤记录时,老是不全,后来发现这个用户ID属性不能为Long,改为String就好了,有什么问题大家可以多看看文档,里面啥都有,就是有点不友好,我以前开发完之后现在钉钉改了接口参数 ,正好以前写的也不是很好于是重新改了一版,不要再问我要代码,主要代码和思路已经写好分享了,其余基础代码还要问我要你觉得合适吗?

获取钉钉的accessToken

/**
 * 获取钉钉的accessToken
 */
public String getAccessToken(String corpid, String secret) {
    String requestUrl = "https://oapi.dingtalk.com/gettoken?corpid=" + corpid + "&corpsecret=" + secret;
    RequestResult result = SendHttpRequestUtil.doGet(requestUrl);
    String accessToken = null;
    JSONObject jsonObject = JSON.parseObject(result.getResult());
    String msg = jsonObject.get("errmsg").toString();
    if ("ok".equals(msg)) {
        accessToken = (String) jsonObject.get("access_token");
    }
    return accessToken;
}

获取钉钉的用户并与自己系统相关联,人事在上工号的时候需要在钉钉那边填一下该员工在系统里的工号(当然,钉钉也有接口你可以自己直接加)

Controller
/**
 * 获取钉钉用户并保存
 */
@ResponseBody
@RequestMapping(value = "getDingUser")
public ActionResult<Map<String, Object>> getDingUser() {
    return dingUserService.getDingUser();
}


Service
/**
 * 获取钉钉的用户信息
 */
@Transactional(readOnly = false)
public ActionResult<Map<String, Object>> getDingUser() {
    //清空表数据
    dao.deleteTable();
    //两个公司遍历
    List<HrmDingCompany> companyList = companyService.findList(new HrmDingCompany());
    for (HrmDingCompany companyEach : companyList) {
        //获取token
        String accessToken = recordsService.getAccessToken(companyEach.getCorpId(), companyEach.getCorpSecret());
        //获取子部门ID列表
        String requestUrl = "https://oapi.dingtalk.com/department/list_ids?access_token=" + accessToken + "&id=1";
        RequestResult result = SendHttpRequestUtil.doGet(requestUrl);
        JSONObject jsonObject = JSON.parseObject(result.getResult());
        String msg = (String) jsonObject.get("errmsg");
        List<Integer> departIds = new ArrayList<>();
        if ("ok".equals(msg)) {
            departIds = (List<Integer>) jsonObject.get("sub_dept_id_list");
        } else {
            logger.error(jsonObject.toString());
        }

        //获取部门用户userid列表
        List<String> userIds = new ArrayList<>();
        for (Integer departId : departIds) {
            requestUrl = "https://oapi.dingtalk.com/user/getDeptMember?access_token=" + accessToken + "&deptId=" + departId;
            result = SendHttpRequestUtil.doGet(requestUrl);
            jsonObject = JSON.parseObject(result.getResult());
            msg = (String) jsonObject.get("errmsg");
            if ("ok".equals(msg)) {
                List<String> tempList = new ArrayList<>();
                tempList = (List<String>) jsonObject.get("userIds");
                userIds.addAll(tempList);
            } else {
                logger.error(jsonObject.toString());
            }
        }

        //保存用户对照
        for (String userId : userIds) { 
            HrmDingUser dingUser = getSingleDingUser(userId, accessToken);
            dingUser.setCorpId(companyEach.getCorpId());
            dingUser.setUserId(userId);
            save(dingUser);
        }
    }

    return new ActionResult<Map<String, Object>>(ErpStatusCode.SUCCESS, "操作成功", null);
}


/**
 * 获取单个钉钉的用户信息
 */
private HrmDingUser getSingleDingUser(String userId, String accessToken) {
    String requestUrl = "https://oapi.dingtalk.com/user/get?access_token=" + accessToken + "&userid=" + userId;
    RequestResult result = SendHttpRequestUtil.doGet(requestUrl);
    HrmDingUser dingUser = new HrmDingUser();
    JSONObject jsonObject = JSON.parseObject(result.getResult());
    String msg = (String) jsonObject.get("errmsg");
    if ("ok".equals(msg)) {
        dingUser.setStaffName(jsonObject.get("name").toString());
        dingUser.setStaffNo(jsonObject.get("jobnumber").toString());
    }
    return dingUser;
}

获取钉钉的考勤记录并保存

Controller
@RequestMapping(value = "syncByDays")
public ActionResult<Map<String, Object>> syncByDays(int days) {
    String offset = "0";//分页获取数据,0表示第一页
    String limit = "50";//每页50条数据
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//需要的时间的格式
    String workDateFrom = DateUtils.formatDate(DateUtils.getDestDate(new Date(), -days)) + " 00:00:00";
    String workDateTo = sdf.format(new Date()) + " 23:59:59";
    //多个公司数据合并
    List<HrmDingCompany> companyList = companyService.findList(new HrmDingCompany());
    for (HrmDingCompany companyEach : companyList) {
        String accessToken = recordsService.getAccessToken(companyEach.getCorpId(), companyEach.getCorpSecret());
        recordsService.getUserId(accessToken, workDateFrom, workDateTo, offset, limit, companyEach.getCorpId());
    }

    return new ActionResult<Map<String, Object>>(ErpStatusCode.SUCCESS, "操作成功", null);

}

Service
/**
 * 获取钉钉用户的userid
 */
public void getUserId(String accessToken, String workDateFrom, String workDateTo, String offset, String limit, String corpId) {
    List<String> userIdList = dingUserDao.findUserIdList(corpId);
    List<String> userIdListResult = new ArrayList<>();
    if (userIdList.size() > 50) {
        for (int i = 0; 50 * i < userIdList.size(); i++) {
            userIdListResult = userIdList.subList(50 * i, userIdList.size() > 50 * (i + 1) ? 50 * (i + 1) : userIdList.size());
            getDingRecords(accessToken, workDateFrom, workDateTo, offset, limit, corpId, userIdListResult);
        }
    } else {
        userIdListResult = userIdList;
        getDingRecords(accessToken, workDateFrom, workDateTo, offset, limit, corpId, userIdListResult);
    }
}

/**
 * 获取钉钉的考勤记录
 */
@Transactional(readOnly = false)
public void getDingRecords(String accessToken, String workDateFrom, String workDateTo, String offset, String limit, String corpId, List<String> userIdList) {
    String requestUrl = "https://oapi.dingtalk.com/attendance/list?access_token=" + accessToken;
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("workDateFrom", workDateFrom);
    jsonObject.put("workDateTo", workDateTo);
    jsonObject.put("offset", offset);
    jsonObject.put("limit", limit);
    jsonObject.put("userIdList", userIdList);
    RequestResult result = SendHttpRequestUtil.doPost(requestUrl, "", jsonObject);
    JSONObject resultJSON = JSONObject.parseObject(result.getResult());
    String msg = (String) resultJSON.get("errmsg");
    String hasMore = resultJSON.get("hasMore").toString();
    List<HrmDingRecords> resultList = new ArrayList<HrmDingRecords>();
    if ("ok".equals(msg)) {
        resultList = JSONObject.parseArray(resultJSON.get("recordresult").toString(), HrmDingRecords.class);
    }
    //保存钉钉的考勤记录
    saveDingList(resultList);
    //如果还有继续获取
    if (resultList.size() == 50) {
        //表示获取考勤数据的起始点,第一次传0,如果还有多余数据,下次获取传的offset值为之前的offset+limit
        offset = String.valueOf(Integer.parseInt(offset) + Integer.parseInt(limit));
        getDingRecords(accessToken, workDateFrom, workDateTo, offset, limit, corpId, userIdList);
    }
}


private void saveDingList(List<HrmStaffDingRecords> list) {
    //保存钉钉数据
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//需要的时间的格式
    SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");//需要的时间的格式
    for (HrmStaffDingRecords hrmStaffDingRecords : list) {
        //如果数据库里已经有了就不插入数据
        HrmStaffDingRecords hrmStaffDingRecordsCheck = new HrmStaffDingRecords();
        hrmStaffDingRecordsCheck.setId(hrmStaffDingRecords.getId());
        List<HrmStaffDingRecords> hrmStaffDingRecordsCheckList = findList(hrmStaffDingRecordsCheck);
        if (hrmStaffDingRecordsCheckList.size() > 0) {
            hrmStaffDingRecords.setIsNewRecord(false);
        } else {
            hrmStaffDingRecords.setIsNewRecord(true);
        }
        //转换获取到的时间格式
        hrmStaffDingRecords.setBaseCheckTime(sdf.format(new Date(Long.parseLong(String.valueOf(hrmStaffDingRecords.getBaseCheckTime())))));
        hrmStaffDingRecords.setUserCheckTime(sdf.format(new Date(Long.parseLong(String.valueOf(hrmStaffDingRecords.getUserCheckTime())))));
        hrmStaffDingRecords.setWorkDate(sdf2.format(new Date(Long.parseLong(String.valueOf(hrmStaffDingRecords.getWorkDate())))));
        save(hrmStaffDingRecords);

        //保存页面展示数据
        HrmStaffAttendanceRecords hrmStaffAttendanceRecords = new HrmStaffAttendanceRecords();
        //上班数据保存
        if (hrmStaffDingRecords.getCheckType().equals("OnDuty")) {
            try {
                hrmStaffAttendanceRecords.setAttendanceBeginTime(sdf.parse(hrmStaffDingRecords.getUserCheckTime()));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            hrmStaffAttendanceRecords.setUserId(hrmStaffDingRecords.getUserId());
            hrmStaffAttendanceRecords.setWorkDate(hrmStaffDingRecords.getWorkDate());
            if (hrmStaffDingRecords.getTimeResult().equals("Normal")) {
                hrmStaffAttendanceRecords.setAttendanceStatus("0");
            } else if (hrmStaffDingRecords.getTimeResult().equals("Late")) {
                hrmStaffAttendanceRecords.setAttendanceStatus("5");
            } else if (hrmStaffDingRecords.getTimeResult().equals("SeriousLate")) {
                hrmStaffAttendanceRecords.setAttendanceStatus("5");
            } else if (hrmStaffDingRecords.getTimeResult().equals("Absenteeism")) {
                hrmStaffAttendanceRecords.setAttendanceStatus("2");
            } else if (hrmStaffDingRecords.getTimeResult().equals("NotSigned")) {
                hrmStaffAttendanceRecords.setAttendanceStatus("2");
            }
            //如果数据库里有记录了则更新上班时间
            HrmStaffAttendanceRecords hrmStaffAttendanceRecordsCheck = new HrmStaffAttendanceRecords();
            hrmStaffAttendanceRecordsCheck.setUserId(hrmStaffAttendanceRecords.getUserId());
            hrmStaffAttendanceRecordsCheck.setWorkDate(hrmStaffAttendanceRecords.getWorkDate());
            List<HrmStaffAttendanceRecords> hrmStaffAttendanceRecordsCheckList = hrmStaffAttendanceRecordsService.findList(hrmStaffAttendanceRecordsCheck);
            if (hrmStaffAttendanceRecordsCheckList.size() != 0) {
                hrmStaffAttendanceRecordsCheck = hrmStaffAttendanceRecordsCheckList.get(0);
                hrmStaffAttendanceRecordsCheck.setAttendanceBeginTime(hrmStaffAttendanceRecords.getAttendanceBeginTime());
                hrmStaffAttendanceRecordsService.save(hrmStaffAttendanceRecordsCheck);
            } else {
                hrmStaffAttendanceRecordsService.save(hrmStaffAttendanceRecords);
            }
        }

        //下班数据保存,找到上班记录并更新
        if (hrmStaffDingRecords.getCheckType().equals("OffDuty")) {
            HrmStaffAttendanceRecords hrmStaffAttendanceRecordsFind = new HrmStaffAttendanceRecords();
            hrmStaffAttendanceRecordsFind.setUserId(hrmStaffDingRecords.getUserId());
            hrmStaffAttendanceRecordsFind.setWorkDate(hrmStaffDingRecords.getWorkDate());
            List<HrmStaffAttendanceRecords> hrmStaffAttendanceRecordsCheckList = hrmStaffAttendanceRecordsService.findList(hrmStaffAttendanceRecordsFind);
            if (hrmStaffAttendanceRecordsCheckList.size() != 0) {
                hrmStaffAttendanceRecordsFind = hrmStaffAttendanceRecordsCheckList.get(0);
                try {
                    hrmStaffAttendanceRecordsFind.setAttendanceEndTime(sdf.parse(hrmStaffDingRecords.getUserCheckTime()));
                    if (StringUtils.isNotBlank(hrmStaffAttendanceRecordsFind.getAttendanceBeginTime().toString()) && StringUtils.isNotBlank(hrmStaffAttendanceRecordsFind.getAttendanceEndTime().toString())) {
                        //午休一个半小时逻辑判断
                        String restTime = hrmStaffAttendanceRecordsFind.getWorkDate() + " 13:30:00";
                        Date checkDate = DateUtils.parseDate(restTime);
                        long between;
                        if (checkDate.getTime() < hrmStaffAttendanceRecordsFind.getAttendanceEndTime().getTime()) {
                            between = hrmStaffAttendanceRecordsFind.getAttendanceEndTime().getTime() - hrmStaffAttendanceRecordsFind.getAttendanceBeginTime().getTime() - 1000 * 60 * 90;
                        } else {
                            between = hrmStaffAttendanceRecordsFind.getAttendanceEndTime().getTime() - hrmStaffAttendanceRecordsFind.getAttendanceBeginTime().getTime();
                        }
                        hrmStaffAttendanceRecordsFind.setWorkHours(TimeUtils.toTimeString(between));
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                hrmStaffAttendanceRecordsService.save(hrmStaffAttendanceRecordsFind);
            }
        }
    }
}

实体

HrmDingCompany
private String corpId;			// 企业ID
private String corpSecret;		// 企业密匙


HrmDingUser 
private String corpId;			// 企业ID
private String groupId;			// 考勤组ID
private String userId;			// 用户ID
private String staffNo;			// 员工工号
private String staffName;		// 员工姓名
private String officeName;		// 部门名称


HrmDingRecords
private String baseCheckTime;		// 计算迟到和早退,基准时间
private String checkType;		// 考勤类型(OnDuty:上班,OffDuty:下班)
private String corpId;			// 企业ID
private String groupId;			// 考勤组ID
private String locationResult;		// 上班打卡时间
private String planId;			// 排班ID
private String recordId;		// 打卡记录ID
private String timeResult;		// 时间结果(Normal:正常;Early:早退; Late:迟到;SeriousLate:严重迟到;Absenteeism:旷工迟到; NotSigned:未打卡)
private String userCheckTime;		// 实际打卡时间
private String userId;			// 用户ID
private String workDate;		// 工作日
private String procInstId;		// 关联的审批实例id
//用于页面展示
private String staffNo;			// 员工工号
private String staffName;		// 员工姓名
private String officeName;		// 部门名称


HrmDingAttendance
private String userId;			// 钉钉用户ID
private String corpId;			// 企业ID
private String staffNo;			// 员工工号
private String staffName;		// 员工姓名
private String officeName;		// 部门名称
private String attendanceStatus;	// 考勤状态0正常1补勤2缺勤3请假4放假5迟到
private String workDate;		// 考勤日期
private Date attendanceBeginTime;	// 上班打卡时间
private Date attendanceEndTime;		// 下班打卡时间
private String workHours;		// 当日上班时长
private String zhengChangDays;		// 正常天数
private String queQinDays;		// 缺勤天数
private String qingJiaDays;		// 请假天数
private String fangJiaDays;		// 放假天数

private String beginDate;		// 时间查询
private String endDate;			// 时间查询
private String time;                    // 统计用

 

 

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值