570 likes | 593 Views
Learn how to build B1 to B1 integration scenarios in SAP Business One Integration Framework (B1iF). This training covers setup steps, testing, and case analysis for seamless integration between systems.
E N D
Integration framework of SAP Business One Training Solution Architects TeamFebruary 2011 How to build a B1 to B1 scenario in B1iF
B1iF Training: How to build a B1 to B1 Scenario in B1iF • The following training is designed to show you how to build a B1 to B1 integration scenario using B1if. When you end this training you should be able to: • Build a scenario to integrate two SAP Business One Systems. • Setup the scenario and test it for running.
Agenda • Case Analysis BPM Diagram • B1 Config. Create BP • Integration Scenario Package Scenario Step Inbound Outbound Processing • Setup Steps Sender System Receiver System Data Management Activate • Test B1 Event Log Message Log • For information on how to install B1if please refer to the Installation How To.
Agenda • Case Analysis BPM Diagram • B1 Config. Create BP • Integration Scenario Package Scenario Step Inbound Outbound Processing • Setup Steps Sender System Receiver System Data Management Activate • Test B1 Event Log Message Log
Agenda • Case Analysis BPM Diagram • B1 Config. Create BP • Integration Scenario Package Scenario Step Inbound Outbound Processing • Setup Steps Sender System Receiver System Activate • Test B1 Event Log Message Log
B1Config: Create BP Create the Business Partners in the Subsidiary and the Headquarter. Its important that they match the information used in the UDT. Because the Subsidiary will be Purchasing goods from the HQ, the HQ BP (CardCode B1iFHQ) should be created as a Vendor in the Subsidiary company. Because the HQ will be selling goods to the Subsidiary, the Subsidiary BP (CardCode B1iFS1) should be created as a Customer in the HQ company.
Agenda • Case Analysis BPM Diagram • B1 Config. Create BP • Integration Scenario Package Scenario Step Inbound Outbound Processing • Setup Steps Sender System Receiver System Data Management Activate • Test B1 Event Log Message Log
Integration: Scenario Package Path: Scenarios/Package Design 1 2 3 B1i will add a prefix to the Scenario identifier corresponding to the namespace configured. The package will be created in design mode after save. If you want to modify the package later on, you can use the ellipsis (…) button next to the Scenario Package Identifier textbox to select your package.
Integration: Scenario Package Path: Scenarios/Package Design/[Definitions] 1 2 3
Integration: Scenario Package Path: Scenarios/Package Design/[Definitions] 1 2 3
Integration: Scenario Package Path: Scenarios/Package Design/[Definitions] 1 2
Integration: Scenario Package Path: Scenarios/Package Design/[Definitions] 2 1
Integration: Scenario Package Path: Scenarios/Package Design/[Definitions] 1
Integration: Scenario Step Path: Scenarios/Step Design 2 3 1 4 B1i will add a prefix to the Scenario identifier corresponding to the namespace configured. The step will be empty and a version number will be automatically assigned for version control.
Integration: Inbound (1/2) Path: Scenarios/Step Design/Working Step/[Inbound] 1 1 2 2 3 6 4 5 7 8
Integration: Inbound (2/2) 1 2 3 1 3 2 2 4 5
Integration: Outbound Path: Scenarios/Step Design/Working Step/[Outbound] 1 2 3 8 3 6 7 9 2 4 5 1 2
Integration: Processing Path: Scenarios/Step Design/Working Step/[Processing] The processing is the part in which B1if transforms the inbound message to the outbound message in order to get the desired results. Each processing unit inside the scenario step is called an atom and can do different actions. By default all scenario steps have one atom (called final) associated to an XSLT file to perform the last transformation.
Integration: Processing Path: Scenarios/Step Design/Working Step/[Processing] Create the following atom flow using the arrows at the right an bottom of the atoms: (XSL Transformation, Conditional Processing, Path, XSL Transformation and XSL Transformation)
Integration: Processing Path: Scenarios/Step Design/Working Step/[Processing] 1 2 3 4 If you enter the characters “[ ]” with some text inside, it will replace the generic name in the diagram.
Integration: Processing Path: Scenarios/Step Design/Working Step/[Processing] 1 2 3 4
Integration: Processing Path: Scenarios/Step Design/Working Step/[Processing] 1 2 3 4
Integration: Processing Path: Scenarios/Step Design/Working Step/[Processing] • Additional considerations for the xForm atoms • The XSL file of each atom will be modified outside B1if. • The description of the configuration is meant for reference, the information needed for the modification is the name of the atom XSLT file that is found on each xForm atom.
Integration: Processing Path: Scenarios/Step Design/Working Step/[Processing] The next step is to modify the XSLT file of the xForm atoms using your preferred XML Editor. In order to have access to the XSLT file you should give full access to the BizStore using WebDAV. For instructions please see B1if documentation.
Integration: Processing (atom1 - Global Table) <xsl:template name="transform"> <xsl:variable name="HQSysCode" select="/vpf:Msg/vpf:Header/vpf:ReceiverList/vpf:Receiver/@Id"/> <xsl:variable name="SenderSysCode" select="/vpf:Msg/vpf:Header/vpf:ReceiverList/vpf:Receiver/@Id"/> <xsl:for-each select="document('/com.sap.b1i.vplatform.scenarios.design/vPac.XXX.SASD001/vTbl.SysProp.xml')//table/row"> <xsl:choose> <xsl:when test="./col[1]=$HQSysCode"> <xsl:copy-of select="."/> </xsl:when> <xsl:when test="./col[1]=$vpSender"> <xsl:copy-of select="."/> </xsl:when> </xsl:choose> </xsl:for-each> </xsl:template> Locate the transform template tag to include your code
Integration: Processing (atom1 - Global Table) <xsl:template name="transform"> <xsl:variable name="HQSysCode" select="/vpf:Msg/vpf:Header/vpf:ReceiverList/vpf:Receiver/@Id"/> <xsl:for-each select="document('/com.sap.b1i.vplatform.scenarios.design/vPac.XXX.SASD001/vTbl.SysProp.xml')//table/row"> <xsl:choose> <xsl:when test="./col[1]=$HQSysCode"> <xsl:copy-of select="."/> </xsl:when> <xsl:when test="./col[1]=$vpSender"> <xsl:copy-of select="."/> </xsl:when> </xsl:choose> </xsl:for-each> </xsl:template> We create variables to get the information of the Internal System Id of the HQ (the receiver system).
Integration: Processing (atom1 - Global Table) <xsl:template name="transform"> <xsl:variable name="HQSysCode" select="/vpf:Msg/vpf:Header/vpf:ReceiverList/vpf:Receiver/@Id"/> <xsl:for-each select="document('/com.sap.b1i.vplatform.scenarios.design/vPac.XXX.B1PO2B1SO/vTbl.SysPropertiesTable.xml’)//table/row"> <xsl:choose> <xsl:when test="./col[1]=$HQSysCode"> <xsl:copy-of select="."/> </xsl:when> <xsl:when test="./col[1]=$vpSender"> <xsl:copy-of select="."/> </xsl:when> </xsl:choose> </xsl:for-each> </xsl:template> Global Tables are stored in XML files inside the Bizstore. We are copying the information that will be stored inside the table (that is filled during setup) and bring it to the message in order to simplify the xsl commands and queries. In this operation we are only copying the information of the systems involved in the scenario. Note: The path inside the document function in XSLT must be changed accordingly based on the bizstore path of your vPac file.
Integration: Processing Path: Scenarios/Step Design/Working Step/[Processing] 1 2 3 4 xPath Expression details on the next slide
Integration: Processing Path: Scenarios/Step Design/Working Step/[Processing] • Additional considerations for the Conditional and Path atoms • The conditional atom is NOT an exclusive execute condition. It will enter all the paths where the validation is true. • After the execution of the conditional atom a new root node is created to consolidate all the results. You should take that into account in the following steps. • The path atom doesn’t use variables so if the xPath condition is too long consider creating a previous xForm atom. • The xPath of the path atom consists of the xPath selection condition that will be copied to the next atom. In our example: /*[/vpf:Msg/vpf:Body/vpf:Payload[@id='atom1']/row[./col[1]=/vpf:Msg/vpf:Header/vpf:ReceiverList/vpf:Receiver/@Id]/col[2] = /vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']/BOM/BO/Documents/row/CardCode]
Integration: Processing (atom3 - SO Trans.) • <xsl:template name="transform"> • <xsl:variable name="DocEntryCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']/BOM/BO/Documents/row/DocEntry"/> • <xsl:variable name="DocNumCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']/BOM/BO/Documents/row/DocNum"/> • <FinalAtomResult xmlns=""> • <B1out type="object"> • <Documents> • <row> • <CardCode><xsl:value-of select="/vpf:Msg/vpf:Body/vpf:Payload[@id='atom1']/row[./col[1]=$vpSender]/col[2]"/></CardCode> • <DocCurrency><xsl:value-of select="$msg/BOM/BO/Documents/row/DocCurrency"/></DocCurrency> • <Reference1><xsl:value-of select="$msg/BOM/BO/Documents/row/Reference1"/></Reference1> • <Reference2><xsl:value-of select="$msg/BOM/BO/Documents/row/Reference2"/></Reference2> • <Comments><xsl:value-of select="$msg/BOM/BO/Documents/row/Comments"/></Comments> • <DocDueDate><xsl:value-of select="$msg/BOM/BO/Documents/row/DocDueDate"/></DocDueDate> • <NumAtCard>PO <xsl:value-of select="$DocNumCode"/>(<xsl:value-of select="$DocEntryCode"/>)</NumAtCard> • </row> • </Documents> • <Document_Lines> • <xsl:for-each select="$msg/BOM/BO/Document_Lines/*"> • <row> • <LineNum><xsl:value-of select="LineNum"/></LineNum> • <ItemCode><xsl:value-of select="ItemCode"/></ItemCode> • <Quantity><xsl:value-of select="Quantity"/></Quantity> • <Price><xsl:value-of select="Price"/></Price> • <Currency><xsl:value-of select="Currency"/></Currency> • </row> • </xsl:for-each> • </Document_Lines> • </B1out> • </FinalAtomResult> • </xsl:template> Locate the XSL template where to include your code
Integration: Processing (atom3 - SO Trans.) • <xsl:template name="transform"> • <xsl:variable name="DocEntryCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']/BOM/BO/Documents/row/DocEntry"/> • <xsl:variable name="DocNumCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']/BOM/BO/Documents/row/DocNum"/> • <FinalAtomResult xmlns=""> • <B1out type="object"> • <Documents> • <row> • <CardCode><xsl:value-of select="/vpf:Msg/vpf:Body/vpf:Payload[@id='atom1']/row[./col[1]=$vpSender]/col[2]"/></CardCode> • <DocCurrency><xsl:value-of select="$msg/BOM/BO/Documents/row/DocCurrency"/></DocCurrency> • <Reference1><xsl:value-of select="$msg/BOM/BO/Documents/row/Reference1"/></Reference1> • <Reference2><xsl:value-of select="$msg/BOM/BO/Documents/row/Reference2"/></Reference2> • <Comments><xsl:value-of select="$msg/BOM/BO/Documents/row/Comments"/></Comments> • <DocDueDate><xsl:value-of select="$msg/BOM/BO/Documents/row/DocDueDate"/></DocDueDate> • <NumAtCard>PO <xsl:value-of select="$DocNumCode"/>(<xsl:value-of select="$DocEntryCode"/>)</NumAtCard> • </row> • </Documents> • <Document_Lines> • <xsl:for-each select="$msg/BOM/BO/Document_Lines/*"> • <row> • <LineNum><xsl:value-of select="LineNum"/></LineNum> • <ItemCode><xsl:value-of select="ItemCode"/></ItemCode> • <Quantity><xsl:value-of select="Quantity"/></Quantity> • <Price><xsl:value-of select="Price"/></Price> • <Currency><xsl:value-of select="Currency"/></Currency> • </row> • </xsl:for-each> • </Document_Lines> • </B1out> • </FinalAtomResult> • </xsl:template> We create variables to simplify the coding of the reference of the document in the Sales Order.
Integration: Processing (atom3 - SO Trans.) • <xsl:template name="transform"> • <xsl:variable name="DocEntryCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']/BOM/BO/Documents/row/DocEntry"/> • <xsl:variable name="DocNumCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']/BOM/BO/Documents/row/DocNum"/> • <FinalAtomResult xmlns=""> • <B1out type="object"> • <Documents> • <row> • <CardCode><xsl:value-of select="/vpf:Msg/vpf:Body/vpf:Payload[@id='atom1']/row[./col[1]=$vpSender]/col[2]"/></CardCode> • <DocCurrency><xsl:value-of select="$msg/BOM/BO/Documents/row/DocCurrency"/></DocCurrency> • <Reference1><xsl:value-of select="$msg/BOM/BO/Documents/row/Reference1"/></Reference1> • <Reference2><xsl:value-of select="$msg/BOM/BO/Documents/row/Reference2"/></Reference2> • <Comments><xsl:value-of select="$msg/BOM/BO/Documents/row/Comments"/></Comments> • <DocDueDate><xsl:value-of select="$msg/BOM/BO/Documents/row/DocDueDate"/></DocDueDate> • <NumAtCard>PO <xsl:value-of select="$DocNumCode"/>(<xsl:value-of select="$DocEntryCode"/>)</NumAtCard> • </row> • </Documents> • <Document_Lines> • <xsl:for-each select="$msg/BOM/BO/Document_Lines/*"> • <row> • <LineNum><xsl:value-of select="LineNum"/></LineNum> • <ItemCode><xsl:value-of select="ItemCode"/></ItemCode> • <Quantity><xsl:value-of select="Quantity"/></Quantity> • <Price><xsl:value-of select="Price"/></Price> • <Currency><xsl:value-of select="Currency"/></Currency> • </row> • </xsl:for-each> • </Document_Lines> • </B1out> • </FinalAtomResult> • </xsl:template> Because we are in a conditional atom, we need to provide an easy way to select the results in all the available paths, no matter which route was taken. Including a single root node can help us later.
Integration: Processing (atom3 - SO Trans.) • <xsl:template name="transform"> • <xsl:variable name="DocEntryCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']/BOM/BO/Documents/row/DocEntry"/> • <xsl:variable name="DocNumCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']/BOM/BO/Documents/row/DocNum"/> • <FinalAtomResult xmlns=""> • <B1out type="object"> • <Documents> • <row> • <CardCode><xsl:value-of select="/vpf:Msg/vpf:Body/vpf:Payload[@id='atom1']/row[./col[1]=$vpSender]/col[2]"/></CardCode> • <DocCurrency><xsl:value-of select="$msg/BOM/BO/Documents/row/DocCurrency"/></DocCurrency> • <Reference1><xsl:value-of select="$msg/BOM/BO/Documents/row/Reference1"/></Reference1> • <Reference2><xsl:value-of select="$msg/BOM/BO/Documents/row/Reference2"/></Reference2> • <Comments><xsl:value-of select="$msg/BOM/BO/Documents/row/Comments"/></Comments> • <DocDueDate><xsl:value-of select="$msg/BOM/BO/Documents/row/DocDueDate"/></DocDueDate> • <NumAtCard>PO <xsl:value-of select="$DocNumCode"/>(<xsl:value-of select="$DocEntryCode"/>)</NumAtCard> • </row> • </Documents> • <Document_Lines> • <xsl:for-each select="$msg/BOM/BO/Document_Lines/*"> • <row> • <LineNum><xsl:value-of select="LineNum"/></LineNum> • <ItemCode><xsl:value-of select="ItemCode"/></ItemCode> • <Quantity><xsl:value-of select="Quantity"/></Quantity> • <Price><xsl:value-of select="Price"/></Price> • <Currency><xsl:value-of select="Currency"/></Currency> • </row> • </xsl:for-each> • </Document_Lines> • </B1out> • </FinalAtomResult> • </xsl:template> This is a basic XSLT transformation to generate the Sales Order. The <B1out> node will take care of the internal code of the target document and other technical procedures.
Integration: Processing (atom3 - SO Trans.) BIS <xsl:template name="transform"> <xsl:variable name="DocEntryCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']/BOM/BO/Documents/row/DocEntry"/> <xsl:variable name="DocNumCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role='S']/BOM/BO/Documents/row/DocNum"/> <FinalAtomResultxmlns=""> <BOM> <BO> <AdmInfo> <Object>17</Object> <Version>2</Version> </AdmInfo > <Documents> <row> <CardCode><xsl:value-of select="/vpf:Msg/vpf:Body/vpf:Payload[@id='atom1']/row[./col[1]=$vpSender]/col[2]"/></CardCode> <DocCurrency><xsl:value-of select="$msg/BOM/BO/Documents/row/DocCurrency"/></DocCurrency> <Reference1><xsl:value-of select="$msg/BOM/BO/Documents/row/Reference1"/></Reference1> <Reference2><xsl:value-of select="$msg/BOM/BO/Documents/row/Reference2"/></Reference2> <Comments><xsl:value-of select="$msg/BOM/BO/Documents/row/Comments"/></Comments> <DocDueDate><xsl:value-of select="$msg/BOM/BO/Documents/row/DocDueDate"/></DocDueDate> <NumAtCard>PO <xsl:value-of select="$DocNumCode"/>(<xsl:value-of select="$DocEntryCode"/>)</NumAtCard> </row> </Documents> <Document_Lines> <xsl:for-each select="$msg/BOM/BO/Document_Lines/*"> <row> <LineNum><xsl:value-of select="LineNum"/></LineNum> <ItemCode><xsl:value-of select="ItemCode"/></ItemCode> <Quantity><xsl:value-of select="Quantity"/></Quantity> <Price><xsl:value-of select="Price"/></Price> <Currency><xsl:value-of select="Currency"/></Currency> </row> </xsl:for-each> </Document_Lines> </BO> </BOM> </FinalAtomResult> </xsl:template>
Integration: Processing (atom4 – Ignore) <xsl:template name="transform"> <xsl:variable name="SenderCardCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role=‘S’]/BOM/BO/Documents/row/CardCode"/> <FinalAtomResultxmlns=""> <b1im_skip info="Filtered Card: {$SenderCardCode}"msglog="true"/> </FinalAtomResult> </xsl:template> Locate the XSL template where to include your code
Integration: Processing (atom4 – Ignore) <xsl:template name="transform"> <xsl:variable name="SenderCardCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role=‘S’]/BOM/BO/Documents/row/CardCode"/> <FinalAtomResultxmlns=""> <b1im_skip info="Filtered Card: {$SenderCardCode}"msglog="true"/> </FinalAtomResult> </xsl:template> Add variables to simplify the XSLT code. In this case we are retrieving the Subsidiary BP Code from the Global Table information that was retrieved earlier.
Integration: Processing (atom4 – Ignore) <xsl:template name="transform"> <xsl:variable name="SenderCardCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role=‘S’]/BOM/BO/Documents/row/CardCode"/> <FinalAtomResultxmlns=""> <b1im_skip info="Filtered Card: {$SenderCardCode}"msglog="true"/> </FinalAtomResult> </xsl:template> Because we are in a conditional atom, we need to provide an easy way to select the results in all the available paths, no matter which route was taken. Including a single root node can help us later.
Integration: Processing (atom4 – Ignore) <xsl:template name="transform"> <xsl:variable name="SenderCardCode" select="/vpf:Msg/vpf:Body/vpf:Payload[./@Role=‘S’]/BOM/BO/Documents/row/CardCode"/> <FinalAtomResultxmlns=""> <b1im_skip info="Filtered Card: {$SenderCardCode}"msglog="true"/> </FinalAtomResult> </xsl:template> The node generates a command to ignore the document.
Integration: Processing (atom0 - final) • Additional considerations for the final atom • When using conditional atoms the header of the message is modified so we need to correct it before the transformation. 1 2 6 5 3 4
Integration: Processing (atom0 - final) <xsl:template match="/"> <Msgxmlns="urn:com.sap.b1i.vplatform:entity"> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/@*"/> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/vpf:Header"/> <Body> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/vpf:Body/*"/> <Payload Role="R" id="{$atom}"> <xsl:call-template name="transform"/> </Payload> </Body> </Msg> </xsl:template> <xsl:template name="transform"> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/vpf:Body/vpf:Payload/FinalAtomResult/*"/> </xsl:template> Check the template at the header of the document.
Integration: Processing (atom0 - final) <xsl:template match="/"> <Msgxmlns="urn:com.sap.b1i.vplatform:entity"> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/@*"/> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/vpf:Header"/> <Body> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/vpf:Body/*"/> <Payload Role="R" id="{$atom}"> <xsl:call-template name="transform"/> </Payload> </Body> </Msg> </xsl:template> <xsl:template name="transform"> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/vpf:Body/vpf:Payload/FinalAtomResult/*"/> </xsl:template> After the Correct After Branch operation /bfa:unbranchis included on each one of the xsl:copy-of commands.
Integration: Processing (atom0 - final) <xsl:template match="/"> <Msgxmlns="urn:com.sap.b1i.vplatform:entity"> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/@*"/> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/vpf:Header"/> <Body> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/vpf:Body/*"/> <Payload Role="R" id="{$atom}"> <xsl:call-template name="transform"/> </Payload> </Body> </Msg> </xsl:template> <xsl:template name="transform"> <xsl:copy-of select="/bfa:unbranch/vpf:Msg/vpf:Body/vpf:Payload/FinalAtomResult/*"/> </xsl:template> The command selects the results of all the taken paths no matter the route that the message took.
Agenda • Case Analysis BPM Diagram • B1 Config. Create UDT Create UDF Fill Information Create BP • Integration Scenario Package Scenario Step Inbound Outbound Processing • Setup Steps Sender System Receiver System Data Management Activate • Test B1 Event Log Message Log
Setup: Steps 2 3 Path: Scenarios/Setup 4 5 6 1 4 2 3
Setup: Sender 2 3 Path: Scenarios/Setup 4 5 6 1 2 3 4 5 6
Setup: Receiver 2 3 Path: Scenarios/Setup 4 5 6 3 1 2 3 4 6 5
Setup: Data Management 2 3 Path: Scenarios/Setup 4 5 6 3 1 2 3 4
Setup: Data Management 2 3 Path: Scenarios/Setup 4 5 6 3 1 The SysId of the systems depends on your configuration.
Setup: Activate 2 3 Path: Scenarios/Setup 4 5 6 1 After the operation is completed the status of the Package is changed from design to activate 2