Skip to Content

Introduction

On the second part of this blog we will see a way to automate Employee Import process using web-services.

The automation will be provided using SAP Cloud Platform Integration Services and API Replicate Basic Master Data for Workforce from External HR Systems.

On our sample scenario a file produced by an external systems is placed in a folder of a SFTP server containing Employee Master Data. CPI will consume this file, transform, map it and call S/4HANA Cloud API to complete employee creation.

Because we are working with a synchronous API integration flow will also take care of the response and send it back to the SFTP folder to be consumed by the external system.

The information contained in the response will allow the external system to update already created employees.

 

S/4HANA Cloud configuration

First step is to correctly identify our API and get documentation. To do so we go to api.sap.com and search for our API. The full name is Replicate Basic Master Data for Workforce from External HR Systems.

 

In the API details we find what are scope items using this API and what communication arrangement needs to be activated in S/4HANA Cloud to make this API active.

You can also find relevant business information by following the Business Documentation link. You can also find information about field data types and field cardinality can be found on API Reference tab.

 

Logon to your S/4HANA Cloud system and using Communication Arrangement application create a communication arrangement based on communication scenario SAP_COM_0301. During this process you will also need to create a communication system (representing the sending system) and communication user to set execute  basic authentication. From list of inbound services download the WSDL file for the API. This WSDL file will contain all required information i.e. endpoints.

After communication arrangement setup API is available and can be tested using tools like SOAP UI.

 

CPI – Integration flow design and configuration

On CPI we create an integration flow containing 3 communication components:

  • SFTP-out – representing folder to read Employee master data coming from the external system
  • S4HC – representing S/4HANA Cloud system
  • SFTP-in representing folder to write employee master data replication results

 

Step 0: Sender adapter configuration

Setup your sender adapter configuration with the details of your SFTP server. If using basic authentication you need to create user credentials first before you can finish the SFTP adapter configuration. Also for SFTP connections remember you need to add your SFTP fingerprint to the know_hosts file hosted on your CPI tenant.

You can test and get your SFTP server fingerprint by using the connectivity tests in CPI.

 

Step 1: CSV to XML converter

To convert from the CSV file to XML CPI offers a converter.

Configuration of the CSV to XML converter requires an XSD to define the output XML.

Documentation for this converter can be found here.

<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="http://www.example.org/basic_employee_import" elementFormDefault="unqualified" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.org/basic_employee_import">
    <complexType name="list_employee_type">
    	<sequence>
    		<element name="employee" type="tns:employee_type"
    			maxOccurs="unbounded" minOccurs="1">
    		</element>
    	</sequence>
    </complexType>
    <complexType name="employee_type">
        <sequence>
        	<element name="PersonUUID" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>
        	<element name="PersonExternalID" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="Username" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="BusinessPartnerRole" type="string"
        		maxOccurs="1" minOccurs="0">
        	</element>

        	<element name="Supplier" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="FirstName" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="LastName" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="PersonFullName" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="GenderCode" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="EmailAddress" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="PhoneNumber" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="MobilePhoneNumber" type="string"
        		maxOccurs="1" minOccurs="0">
        	</element>

        	<element name="Language" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="CompanyCode" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="CostCenter" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="StartDate" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>

        	<element name="EndDate" type="string" maxOccurs="1"
        		minOccurs="0">
        	</element>
        	<element name="PersonWorkAgreementUUID" type="string"
        		maxOccurs="1" minOccurs="0">
        	</element>
        	<element name="PersonWorkAgreementExternalID" type="string" maxOccurs="1" minOccurs="0"></element>
        </sequence>
    </complexType>
    <element name="root" type="tns:list_employee_type"></element>
</schema>

 

Step 2: Design a mapping from previous XSD to the request message of Replicate Basic Master Data for Workforce from External HR Systems API. The WSDL file needs to be uploaded to your Integration flow before you can assign to the target structure of the mapping.

Step 3: Call service

Use Call service and setup SOAP adapter receiver to configure the connection to S/4HANA Cloud API.

 

Step 4: Process response and transform response to CSV.

Using a Groovy script convert the SOAP API response back to CSV.

import com.sap.gateway.ip.core.customdev.util.Message;
import java.lang.StringBuilder;
import javax.xml.namespace.NamespaceContext;
import java.util.HashMap;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Document;


class localNamespaceContext implements NamespaceContext {
    
    public String getNamespaceURI(String prefix) {
    	if (prefix.equals("n0")) return "http://sap.com/xi/PASEIN";
    }

    public String getPrefix(String uri) {
        throw new UnsupportedOperationException();
    }

    public Iterator getPrefixes(String uri) {
        throw new UnsupportedOperationException();
    }
}


def Message processData(Message message) {
    

def sourceDocument = message.getBody(org.w3c.dom.Document);
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
xPath.setNamespaceContext(new localNamespaceContext());


StringBuilder finalMessage = new StringBuilder();

for (Node logNode : (NodeList) xPath.evaluate("//n0:WorkforcePersonMasterDataReplicationResponse_sync/WorkforcePersonMasterDataReplResponse", sourceDocument, XPathConstants.NODESET)) {

if(logNode!=null){

// Read ProcessStatusCode
Node processingStatusNode = ((Node) xPath.evaluate("./ProcessingStatusCode", logNode, XPathConstants.NODE));
String processingStatusValue = processingStatusNode.getTextContent();
int processingStatusValueInt = (Integer.valueOf(processingStatusValue)).intValue();

    // Read PersonExternalID
Node personExternalIdNode = ((Node) xPath.evaluate("./PersonExternalID", logNode, XPathConstants.NODE));
String personExternalIdValue = personExternalIdNode.getTextContent();

// Read PersonUUID
Node personUUIDNode = ((Node) xPath.evaluate("./PersonUUID", logNode, XPathConstants.NODE));
String personPersonUUIDValue = personUUIDNode.getTextContent();

//process workAgreementNode

        for (Node workAgreementNode : (NodeList) xPath.evaluate("./WorkforcePersonMasterDataReplConfLogMessage", logNode, XPathConstants.NODESET)) {
        
            finalMessage.append(personExternalIdValue+",");
            finalMessage.append(personPersonUUIDValue+",");
            finalMessage.append(processingStatusValue+",");
            
            Node personWorkAgreementExternalIdNode  = ((Node) xPath.evaluate("./PersonWorkAgreementExternalID", workAgreementNode, XPathConstants.NODE));
        	String personWorkAgreementExternalIdValue = personWorkAgreementExternalIdNode.getTextContent();
        	finalMessage.append(personWorkAgreementExternalIdValue+",");
        	Node personWorkAgreementUUIDNode  = ((Node) xPath.evaluate("./PersonWorkAgreementUUID", workAgreementNode, XPathConstants.NODE));
        	String personWorkAgreementUUIDValue = personWorkAgreementUUIDNode.getTextContent();
            finalMessage.append(personWorkAgreementUUIDValue+"\n");
        
        }
    }
}
    message.setBody(finalMessage.toString());    
    
       return message;
}

 

Step 5: Set file name

Using a Content Modifier set the target file name for the file.

Step 6: Send API result

On last step configure the inbound connection to your SFTP server. Use a different folder to store the API results.

 

Running the scenario

To start our integration scenario a file is added to the source folder of the SFTP server.

Wait for the polling time. The integration flow will start, read the file from the SFTP server and pass it to the CSV to XML converter.

After this step the payload will have an XML flat structure containing our Employee data.

<?xml version="1.0" encoding="UTF-8"?>
<ns0:root xmlns:ns0="http://www.example.org/basic_employee_import">
  <employee>
    <PersonUUID>
    </PersonUUID>
    <PersonExternalID>ET407</PersonExternalID>
    <Username>
    </Username>
    <BusinessPartnerRole>BUP003</BusinessPartnerRole>
    <Supplier>
    </Supplier>
    <FirstName>Harvey</FirstName>
    <LastName>Specter</LastName>
    <PersonFullName>Harvey Specter</PersonFullName>
    <GenderCode>1</GenderCode>
    <EmailAddress>
    </EmailAddress>
    <PhoneNumber>
    </PhoneNumber>
    <MobilePhoneNumber>
    </MobilePhoneNumber>
    <Language>EN</Language>
    <CompanyCode>1010</CompanyCode>
    <CostCenter>
    </CostCenter>
    <StartDate>20170401</StartDate>
    <EndDate>99991231</EndDate>
    <PersonWorkAgreementUUID>
    </PersonWorkAgreementUUID>
    <PersonWorkAgreementExternalID>ET407-1</PersonWorkAgreementExternalID>
  </employee>
</ns0:root>

 

Next step executes a mapping from the XML flat structure to API XML structure. The result is the following XML:

<?xml version="1.0" encoding="UTF-8"?>
<ns3:WorkforcePersonMasterDataReplicationRequest_sync xmlns:ns3="http://sap.com/xi/PASEIN">
  <WorkforcePersonMasterData>
    <PersonUUID>79fb0c90-cc78-4d2f-98f7-a03d1871d909</PersonUUID>
    <PersonExternalID>ET407</PersonExternalID>
    <UserName>
    </UserName>
    <PersonalInformation>
      <FirstName>Harvey</FirstName>
      <LastName>Specter</LastName>
      <PersonFullName>Harvey Specter</PersonFullName>
      <GenderCode>1</GenderCode>
    </PersonalInformation>
    <WorkAgreementInformation>
      <PersonWorkAgreementUUID>4678d2bc-3dbc-45e4-a526-3ecee631191b</PersonWorkAgreementUUID>
      <PersonWorkAgreementExternalID>ET407-1</PersonWorkAgreementExternalID>
      <PersonWorkAgreementType>1</PersonWorkAgreementType>
      <WorkAgreementJobInformation>
        <ValidityPeriod>
          <StartDate>2017-04-01</StartDate>
          <EndDate>9999-12-31</EndDate>
        </ValidityPeriod>
        <WorkAgreementStatus>1</WorkAgreementStatus>
        <CompanyCode>1010</CompanyCode>
        <CostCenter>
        </CostCenter>
      </WorkAgreementJobInformation>
    </WorkAgreementInformation>
  </WorkforcePersonMasterData>
</ns3:WorkforcePersonMasterDataReplicationRequest_sync>

 

The request is sent to the S/4HANA Cloud API for Employee replication. The synchronous interface returns the response with the results.

 

<n0:WorkforcePersonMasterDataReplicationResponse_sync xmlns:n0="http://sap.com/xi/PASEIN" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:prx="urn:sap.com:proxy:EAY:/1SAI/TAS47FED14EF0DCEA2C4738:772">
  <WorkforcePersonMasterDataReplResponse>
    <PersonUUID>79fb0c90-cc78-4d2f-98f7-a03d1871d909</PersonUUID>
    <PersonExternalID>ET407</PersonExternalID>
    <ProcessingStatusCode>01</ProcessingStatusCode>
    <WorkforcePersonMasterDataReplConfLogMessage>
      <PersonWorkAgreementUUID>4678d2bc-3dbc-45e4-a526-3ecee631191b</PersonWorkAgreementUUID>
      <PersonWorkAgreementExternalID>ET407-1</PersonWorkAgreementExternalID>
      <PersonWorkAgreement>50004703</PersonWorkAgreement>
      <LogItem>
        <TypeID>057(ECPAO_IN_PROCESSING)</TypeID>
        <SeverityCode>I</SeverityCode>
        <Note>Replication of employee data was successful for Employee ID ET407</Note>
      </LogItem>
    </WorkforcePersonMasterDataReplConfLogMessage>
  </WorkforcePersonMasterDataReplResponse>
</n0:WorkforcePersonMasterDataReplicationResponse_sync>

 

Last step  is to convert from the API XML service response to CSV and place it in the target destination folder.

 

That’s it! I hope you like it and if you have questions leave your comment bellow!

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

  1. Amaury Van Espen

    Good morning Carlos Dias

    thank you for this 2 parts blog post.

    I would like to know how could I get skills data from an Employee.

    As far as I know (and understood), there is a skills library and a skill management system (maybe related to the Learning Management System). Do these data would be exposable by API ?

    Thank you

    Amaury

    (0) 

Leave a Reply