From 95fdf2b06bcb756cc7185b7fef7134641cb05464 Mon Sep 17 00:00:00 2001 From: YXY <932687738@qq.com> Date: Tue, 29 Aug 2023 22:06:18 +0800 Subject: [PATCH] =?UTF-8?q?=E9=92=88=E5=AF=B9=E8=B4=A6=E5=8F=B7=E4=BA=8C?= =?UTF-8?q?=E5=8A=A0=E5=B7=A5=E5=8D=95=E7=9A=84=E8=A1=A5=E5=81=BF=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=8E=AA=E6=96=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruoyi/common/constant/RedisConstants.java | 2 + .../com/ruoyi/common/utils/DateUtils.java | 12 + .../LarkHelper/LarkTableHelper.java | 46 +++ .../domain/lark/LarkTableRequest.java | 2 +- .../mapper/ErpLarkRelationMapper.java | 2 + .../mapper/ErpLarkRelationMapper.xml | 27 +- .../ruoyi/quartz/domain/CJTJobContext.java | 5 + .../task/CJT/SyncAccountsJobAbstract.java | 265 ++++++++++++------ 8 files changed, 270 insertions(+), 91 deletions(-) diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/RedisConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/RedisConstants.java index d75f069..a8c2f1a 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/RedisConstants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/RedisConstants.java @@ -27,4 +27,6 @@ public class RedisConstants { public static final String CJT_TICKET_CACHE_KEY = "TICKET_KEY"; public static final String CJT_TOKEN_CACHE_KEY = "OPEN_TOKEN"; + public static final String CJT_ASYNCHRONOUS = "CJT_ASYNCHRONOUS"; + } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java index cae5a20..015aa52 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java @@ -142,6 +142,18 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { return day + "天" + hour + "小时" + min + "分钟"; } + public static String startOfDate(LocalDate now){ + LocalDateTime today_start = LocalDateTime.of(now,LocalTime.MIN); + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return df.format(today_start); + } + + public static String endOfDate(LocalDate now){ + LocalDateTime today_end = LocalDateTime.of(now,LocalTime.MAX); + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return df.format(today_end); + } + public static String ldt2str(LocalDateTime time, String pattern) { DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern); return time.format(fmt); diff --git a/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/LarkHelper/LarkTableHelper.java b/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/LarkHelper/LarkTableHelper.java index ec1dbcf..108f296 100644 --- a/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/LarkHelper/LarkTableHelper.java +++ b/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/LarkHelper/LarkTableHelper.java @@ -1,6 +1,7 @@ package com.ruoyi.flyingbook.LarkHelper; import com.alibaba.fastjson.JSONObject; +import com.lark.oapi.core.response.EmptyData; import com.lark.oapi.service.bitable.v1.model.*; import com.ruoyi.flyingbook.domain.lark.LarkException; import com.ruoyi.flyingbook.domain.lark.LarkTableRequest; @@ -113,6 +114,27 @@ public class LarkTableHelper extends LarkHelper{ } } + /** + * 删除多维表格数据表 + */ + public void deleteDataTable(LarkTableRequest request) { + try { + buildClient(request).bitable().appTable().delete( + DeleteAppTableReq.newBuilder() + .appToken(request.getAppToken()) + .tableId(request.getAppTable()) + .build() + ); + } catch (Exception e) { + throw new RuntimeException(new LarkException("LarkTableHelper.createDataTable",e.getMessage(),request).getErrorMessageBody()); + } +// if (deleteAppTableResp != null && deleteAppTableResp.getCode() == 0){ +// EmptyData data = deleteAppTableResp.getData(); +// }else { +// throw new RuntimeException(new LarkException("LarkTableHelper.deleteDataTable", deleteAppTableResp.getMsg(),request).getErrorMessageBody()); +// } + } + /** * 获取行详情 @@ -180,6 +202,30 @@ public class LarkTableHelper extends LarkHelper{ } } + public BatchDeleteAppTableRecordRespBody deleteTableRecordBatch(LarkTableRequest request) { + BatchDeleteAppTableRecordResp delete = null; + try { + delete = buildClient(request).bitable().appTableRecord().batchDelete( + BatchDeleteAppTableRecordReq.newBuilder() + .appToken(request.getAppToken()) + .tableId(request.getAppTable()) + .batchDeleteAppTableRecordReqBody( + BatchDeleteAppTableRecordReqBody.newBuilder() + .records(request.getRecords()) + .build() + ) + .build() + ); + } catch (Exception e) { + throw new RuntimeException(new LarkException("LarkTableHelper.deleteTableRecordBatch",e.getMessage(),request).getErrorMessageBody()); + } + if (delete != null && delete.getCode() == 0){ + return delete.getData(); + }else { + throw new RuntimeException(new LarkException("LarkTableHelper.deleteTableRecordBatch",delete.getMsg(),request).getErrorMessageBody()); + } + } + public UpdateAppTableRecordRespBody updateTableRecord(LarkTableRequest request) { UpdateAppTableRecordResp update = null; try { diff --git a/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/domain/lark/LarkTableRequest.java b/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/domain/lark/LarkTableRequest.java index c2bdb41..348731a 100644 --- a/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/domain/lark/LarkTableRequest.java +++ b/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/domain/lark/LarkTableRequest.java @@ -17,6 +17,7 @@ public class LarkTableRequest extends LarkRequest{ private String appToken; private String appTable; private String record; + private String[] records; private String filter; private String tableName; private String defaultViewName; @@ -62,6 +63,5 @@ public class LarkTableRequest extends LarkRequest{ super(appId,appSecret); this.appToken = appToken; this.appTable = appTable; - this.record = record; } } diff --git a/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/mapper/ErpLarkRelationMapper.java b/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/mapper/ErpLarkRelationMapper.java index 5e0279b..f4f6b17 100644 --- a/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/mapper/ErpLarkRelationMapper.java +++ b/ruoyi-flyingbook/src/main/java/com/ruoyi/flyingbook/mapper/ErpLarkRelationMapper.java @@ -65,6 +65,8 @@ public interface ErpLarkRelationMapper public List queryListByKeyList(@Param("keyList") List keyList,@Param("method") String method); public List queryListByKeyListAndRemark(@Param("keyList") List keyList,@Param("method") String method,@Param("remark") String remark); + public List queryWaitDeleteRecordList(@Param("currentDay") String currentDay,@Param("method") String method,@Param("remark") String remark); + public void deleteRecordList(@Param("currentDay") String currentDay,@Param("method") String method,@Param("remark") String remark); /** * 批量插入 diff --git a/ruoyi-flyingbook/src/main/resources/mapper/ErpLarkRelationMapper.xml b/ruoyi-flyingbook/src/main/resources/mapper/ErpLarkRelationMapper.xml index 8447522..7509669 100644 --- a/ruoyi-flyingbook/src/main/resources/mapper/ErpLarkRelationMapper.xml +++ b/ruoyi-flyingbook/src/main/resources/mapper/ErpLarkRelationMapper.xml @@ -18,7 +18,7 @@ - select id, key, method, create_by, create_time, update_by, update_time, flag, remark,lark_key + select id, key, method, create_by, create_time, update_by, update_time, flag, remark, lark_key from erp_lark_relation @@ -55,10 +55,26 @@ + + + + delete FROM erp_lark_relation + WHERE DATE (create_time) = #{currentDay} + and remark = #{remark} + and `method` = #{method} + + #{larkKey}, - + insert into erp_lark_relation(`key`,`method`,create_by,create_time,flag,lark_key,remark) values @@ -125,7 +142,7 @@ where id = #{id} - + delete from erp_lark_relation where id in #{id} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/CJTJobContext.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/CJTJobContext.java index d786bee..3b6ae7e 100644 --- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/CJTJobContext.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/CJTJobContext.java @@ -25,6 +25,11 @@ public class CJTJobContext implements Serializable { private String queryToTime; private String cjt; + /** + * 是否需要异步操作 + */ + private Boolean asynchronous = Boolean.FALSE; + /** * 用于获取ticket信息 */ diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CJT/SyncAccountsJobAbstract.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CJT/SyncAccountsJobAbstract.java index 2575931..29399ae 100644 --- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CJT/SyncAccountsJobAbstract.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CJT/SyncAccountsJobAbstract.java @@ -1,6 +1,7 @@ package com.ruoyi.quartz.task.CJT; import com.alibaba.fastjson.JSONObject; +import com.lark.oapi.core.utils.Lists; import com.lark.oapi.service.bitable.v1.model.CreateAppTableRecordRespBody; import com.ruoyi.common.constant.RedisConstants; 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.StringUtils; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -50,6 +53,8 @@ public abstract class SyncAccountsJobAbstract { private LarkTableHelper larkTableHelper; @Autowired private LarkRobotHelper larkRobotHelper; + @Autowired + private CJTCreateLarkTableJob cjtCreateLarkTableJob; @Value("${lark.robot.group}") private String ROBOT_GROUP; @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 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(); - if (StringUtils.isEmpty(queryFromTime)){ - queryFromTime = DateUtils.ldt2str(now.minusMinutes(REDUCE_MINUTES), DateUtils.YYYY_MM_DD_HH_MM_SS); + Boolean asynchronous = asynchronousCheck(now, cjt); + 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); - if (StringUtils.isEmpty(queryToTime)){ - queryToTime = DateUtils.ldt2str(now, DateUtils.YYYY_MM_DD_HH_MM_SS); + if (StringUtils.isEmpty(queryToTime)) { + queryToTime = asynchronous + ? DateUtils.endOfDate(localDate) + : DateUtils.ldt2str(now, DateUtils.YYYY_MM_DD_HH_MM_SS); } context.setQueryToTime(queryToTime); context.setCjt(cjt); @@ -93,7 +129,7 @@ public abstract class SyncAccountsJobAbstract { if (Boolean.FALSE.equals(syncFlag)) { return; } - if (request == null){ + if (request == null) { return; } CJTJobContext context = new CJTJobContext(); @@ -101,7 +137,7 @@ public abstract class SyncAccountsJobAbstract { context.setQueryToTime(request.getQueryTo()); context.setCjt(request.getCjt()); try { - log.info("===================== {} {} retry strat ======================",this.getClassName(),context.getQueryToTime()); + log.info("===================== {} {} retry strat ======================", this.getClassName(), context.getQueryToTime()); //初始化飞书信息及相关配置 initLarkInfo(context); //重置ticket @@ -110,68 +146,110 @@ public abstract class SyncAccountsJobAbstract { sync(context); } catch (Exception e) { log.error("{} ", getClassName(), e); - if (request.getCount() == 2){ - larkRobotHelper.sendMessageByBot(ROBOT_GROUP, buildRobotErrorCountMessage(e,request)); - }else { + if (request.getCount() == 2) { + larkRobotHelper.sendMessageByBot(ROBOT_GROUP, buildRobotErrorCountMessage(e, request)); + } else { request.addCount(); - redisCache.rightPush(getRetryKey(request.getCjt()),request); + redisCache.rightPush(getRetryKey(request.getCjt()), request); } - }finally { - log.info("===================== {} {} retry end ======================",this.getClassName(),context.getQueryToTime()); + } finally { + 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)) { return; } LocalDateTime now = LocalDateTime.now(); - CJTJobContext context = initContext(queryFromTime,queryToTime,now,cjt); + CJTJobContext context = initContext(queryFromTime, queryToTime, now, cjt); try { - log.info("===================== {} strat ======================",this.getClassName()); + log.info("===================== {} strat ======================", this.getClassName()); //初始化飞书信息及相关配置 initLarkInfo(context); + if (Boolean.TRUE.equals(context.getAsynchronous())) { + Boolean deleteSuccess = handleRepeatData(now, cjt, context); + if (!deleteSuccess){ + return; + } + } //重置ticket resetTicket(context); //执行分页同步 sync(context); } catch (Exception e) { log.error("{} 执行失败", getClassName(), e); - CJTRetryRequest request = new CJTRetryRequest(now,1,cjt); - redisCache.rightPush(getRetryKey(cjt),request); - }finally { - log.info("===================== {} end ======================",this.getClassName()); + if (Boolean.TRUE.equals(context.getAsynchronous())) { + String asynchronous = getAsynchronousKey(cjt); + redisCache.deleteObject(asynchronous); + }else { + CJTRetryRequest request = new CJTRetryRequest(now, 1, cjt); + redisCache.rightPush(getRetryKey(cjt), request); + } + } finally { + log.info("===================== {} end ======================", this.getClassName()); } } - public String getRetryKey(String cjt){ - return String.format(RETRY_KEY,cjt, syncLarkAppType().getCode()); + private Boolean handleRepeatData(LocalDateTime now, String cjt, CJTJobContext context) { + 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 recordList = erpLarkRelationMapper.queryWaitDeleteRecordList(date, getRequestUrl(), cjt); + List 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); } - private String buildRobotErrorCountMessage(Exception e,CJTRetryRequest request){ + private String buildRobotErrorCountMessage(Exception e, CJTRetryRequest request) { JSONObject jsonObject = new JSONObject(); - jsonObject.put("同步任务",getClassName()); - jsonObject.put("重试失败",request.getCount()); - jsonObject.put("重试开始时间",request.getQueryFrom(REDUCE_MINUTES)); - jsonObject.put("重试结束时间",request.getQueryTo()); + jsonObject.put("同步任务", getClassName()); + jsonObject.put("重试失败", request.getCount()); + jsonObject.put("重试开始时间", request.getQueryFrom(REDUCE_MINUTES)); + jsonObject.put("重试结束时间", request.getQueryTo()); String errorMessage = e.getMessage(); - if (org.apache.commons.lang3.StringUtils.isNotBlank(errorMessage)){ - errorMessage = errorMessage.replaceAll("\\\\",""); + if (org.apache.commons.lang3.StringUtils.isNotBlank(errorMessage)) { + errorMessage = errorMessage.replaceAll("\\\\", ""); } jsonObject.put("异常信息", errorMessage); return jsonObject.toJSONString(); } - private String buildRobotErrorMessage(Exception e){ + private String buildRobotErrorMessage(Exception e) { JSONObject jsonObject = new JSONObject(); - jsonObject.put("同步任务(待重试)",getClassName()); + jsonObject.put("同步任务(待重试)", getClassName()); String errorMessage = e.getMessage(); - if (org.apache.commons.lang3.StringUtils.isNotBlank(errorMessage)){ - errorMessage = errorMessage.replaceAll("\\\\",""); + if (org.apache.commons.lang3.StringUtils.isNotBlank(errorMessage)) { + errorMessage = errorMessage.replaceAll("\\\\", ""); } jsonObject.put("异常信息", errorMessage); return jsonObject.toJSONString(); @@ -181,6 +259,7 @@ public abstract class SyncAccountsJobAbstract { * 获取同步多维表格类型配置 */ protected abstract AppType syncLarkAppType(); + protected abstract TableRelationTypeEnum syncLarkType(); /** @@ -197,38 +276,40 @@ public abstract class SyncAccountsJobAbstract { * 获取待查询的字段 */ protected abstract List getQueryFields(); + /** * 获取待查询的字段与飞书的映射关系 */ - protected abstract Map getQueryFieldsMap(String cjt); + protected abstract Map getQueryFieldsMap(String cjt); /** * 获取查询条件 */ protected abstract String getQueryKey(); - protected JSONObject getQueryCondition(CJTJobContext context){ + + protected JSONObject getQueryCondition(CJTJobContext context) { JSONObject jsonObject = new JSONObject(); LocalDateTime now = LocalDateTime.now(); 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); } String endTime = context.getQueryToTime(); - if (StringUtils.isEmpty(endTime)){ + if (StringUtils.isEmpty(endTime)) { endTime = DateUtils.ldt2str(now, DateUtils.YYYY_MM_DD_HH_MM_SS); } Map startTimeMap = new HashMap<>(); - startTimeMap.put("text",startTime); - startTimeMap.put("value",startTime); + startTimeMap.put("text", startTime); + startTimeMap.put("value", startTime); Map endTimeMap = new HashMap<>(); - endTimeMap.put("text",endTime); - endTimeMap.put("value",endTime); + endTimeMap.put("text", endTime); + endTimeMap.put("value", endTime); List> timeRange = Arrays.asList(startTimeMap, endTimeMap); - String queryKey = String.format("%s.AuditedTime",getQueryKey()); - if (AppType.SYNC_CJT_SALE_DISPATCH_DATA_TO_MULTI_TABLE.equals(syncLarkAppType())){ - queryKey = String.format("%s.createdtime",getQueryKey()); + String queryKey = String.format("%s.AuditedTime", getQueryKey()); + if (AppType.SYNC_CJT_SALE_DISPATCH_DATA_TO_MULTI_TABLE.equals(syncLarkAppType())) { + queryKey = String.format("%s.createdtime", getQueryKey()); } - jsonObject.put(queryKey,timeRange); + jsonObject.put(queryKey, timeRange); return jsonObject; } @@ -238,7 +319,9 @@ public abstract class SyncAccountsJobAbstract { */ protected String getClassName() { return this.getClass().getSimpleName(); - }; + } + + ; /** * 同步数据 @@ -270,13 +353,13 @@ public abstract class SyncAccountsJobAbstract { CJTResponseBodyDetail response = request(cjtRequest); //实际返回数据 rows = response.getRows(); - if (!CollectionUtils.isEmpty(rows)){ - Map existKeyMap = getExistKeyMap(cjtRequest,response.getColumns(), rows,context.getCjt()); + if (!CollectionUtils.isEmpty(rows)) { + Map existKeyMap = getExistKeyMap(cjtRequest, response.getColumns(), rows, context.getCjt()); //批量同步飞书 - List errorCodeList = syncLarkBatch(response.getColumns(), rows, existKeyMap,addRecordRequest,context.getCjt()); - if (!CollectionUtils.isEmpty(errorCodeList)){ + List errorCodeList = syncLarkBatch(response.getColumns(), rows, existKeyMap, addRecordRequest, context.getCjt(),context.getAsynchronous()); + if (!CollectionUtils.isEmpty(errorCodeList)) { String errorKey = String.join(",", errorCodeList); - throw new RuntimeException(String.format("存在同步失败的记录 %s",errorKey)); + throw new RuntimeException(String.format("存在同步失败的记录 %s", errorKey)); } } } catch (Exception e) { @@ -285,13 +368,13 @@ public abstract class SyncAccountsJobAbstract { } finally { page++; } - }while (!CollectionUtils.isEmpty(rows)); - if (!StringUtils.isEmpty(errorMessage)){ + } while (!CollectionUtils.isEmpty(rows)); + if (!StringUtils.isEmpty(errorMessage)) { throw new RuntimeException(errorMessage); } } - private List getUniqueKey(List keyList,List> rows,String cjt) { + private List getUniqueKey(List keyList, List> rows, String cjt) { //组成唯一键的集合 List uniqueFields = getUniqueFields(cjt); List result = new ArrayList<>(); @@ -299,11 +382,11 @@ public abstract class SyncAccountsJobAbstract { for (List row : rows) { List midList = new ArrayList<>(); 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)); } } - String uniqueKey = String.join("_", midList).toUpperCase(); + String uniqueKey = String.join("_", midList).toUpperCase(); result.add(uniqueKey); } } @@ -313,30 +396,30 @@ public abstract class SyncAccountsJobAbstract { /** * 使用唯一key区分创建或更新 */ - protected Map getExistKeyMap(CJTRequest req,List keyList, List> rows,String cjt) { + protected Map getExistKeyMap(CJTRequest req, List keyList, List> rows, String cjt) { if (CollectionUtils.isEmpty(rows)) { return new HashMap<>(); } - List uniqueKeyList = getUniqueKey(keyList,rows,cjt); + List uniqueKeyList = getUniqueKey(keyList, rows, cjt); if (CollectionUtils.isEmpty(uniqueKeyList)) { 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)); } - private Object changeValueType(String value,CJTSyncTypeRelation cjtSyncTypeRelation){ + private Object changeValueType(String value, CJTSyncTypeRelation cjtSyncTypeRelation) { 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; } - switch (type){ + switch (type) { case NUMBER: return Double.valueOf(value); case DATE: LocalDateTime localDateTime = DateUtils.str2ldt(value, cjtSyncTypeRelation.getPattern()); - return DateUtils.ldt2Long(localDateTime); + return DateUtils.ldt2Long(localDateTime); default: return value; } @@ -345,7 +428,8 @@ public abstract class SyncAccountsJobAbstract { /** * 执行字段映射 */ - protected List syncLarkBatch(List keyList,List> rows,Map existKeyMap,LarkTableRequest addRecordRequest,String cjt){ + protected List syncLarkBatch(List keyList, List> rows, Map existKeyMap + , LarkTableRequest addRecordRequest, String cjt,Boolean asynchronous) { List relationList = new ArrayList<>(); //查询字段与飞书字段的对应关系 Map queryFieldsMap = getQueryFieldsMap(cjt); @@ -353,52 +437,58 @@ public abstract class SyncAccountsJobAbstract { List uniqueFields = getUniqueFields(cjt); //错误唯一键 List errorKey = new ArrayList<>(); + //判断当前查询条件内是否存在重复数据 + Map repeatMap = new HashMap<>(); for (List row : rows) { String uniqueKey = null; try { - Map body = new HashMap<>(); + Map body = new HashMap<>(); List uniqueKeyList = new ArrayList<>(); for (int i = 0; i < row.size(); i++) { CJTSyncTypeRelation cjtSyncTypeRelation = queryFieldsMap.get(keyList.get(i)); - if (cjtSyncTypeRelation == null){ + if (cjtSyncTypeRelation == null) { continue; } String larkLabel = cjtSyncTypeRelation.getLarkFileName(); String value = row.get(i); - if (uniqueFields.contains(keyList.get(i))){ + if (uniqueFields.contains(keyList.get(i))) { uniqueKeyList.add(value); } - body.put(larkLabel,this.changeValueType(value,cjtSyncTypeRelation)); + body.put(larkLabel, this.changeValueType(value, cjtSyncTypeRelation)); } uniqueKey = String.join("_", uniqueKeyList).toUpperCase(); + if (repeatMap.containsKey(uniqueKey)) { + continue; + } + repeatMap.put(uniqueKey, 1); String larkKey = existKeyMap.get(uniqueKey); addRecordRequest.setBody(body); - if (StringUtils.isEmpty(larkKey)){ + if (StringUtils.isEmpty(larkKey)) { //在飞书创建一行,并根据创建返回的行id在本地保留一条映射纪律 CreateAppTableRecordRespBody respBody = larkTableHelper.addTableRecord(addRecordRequest); larkKey = respBody.getRecord().getRecordId(); - relationList.add(buildErpLarkRelation(uniqueKey,larkKey,cjt)); - }else { - if (!AppType.SYNC_CJT_SALE_DISPATCH_DATA_TO_MULTI_TABLE.equals(syncLarkAppType())){ + relationList.add(buildErpLarkRelation(uniqueKey, larkKey, cjt,asynchronous)); + } else { + if (!AppType.SYNC_CJT_SALE_DISPATCH_DATA_TO_MULTI_TABLE.equals(syncLarkAppType())) { //根据本地保留映射,确认飞书的更新行,更新后防止影响后续更新,需要将行id进行置空 addRecordRequest.setRecord(larkKey); larkTableHelper.updateTableRecord(addRecordRequest); addRecordRequest.setRecord(null); } } - }catch (Exception e){ - log.error("{} addOrUpdate exception {}", this.getClassName(),uniqueKey, e); - errorKey.add(String.format("【%s,%s】",uniqueKey,e.getMessage())); + } catch (Exception e) { + log.error("{} addOrUpdate exception {}", this.getClassName(), uniqueKey, e); + errorKey.add(String.format("【%s,%s】", uniqueKey, e.getMessage())); } } - if (!CollectionUtils.isEmpty(relationList)){ + if (!CollectionUtils.isEmpty(relationList)) { erpLarkRelationMapper.batchInsert(relationList); } return errorKey; } //构建飞书行与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.setKey(key); erpLarkRelation.setLarkKey(larkKey); @@ -406,12 +496,17 @@ public abstract class SyncAccountsJobAbstract { erpLarkRelation.setFlag(FlagStatus.OK.getCode()); erpLarkRelation.setRemark(cjt); 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; } - private String buildCacheUniqueKey(String key,String appKey){ - return String.format("%s:%s",key,appKey); + private String buildCacheUniqueKey(String key, String appKey) { + return String.format("%s:%s", key, appKey); } /** @@ -430,7 +525,7 @@ public abstract class SyncAccountsJobAbstract { } try { Thread.sleep(1000); - }catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); } String ticket = (String) redisCache.getCacheObject(ticketCacheKey); @@ -443,7 +538,7 @@ public abstract class SyncAccountsJobAbstract { private String generateToken(CJTJobContext context) { String tokenCacheKey = buildCacheUniqueKey(RedisConstants.CJT_TOKEN_CACHE_KEY, context.getAppKey()); String openToken = (String) redisCache.getCacheObject(tokenCacheKey); - if (StringUtils.isEmpty(openToken)){ + if (StringUtils.isEmpty(openToken)) { CJTRequest cjtRequest = new CJTRequest(REQUEST_GENERATE_TOKEN_PATH , context.getAppKey() , context.getAppSecret() @@ -454,9 +549,9 @@ public abstract class SyncAccountsJobAbstract { JSONObject value = body.getJSONObject("value"); String token = value.getString("accessToken"); context.setOpenToken(token); - redisCache.setCacheObject(tokenCacheKey,token,5, TimeUnit.MINUTES); + redisCache.setCacheObject(tokenCacheKey, token, 5, TimeUnit.MINUTES); return token; - }else{ + } else { context.setOpenToken(openToken); return openToken; }