IdentityNow Rule Guide - SAP HR Provisioning Modify Rule
Purpose
This rule is used to perform SAP HR modification operations during provisioning. This is often used for attribute sync to custom SAP HR attributes.
Execution
- Connector Execution - This rule executes within the Virtual Appliance and may offer special abilities to perform connector-related functions, and may offer managed connections to sources.
- Logging - Logging statements are viewable within the ccg.log on the Virtual Appliance and by SailPoint personnel.
Input
Argument | Type | Purpose |
---|---|---|
application | sailpoint.object.Application |
Reference to the application object |
schema | sailpoint.object.Schema |
Reference to the application schema |
destination | com.sap.conn.jco.JCoDestination | A connected and ready to use SAP destination object that can be used to call BAPI function modules and call to SAP tables. |
plan | sailpoint.object.ProvisioningPlan |
Provisioning plan containing the provisioning request(s) |
request |
sailpoint.object.ProvisioningPlan. AbstractRequest |
AccountRequest being processed; always null for this global rule; only set for SapHrOperationProvisioning |
connector | sailpoint.connector.SAPHRConnector | Application connector being used for the operation |
Output
Argument | Type | Purpose |
---|---|---|
result | sailpoint.object.ProvisioningResult |
ProvisioningResult object containing the status (success, failure, retry, etc.) of the provisioning request |
Template
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="SapHrOperationProvisioning">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
Example
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="SapHrOperationProvisioning">
<Description>
This rule is used by the SAP HR connector for provisioning of the data.
</Description>
<Source><![CDATA[
import sailpoint.object.*;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AttributeRequest;
import sailpoint.object.ProvisioningPlan.ObjectOperation;
import sailpoint.object.ProvisioningPlan.AccountRequest.Operation;
import sailpoint.tools.Util;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;
import com.sap.conn.jco.AbapException;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;
import sailpoint.connector.ConnectorException;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoParameterField;
import com.sap.conn.jco.JCoParameterFieldIterator;
import com.sap.conn.jco.JCoParameterList;
import com.sap.conn.jco.JCoStructure;
import com.sap.conn.jco.JCoTable;
import com.sap.conn.jco.JCoContext;
// subtype values for email , Telephone or system user name
String SUBTYPE_EMAIL = "0010"; //Sub info type for email address
String SUBTYPE_PHONE= "0020"; //Sub info type for telephone number
String SUBTYPE_SY_USERNAME= "0001"; //Sub info type for sy-username which can be mapped to SAMAccountName of AD
ProvisioningResult result = new ProvisioningResult();
//This function will modify the email address , Telephone or system user name if recieved in the plan
public void doProvision() throws Exception {
List<AccountRequest> accReqList = plan.getAccountRequests();
String accNativeIdentity = null;
String endDateStr = "", beginDateStr = "";
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
if (!Util.isEmpty(accReqList)) {
for( AccountRequest accountReq : accReqList ) {
result.setStatus( ProvisioningResult.STATUS_COMMITTED );
accNativeIdentity = accountReq.getNativeIdentity();
// For update operation only Email,Telephone,SY-UNAME atrribute are supported
AttributeRequest emailAttr = accountReq.getAttributeRequest("Email");
AttributeRequest phoneAttrib = accountReq.getAttributeRequest("Telephone");
AttributeRequest syUserAttrib = accountReq.getAttributeRequest("System user name (SY-UNAME)");
HashMap beginEndDateList = getCommunicationData( accNativeIdentity );
//Finding the email attribute in provisioning plan and trying to modify the account's email id
if ( null != emailAttr ) {
if(null !=beginEndDateList && beginEndDateList.containsKey("emailBegin")) {
beginDateStr = formatter.format(beginEndDateList.get("emailBegin"));
endDateStr = formatter.format(beginEndDateList.get("emailEnd"));
}
modifyCommunicationData(accNativeIdentity, emailAttr.getValue(), SUBTYPE_EMAIL,beginDateStr,endDateStr);
}
//Finding the Telephone attribute in provisioning plan and trying to modify the account's phone
if ( null != phoneAttrib ) {
if(null !=beginEndDateList && beginEndDateList.containsKey("phoneBegin")) {
beginDateStr = formatter.format(beginEndDateList.get("phoneBegin"));
endDateStr = formatter.format(beginEndDateList.get("phoneEnd"));
}
modifyCommunicationData(accNativeIdentity, phoneAttrib.getValue(), SUBTYPE_PHONE,beginDateStr,endDateStr);
}
//Finding the system user name attribute in provisioning plan and trying to modify the account's System User Name
if ( null != syUserAttrib) {
if(null !=beginEndDateList && beginEndDateList.containsKey("syUserBegin")) {
beginDateStr = formatter.format(beginEndDateList.get("syUserBegin"));
endDateStr = formatter.format(beginEndDateList.get("syUserEnd"));
}
modifyCommunicationData(accNativeIdentity,syUserAttrib.getValue(), SUBTYPE_SY_USERNAME,beginDateStr,endDateStr);
}
}
}
}
// This function will get the communication details about a given employee
// In this example the email, Telephone and system user name begin and end date will be retrieved
public HashMap getCommunicationData( String id ) throws Exception {
HashMap commAttrsList = new HashMap();
JCoFunction getCommDetail = connector.getFunction(destination, "BAPI_EMPLCOMM_GETDETAILEDLIST");
getCommDetail.getImportParameterList().setValue("EMPLOYEENUMBER", id);
getCommDetail.getImportParameterList().setValue("TIMEINTERVALLOW", new Date());
getCommDetail.getImportParameterList().setValue("TIMEINTERVALHIGH", new Date());
try {
getCommDetail.execute(destination);
} catch (Exception e) {
connector.checkForExceptions(getCommDetail);
throw new Exception(e);
}
JCoTable commTable = getCommDetail.getTableParameterList().getTable("COMMUNICATION");
if ( commTable != null ) {
int rows = commTable.getNumRows();
for (int i = 0; i < rows; i++) {
commTable.setRow(i);
String commType = commTable.getString("SUBTYPE");
commAttrsList = getDateData(commTable, commAttrsList, commType);
}
}
return commAttrsList;
}
// function captures the begin date and end date
public HashMap getDateData(JCoTable commTable, HashMap commAttrsList, String commType) {
Date validBegDate = commTable.getDate("VALIDBEGIN");
Date validEndDate = commTable.getDate("VALIDEND");
if ( validBegDate != null && validEndDate != null ) {
if (commType.equals(SUBTYPE_EMAIL)) {
commAttrsList.put("emailBegin", validBegDate);
commAttrsList.put("emailEnd", validEndDate);
} else if (commType.equals(SUBTYPE_PHONE)) {
commAttrsList.put("phoneBegin", validBegDate);
commAttrsList.put("phoneEnd", validEndDate);
}else if (commType.equals(SUBTYPE_SY_USERNAME)) {
commAttrsList.put("syUserBegin", validBegDate);
commAttrsList.put("syUserEnd", validEndDate);
}
}
return commAttrsList;
}
/**Function modifies the email address , Telephone number and System user name of SAP HR record.
If Email or Phone is present(assigned) then used BAPI_EMPLCOMM_CHANGE
If Email or Phone is not present(assigned) then used BAPI_EMPLCOMM_CREATE
* @param userId
* @param parValue
* @param type
* @param begDate
* @param endDate
* @throws ConnectorException
*/
private void modifyCommunicationData( String userId, String parValue, String type,String begDate,String endDate ) throws ConnectorException {
JCoFunction jcoFunctionObject;
if (begDate.length() > 1 ) { //If date is alreday present then use BAPI_EMPLCOMM_CHANGE to modify data
jcoFunctionObject = connector.getFunction(destination,"BAPI_EMPLCOMM_CHANGE");
} else { //If date is not present then use BAPI_EMPLCOMM_CREATE to add data
jcoFunctionObject = connector.getFunction(destination,"BAPI_EMPLCOMM_CREATE");
}
// BAPI locks the record for processing
JCoFunction functionEnqueue = destination.getRepository().getFunction("BAPI_EMPLOYEE_ENQUEUE");
functionEnqueue.getImportParameterList().setValue("NUMBER", userId);
if ( functionEnqueue == null )
throw new RuntimeException("BAPI_EMPLOYEE_ENQUEUE not found in SAP.");
// BAPI to modify Communication data - email and phone
if ( jcoFunctionObject == null )
throw new RuntimeException("BAPI_EMPLCOMM_CHANGE not found in SAP.");
String returnPersonnelID = null;
jcoFunctionObject.getImportParameterList().setValue("EMPLOYEENUMBER", userId); // Personal Number
jcoFunctionObject.getImportParameterList().setValue("SUBTYPE", type); // SubType 0010/0020 - Email/Phone
jcoFunctionObject.getImportParameterList().setValue("VALIDITYBEGIN", begDate); // Begin Date
jcoFunctionObject.getImportParameterList().setValue("VALIDITYEND", endDate); // End Date
jcoFunctionObject.getImportParameterList().setValue("COMMUNICATIONID", parValue); // Email Address to modify
// BAPI unlocks the record after processing
JCoFunction functionDequeue = destination.getRepository().getFunction("BAPI_EMPLOYEE_DEQUEUE");
functionDequeue.getImportParameterList().setValue("NUMBER", userId);
if ( functionDequeue == null )
throw new RuntimeException("BAPI_EMPLOYEE_DEQUEUE not found in SAP.");
try {
// executing Bapis
JCoContext.begin(destination);
functionEnqueue.execute(destination);
jcoFunctionObject.execute(destination);
functionDequeue.execute(destination);
} catch (ConnectorException e) {
throw e;
} finally {
JCoContext.end(destination);
}
}
doProvision();
return result;
]]></Source>
</Rule>
Version history
Revision #:
4 of 4
Last update:
Sep 21, 2021
09:12 PM
Updated by: