Logging In


You can only access B1iF through our VPN using its local IP

https://192.168.12.7:8443/B1iXcellerator/

You should see the screen below. Use the credentials given for B1ipeer

B1iF login


Cockpit


If successfully logged in, you should see the cockpit tab below

B1iF Cockpit

The cockpit view will show you if anything went wrong with a process, like if it’s stuck in a loop. These appear under DBQ Messages, but note that there are integrations by other offices that may have messages here.


SLD


The SLD tab is where the credentials for all the servers and databases are kept. Unless something goes wrong, you shouldn’t need to edit anything here.

You can add your own entry here for things like preconfigured HTTP requests which you can then select from a dropdown in the scenario builder.

B1iF SLD


Maintenance


The Maintenance tab is used for administrative tasks like user and customer administration and importing entire BizStore backups. You shouldn’t need to use anything in this tab. Deployment is better handled through the Scenarios tab.

B1iF Maintenance


Scenarios


The Scenarios tab is where you will be spending most of your time.

B1iF Scenarios

This is where all the integrations are along with all the tools you need to manage them.

Integrations have the structure below

  • Package
    • Scenario
      • Step

Warning: The current state does not fit the ideal structure.
Most steps should have their own scenarios.

Double click on a step to see a block code view of its logic.

Menu Items

In order the menu items are

  1. Inbound and Outbound
  2. Inbound
  3. Outbound
  4. External Adapter Call
  5. Include Scenario Step or BizFlow
  6. XSL/JavaScript Transformation
  7. Split (For-Each Processing)
  8. Join (For-Each Processing)
  9. Persist (BizStore Access)
  10. Adapter Call in BizFlow
  11. Call Java Class
  12. Branch (Conditional Processing)
  13. Unbranch (Conditional Processing)

There is also an arrow tool at the end which lets you join processes together.

The Inbound and Outbound blocks let you set the logic, encoding and authorization for incoming and outgoing requests, whether HTTP or internal requests.

Above the menu there is a branching tree icon (Adjust Step Flow Layout).
This will automatically rearrange the blocks in the step to be easy to follow.

Click on an I/O block to see its configuration menu in the bottom right corner.

IO Config

If you want to have unique ID’s to use in the smart messaging system, enclose a value in the description in [ ] to set it.

The json under Inbound pltype tells the scenario to parse the incoming request body as a JSON file. Similarly, the xml tells the scenario what format to send the response in. See JSON output below for details.

Storing query values

If you need to get information from a request with form data or query keys, simply click on the + icon next to Information Properties and add querykey.[key_name]. For example if you want to store the value for the queried so_number, (E.g. [request_url]?so_number=123123) enter querykey.so_number. 123123 will now be stored as a global variable and you will be able to access it from anywhere in the current step.


XSL/JavaScript Transformation and XPath


To edit any of the mappings or business logic, you need to first understand XSL Transformation (XSLT) and XPath. XSLT takes an XML file as an input and produces a new XML file. The way it does this is where things get messy.


XPath


XPath is a query language that lets you select parts of an XML document. It is used in virtually all blocks in B1iF since all internal messages are XML documents, and any external message that isn’t XML will get transformed into one.

Check out the syntax here.

The fastest way to learn XPath is by playing around with it yourself. This online XPath tester tool gives you instant feedback, so it’s a great way to experiment.


SAP-specific XPath queries


For incoming JSON files

The JSON file itself is accessed using the XPath below

bfa:io/bfa:object

To access a value at the root level of a JSON file (E.g. {"note": "Urgent"...})

bfa:io/bfa:object/bfa:string[./@name='note']

bfa:string[./@name='note'] points to the note property in the JSON.
The :string part indicates that the value is a valid JSON string.

Other possible values are :number, :bool, :array and :object

XSLT Block

XSL Transformations are specified by the yellow blocks above

Here is a part of the XSLT that maps an incoming order from Shopify to SAP’s expected order format/schema.

    <Documents>
        <row><!--multiple such elements are allowed-->
            <DocType>I</DocType>
            <HandWritten>N</HandWritten>
            <Printed>N</Printed>
            <DocDate><xsl:value-of select="bfa:io/bfa:object/bfa:string[./@name='created_at']"/></DocDate>
            <DocDueDate>20210607</DocDueDate><!-- TODO: Replace once business logic is known -->
            <CardCode>C000</CardCode><!-- Create a Shopify customer to use -->
            <NumAtCard><xsl:value-of select="bfa:io/bfa:object/bfa:string[./@name='order_name']"/></NumAtCard>
            <DocTotal><xsl:value-of select="bfa:io/bfa:object/bfa:string[./@name='total_price']"/></DocTotal>
            <DocCurrency>$</DocCurrency>
            <Comments object_code="{$object_code_var}">
                Shopify Note: <xsl:value-of select="bfa:io/bfa:object/bfa:string[./@name='note']"/>
            </Comments>
            <JournalMemo>Test Sales Order from Shopify</JournalMemo>
            <Confirmed>N</Confirmed>
            <PaymentGroupCode>2</PaymentGroupCode><!-- Assumes all orders are prepaid -->
            <Reference1><xsl:value-of select="bfa:io/bfa:object/bfa:string[./@name='order_name']"/></Reference1>
            <Reference2/>
        </row>
    </Documents>

XSL is essentially a templating language for XML, similar to how Liquid and PHP are templating languages for HTML.

The <xsl:...></xsl:...> tags are replaced with calculated values for a variable, an element from the incoming XML file, or an array of XML elements in the case of <xsl:for-each>.


Commonly used XSLT tags


value-of

<xsl:value-of 
    select="bfa:io/bfa:object/bfa:string[./@name='order_name']"
/>

Will get the result of the XPath expression in the select property and replace itself with that XML element.


variable

<xsl:variable 
    name="object_code_var" 
    select="bfa:io/bfa:object/bfa:string[./@name='object_code']"
/>

Instead of immediately rendering the element specified by select, the value is stored in a variable with name given.

To access the variable in a <xsl:value-of /> tag

<xsl:value-of select="$object_code_var"/>

To access the value of the variable inline, enclose it in { }. Generally used to set element properties.

<Comments object_code="{$object_code_var}">...</Comments>

Note: A variable with a given name can only be declared once.


for-each

<xsl:for-each select="bfa:io/bfa:object/bfa:array[./@name='line_items']/bfa:object">
    <row>    
        ...
    </row>
</xsl:for-each>

Creates a new XML element for each element in the array specified in select.

Most of the time your first element will be <row> since arrays in SAP require each member to be wrapped in <row></row> tags.


Finding the schema of an SAP B1 object


Thankfully B1iF provides a tool which gives the expected schema for any B1 object you may want to mutate.

Click on the Help tab and then B1 DI-API Object on the left side. Click on Object List, find the object that you want to mutate and click on Object Template next to it.

A pop-up will appear with the object template.

If you are using the DI API Object Ver.1.x block (B1DJ.1), do not include the BOM or BO.

Only include <Documents>, <Document_Lines> and any other relevant elements on the same level, otherwise the query will fail.


Inserting/Mutating objects


The final step in inserting a new object or mutating an existing one is the Adapter Call in BizFlow block.

To insert an object, set the Method to Synchronous Insert and Retrieval Mode to Read/Write with Field Names (ValidNodesOnly).

To update an existing object, set the Method to Synchronous Update and Retrieval Mode to All with Public Properties (NodesAsProperties).

The only thing the retrieval mode changes is what fields are available and how their names are formatted.

Set the Object Identifier to the object key of the object you want to change (E.g. 17 for Orders).

Set the payload to the preceding XSL Transformation object (E.g Xform1).

Finally, link the adapter call back to the I/O block and your basic integration is now complete!


JSON Output


JSON output in B1iF is arcane magic, so if you need it just use the template below.

Use this XSLT as the last step before sending the response, and make sure to set pltype to json in your I/O configuration.

<?bpc.pltype.out bpm.pltype=xml?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:app="urn:com.sap.b1i.xcellerator:appconfig" xmlns:b1e="urn:com.sap.b1i.sim:b1event" xmlns:b1ie="urn:com.sap.b1i.sim:b1ievent" xmlns:b1im="urn:com.sap.b1i.sim:b1imessage" xmlns:bfa="urn:com.sap.b1i.bizprocessor:bizatoms" xmlns:dev="urn:com.sap.b1i.dev.package" xmlns:jdbc="urn:com.sap.b1i.adapter:jdbcadapter" xmlns:js="com.sap.b1i.bpc_tools.Javascript" xmlns:rfc="urn:sap-com:document:sap:rfc:functions" xmlns:sim="urn:com.sap.b1i.sim:entity" xmlns:utils="com.sap.b1i.bpc_tools.Utilities" xmlns:vpf="urn:com.sap.b1i.vplatform:entity" xmlns:xci="urn:com.sap.b1i.xcellerator:intdoc" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="app b1e b1ie b1im bfa dev jdbc js rfc sim utils vpf xci" version="1.0" dev:force="" bfa:force="" vpf:force="" utils:force="" jdbc:force="" rfc:force="" b1e:force="" b1ie:force="" b1im:force="" sim:force="" xci:force="" app:force="" js:force="">
        <xsl:include href="../../com.sap.b1i.dev.repository/IDE/init.xsl"/>
            <xsl:template match="/">
                
                <io xmlns="urn:com.sap.b1i.bizprocessor:bizatoms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" pltype="json" xsi:schemaLocation="urn:com.sap.b1i.bizprocessor:bizatoms json_pltype.xsd">
                    <object>
                        <array name="Orders" >
                        <xsl:for-each select="(bfa:call/bfa:outbound/bfa:payload/*)[1]/*">
                            <object>
                              <string name="CardCode">
                                <xsl:copy-of select="namespace-uri(.)"/>
                                <xsl:copy-of select="name(./*)"/>
                              </string>
                              <string name="CardName">
                                <xsl:copy-of select="name(./*/*)"/>
                              </string>
                              <object name="Orders">
                                  <xsl:for-each select="./*">
                                      
                                      <object name="{string((./*)[1])}">
                                          <string name="DocNum">
                                            <xsl:value-of select="./*[name()='DocNum']"/>
                                          </string>
                                          <string name="NumAtCard">
                                            <xsl:value-of select="./*[name()='NumAtCard']"/>
                                          </string>
                                          <string name="CardCode">
                                            <xsl:value-of select="./*[name()='CardCode']"/>
                                          </string>
                                          <string name="CardName">
                                            <xsl:value-of select="./*[name()='CardName']"/>
                                          </string>
                                          <string name="DocDate">
                                            <xsl:value-of select="./*[name()='DocDate']"/>
                                          </string>                          
                                          <string name="CreateDate">
                                            <xsl:value-of select="./*[name()='CreateDate']"/>
                                          </string> 
                                          <string name="UpdateDate">
                                            <xsl:value-of select="./*[name()='UpdateDate']"/>
                                          </string> 
                                          <string name="DocTime">
                                            <xsl:value-of select="./*[name()='DocTime']"/>
                                          </string> 
                                          <string name="DocTotal">
                                            <xsl:value-of select="./*[name()='DocTotal']"/>
                                          </string> 
                                          <string name="Address">
                                            <xsl:value-of select="./*[name()='Address']"/>
                                          </string> 
                                          <string name="Comments">
                                            <xsl:value-of select="./*[name()='Comments']"/>
                                          </string>    
                                          <string name="DocStatus">
                                            <xsl:value-of select="./*[name()='DocStatus']"/>
                                          </string>    
                                          <string name="CANCELED">
                                            <xsl:value-of select="./*[name()='CANCELED']"/>
                                          </string>    
                                          <string name="SlpCode">
                                            <xsl:value-of select="./*[name()='SlpCode']"/>
                                          </string>                                              
                                      </object>
                                  </xsl:for-each>
                              </object>
                            </object>
                      </xsl:for-each>
                      </array>
                    </object>
                </io>
            </xsl:template>
    </xsl:stylesheet>