一、同步前自定义函数执行支持数据过滤
即函中返回结果中包含"isExec":"false",即该次同步将不再往后执行,目标数据将不会做出相应的更改。
测试场景:在自定义函数返回的Map中加入"isExec":"false",或"isExec":false目标数据将不会发生更改。
函数代码:
Map map = ["details":syncArg.details, "objectData":syncArg.objectData, "isExec":"false" ]; return map;
二、同步中执行自定义函数
函数执行后,在函数中编写的映射值修改,企业id和对象apiName不会更改。
测试场景:只有新增数据,才会携带从对象;更新时会更新对象映射值,因此如果没有对从对象做出特殊鉴别,更新的对象将不区分主从对象,一律更新,主从对象名称都会更新为自定义函数赋值
函数代码:
log.info("事件类型:" + syncArg.destEventType); log.info(syncArg.objectData); log.info(syncArg.details); Map objectData = syncArg.objectData as Map; objectData.name = "自定义函数修改" Map map = ["details":syncArg.details, "objectData":syncArg.objectData]; log.info(map); return map;
三、同步后执行自定义函数
函数执行后,在函数中编写的映射值修改,企业id和对象apiName不会更改。
测试场景:数据同步不会受到影响,只是将数据传给自定义函数即可,需要通过查看日志进行判断
函数代码:
Map map = ["details":context.details, "objectData":context.data, "afterSync" : "yes001"]; return map;
具体入参字段(如果不清楚入参有什么字段就先把函数写好,然后打印入参看一下,注意新增和更新入参不一样)和函数例子如下
同步前:通过数据范围的校验之后
主要入参字段:
{ "destObjectApiName": "",//目标对象apiName "sourceData": {"字段apiName":"字段值"}//对象字段信息 }
简单例子:
log.info(syncArg); String destObjApiName=syncArg["destObjectApiName"] as String; log.info("destObjectApiName:"+destObjApiName); if("object_xo21i__c"==destObjApiName){ return syncArg; } Map objectData=syncArg["objectData"] as Map; String customerCode=objectData["customerCodeHead"] as String; syncArg["isExec"]=false;//把这个字段设置为false,会过滤掉这条数据不同步 return syncArg;
同步中:写入目标系统之前
主要入参字段:
{ "destDetailSyncDataIdAndDestDataMap": {"":{"字段apiName":"字段值"}},//目标对象明细 "destData": {"字段apiName":"字段值"}//目标对象字段信息 //如果新增主对象在destData,明细数据在destDetailSyncDataIdAndDestDataMap,如果是更新主从数据都在destData(更新是单独更新的) }
简单例子:
//修改customerShortName字段值 log.info(syncArg); syncArg["objectData"]["customerShortName"]="dddddd" log.info(syncArg); return syncArg;
同步后:写入目标系统之后
主要入参字段:
{ "sourceDataId": "5fead1146660700001170e3d",//源数据id,只有crm->erp方向有这个字段 "sourceObjectApiName": "AccountObj",//源对象apiName "completeDataWriteResult": {//写入目标数据的结果 "detailWriteResults": [],//明细数据结果 "errCode": 0, "success": true, "destEventType": 1, "errMsg": "success", "writeResult": {//主数据结果,errCode为s106240000成功,其他的失败接口返回的错误码 "errCode": 5001, "success": false, "syncDataId": "3ab1c2c2ffe04111b3e713632d5a4f76", "errMsg": "预处理服务调用错误:调用外部http接口失败,错误信息:100,SAP系统BP名称已创建,不允许重复创建。::errCode=s306240003", "destDetailSyncDataIdAndDestDataMap": {} } }, "destObjectApiName": "AccountObj_1el03su6s",//目标数据对象apiName "objectData": {//目标数据 "tenant_id": "706089",//企业ei "object_describe_api_name": "AccountObj_1el03su6s",//对象apiName "_id": "5fead2696532bf0001e524e4" }, "details": {},//明细数据 }
简单例子:
//crm->erp,把目标对象的id写到crm源对象 log.info(syncArg) if(syncArg["objectData"]["_id"]!=null&&syncArg["objectData"]["_id"]!="" &&syncArg["sourceDataId"]!=null&&syncArg["sourceDataId"]!=""){ String destDataId=syncArg["objectData"]["_id"] as String;//目标数据id String sourceDataId=syncArg["sourceDataId"] as String;//源数据id String errCode=syncArg["completeDataWriteResult"]["writeResult"]["errCode"]as String; log.info("--"+errCode) if (errCode =="0"){//&&destDataId.length()<11 def (Boolean error,Map data,String errorMessage) = Fx.object.update("AccountObj",sourceDataId, ["field_b25i7__c":destDataId],true); log.info(errorMessage) } } return syncArg;
四、 登录k3的webapi获取数据
//定义请求参数,url,用户名,密码,数据中心
String url = "";//http://jxsz.fortiddns.com:58000/k3cloud/
String userName = "";
String passWord = "";
String acctId = "";//62415a905fb572
//请求头
Map headMap = ["Content-Type":"application/json"];
//金蝶k3c登录授权处理,登录授权需要参数:URL地址,登录用户名,密码,语言,数据中心ID,调用方法名
String login = "Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc";
//查询接口方法
String queryMethod = "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc";
Map bodyMap1 = [:];
//返回结构
Map returnMap = [:];
bodyMap1.put("lcid", "2052");
bodyMap1.put("userName", userName);
bodyMap1.put("passWord", passWord);
bodyMap1.put("acctId", acctId);
StringBody body = StringBody.builder().content(bodyMap1).build()
Request request = Request.builder()
.method("POST")
.url(url+login)
.timeout(7000)
.retryCount(0)
.header("Content-Type","application/json")
.body(body)
.build()
def(Boolean error1, HttpResult data1, String errorMessage1) = Fx.http.execute(request);
if(error1){
log.info("调用登录接口异常:"+errorMessage1)
}
//从登录结果取kdservice-sessionid和ASP.NET_SessionId
Map headers = data1["headers"] as Map;
if(headers==null){
Fx.message.throwErrorMessage("登录失败:"+data1);
}
String Cookies = headers["Cookies"] as String;
log.info("Cookies是"+Cookies);
String sessionid=Cookies.split(";")[0];
String NET_SessionId=Cookies.split(";")[1];
sessionid=sessionid.split("=")[1];
NET_SessionId=NET_SessionId.split("=")[1];
//请求体
Map bodyMap = [:];
//返回最大行数
Integer TopRowCount=0;
//需查询的字段key集合
String FieldKeys="FCUSTID,FNumber";
//业务对象表单Id,
String FormId="BD_Customer";
//查询条件
String FilterString="FNumber != ''";
//最大行数
Integer Limit=10;
//开始行索引
Integer StartRow=0;
//组合参数
//组合查询条件参数
Map data = ["TopRowCount":TopRowCount,"FieldKeys":FieldKeys,"FormId":FormId,"FilterString":FilterString,"Limit":Limit,"StartRow":StartRow];
bodyMap.put("data", data);
//查询数据
StringBody body1 = StringBody.builder().content(bodyMap).build()
Request request1 = Request.builder()
.method("POST")
.url(url+queryMethod)
.timeout(7000)
.retryCount(0)
.header("Content-Type","application/json")
.header("kdservice-sessionid",sessionid)
.header("ASP.NET_SessionId",NET_SessionId)
.body(body1)
.build()
//log.info(url+method);
def(Boolean error, HttpResult Result, String Message) = Fx.http.execute(request1);
log.info("返回的数据信息为:"+Result);
//开始处理数据
String contentStr = Result["content"] as String;
if(contentStr){
//查询失败
if(contentStr.contains("ResponseStatus")){
Fx.message.throwErrorMessage(contentStr);
}
//有数据就开始处理,返回为空就跳过
List contentList = Fx.json.parseList(contentStr);
log.info("contentList:"+contentList);
String[] keyList = FieldKeys.split(",");
contentList.each{ item ->
List eachDataList=item as List;
log.info("eachDataList:"+eachDataList)
Map eachData=[:]
//每一条数据
eachDataList.eachWithIndex{ value,int i ->
eachData.put(keyList[i], value)
}
log.info("eachData:"+eachData)
}
}