|
|
@ -1,6 +1,7 @@
|
|
|
|
package com.ruoyi.quartz.task.CJT;
|
|
|
|
package com.ruoyi.quartz.task.CJT;
|
|
|
|
|
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
|
|
|
import com.lark.oapi.core.utils.Lists;
|
|
|
|
import com.lark.oapi.service.bitable.v1.model.CreateAppTableRecordRespBody;
|
|
|
|
import com.lark.oapi.service.bitable.v1.model.CreateAppTableRecordRespBody;
|
|
|
|
import com.ruoyi.common.constant.RedisConstants;
|
|
|
|
import com.ruoyi.common.constant.RedisConstants;
|
|
|
|
import com.ruoyi.common.core.redis.RedisCache;
|
|
|
|
import com.ruoyi.common.core.redis.RedisCache;
|
|
|
@ -22,7 +23,9 @@ import org.springframework.beans.factory.annotation.Value;
|
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
|
|
|
import java.time.ZoneId;
|
|
|
|
import java.util.*;
|
|
|
|
import java.util.*;
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
import java.util.stream.Collectors;
|
|
|
@ -50,6 +53,8 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
private LarkTableHelper larkTableHelper;
|
|
|
|
private LarkTableHelper larkTableHelper;
|
|
|
|
@Autowired
|
|
|
|
@Autowired
|
|
|
|
private LarkRobotHelper larkRobotHelper;
|
|
|
|
private LarkRobotHelper larkRobotHelper;
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
|
|
|
private CJTCreateLarkTableJob cjtCreateLarkTableJob;
|
|
|
|
@Value("${lark.robot.group}")
|
|
|
|
@Value("${lark.robot.group}")
|
|
|
|
private String ROBOT_GROUP;
|
|
|
|
private String ROBOT_GROUP;
|
|
|
|
@Value("${sync.flag}")
|
|
|
|
@Value("${sync.flag}")
|
|
|
@ -75,14 +80,45 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private static final String REQUEST_GENERATE_TOKEN_PATH = REQUEST_ROOT_PATH + "/v1/common/auth/selfBuiltApp/generateToken";
|
|
|
|
private static final String REQUEST_GENERATE_TOKEN_PATH = REQUEST_ROOT_PATH + "/v1/common/auth/selfBuiltApp/generateToken";
|
|
|
|
|
|
|
|
|
|
|
|
private CJTJobContext initContext(String queryFromTime,String queryToTime,LocalDateTime now,String cjt){
|
|
|
|
private Boolean asynchronousCheck(LocalDateTime now, String cjt) {
|
|
|
|
|
|
|
|
int hour = now.getHour();
|
|
|
|
|
|
|
|
if (hour != 1) {
|
|
|
|
|
|
|
|
return Boolean.FALSE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//目前只给畅捷通账号二加工单开补偿劝降
|
|
|
|
|
|
|
|
if (AppType.SYNC_CJT_MANUFACTURE_ORDER_DATA_TO_MULTI_TABLE.getCode().equals(syncLarkAppType().getCode())
|
|
|
|
|
|
|
|
&& CjtAccountEnum.TWO.getCode().equals(cjt)){
|
|
|
|
|
|
|
|
String asynchronous = getAsynchronousKey(cjt);
|
|
|
|
|
|
|
|
Object cacheObject = redisCache.getCacheObject(asynchronous);
|
|
|
|
|
|
|
|
if (cacheObject != null) {
|
|
|
|
|
|
|
|
return Boolean.FALSE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
redisCache.setCacheObject(asynchronous, asynchronous, 2, TimeUnit.HOURS);
|
|
|
|
|
|
|
|
return Boolean.TRUE;
|
|
|
|
|
|
|
|
}else {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getAsynchronousKey(String cjt){
|
|
|
|
|
|
|
|
return String.format("%s:%s:%s", RedisConstants.CJT_ASYNCHRONOUS, syncLarkAppType().getCode(), cjt);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private CJTJobContext initContext(String queryFromTime, String queryToTime, LocalDateTime now, String cjt) {
|
|
|
|
CJTJobContext context = new CJTJobContext();
|
|
|
|
CJTJobContext context = new CJTJobContext();
|
|
|
|
if (StringUtils.isEmpty(queryFromTime)){
|
|
|
|
Boolean asynchronous = asynchronousCheck(now, cjt);
|
|
|
|
queryFromTime = DateUtils.ldt2str(now.minusMinutes(REDUCE_MINUTES), DateUtils.YYYY_MM_DD_HH_MM_SS);
|
|
|
|
context.setAsynchronous(asynchronous);
|
|
|
|
|
|
|
|
LocalDate localDate = LocalDate.now().minusDays(1L);
|
|
|
|
|
|
|
|
if (StringUtils.isEmpty(queryFromTime)) {
|
|
|
|
|
|
|
|
queryFromTime = asynchronous
|
|
|
|
|
|
|
|
? DateUtils.startOfDate(localDate)
|
|
|
|
|
|
|
|
: DateUtils.ldt2str(now.minusMinutes(REDUCE_MINUTES), DateUtils.YYYY_MM_DD_HH_MM_SS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
context.setQueryFromTime(queryFromTime);
|
|
|
|
context.setQueryFromTime(queryFromTime);
|
|
|
|
if (StringUtils.isEmpty(queryToTime)){
|
|
|
|
if (StringUtils.isEmpty(queryToTime)) {
|
|
|
|
queryToTime = DateUtils.ldt2str(now, DateUtils.YYYY_MM_DD_HH_MM_SS);
|
|
|
|
queryToTime = asynchronous
|
|
|
|
|
|
|
|
? DateUtils.endOfDate(localDate)
|
|
|
|
|
|
|
|
: DateUtils.ldt2str(now, DateUtils.YYYY_MM_DD_HH_MM_SS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
context.setQueryToTime(queryToTime);
|
|
|
|
context.setQueryToTime(queryToTime);
|
|
|
|
context.setCjt(cjt);
|
|
|
|
context.setCjt(cjt);
|
|
|
@ -93,7 +129,7 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
if (Boolean.FALSE.equals(syncFlag)) {
|
|
|
|
if (Boolean.FALSE.equals(syncFlag)) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (request == null){
|
|
|
|
if (request == null) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CJTJobContext context = new CJTJobContext();
|
|
|
|
CJTJobContext context = new CJTJobContext();
|
|
|
@ -101,7 +137,7 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
context.setQueryToTime(request.getQueryTo());
|
|
|
|
context.setQueryToTime(request.getQueryTo());
|
|
|
|
context.setCjt(request.getCjt());
|
|
|
|
context.setCjt(request.getCjt());
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
log.info("===================== {} {} retry strat ======================",this.getClassName(),context.getQueryToTime());
|
|
|
|
log.info("===================== {} {} retry strat ======================", this.getClassName(), context.getQueryToTime());
|
|
|
|
//初始化飞书信息及相关配置
|
|
|
|
//初始化飞书信息及相关配置
|
|
|
|
initLarkInfo(context);
|
|
|
|
initLarkInfo(context);
|
|
|
|
//重置ticket
|
|
|
|
//重置ticket
|
|
|
@ -110,68 +146,110 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
sync(context);
|
|
|
|
sync(context);
|
|
|
|
} catch (Exception e) {
|
|
|
|
} catch (Exception e) {
|
|
|
|
log.error("{} ", getClassName(), e);
|
|
|
|
log.error("{} ", getClassName(), e);
|
|
|
|
if (request.getCount() == 2){
|
|
|
|
if (request.getCount() == 2) {
|
|
|
|
larkRobotHelper.sendMessageByBot(ROBOT_GROUP, buildRobotErrorCountMessage(e,request));
|
|
|
|
larkRobotHelper.sendMessageByBot(ROBOT_GROUP, buildRobotErrorCountMessage(e, request));
|
|
|
|
}else {
|
|
|
|
} else {
|
|
|
|
request.addCount();
|
|
|
|
request.addCount();
|
|
|
|
redisCache.rightPush(getRetryKey(request.getCjt()),request);
|
|
|
|
redisCache.rightPush(getRetryKey(request.getCjt()), request);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}finally {
|
|
|
|
} finally {
|
|
|
|
log.info("===================== {} {} retry end ======================",this.getClassName(),context.getQueryToTime());
|
|
|
|
log.info("===================== {} {} retry end ======================", this.getClassName(), context.getQueryToTime());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void executeSync(String cjt,String queryFromTime,String queryToTime) {
|
|
|
|
public void executeSync(String cjt, String queryFromTime, String queryToTime) {
|
|
|
|
if (Boolean.FALSE.equals(syncFlag)) {
|
|
|
|
if (Boolean.FALSE.equals(syncFlag)) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LocalDateTime now = LocalDateTime.now();
|
|
|
|
LocalDateTime now = LocalDateTime.now();
|
|
|
|
CJTJobContext context = initContext(queryFromTime,queryToTime,now,cjt);
|
|
|
|
CJTJobContext context = initContext(queryFromTime, queryToTime, now, cjt);
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
log.info("===================== {} strat ======================",this.getClassName());
|
|
|
|
log.info("===================== {} strat ======================", this.getClassName());
|
|
|
|
//初始化飞书信息及相关配置
|
|
|
|
//初始化飞书信息及相关配置
|
|
|
|
initLarkInfo(context);
|
|
|
|
initLarkInfo(context);
|
|
|
|
|
|
|
|
if (Boolean.TRUE.equals(context.getAsynchronous())) {
|
|
|
|
|
|
|
|
Boolean deleteSuccess = handleRepeatData(now, cjt, context);
|
|
|
|
|
|
|
|
if (!deleteSuccess){
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
//重置ticket
|
|
|
|
//重置ticket
|
|
|
|
resetTicket(context);
|
|
|
|
resetTicket(context);
|
|
|
|
//执行分页同步
|
|
|
|
//执行分页同步
|
|
|
|
sync(context);
|
|
|
|
sync(context);
|
|
|
|
} catch (Exception e) {
|
|
|
|
} catch (Exception e) {
|
|
|
|
log.error("{} 执行失败", getClassName(), e);
|
|
|
|
log.error("{} 执行失败", getClassName(), e);
|
|
|
|
CJTRetryRequest request = new CJTRetryRequest(now,1,cjt);
|
|
|
|
if (Boolean.TRUE.equals(context.getAsynchronous())) {
|
|
|
|
redisCache.rightPush(getRetryKey(cjt),request);
|
|
|
|
String asynchronous = getAsynchronousKey(cjt);
|
|
|
|
}finally {
|
|
|
|
redisCache.deleteObject(asynchronous);
|
|
|
|
log.info("===================== {} end ======================",this.getClassName());
|
|
|
|
}else {
|
|
|
|
|
|
|
|
CJTRetryRequest request = new CJTRetryRequest(now, 1, cjt);
|
|
|
|
|
|
|
|
redisCache.rightPush(getRetryKey(cjt), request);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
log.info("===================== {} end ======================", this.getClassName());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public String getRetryKey(String cjt){
|
|
|
|
private Boolean handleRepeatData(LocalDateTime now, String cjt, CJTJobContext context) {
|
|
|
|
return String.format(RETRY_KEY,cjt, syncLarkAppType().getCode());
|
|
|
|
CjtAccountEnum accountEnum = CjtAccountEnum.getByCode(cjt);
|
|
|
|
|
|
|
|
if (accountEnum == null) {
|
|
|
|
|
|
|
|
return Boolean.FALSE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
LarkCompanyRelation companyRelation = context.getCompanyRelation();
|
|
|
|
|
|
|
|
LarkTableRelation tableRelation = context.getTableRelation();
|
|
|
|
|
|
|
|
LarkTableRequest request = new LarkTableRequest(companyRelation.getAppId(),companyRelation.getSecret(),tableRelation.getToAppToken(),tableRelation.getToTableId());
|
|
|
|
|
|
|
|
String date = DateUtils.ldt2str(now.minusDays(1L), DateUtils.YYYY_MM_DD);
|
|
|
|
|
|
|
|
List<String> recordList = erpLarkRelationMapper.queryWaitDeleteRecordList(date, getRequestUrl(), cjt);
|
|
|
|
|
|
|
|
List<String> waitDeleteList = new ArrayList<>();
|
|
|
|
|
|
|
|
for (String record : recordList) {
|
|
|
|
|
|
|
|
waitDeleteList.add(record);
|
|
|
|
|
|
|
|
if (waitDeleteList.size() == 500){
|
|
|
|
|
|
|
|
request.setRecords(waitDeleteList.toArray(new String[0]));
|
|
|
|
|
|
|
|
larkTableHelper.deleteTableRecordBatch(request);
|
|
|
|
|
|
|
|
waitDeleteList = new ArrayList<>();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!CollectionUtils.isEmpty(waitDeleteList)){
|
|
|
|
|
|
|
|
request.setRecords(waitDeleteList.toArray(new String[0]));
|
|
|
|
|
|
|
|
larkTableHelper.deleteTableRecordBatch(request);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
erpLarkRelationMapper.deleteRecordList(date, getRequestUrl(), cjt);
|
|
|
|
|
|
|
|
}catch (Exception e){
|
|
|
|
|
|
|
|
return Boolean.FALSE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return Boolean.TRUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getRetryKey(String cjt) {
|
|
|
|
|
|
|
|
return String.format(RETRY_KEY, cjt, syncLarkAppType().getCode());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected CjtAccountEnum cjtAccount(String cjt){
|
|
|
|
protected CjtAccountEnum cjtAccount(String cjt) {
|
|
|
|
return CjtAccountEnum.valueOf(cjt);
|
|
|
|
return CjtAccountEnum.valueOf(cjt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private String buildRobotErrorCountMessage(Exception e,CJTRetryRequest request){
|
|
|
|
private String buildRobotErrorCountMessage(Exception e, CJTRetryRequest request) {
|
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
|
jsonObject.put("同步任务",getClassName());
|
|
|
|
jsonObject.put("同步任务", getClassName());
|
|
|
|
jsonObject.put("重试失败",request.getCount());
|
|
|
|
jsonObject.put("重试失败", request.getCount());
|
|
|
|
jsonObject.put("重试开始时间",request.getQueryFrom(REDUCE_MINUTES));
|
|
|
|
jsonObject.put("重试开始时间", request.getQueryFrom(REDUCE_MINUTES));
|
|
|
|
jsonObject.put("重试结束时间",request.getQueryTo());
|
|
|
|
jsonObject.put("重试结束时间", request.getQueryTo());
|
|
|
|
String errorMessage = e.getMessage();
|
|
|
|
String errorMessage = e.getMessage();
|
|
|
|
if (org.apache.commons.lang3.StringUtils.isNotBlank(errorMessage)){
|
|
|
|
if (org.apache.commons.lang3.StringUtils.isNotBlank(errorMessage)) {
|
|
|
|
errorMessage = errorMessage.replaceAll("\\\\","");
|
|
|
|
errorMessage = errorMessage.replaceAll("\\\\", "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
jsonObject.put("异常信息", errorMessage);
|
|
|
|
jsonObject.put("异常信息", errorMessage);
|
|
|
|
return jsonObject.toJSONString();
|
|
|
|
return jsonObject.toJSONString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private String buildRobotErrorMessage(Exception e){
|
|
|
|
private String buildRobotErrorMessage(Exception e) {
|
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
|
jsonObject.put("同步任务(待重试)",getClassName());
|
|
|
|
jsonObject.put("同步任务(待重试)", getClassName());
|
|
|
|
String errorMessage = e.getMessage();
|
|
|
|
String errorMessage = e.getMessage();
|
|
|
|
if (org.apache.commons.lang3.StringUtils.isNotBlank(errorMessage)){
|
|
|
|
if (org.apache.commons.lang3.StringUtils.isNotBlank(errorMessage)) {
|
|
|
|
errorMessage = errorMessage.replaceAll("\\\\","");
|
|
|
|
errorMessage = errorMessage.replaceAll("\\\\", "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
jsonObject.put("异常信息", errorMessage);
|
|
|
|
jsonObject.put("异常信息", errorMessage);
|
|
|
|
return jsonObject.toJSONString();
|
|
|
|
return jsonObject.toJSONString();
|
|
|
@ -181,6 +259,7 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
* 获取同步多维表格类型配置
|
|
|
|
* 获取同步多维表格类型配置
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
protected abstract AppType syncLarkAppType();
|
|
|
|
protected abstract AppType syncLarkAppType();
|
|
|
|
|
|
|
|
|
|
|
|
protected abstract TableRelationTypeEnum syncLarkType();
|
|
|
|
protected abstract TableRelationTypeEnum syncLarkType();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -197,38 +276,40 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
* 获取待查询的字段
|
|
|
|
* 获取待查询的字段
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
protected abstract List<String> getQueryFields();
|
|
|
|
protected abstract List<String> getQueryFields();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* 获取待查询的字段与飞书的映射关系
|
|
|
|
* 获取待查询的字段与飞书的映射关系
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
protected abstract Map<String,CJTSyncTypeRelation> getQueryFieldsMap(String cjt);
|
|
|
|
protected abstract Map<String, CJTSyncTypeRelation> getQueryFieldsMap(String cjt);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* 获取查询条件
|
|
|
|
* 获取查询条件
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
protected abstract String getQueryKey();
|
|
|
|
protected abstract String getQueryKey();
|
|
|
|
protected JSONObject getQueryCondition(CJTJobContext context){
|
|
|
|
|
|
|
|
|
|
|
|
protected JSONObject getQueryCondition(CJTJobContext context) {
|
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
|
LocalDateTime now = LocalDateTime.now();
|
|
|
|
LocalDateTime now = LocalDateTime.now();
|
|
|
|
String startTime = context.getQueryFromTime();
|
|
|
|
String startTime = context.getQueryFromTime();
|
|
|
|
if (StringUtils.isEmpty(startTime)){
|
|
|
|
if (StringUtils.isEmpty(startTime)) {
|
|
|
|
startTime = DateUtils.ldt2str(now.minusMinutes(REDUCE_MINUTES), DateUtils.YYYY_MM_DD_HH_MM_SS);
|
|
|
|
startTime = DateUtils.ldt2str(now.minusMinutes(REDUCE_MINUTES), DateUtils.YYYY_MM_DD_HH_MM_SS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
String endTime = context.getQueryToTime();
|
|
|
|
String endTime = context.getQueryToTime();
|
|
|
|
if (StringUtils.isEmpty(endTime)){
|
|
|
|
if (StringUtils.isEmpty(endTime)) {
|
|
|
|
endTime = DateUtils.ldt2str(now, DateUtils.YYYY_MM_DD_HH_MM_SS);
|
|
|
|
endTime = DateUtils.ldt2str(now, DateUtils.YYYY_MM_DD_HH_MM_SS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Map<String, String> startTimeMap = new HashMap<>();
|
|
|
|
Map<String, String> startTimeMap = new HashMap<>();
|
|
|
|
startTimeMap.put("text",startTime);
|
|
|
|
startTimeMap.put("text", startTime);
|
|
|
|
startTimeMap.put("value",startTime);
|
|
|
|
startTimeMap.put("value", startTime);
|
|
|
|
Map<String, String> endTimeMap = new HashMap<>();
|
|
|
|
Map<String, String> endTimeMap = new HashMap<>();
|
|
|
|
endTimeMap.put("text",endTime);
|
|
|
|
endTimeMap.put("text", endTime);
|
|
|
|
endTimeMap.put("value",endTime);
|
|
|
|
endTimeMap.put("value", endTime);
|
|
|
|
List<Map<String, String>> timeRange = Arrays.asList(startTimeMap, endTimeMap);
|
|
|
|
List<Map<String, String>> timeRange = Arrays.asList(startTimeMap, endTimeMap);
|
|
|
|
String queryKey = String.format("%s.AuditedTime",getQueryKey());
|
|
|
|
String queryKey = String.format("%s.AuditedTime", getQueryKey());
|
|
|
|
if (AppType.SYNC_CJT_SALE_DISPATCH_DATA_TO_MULTI_TABLE.equals(syncLarkAppType())){
|
|
|
|
if (AppType.SYNC_CJT_SALE_DISPATCH_DATA_TO_MULTI_TABLE.equals(syncLarkAppType())) {
|
|
|
|
queryKey = String.format("%s.createdtime",getQueryKey());
|
|
|
|
queryKey = String.format("%s.createdtime", getQueryKey());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
jsonObject.put(queryKey,timeRange);
|
|
|
|
jsonObject.put(queryKey, timeRange);
|
|
|
|
|
|
|
|
|
|
|
|
return jsonObject;
|
|
|
|
return jsonObject;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -238,7 +319,9 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
protected String getClassName() {
|
|
|
|
protected String getClassName() {
|
|
|
|
return this.getClass().getSimpleName();
|
|
|
|
return this.getClass().getSimpleName();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* 同步数据
|
|
|
|
* 同步数据
|
|
|
@ -270,13 +353,13 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
CJTResponseBodyDetail response = request(cjtRequest);
|
|
|
|
CJTResponseBodyDetail response = request(cjtRequest);
|
|
|
|
//实际返回数据
|
|
|
|
//实际返回数据
|
|
|
|
rows = response.getRows();
|
|
|
|
rows = response.getRows();
|
|
|
|
if (!CollectionUtils.isEmpty(rows)){
|
|
|
|
if (!CollectionUtils.isEmpty(rows)) {
|
|
|
|
Map<String, String> existKeyMap = getExistKeyMap(cjtRequest,response.getColumns(), rows,context.getCjt());
|
|
|
|
Map<String, String> existKeyMap = getExistKeyMap(cjtRequest, response.getColumns(), rows, context.getCjt());
|
|
|
|
//批量同步飞书
|
|
|
|
//批量同步飞书
|
|
|
|
List<String> errorCodeList = syncLarkBatch(response.getColumns(), rows, existKeyMap,addRecordRequest,context.getCjt());
|
|
|
|
List<String> errorCodeList = syncLarkBatch(response.getColumns(), rows, existKeyMap, addRecordRequest, context.getCjt(),context.getAsynchronous());
|
|
|
|
if (!CollectionUtils.isEmpty(errorCodeList)){
|
|
|
|
if (!CollectionUtils.isEmpty(errorCodeList)) {
|
|
|
|
String errorKey = String.join(",", errorCodeList);
|
|
|
|
String errorKey = String.join(",", errorCodeList);
|
|
|
|
throw new RuntimeException(String.format("存在同步失败的记录 %s",errorKey));
|
|
|
|
throw new RuntimeException(String.format("存在同步失败的记录 %s", errorKey));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
} catch (Exception e) {
|
|
|
@ -285,13 +368,13 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
page++;
|
|
|
|
page++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}while (!CollectionUtils.isEmpty(rows));
|
|
|
|
} while (!CollectionUtils.isEmpty(rows));
|
|
|
|
if (!StringUtils.isEmpty(errorMessage)){
|
|
|
|
if (!StringUtils.isEmpty(errorMessage)) {
|
|
|
|
throw new RuntimeException(errorMessage);
|
|
|
|
throw new RuntimeException(errorMessage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private List<String> getUniqueKey(List<String> keyList,List<List<String>> rows,String cjt) {
|
|
|
|
private List<String> getUniqueKey(List<String> keyList, List<List<String>> rows, String cjt) {
|
|
|
|
//组成唯一键的集合
|
|
|
|
//组成唯一键的集合
|
|
|
|
List<String> uniqueFields = getUniqueFields(cjt);
|
|
|
|
List<String> uniqueFields = getUniqueFields(cjt);
|
|
|
|
List<String> result = new ArrayList<>();
|
|
|
|
List<String> result = new ArrayList<>();
|
|
|
@ -299,11 +382,11 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
for (List<String> row : rows) {
|
|
|
|
for (List<String> row : rows) {
|
|
|
|
List<String> midList = new ArrayList<>();
|
|
|
|
List<String> midList = new ArrayList<>();
|
|
|
|
for (int i = 0; i < row.size(); i++) {
|
|
|
|
for (int i = 0; i < row.size(); i++) {
|
|
|
|
if (uniqueFields.contains(keyList.get(i))){
|
|
|
|
if (uniqueFields.contains(keyList.get(i))) {
|
|
|
|
midList.add(row.get(i));
|
|
|
|
midList.add(row.get(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
String uniqueKey = String.join("_", midList).toUpperCase();
|
|
|
|
String uniqueKey = String.join("_", midList).toUpperCase();
|
|
|
|
result.add(uniqueKey);
|
|
|
|
result.add(uniqueKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -313,30 +396,30 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* 使用唯一key区分创建或更新
|
|
|
|
* 使用唯一key区分创建或更新
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
protected Map<String, String> getExistKeyMap(CJTRequest req,List<String> keyList, List<List<String>> rows,String cjt) {
|
|
|
|
protected Map<String, String> getExistKeyMap(CJTRequest req, List<String> keyList, List<List<String>> rows, String cjt) {
|
|
|
|
if (CollectionUtils.isEmpty(rows)) {
|
|
|
|
if (CollectionUtils.isEmpty(rows)) {
|
|
|
|
return new HashMap<>();
|
|
|
|
return new HashMap<>();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
List<String> uniqueKeyList = getUniqueKey(keyList,rows,cjt);
|
|
|
|
List<String> uniqueKeyList = getUniqueKey(keyList, rows, cjt);
|
|
|
|
if (CollectionUtils.isEmpty(uniqueKeyList)) {
|
|
|
|
if (CollectionUtils.isEmpty(uniqueKeyList)) {
|
|
|
|
return new HashMap<>();
|
|
|
|
return new HashMap<>();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return erpLarkRelationMapper.queryListByKeyListAndRemark(uniqueKeyList, getRequestUrl(),cjt)
|
|
|
|
return erpLarkRelationMapper.queryListByKeyListAndRemark(uniqueKeyList, getRequestUrl(), cjt)
|
|
|
|
.stream().collect(Collectors.toMap(ErpLarkRelation::getKey, ErpLarkRelation::getLarkKey, (k1, k2) -> k1));
|
|
|
|
.stream().collect(Collectors.toMap(ErpLarkRelation::getKey, ErpLarkRelation::getLarkKey, (k1, k2) -> k1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Object changeValueType(String value,CJTSyncTypeRelation cjtSyncTypeRelation){
|
|
|
|
private Object changeValueType(String value, CJTSyncTypeRelation cjtSyncTypeRelation) {
|
|
|
|
TableFieldTypeEnum type = cjtSyncTypeRelation.getType();
|
|
|
|
TableFieldTypeEnum type = cjtSyncTypeRelation.getType();
|
|
|
|
if (org.apache.commons.lang3.StringUtils.isBlank(value) || type == null){
|
|
|
|
if (org.apache.commons.lang3.StringUtils.isBlank(value) || type == null) {
|
|
|
|
return value;
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (type){
|
|
|
|
switch (type) {
|
|
|
|
case NUMBER:
|
|
|
|
case NUMBER:
|
|
|
|
return Double.valueOf(value);
|
|
|
|
return Double.valueOf(value);
|
|
|
|
case DATE:
|
|
|
|
case DATE:
|
|
|
|
LocalDateTime localDateTime = DateUtils.str2ldt(value, cjtSyncTypeRelation.getPattern());
|
|
|
|
LocalDateTime localDateTime = DateUtils.str2ldt(value, cjtSyncTypeRelation.getPattern());
|
|
|
|
return DateUtils.ldt2Long(localDateTime);
|
|
|
|
return DateUtils.ldt2Long(localDateTime);
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
return value;
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -345,7 +428,8 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* 执行字段映射
|
|
|
|
* 执行字段映射
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
protected List<String> syncLarkBatch(List<String> keyList,List<List<String>> rows,Map<String, String> existKeyMap,LarkTableRequest addRecordRequest,String cjt){
|
|
|
|
protected List<String> syncLarkBatch(List<String> keyList, List<List<String>> rows, Map<String, String> existKeyMap
|
|
|
|
|
|
|
|
, LarkTableRequest addRecordRequest, String cjt,Boolean asynchronous) {
|
|
|
|
List<ErpLarkRelation> relationList = new ArrayList<>();
|
|
|
|
List<ErpLarkRelation> relationList = new ArrayList<>();
|
|
|
|
//查询字段与飞书字段的对应关系
|
|
|
|
//查询字段与飞书字段的对应关系
|
|
|
|
Map<String, CJTSyncTypeRelation> queryFieldsMap = getQueryFieldsMap(cjt);
|
|
|
|
Map<String, CJTSyncTypeRelation> queryFieldsMap = getQueryFieldsMap(cjt);
|
|
|
@ -353,52 +437,58 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
List<String> uniqueFields = getUniqueFields(cjt);
|
|
|
|
List<String> uniqueFields = getUniqueFields(cjt);
|
|
|
|
//错误唯一键
|
|
|
|
//错误唯一键
|
|
|
|
List<String> errorKey = new ArrayList<>();
|
|
|
|
List<String> errorKey = new ArrayList<>();
|
|
|
|
|
|
|
|
//判断当前查询条件内是否存在重复数据
|
|
|
|
|
|
|
|
Map<String, Integer> repeatMap = new HashMap<>();
|
|
|
|
for (List<String> row : rows) {
|
|
|
|
for (List<String> row : rows) {
|
|
|
|
String uniqueKey = null;
|
|
|
|
String uniqueKey = null;
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
Map<String,Object> body = new HashMap<>();
|
|
|
|
Map<String, Object> body = new HashMap<>();
|
|
|
|
List<String> uniqueKeyList = new ArrayList<>();
|
|
|
|
List<String> uniqueKeyList = new ArrayList<>();
|
|
|
|
for (int i = 0; i < row.size(); i++) {
|
|
|
|
for (int i = 0; i < row.size(); i++) {
|
|
|
|
CJTSyncTypeRelation cjtSyncTypeRelation = queryFieldsMap.get(keyList.get(i));
|
|
|
|
CJTSyncTypeRelation cjtSyncTypeRelation = queryFieldsMap.get(keyList.get(i));
|
|
|
|
if (cjtSyncTypeRelation == null){
|
|
|
|
if (cjtSyncTypeRelation == null) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
String larkLabel = cjtSyncTypeRelation.getLarkFileName();
|
|
|
|
String larkLabel = cjtSyncTypeRelation.getLarkFileName();
|
|
|
|
String value = row.get(i);
|
|
|
|
String value = row.get(i);
|
|
|
|
if (uniqueFields.contains(keyList.get(i))){
|
|
|
|
if (uniqueFields.contains(keyList.get(i))) {
|
|
|
|
uniqueKeyList.add(value);
|
|
|
|
uniqueKeyList.add(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
body.put(larkLabel,this.changeValueType(value,cjtSyncTypeRelation));
|
|
|
|
body.put(larkLabel, this.changeValueType(value, cjtSyncTypeRelation));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uniqueKey = String.join("_", uniqueKeyList).toUpperCase();
|
|
|
|
uniqueKey = String.join("_", uniqueKeyList).toUpperCase();
|
|
|
|
|
|
|
|
if (repeatMap.containsKey(uniqueKey)) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
repeatMap.put(uniqueKey, 1);
|
|
|
|
String larkKey = existKeyMap.get(uniqueKey);
|
|
|
|
String larkKey = existKeyMap.get(uniqueKey);
|
|
|
|
addRecordRequest.setBody(body);
|
|
|
|
addRecordRequest.setBody(body);
|
|
|
|
if (StringUtils.isEmpty(larkKey)){
|
|
|
|
if (StringUtils.isEmpty(larkKey)) {
|
|
|
|
//在飞书创建一行,并根据创建返回的行id在本地保留一条映射纪律
|
|
|
|
//在飞书创建一行,并根据创建返回的行id在本地保留一条映射纪律
|
|
|
|
CreateAppTableRecordRespBody respBody = larkTableHelper.addTableRecord(addRecordRequest);
|
|
|
|
CreateAppTableRecordRespBody respBody = larkTableHelper.addTableRecord(addRecordRequest);
|
|
|
|
larkKey = respBody.getRecord().getRecordId();
|
|
|
|
larkKey = respBody.getRecord().getRecordId();
|
|
|
|
relationList.add(buildErpLarkRelation(uniqueKey,larkKey,cjt));
|
|
|
|
relationList.add(buildErpLarkRelation(uniqueKey, larkKey, cjt,asynchronous));
|
|
|
|
}else {
|
|
|
|
} else {
|
|
|
|
if (!AppType.SYNC_CJT_SALE_DISPATCH_DATA_TO_MULTI_TABLE.equals(syncLarkAppType())){
|
|
|
|
if (!AppType.SYNC_CJT_SALE_DISPATCH_DATA_TO_MULTI_TABLE.equals(syncLarkAppType())) {
|
|
|
|
//根据本地保留映射,确认飞书的更新行,更新后防止影响后续更新,需要将行id进行置空
|
|
|
|
//根据本地保留映射,确认飞书的更新行,更新后防止影响后续更新,需要将行id进行置空
|
|
|
|
addRecordRequest.setRecord(larkKey);
|
|
|
|
addRecordRequest.setRecord(larkKey);
|
|
|
|
larkTableHelper.updateTableRecord(addRecordRequest);
|
|
|
|
larkTableHelper.updateTableRecord(addRecordRequest);
|
|
|
|
addRecordRequest.setRecord(null);
|
|
|
|
addRecordRequest.setRecord(null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}catch (Exception e){
|
|
|
|
} catch (Exception e) {
|
|
|
|
log.error("{} addOrUpdate exception {}", this.getClassName(),uniqueKey, e);
|
|
|
|
log.error("{} addOrUpdate exception {}", this.getClassName(), uniqueKey, e);
|
|
|
|
errorKey.add(String.format("【%s,%s】",uniqueKey,e.getMessage()));
|
|
|
|
errorKey.add(String.format("【%s,%s】", uniqueKey, e.getMessage()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!CollectionUtils.isEmpty(relationList)){
|
|
|
|
if (!CollectionUtils.isEmpty(relationList)) {
|
|
|
|
erpLarkRelationMapper.batchInsert(relationList);
|
|
|
|
erpLarkRelationMapper.batchInsert(relationList);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return errorKey;
|
|
|
|
return errorKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//构建飞书行与cjt唯一键的对应关系对象
|
|
|
|
//构建飞书行与cjt唯一键的对应关系对象
|
|
|
|
private ErpLarkRelation buildErpLarkRelation(String key,String larkKey,String cjt){
|
|
|
|
private ErpLarkRelation buildErpLarkRelation(String key, String larkKey, String cjt,Boolean asynchronous) {
|
|
|
|
ErpLarkRelation erpLarkRelation = new ErpLarkRelation();
|
|
|
|
ErpLarkRelation erpLarkRelation = new ErpLarkRelation();
|
|
|
|
erpLarkRelation.setKey(key);
|
|
|
|
erpLarkRelation.setKey(key);
|
|
|
|
erpLarkRelation.setLarkKey(larkKey);
|
|
|
|
erpLarkRelation.setLarkKey(larkKey);
|
|
|
@ -406,12 +496,17 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
erpLarkRelation.setFlag(FlagStatus.OK.getCode());
|
|
|
|
erpLarkRelation.setFlag(FlagStatus.OK.getCode());
|
|
|
|
erpLarkRelation.setRemark(cjt);
|
|
|
|
erpLarkRelation.setRemark(cjt);
|
|
|
|
erpLarkRelation.setCreateBy("SYSTEM");
|
|
|
|
erpLarkRelation.setCreateBy("SYSTEM");
|
|
|
|
erpLarkRelation.setCreateTime(new Date());
|
|
|
|
Date date = new Date();
|
|
|
|
|
|
|
|
if (Boolean.TRUE.equals(asynchronous)){
|
|
|
|
|
|
|
|
LocalDateTime localDateTime = LocalDateTime.now().minusDays(1L);
|
|
|
|
|
|
|
|
date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
erpLarkRelation.setCreateTime(date);
|
|
|
|
return erpLarkRelation;
|
|
|
|
return erpLarkRelation;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private String buildCacheUniqueKey(String key,String appKey){
|
|
|
|
private String buildCacheUniqueKey(String key, String appKey) {
|
|
|
|
return String.format("%s:%s",key,appKey);
|
|
|
|
return String.format("%s:%s", key, appKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -430,7 +525,7 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
Thread.sleep(1000);
|
|
|
|
Thread.sleep(1000);
|
|
|
|
}catch (Exception e){
|
|
|
|
} catch (Exception e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
String ticket = (String) redisCache.getCacheObject(ticketCacheKey);
|
|
|
|
String ticket = (String) redisCache.getCacheObject(ticketCacheKey);
|
|
|
@ -443,7 +538,7 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
private String generateToken(CJTJobContext context) {
|
|
|
|
private String generateToken(CJTJobContext context) {
|
|
|
|
String tokenCacheKey = buildCacheUniqueKey(RedisConstants.CJT_TOKEN_CACHE_KEY, context.getAppKey());
|
|
|
|
String tokenCacheKey = buildCacheUniqueKey(RedisConstants.CJT_TOKEN_CACHE_KEY, context.getAppKey());
|
|
|
|
String openToken = (String) redisCache.getCacheObject(tokenCacheKey);
|
|
|
|
String openToken = (String) redisCache.getCacheObject(tokenCacheKey);
|
|
|
|
if (StringUtils.isEmpty(openToken)){
|
|
|
|
if (StringUtils.isEmpty(openToken)) {
|
|
|
|
CJTRequest cjtRequest = new CJTRequest(REQUEST_GENERATE_TOKEN_PATH
|
|
|
|
CJTRequest cjtRequest = new CJTRequest(REQUEST_GENERATE_TOKEN_PATH
|
|
|
|
, context.getAppKey()
|
|
|
|
, context.getAppKey()
|
|
|
|
, context.getAppSecret()
|
|
|
|
, context.getAppSecret()
|
|
|
@ -454,9 +549,9 @@ public abstract class SyncAccountsJobAbstract {
|
|
|
|
JSONObject value = body.getJSONObject("value");
|
|
|
|
JSONObject value = body.getJSONObject("value");
|
|
|
|
String token = value.getString("accessToken");
|
|
|
|
String token = value.getString("accessToken");
|
|
|
|
context.setOpenToken(token);
|
|
|
|
context.setOpenToken(token);
|
|
|
|
redisCache.setCacheObject(tokenCacheKey,token,5, TimeUnit.MINUTES);
|
|
|
|
redisCache.setCacheObject(tokenCacheKey, token, 5, TimeUnit.MINUTES);
|
|
|
|
return token;
|
|
|
|
return token;
|
|
|
|
}else{
|
|
|
|
} else {
|
|
|
|
context.setOpenToken(openToken);
|
|
|
|
context.setOpenToken(openToken);
|
|
|
|
return openToken;
|
|
|
|
return openToken;
|
|
|
|
}
|
|
|
|
}
|
|
|
|