SAP HR Provisioning Modify Rule
Overview
This rule performs SAP HR modification operations during provisioning. This rule is typically used for attribute sync to custom SAP HR attributes.
Execution
- Connector Execution - This rule executes within the virtual appliance. It may offer special abilities to perform connector-related functions, and it may offer managed connections to sources.
- Logging - Logging statements are viewable within the ccg.log on the virtual appliance, and they are viewable 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 | 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. It is always null for this global rule. It is 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 provisioning request's status (success, failure, retry, etc.). |
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>
Attach to Source
Refer to Attaching Connector-Related Rules to Sources for details on how to attach your rule to your source.