|
|
@@ -0,0 +1,223 @@
|
|
|
+package com.malk.kangcheng.service.Impl;
|
|
|
+
|
|
|
+import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.malk.kangcheng.service.YSEITaskService;
|
|
|
+import com.malk.server.common.VenR;
|
|
|
+import com.malk.service.dingtalk.DDClient;
|
|
|
+import com.malk.service.dingtalk.DDClient_Attendance;
|
|
|
+import com.malk.service.dingtalk.DDClient_Contacts;
|
|
|
+import com.malk.utils.UtilHttp;
|
|
|
+import com.malk.utils.UtilMap;
|
|
|
+import com.malk.utils.UtilToken;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 功能:
|
|
|
+ * 作者:hanxue
|
|
|
+ * 日期:2026/2/4 15:23
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class YSEITaskServiceImpl implements YSEITaskService {
|
|
|
+ @Autowired
|
|
|
+ private DDClient_Attendance ddClientAttendance;
|
|
|
+ @Autowired
|
|
|
+ private DDClient ddClient;
|
|
|
+ @Autowired
|
|
|
+ private DDClient_Contacts ddClientContacts;
|
|
|
+ @Value("${neocrm.client_id}")
|
|
|
+ private String clientId;
|
|
|
+ @Value("${neocrm.client_secret}")
|
|
|
+ private String clientSecret;
|
|
|
+ @Value("${neocrm.username}")
|
|
|
+ private String username;
|
|
|
+ @Value("${neocrm.password}")
|
|
|
+ private String password;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void syncAttendance() throws JsonProcessingException, UnsupportedEncodingException {
|
|
|
+ log.info("开始同步钉钉打卡记录");
|
|
|
+// 获取当天所有的售后打卡数据
|
|
|
+ Long [] attendanceList =getSYAttendance();
|
|
|
+// Long[] attendanceList = new Long[]{4256678656838946L};
|
|
|
+ String token =getSYToken();
|
|
|
+ Map header = new HashMap();
|
|
|
+ header.put("Authorization",token);
|
|
|
+// 遍历上传打卡信息
|
|
|
+ for(Long attendanceId:attendanceList){
|
|
|
+ String personAllAttInfo = UtilHttp.doGet("https://api-p05.xiaoshouyi.com/rest/data/v2.0/xobjects/serviceAttendance/"+attendanceId, header, (Map) null);
|
|
|
+ ObjectMapper rootMap = new ObjectMapper();
|
|
|
+ Map personAllAttInfoMap = rootMap.readValue(personAllAttInfo, Map.class);
|
|
|
+ Map personAttData = UtilMap.getMap(personAllAttInfoMap, "data");
|
|
|
+ String query = "select phone,name from user where id =" + UtilMap.getLong(personAttData, "ownerId");
|
|
|
+ String userInfo =UtilHttp.doGet( "https://api-p05.xiaoshouyi.com//rest/data/v2/query?q=" + query, header, (Map) null);
|
|
|
+ Map userInfoMap = rootMap.readValue(userInfo, Map.class);
|
|
|
+ Map userInfoResult = UtilMap.getMap(userInfoMap, "result");
|
|
|
+ List<Map> userInfoList = UtilMap.getList(userInfoResult, "records");
|
|
|
+ Map userdetail= userInfoList.get(0);
|
|
|
+// 同步钉钉打卡数据
|
|
|
+ String userId = UtilMap.getString(ddClientContacts.getUserInfoByMobile(ddClient.getAccessToken(),UtilMap.getString(userdetail, "phone")),"userid");
|
|
|
+ String addressCode ="address";
|
|
|
+ long departureTime =0;
|
|
|
+ long checkinTime =0;
|
|
|
+ long checkoutTime =0;
|
|
|
+ if(!UtilMap.isBlankString(personAttData,"departureTime")){
|
|
|
+ departureTime =UtilMap.getLong(personAttData,"departureTime");
|
|
|
+ String address=UtilMap.isBlankString(personAttData,"departureAddr")?"销售易签到":UtilMap.getString(personAttData, "departureAddr");
|
|
|
+ boolean uploaddepartureResult = ddClientAttendance.uploadAttendanceRecord(ddClient.getAccessToken(),userId,address,addressCode,null,departureTime);
|
|
|
+ }
|
|
|
+ if(!UtilMap.isBlankString(personAttData,"checkinTime")){
|
|
|
+ checkinTime =UtilMap.getLong(personAttData,"checkinTime");
|
|
|
+ String address=UtilMap.isBlankString(personAttData,"checkinAddr")?"销售易签到":UtilMap.getString(personAttData, "checkinAddr");
|
|
|
+ boolean uploadcheckinResult = ddClientAttendance.uploadAttendanceRecord(ddClient.getAccessToken(),userId,address,addressCode,null,checkinTime);
|
|
|
+ }
|
|
|
+ if(!UtilMap.isBlankString(personAttData,"checkoutTime")){
|
|
|
+ checkoutTime =UtilMap.getLong(personAttData,"checkoutTime");
|
|
|
+ String address=UtilMap.isBlankString(personAttData,"checkoutAddr")?"销售易签到":UtilMap.getString(personAttData, "checkoutAddr");
|
|
|
+ boolean uploadcheckoutResult = ddClientAttendance.uploadAttendanceRecord(ddClient.getAccessToken(),userId,address,addressCode,null,checkoutTime);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 获取现场服务考勤id列表
|
|
|
+ */
|
|
|
+
|
|
|
+ public Long[] getSYAttendance() throws JsonProcessingException, UnsupportedEncodingException {
|
|
|
+ String token =getSYToken();
|
|
|
+ Map header = new HashMap();
|
|
|
+ header.put("Authorization",token);
|
|
|
+ long startTime = LocalDate.now()
|
|
|
+ .atStartOfDay() // 设置为当天 00:00:00
|
|
|
+ .atZone(ZoneId.systemDefault()) // 转换为系统时区
|
|
|
+ .toInstant()
|
|
|
+ .toEpochMilli();
|
|
|
+ long endTime = LocalDate.now()
|
|
|
+ .atTime(23, 59, 59, 999_000_000) // 设置为当天 23:59:59.999
|
|
|
+ .atZone(ZoneId.systemDefault())
|
|
|
+ .toInstant()
|
|
|
+ .toEpochMilli();
|
|
|
+// 测试阶段先同步林成-13098772906- 3513810242771626和陈佩锋-13372629269- 3462626334399040 数据
|
|
|
+ String baseQuery = "select id from serviceAttendance where checkinTime>=" + startTime + " AND checkinTime<=" + endTime+"AND ownerId IN (3513810242771626, 3462626334399040)";
|
|
|
+ ObjectMapper rootMap = new ObjectMapper();
|
|
|
+ ArrayList<Map> allRecordsList = new ArrayList<>(); // 用于存储所有结果
|
|
|
+ int pageSize = 100; // 接口允许的最大条数,建议设为100
|
|
|
+ int offset = 0;
|
|
|
+ int totalSize = -1; // 初始化为-1,表示未知
|
|
|
+ int fetchedCount = 0; // 当前已获取的总数
|
|
|
+ log.info("开始分页拉取打卡记录...");
|
|
|
+ do {
|
|
|
+ String qs = baseQuery + " order by id asc limit " + offset + "," + pageSize;
|
|
|
+ // URL编码可能需要处理
|
|
|
+ String fullUrl = "https://api-p05.xiaoshouyi.com//rest/data/v2/query?q=" +qs;
|
|
|
+ String attendanceRecord = UtilHttp.doGet(fullUrl, header, (Map) null);
|
|
|
+ if (attendanceRecord == null || attendanceRecord.isEmpty()) {
|
|
|
+ log.error("接口返回为空,请检查程序错误");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ Map attendanceMap = rootMap.readValue(attendanceRecord, Map.class);
|
|
|
+ Map attendanceResult = UtilMap.getMap(attendanceMap, "result");
|
|
|
+ if (attendanceResult == null) {
|
|
|
+ log.error("返回结果中缺少result字段");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // 第一次请求时获取总条数
|
|
|
+ if (totalSize == -1) {
|
|
|
+ totalSize = UtilMap.getInt(attendanceResult, "totalSize");
|
|
|
+ log.info("打卡记录总数(totalSize): {}", totalSize);
|
|
|
+ if (totalSize == 0) {
|
|
|
+ break; // 没有数据直接退出
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 获取当前页记录
|
|
|
+ List<Map> records = UtilMap.getList(attendanceResult, "records");
|
|
|
+ if (records == null || records.isEmpty()) {
|
|
|
+ log.warn("当前页未获取到数据,可能已达末尾,终止拉取。offset: {}, totalSize: {}", offset, totalSize);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // 将当前页数据加入总列表
|
|
|
+ allRecordsList.addAll(records);
|
|
|
+
|
|
|
+ // 更新计数
|
|
|
+ fetchedCount += records.size();
|
|
|
+ offset += pageSize; // 移动偏移量
|
|
|
+ log.info("已拉取: {}/{}, 当前页大小: {}", fetchedCount, totalSize, records.size());
|
|
|
+ } while (fetchedCount < totalSize);
|
|
|
+ log.info("分页拉取完成,最终获取记录数: {}", allRecordsList.size());
|
|
|
+// 提取ID列表
|
|
|
+ if (!allRecordsList.isEmpty()) {
|
|
|
+ Long[] recordsIdList = allRecordsList.stream()
|
|
|
+ .map(map -> {
|
|
|
+ Object idObj = map.get("id");
|
|
|
+ return idObj instanceof Long ? (Long) idObj : Long.valueOf(idObj.toString());
|
|
|
+ })
|
|
|
+ .toArray(Long[]::new);
|
|
|
+ log.info("最终打卡记录ID总数:{}", recordsIdList.length);
|
|
|
+ return recordsIdList;
|
|
|
+ }else{
|
|
|
+ log.info("最终打卡记录ID总数:{}", 0);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 销售易获取token
|
|
|
+ */
|
|
|
+ public String getSYToken() throws JsonProcessingException {
|
|
|
+ String accessToken = UtilToken.get("invalid-token");
|
|
|
+ if (StringUtils.isNotBlank(accessToken)) return accessToken;
|
|
|
+ Map header = new HashMap();
|
|
|
+ header.put("Content-Type","application/x‐www‐form‐urlencoded");
|
|
|
+ Map param = new HashMap();
|
|
|
+ param.put("grant_type","password");
|
|
|
+ param.put("client_id",clientId);
|
|
|
+ param.put("client_secret",clientSecret);
|
|
|
+ param.put("username",username);
|
|
|
+ param.put("password",password);
|
|
|
+ String resultParam = UtilHttp.doPost("https://login.xiaoshouyi.com/auc/oauth2/token", header, param, (Map) null);
|
|
|
+ log.info("获取销售易token结果:{}",resultParam);
|
|
|
+ ObjectMapper rootMap = new ObjectMapper();
|
|
|
+ Map resultMap = rootMap.readValue(resultParam, Map.class);
|
|
|
+ accessToken ="Bearer "+UtilMap.getString(resultMap,"access_token");
|
|
|
+ UtilToken.put("invalid-token", accessToken, 86399 * 1000L);
|
|
|
+ return accessToken;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 同步钉钉打卡记录
|
|
|
+ */
|
|
|
+// public boolean syncDDRecord(Map param) throws JsonProcessingException {
|
|
|
+//// 根据手机号获取userId
|
|
|
+// String userId = UtilMap.getString(ddClientContacts.getUserInfoByMobile(ddClient.getAccessToken(),param.get("mobile").toString()),"userId");
|
|
|
+// String address ="";
|
|
|
+// String addressCode ="";
|
|
|
+// long departureTime =UtilMap.getLong(param,"departureTime");
|
|
|
+// long checkinTime =UtilMap.getLong(param,"checkinTime");
|
|
|
+// long checkoutTime =UtilMap.getLong(param,"checkoutTime");
|
|
|
+//// 上传打卡记录
|
|
|
+// boolean uploaddepartureResult = ddClientAttendance.uploadAttendanceRecord(ddClient.getAccessToken(),userId,address,addressCode,null,departureTime);
|
|
|
+// boolean uploadcheckinResult = ddClientAttendance.uploadAttendanceRecord(ddClient.getAccessToken(),userId,address,addressCode,null,checkinTime);
|
|
|
+// boolean uploadcheckoutResult = ddClientAttendance.uploadAttendanceRecord(ddClient.getAccessToken(),userId,address,addressCode,null,checkoutTime);
|
|
|
+// return uploaddepartureResult&&uploadcheckinResult&&uploadcheckoutResult;
|
|
|
+// }
|
|
|
+}
|