123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- package com.malk.rongzhi.service.impl;
- import com.malk.Util.UtilDateTime;
- import com.malk.Util.UtilHttp;
- import com.malk.Util.UtilMap;
- import com.malk.rongzhi.repository.dao.RzEkbRecordDao;
- import com.malk.rongzhi.repository.entity.RzEkbRecordPo;
- import com.malk.rongzhi.server.RZConf;
- import com.malk.rongzhi.server.RZR;
- import com.malk.rongzhi.service.RZService;
- import com.malk.server.dingtalk.DDConf;
- import com.malk.server.ekuaibao.EKBR;
- import com.malk.service.dingtalk.DDClient_Attendance;
- import com.malk.service.dingtalk.DDClient_Contacts;
- import com.malk.service.ekuaibao.EKBClient;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.codec.digest.DigestUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import java.time.LocalDateTime;
- import java.util.*;
- import java.util.stream.Collectors;
- @Slf4j
- @Service
- public class RZServiceImpl implements RZService {
- @Autowired
- private DDClient_Contacts ddClientImpl_contacts;
- @Autowired
- private DDClient_Attendance ddClient_attendance;
- @Autowired
- private EKBClient ekbClient;
- @Autowired
- private RzEkbRecordDao rzEkbRecordDao;
- /// 获取调用授权
- @Override
- public String getAccessToken(RZConf.TYPE type) {
- String timestamp = String.valueOf(new Date().getTime());
- String signature = DigestUtils.md5Hex("Max" + timestamp + RZConf.NONCE);
- Map header = new HashMap();
- header.put("timestamp", timestamp);
- header.put("nonce", RZConf.NONCE);
- header.put("signature", signature);
- RZR rsp = (RZR) UtilHttp.doGet("https://one-api.max-digital.cn/v1/token" + type.getPath(), header, null, RZR.class);
- return rsp.getData();
- }
- // 同步考勤数据到e快报
- @Override
- public void uploadTravelData() {
- // 获取用户数据
- log.info("###### [DD]开始同步组织架构 ######");
- List<String> userIds = new ArrayList<>();
- syncOrganizationalStructure(DDConf.TOP_DEPARTMENT, userIds);
- log.info("###### [DD]同步组织架构结束 ######");
- // 获取用户考勤
- for (int i = 0; i < userIds.size(); i += 50) {
- int to = (i + 50) > userIds.size() ? userIds.size() : i + 50;
- // 考勤范围从当日 7.30 到次日 7.30
- Date now = new Date();
- String from = UtilDateTime.formatDate(now) + " 07:30:00";
- String end = UtilDateTime.formatDate(now) + " 23:59:59";
- // fixme: [凌晨以后同步新的考勤时段]
- if (LocalDateTime.now().getHour() <= 7) {
- from = UtilDateTime.formatDate(now) + " 00:00:00";
- end = UtilDateTime.formatDate(now) + " 07:30:00";
- }
- // String from = "2023-04-18 07:30:00";
- // String end = "2023-04-19 07:30:00";
- List<String> users = userIds.subList(i, to);
- List<Map> list = ddClient_attendance.listAttendanceRecord(getAccessToken(RZConf.TYPE.dingtalk), users, from, end);
- // 匹配数据考勤
- users.forEach(user -> {
- List<Map> records = list.stream().filter(item -> user.equals(item.get("userId"))).collect(Collectors.toList());
- // 有下班打卡
- if (records.size() > 1) {
- long checkIn = (long) records.get(0).get("userCheckTime");
- long checkOut = (long) records.get(records.size() - 1).get("userCheckTime");
- String userId = String.valueOf(records.get(0).get("userId"));
- LocalDateTime begin = UtilDateTime.getLocalDateTimeFromTimestamp(checkIn);
- LocalDateTime finish = UtilDateTime.getLocalDateTimeFromTimestamp(checkOut);
- // 下班超过22点, 且当天考勤超过11小时
- float hour = UtilDateTime.betweenHour(begin, finish);
- if (hour > 11.0f && finish.getHour() >= 22) {
- String checkDate = UtilDateTime.formatLocalDate(begin.toLocalDate());
- if (!rzEkbRecordDao.existsByUserIdAndCheckDate(userId, checkDate)) {
- log.info("匹配符合数据, {}, {}, {}", userId, UtilDateTime.formatLocalDateTime(begin), UtilDateTime.formatLocalDateTime(finish));
- // 易快报同步默认是打卡结束时间, 若是23点以后下班, 第二天可打车, 结束传递+1天
- if (finish.getHour() == 23) {
- checkOut += 24 * 60 * 60 * 1000L;
- }
- pushTemplateByRecord(userId, checkIn, checkOut, checkDate);
- } else {
- log.info("数据已经推送, {}, {}, {}", userId, UtilDateTime.formatLocalDateTime(begin), UtilDateTime.formatLocalDateTime(finish));
- }
- }
- }
- });
- }
- }
- // 匹配userId, 以最新数据为准
- private void syncOrganizationalStructure(Number deptId, List<String> userIds) {
- // 同步一级部门用户
- if (deptId.equals(DDConf.TOP_DEPARTMENT)) {
- userIds.addAll(ddClientImpl_contacts.listDepartmentUserId(getAccessToken(RZConf.TYPE.dingtalk), DDConf.TOP_DEPARTMENT));
- }
- // 同步除一级部门外所有部门用户
- ddClientImpl_contacts.listSubDepartmentId(getAccessToken(RZConf.TYPE.dingtalk), deptId).forEach(dept -> {
- List<String> ids = ddClientImpl_contacts.listDepartmentUserId(getAccessToken(RZConf.TYPE.dingtalk), dept);
- userIds.addAll(ids);
- syncOrganizationalStructure(dept, userIds);
- });
- }
- // 推送易快报
- private void pushTemplateByRecord(String userId, long start, long end, String checkDate) {
- // 获取用户Id [易快报corpId:钉钉userId]
- Map userInfo = ekbClient.getStaffInfo(getAccessToken(RZConf.TYPE.ekuaibao), "USERID", Arrays.asList(userId)).get(0);
- // 获取自定义模板Id [通过list接口查询到固定模板ID, 再实时换取单据版本ID]
- Map template = ekbClient.getTemplateIdById(getAccessToken(RZConf.TYPE.ekuaibao), Arrays.asList(RZConf.REQUEST_TEMPLATE_ID)).get(0);
- // 组装自定义模板数据 [手动创建一条记录查询比对模板字段]
- Map formData = UtilMap.map("submitterId, specificationId", RZConf.SUBMITTED_ID, template.get("id")); // 固定提交人, 查看权限
- formData.put("travelers", Arrays.asList(userInfo.get("id"))); // 同行人, 即打车人
- formData.put("expenseDepartment", userInfo.get("defaultDepartment"));
- Map travel = UtilMap.map("E_e9101f64b75c7b57a3c0_name, E_e9101f64b75c7b57a3c0_住宿地", "上海市/上海市区", "[{\"key\":\"858\",\"label\":\"上海市/上海市区\"}]"); // 固定打车行程地点
- travel.put("E_e9101f64b75c7b57a3c0_入住日期", start); // 上班打卡日期
- travel.put("E_e9101f64b75c7b57a3c0_离店日期", end); // 下班打卡日期
- formData.put("u_行程规划", Arrays.asList(UtilMap.map("dataLinkForm, dataLinkTemplateId", travel, "ID01nORyvKjEPJ"))); // 行程ID通过查询记录复制
- // 创建单据数据, 推送易快报审批作为打车依据
- EKBR ekbr = ekbClient.createFormInstance(getAccessToken(RZConf.TYPE.ekuaibao), true, false, formData, null);
- // 记录当天的推送结果
- rzEkbRecordDao.save(RzEkbRecordPo.builder()
- .userId(userId)
- .checkDate(checkDate).build());
- log.info("易快报推送结果, {}", ekbr.getFlow());
- }
- }
|