總結:
應用場景:公司ERP裏看到釘釘的考勤記錄
一共建了4個實體 ,如果只有單個公司又想簡化的話可以只建實體2和4
- 公司ID和公司密匙表(我需要涉及多個公司)
- 釘釘用戶與ERP系統用戶的對照表
- 釘釘的考勤記錄
- 系統的考勤記錄
其中踩了個坑,通過接口傳入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; // 統計用