Published at: 2025-10-30
4.3 [Function Components] Three Types of Custom Functions
4.21.1 Introduction to Three Types of Custom Functions Supported by the ERP Integration Platform
- Fixed Input Parameter:
Map syncArg
picture coming soon:
-
Fixed Return:
return syncArg; - Custom Function Validation:
The function body is considered an update/create/invalidate call if it contains any of the following strings:Fx.object.createFx.object.batchCreateFx.object.updateFx.object.batchUpdate
Scenario: If the custom function includes the above strings (even in comments) and contains a string matching the bound field’s
apiName(comments are also checked), the strategy will fail to activate and throw a “Function Validation Failed” exception. - Data Creation:
syncArg.objectDatacontains the Primary Object data.syncArg.detailscontains the Sub-object data.
- Data Update:
syncArg.objectDatamay contain either Primary Object or Sub-object data. UseobjApiNameto determine the type.
4.21.2 Pre-Sync Custom Function Execution for Data Filtering
If the returned result includes "isExec": "false", the sync process will halt, and the target data will remain unchanged.
Test Scenario: Add "isExec": "false" or "isExec": false to the custom function’s return Map. The target data will not update.
Function Code:
java
Map map = ["details":syncArg.details, "objectData":syncArg.objectData, "isExec":"false"];
return map;
4.21.3 Mid-Sync Custom Function Execution
After execution, mapped values written in the function will update, but the enterprise ID and object apiName remain unchanged.
Test Scenario:
- Only new data carries Sub-objects.
- Updates modify mapped values. Without distinguishing between Primary and Sub-objects, all objects will update with the assigned values from the custom function.
Function Code:
java
log.info("Event Type: " + syncArg.destEventType);
log.info(syncArg.objectData);
log.info(syncArg.details);
Map objectData = syncArg.objectData as Map;
objectData.name = "Modified by Custom Function";
Map map = ["details":syncArg.details, "objectData":syncArg.objectData];
log.info(map);
return map;
4.21.4 Post-Sync Custom Function Execution
After execution, mapped values written in the function will update, but the enterprise ID and object apiName remain unchanged.
Test Scenario: The sync process is unaffected. Data is passed to the custom function for logging purposes.
Function Code:
java
Map map = ["details":context.details, "objectData":context.data, "afterSync": "yes001"];
return map;
Key Input Fields and Examples
Pre-Sync (After Data Scope Validation)
Primary Input Fields:
java
{
"destObjectApiName": "", // Target object apiName
"sourceData": {"fieldApiName": "fieldValue"} // Object field info
}
Example:
java
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; // Setting this to false filters out the data from syncing
return syncArg;
Mid-Sync (Before Writing to Target System)
Primary Input Fields:
java
{
"destDetailSyncDataIdAndDestDataMap": {"": {"fieldApiName": "fieldValue"}}, // Target Sub-object data
"destData": {"fieldApiName": "fieldValue"} // Target Primary Object data
// For new Primary Objects, data is in `destData`; Sub-objects are in `destDetailSyncDataIdAndDestDataMap`. Updates handle Primary/Sub-objects separately.
}
Example:
java
// Modify the customerShortName field
log.info(syncArg);
syncArg["objectData"]["customerShortName"] = "dddddd";
log.info(syncArg);
return syncArg;
Post-Sync (After Writing to Target System)
Primary Input Fields:
java
{
"sourceDataId": "5fead1146660700001170e3d", // Source data ID (only for CRM→ERP direction)
"sourceObjectApiName": "AccountObj", // Source object apiName
"completeDataWriteResult": { // Target system write result
"detailWriteResults": [], // Sub-object results
"errCode": 0,
"success": true,
"destEventType": 1,
"errMsg": "success",
"writeResult": { // Primary Object result (errCode "s106240000" = success)
"errCode": 5001,
"success": false,
"syncDataId": "3ab1c2c2ffe04111b3e713632d5a4f76",
"errMsg": "Preprocessing error: External HTTP call failed. Error: 100, SAP system BP name already exists. ::errCode=s306240003",
"destDetailSyncDataIdAndDestDataMap": {}
}
},
"destObjectApiName": "AccountObj_1el03su6s", // Target object apiName
"objectData": { // Target data
"tenant_id": "706089", // Enterprise ID
"object_describe_api_name": "AccountObj_1el03su6s", // Object apiName
"_id": "5fead2696532bf0001e524e4"
},
"details": {} // Sub-object data
}
Example:
java
// CRM→ERP: Write target object ID back to CRM source object
log.info(syncArg);
if (syncArg["objectData"]["id"] != null && syncArg["objectData"]["id"] != ""
&& syncArg["sourceDataId"] != null && syncArg["sourceDataId"] != "") {
String destDataId = syncArg["objectData"]["_id"] as String; // Target data ID
String sourceDataId = syncArg["sourceDataId"] as String; // Source data ID
String errCode = syncArg["completeDataWriteResult"]["writeResult"]["errCode"] as String;
log.info("--" + errCode);
if (errCode == "0") {
def (Boolean error, Map data, String errorMessage) = Fx.object.update(
"AccountObj",
sourceDataId,
["field_b25i7__c": destDataId],
true
);
log.info(errorMessage);
}
}
return syncArg;