parent
5083ad0d6c
commit
521aaeb3cb
@ -0,0 +1,28 @@
|
||||
package com.ruoyi.quartz.domain;
|
||||
|
||||
import com.ruoyi.flyingbook.domain.LarkCompanyRelation;
|
||||
import com.ruoyi.flyingbook.domain.LarkTableRelation;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.xmlrpc.client.XmlRpcClient;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yuxiangyong
|
||||
* @create 2023-07-17 20:31
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class OdooContext implements Serializable {
|
||||
|
||||
private XmlRpcClient models;
|
||||
private Integer uid;
|
||||
|
||||
/**
|
||||
* 飞书权限相关即待同步飞书多维表格配置
|
||||
*/
|
||||
private LarkCompanyRelation companyRelation;
|
||||
private LarkTableRelation tableRelation;
|
||||
}
|
@ -0,0 +1,274 @@
|
||||
package com.ruoyi.quartz.task.odoo;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.lark.oapi.service.bitable.v1.model.CreateAppTableRecordRespBody;
|
||||
import com.ruoyi.common.enums.AppType;
|
||||
import com.ruoyi.common.enums.FlagStatus;
|
||||
import com.ruoyi.common.enums.TableRelationTypeEnum;
|
||||
import com.ruoyi.flyingbook.LarkHelper.LarkRobotHelper;
|
||||
import com.ruoyi.flyingbook.LarkHelper.LarkTableHelper;
|
||||
import com.ruoyi.flyingbook.domain.ErpLarkRelation;
|
||||
import com.ruoyi.flyingbook.domain.LarkCompanyRelation;
|
||||
import com.ruoyi.flyingbook.domain.LarkTableRelation;
|
||||
import com.ruoyi.flyingbook.domain.lark.LarkTableRequest;
|
||||
import com.ruoyi.flyingbook.mapper.ErpLarkRelationMapper;
|
||||
import com.ruoyi.flyingbook.mapper.LarkCompanyRelationMapper;
|
||||
import com.ruoyi.flyingbook.mapper.LarkTableRelationMapper;
|
||||
import com.ruoyi.quartz.domain.CJTJobContext;
|
||||
import com.ruoyi.quartz.domain.OdooContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
import org.apache.xmlrpc.client.XmlRpcClient;
|
||||
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
/**
|
||||
* @author yuxiangyong
|
||||
* @create 2023-07-23 18:18
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class OdooAbstrackob {
|
||||
@Autowired
|
||||
protected ErpLarkRelationMapper erpLarkRelationMapper;
|
||||
@Autowired
|
||||
private LarkCompanyRelationMapper larkCompanyRelationMapper;
|
||||
@Autowired
|
||||
private LarkTableRelationMapper larkTableRelationMapper;
|
||||
@Autowired
|
||||
private LarkTableHelper larkTableHelper;
|
||||
@Autowired
|
||||
private LarkRobotHelper larkRobotHelper;
|
||||
@Value("${lark.robot.group}")
|
||||
private String ROBOT_GROUP;
|
||||
|
||||
public static final String ACCOUNT_MOVE_LINE_MODEL_NAME = "account.move.line";
|
||||
public static final String PRODUCT_PRODUCT_MODEL_NAME = "product.product";
|
||||
public static final String PRODUCT_PACKING_MODEL_NAME = "product_packaging";
|
||||
public static final String PRODUCT_PRODUCT_MODEL_NAME2 = "product_product";
|
||||
public static final String STOCK_QUANT_MODEL_NAME = "stock_quant";
|
||||
|
||||
private static final String GET_DATA_DB = "Fortune_test0716";
|
||||
private static final String GET_DATA_NAME = "test";
|
||||
private static final String GET_DATA_PASSWORD = "00cc06962c4583e562f7f3fcad2f38ef840e1d02";
|
||||
private static final String GET_DATA_P_METHOD_NAME = "execute_kw";
|
||||
|
||||
private static final String INIT_URL = "http://47.115.191.117:8869";
|
||||
|
||||
private static final String PAGE_OFFSET_KEY = "offset";
|
||||
private static final String PAGE_LIMIT_KEY = "limit";
|
||||
private static final Integer PAGE_SIZE = 20;
|
||||
|
||||
protected void execute() {
|
||||
try {
|
||||
log.info("===================== {} strat ======================", this.getClassName());
|
||||
//初始化调用对象
|
||||
OdooContext context = initContext();
|
||||
//初始化飞书信息
|
||||
initLarkInfo(context);
|
||||
//分页调用接口批量更新
|
||||
batchSync(context);
|
||||
} catch (Exception e) {
|
||||
log.error("{} 执行失败"
|
||||
, getClassName()
|
||||
, e);
|
||||
larkRobotHelper.sendMessageByBot(ROBOT_GROUP, buildRobotErrorMessage(e));
|
||||
} finally {
|
||||
log.info("===================== {} end ======================", this.getClassName());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Integer> getPageMap() {
|
||||
return new HashMap() {{
|
||||
put(PAGE_OFFSET_KEY, 0);//分页
|
||||
put(PAGE_LIMIT_KEY, PAGE_SIZE);
|
||||
}};
|
||||
}
|
||||
|
||||
private void batchSync(OdooContext context) {
|
||||
//分页对象
|
||||
Map<String, Integer> pageMap = getPageMap();
|
||||
//查询结果
|
||||
List<JSONObject> dateList = new ArrayList<>();
|
||||
//错误信息
|
||||
List<String> errorList = new ArrayList<>();
|
||||
//构建飞书请求对象
|
||||
LarkCompanyRelation companyRelation = context.getCompanyRelation();
|
||||
LarkTableRelation tableRelation = context.getTableRelation();
|
||||
LarkTableRequest larkRequest = new LarkTableRequest(companyRelation.getAppId(), companyRelation.getSecret(), tableRelation.getToAppToken(), tableRelation.getToTableId());
|
||||
//待创建关联关系
|
||||
List<ErpLarkRelation> waitCreateRelation = new ArrayList<>();
|
||||
do {
|
||||
dateList = getDate(context, pageMap, errorList);
|
||||
Map<String, String> relationMap = getLarkRelation(dateList);
|
||||
for (JSONObject jsonObject : dateList) {
|
||||
sync(jsonObject, errorList, relationMap, larkRequest,waitCreateRelation);
|
||||
}
|
||||
} while (dateList == null || (CollectionUtils.isNotEmpty(dateList) && dateList.size() == PAGE_SIZE));
|
||||
if (!CollectionUtils.isEmpty(errorList)) {
|
||||
String errorKey = String.join(",", errorList);
|
||||
throw new RuntimeException(String.format("存在同步失败的记录 %s", errorKey));
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(waitCreateRelation)){
|
||||
erpLarkRelationMapper.batchInsert(waitCreateRelation);
|
||||
}
|
||||
}
|
||||
|
||||
private void sync(JSONObject jsonObject, List<String> errorList
|
||||
, Map<String, String> relationMap, LarkTableRequest larkRequest
|
||||
, List<ErpLarkRelation> waitCreateRelation) {
|
||||
String uniqueKey = null;
|
||||
try {
|
||||
Map<String, Object> larkBodyMap = this.buildLarkBodyMap(jsonObject);
|
||||
larkRequest.setBody(larkBodyMap);
|
||||
uniqueKey = buildUniqueKey(jsonObject);
|
||||
String larkRecord = relationMap.get(uniqueKey);
|
||||
if (StringUtils.isNotBlank(larkRecord)) {
|
||||
larkRequest.setRecord(larkRecord);
|
||||
larkTableHelper.updateTableRecord(larkRequest);
|
||||
} else {
|
||||
CreateAppTableRecordRespBody respBody = larkTableHelper.addTableRecord(larkRequest);
|
||||
waitCreateRelation.add(buildErpLarkRelation(uniqueKey,respBody.getRecord().getRecordId()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("{} addOrUpdate exception {}", this.getClassName(),uniqueKey, e);
|
||||
errorList.add(String.format("【%s,%s】",uniqueKey,e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
//构建飞书行与cjt唯一键的对应关系对象
|
||||
private ErpLarkRelation buildErpLarkRelation(String key, String larkKey) {
|
||||
ErpLarkRelation erpLarkRelation = new ErpLarkRelation();
|
||||
erpLarkRelation.setKey(key);
|
||||
erpLarkRelation.setLarkKey(larkKey);
|
||||
erpLarkRelation.setMethod(syncLarkType().getCode());
|
||||
erpLarkRelation.setFlag(FlagStatus.OK.getCode());
|
||||
erpLarkRelation.setCreateBy("SYSTEM");
|
||||
erpLarkRelation.setCreateTime(new Date());
|
||||
return erpLarkRelation;
|
||||
}
|
||||
|
||||
private String buildRobotErrorMessage(Exception e) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("同步任务", getClassName());
|
||||
jsonObject.put("异常信息", e.getMessage());
|
||||
return jsonObject.toJSONString();
|
||||
}
|
||||
|
||||
private Map<String, String> getLarkRelation(List<JSONObject> dateList) {
|
||||
List<String> uniqueKeyList = dateList.stream().map(r -> {
|
||||
return buildUniqueKey(r);
|
||||
}).distinct().collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(uniqueKeyList)) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
return erpLarkRelationMapper.queryListByKeyList(uniqueKeyList, syncLarkType().getCode())
|
||||
.stream().collect(Collectors.toMap(ErpLarkRelation::getKey, ErpLarkRelation::getLarkKey, (k1, k2) -> k1));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成调用接口的token信息
|
||||
*/
|
||||
private void initLarkInfo(OdooContext context) {
|
||||
LarkCompanyRelation companyRelationQuery = new LarkCompanyRelation();
|
||||
companyRelationQuery.setAppType(AppType.SYNC_ODOO_DATA_TO_MULTI_TABLE.getCode());
|
||||
companyRelationQuery.setFlag(FlagStatus.OK.getCode());
|
||||
List<LarkCompanyRelation> larkCompanyRelations = larkCompanyRelationMapper.selectLarkCompanyRelationList(companyRelationQuery);
|
||||
LarkCompanyRelation companyRelation = larkCompanyRelations.get(0);
|
||||
context.setCompanyRelation(companyRelation);
|
||||
LarkTableRelation tableRelationQuery = new LarkTableRelation();
|
||||
tableRelationQuery.setLarkCompanyRelationId(companyRelation.getId());
|
||||
tableRelationQuery.setFlag(FlagStatus.OK.getCode());
|
||||
tableRelationQuery.setRelationType(syncLarkType().getCode());
|
||||
List<LarkTableRelation> larkTableRelations = larkTableRelationMapper.selectLarkTableRelationList(tableRelationQuery);
|
||||
LarkTableRelation tableRelation = larkTableRelations.get(0);
|
||||
context.setTableRelation(tableRelation);
|
||||
}
|
||||
|
||||
private String getClassName() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
//获取查询model名称
|
||||
protected abstract String buildUniqueKey(JSONObject body);
|
||||
|
||||
//获取查询model名称
|
||||
protected abstract String getQueryModelName();
|
||||
|
||||
//获取查询条件
|
||||
protected abstract List getQueryConditionList();
|
||||
|
||||
//获取查询字段信息
|
||||
protected abstract Map<String, List<String>> getQueryFieldMap();
|
||||
|
||||
//构建飞书请求体信息
|
||||
protected abstract Map<String, Object> buildLarkBodyMap(JSONObject date);
|
||||
|
||||
//获取待同步飞书表格信息
|
||||
protected abstract TableRelationTypeEnum syncLarkType();
|
||||
|
||||
public List<JSONObject> getDate(OdooContext odooContext, Map<String, Integer> pageMap, List<String> errorList) {
|
||||
try {
|
||||
XmlRpcClient models = odooContext.getModels();
|
||||
Integer uid = getUserId();
|
||||
String modelName = getQueryModelName();
|
||||
List<Object> ids = asList((Object[]) models.execute(GET_DATA_P_METHOD_NAME, asList(
|
||||
GET_DATA_DB, uid, GET_DATA_PASSWORD,
|
||||
modelName, "search", //product.product 表名
|
||||
getQueryConditionList(), //查询条件
|
||||
pageMap//分页
|
||||
)));
|
||||
|
||||
return asList((JSONObject[]) models.execute(GET_DATA_P_METHOD_NAME, asList(
|
||||
GET_DATA_DB, uid, GET_DATA_PASSWORD,
|
||||
modelName, "read",
|
||||
asList(ids),
|
||||
getQueryFieldMap()
|
||||
)));
|
||||
} catch (Exception e) {
|
||||
log.error("{} 获取数据失败", this.getClassName(), e);
|
||||
errorList.add(String.format("%s 获取第【%s】页数据失败 %s", this.getClassName(), pageMap.get(PAGE_OFFSET_KEY), e.getMessage()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public OdooContext initContext() {
|
||||
OdooContext context = new OdooContext();
|
||||
try {
|
||||
final XmlRpcClient models = new XmlRpcClient() {{
|
||||
setConfig(new XmlRpcClientConfigImpl() {{
|
||||
setServerURL(new URL(String.format("%s/xmlrpc/2/object", INIT_URL)));
|
||||
}});
|
||||
}};
|
||||
context.setModels(models);
|
||||
context.setUid(getUserId());
|
||||
} catch (Exception e) {
|
||||
log.error("{} 初始化链接失败", this.getClassName(), e);
|
||||
throw new RuntimeException(String.format("%s 初始化链接失败 %s", this.getClassName(), e.getMessage()));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
public Integer getUserId() throws XmlRpcException, MalformedURLException {
|
||||
XmlRpcClient client = new XmlRpcClient();
|
||||
XmlRpcClientConfigImpl common_config = new XmlRpcClientConfigImpl();
|
||||
common_config.setServerURL(new URL(String.format("%s/xmlrpc/2/common", INIT_URL)));
|
||||
Object version = client.execute(common_config, "version", emptyList());
|
||||
return (int) client.execute(common_config, "authenticate", asList(GET_DATA_DB, GET_DATA_NAME, GET_DATA_PASSWORD, emptyMap()));
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.ruoyi.quartz.task.odoo;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.ruoyi.common.enums.TableRelationTypeEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author yuxiangyong
|
||||
* @create 2023-07-23 18:18
|
||||
*/
|
||||
@Slf4j
|
||||
@Component("productProduceJob")
|
||||
public class ProductProduceJob extends OdooAbstrackob {
|
||||
|
||||
@Override
|
||||
protected String buildUniqueKey(JSONObject body) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getQueryModelName() {
|
||||
return "product.product";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getQueryConditionList() {
|
||||
return Arrays.asList(
|
||||
Arrays.asList(
|
||||
Arrays.asList("active", "=", true)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, List<String>> getQueryFieldMap() {
|
||||
return new HashMap() {{
|
||||
put("fields", Arrays.asList("default_code", "company_id", "display_name"));
|
||||
}};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> buildLarkBodyMap(JSONObject date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TableRelationTypeEnum syncLarkType() {
|
||||
return TableRelationTypeEnum.SYNC_ODOO_PRODUCT_PRODUCT;
|
||||
}
|
||||
}
|
Loading…
Reference in new issue