Skip to main content

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.

Rule Execution

Input

ArgumentTypePurpose
applicationsailpoint.object.ApplicationReference to the application object.
schemasailpoint.object.SchemaReference to the application schema.
destinationcom.sap.conn.jco.JCoDestinationConnected and ready-to-use SAP destination object that can be used to call BAPI function modules and call to SAP tables.
plansailpoint.object.ProvisioningPlanProvisioning plan containing the provisioning request(s).
requestsailpoint.object.ProvisioningPlan.AbstractRequestAccountRequest being processed. It is always null for this global rule. It is only set for SapHrOperationProvisioning.
connectorsailpoint.connector.SAPHRConnectorApplication connector being used for the operation.

Output

ArgumentTypePurpose
resultsailpoint.object.ProvisioningResultProvisioningResult 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.