Once our customer
receives a quote from our quoting system and has decided to proceed with
our company doing the work, we want to leverage SAP's Sales and
Distribution capabilities. SAP also has strengths in Sales and
Financials so instead of trying to build that functionality in our
Quoting system we want to take advantage of SAP's core capabilities in
this area.
The Quoting system will create a Sales Order request,
and provide information about the customer, and the materials
associated with the job. In return, SAP will create the sales order that
can be used for billing purposes and return an order number back to the
Quoting system.
Let's begin our solution by generating our SAP schemas:
Once again, we are going to leverage an out-of-the-box interface called CREATEFROMDAT2b, which can be found in the \BAPI\Sales and Distribution\Sales\Sales Order category.
Once
again, we do not want to expose our SAP Request to our Quoting system so
we are going to expose a more user friendly schema called CreateSalesOrderRequest.xsd. Inside this schema, we will find the following elements. All elements are strings with the exception of isCommitted, which happens to be a Boolean.
Field Name
|
Purpose
|
---|
/Header/DocumentType
|
Also referred to as Order Type. Typical values are OR(English value) or TA (German value).
|
/Header/SalesOrganization
|
Organizational unit within Logistics, which structures the company according to its sales requirements.
|
/Header/DistributionChannel
|
The distribution channel determines how materials or services are sold
and how they are distributed to customers, for example, retail,
wholesale, self-collection.
|
/Header/Division
|
The division is an organizational unit in Logistics in the R/3 System.
|
/Header/SalesOffice
|
The Sales Office or Sales area responsible for this transaction.
|
/Header/RequestedDate
|
The date that the products, or services, are required by.
|
/Header/PurchaseNo
|
Text that describes the Purchase Number.
|
/Header/Currency
|
The currency that the transaction will take place in.
|
/Material/MaterialID
|
The ID of the Material item that we would like to include in our purchase order.
|
/Material/TargetQU/
|
Target unit of measure.
|
/Partner/PartnerRole
|
A business partner role is used to classify a business partner in
business terms. The roles you assign to a business partner reflect the
functions it has and the business transactions in which it is likely to
be involved.
|
/Partner/Number&;
|
A number used to identify a customer.
|
isCommitted
|
This field is for demonstration purposes. It will trigger whether or not
we want to commit the order or roll the order back. In order to easily
determine whether or not this value is true or false, this field has
been marked as a distinguished field.
|
Our next step is to create a map that will transform our CreateSalesOrderRequest from our quoting system to our SALESORDER_CREATEFROMDAT2 SAP BAPI call. The name of this map is called CreateSalesOrderRequest_to_SALESORDER_CREATEFROMDAT2.btm.
The following image contains the detailed mapping instructions. Note
that the Material node is a recurring node so a looping functoid has
been added to ensure the correct amount of BAPISDITM nodes are created in the destination message. We also want to ensure that the BAPIRET2 node is instantiated so that SAP can return any errors. BAPIRET2
is a common table that is used for returning the status of the BAPI
that was just executed. Even if you are calling a custom BAPI, it is a
good practice to return this node. In order to provide this node in our
request message, we will simply drag a link from root node to the BAPIRET2 node.
Once
we have sent our SALESORDER_CREATEFROMDAT2 request to SAP and received a
response, we are going to need to provide our Quoting system with a
response message. A schema called CreateSalesOrderResponse.xsd has been created to handle this responsibility. Inside this schema, we will find three elements. CustomerNumber and SalesOrderNumber are strings while isCommitted is a Boolean.
Field Name
|
Purpose
|
---|
CustomerNumber
|
Since we will be using asynchronous messaging between the Quoting system
and BizTalk, we want to provide the customer number that the Sales
Order belongs to.
|
SalesOrderNumber
|
This is the identifier that SAP will provide when a Sales Order has been successfully created.
|
isCommitted
|
This field is also for demonstration purposes and will provide an
indicator to the quoting systems as to whether the transaction was
committed or rolled back. We will also mark this field as a
distinguished field so that we can conveniently update this flag within
our ProcessCreateSalesOrder.odx orchestration.
|
The map responsible for transforming the SAP Response into the Quoting System response is called SALESORDER_CREATEFROMDAT2Response_to_CreateSalesOrderResponse.btm. Since the isCommitted
field is not being returned from SAP, we will set an initial value of
true from a String Concatenate functoid and subsequently update this
flag in a Message Assignment shape within our ProcessCreateSalesOrder.odx orchestration.
We discussed when Creating,
Updating, and Deleting data via a BAPI that we need to either Commit or
Rollback the transaction. In order to satisfy the requirement of
committing the transaction, we need to create a map that will
instantiate an instance of a BAPI_TRANSACTION_COMMIT
message. The source message for this map can really be anything as we
are not using any of the message body payload data in the Commit
message. With this in mind, the CreateSalesOrderRequest message should work.
Similarly, we need to create a map that deals with Rollback scenarios. A map called CreateSalesRequest_to_BAPI_TRANSACTION_ROLLBACK.btm has been created for this purpose and it follows the same logic as the Commit map.
We are now at the point where we can assemble all of these artefacts within an orchestration called ProcessCreateSalesOrder.odx.
Our initial steps will involve the following actions: Receiving an instance of our CreateSalesOrderRequest message. Transforming our CreateSalesOrderRequest message into our SALESORDER_CREATEFROMDAT2 SAP Request message. Updating the message context to set the ConnectionState to "OPEN".By
setting it to OPEN, we are instructing the adapter to open a new
channel for the transaction. In order to set this message context, we
need to add an assembly reference for Microsoft.Adapters.SAP.BiztalkPropertySchema.dll. You can find this dll in the following locations: 32 bit: C:\Program Files (x86)\Microsoft BizTalk Adapter Pack\bin 64 bit: C:\Program Files\Microsoft BizTalk Adapter Pack(x64)\bin\
Send the SALESORDER_CREATEFROMDAT2Request to SAP. Receive the SALESORDER_CREATEFROMDAT2Response from SAP.
We
now want to perform a check to determine whether or not we should be
committing the transaction in SAP. To do this, we will add a Decide
shape to the orchestration and then check to see if our Request message
has its isCommitted flag set to true:
If msgCreateSalesOrderRequest.isCommitted
is set to true, then we will proceed with calling a transformation that
will convert our CreateSalesOrderRequest message into an instance of
our BAPI_TRANSACTION_COMMIT message. Once
this message has been transformed, we need to update its message
context properties in a Message Assignment shape. Within this shape, we
want to set the ConnectionState property to "CLOSE". By setting this property to CLOSE, we are instructing the adapter to commit the transaction and close the channel.
We now want to send our BAPI_TRANSACTION_COMMIT message to SAP. Once
the transaction has been committed, SAP will send us a response message
acknowledging that the transaction has been completed.
If msgCreateSalesOrderRequest.isCommitted is set to false, we want to rollback the transaction instead of committing the transaction. In order to rollback the transaction, we need to create an instance of a BAPI_TRANSACTION_ROLLBACK message by transforming our CreateSalesOrderRequest message. Once
this message has been transformed, we need to update its message
context properties in a Message Assignment shape. Within this shape, we
want to set the ConnectionState property to "ABORT". By setting this property to ABORT, we are instructing the adapter to abort the transaction and close the channel.
We now want to send our BAPI_TRANSACTION_ROLLBACK message to SAP. Once the transaction has been aborted, SAP will send us a response message acknowledging that the transaction has been canceled.
The
remaining steps include transforming our
SALESORDER_CREATEFROMDAT2Response into our CreateSalesOrderResponse that
we will send to our Quoting system. For
demonstration purposes, we added a flag on the CreateSalesOrderResponse
message to indicate whether or not Commit flag was set. In a Message
Assignment shape, we will simply assign the value that was populated in
the CreateSalesOrderRequest message.
Send a CreateSalesOrderResponse message back to the Quoting System.
We do not need to
re-add a strong name key; we can right mouse click on our Visual Studio
solution file and deploy our application. We need to add a Receive Port that
will receive messages from our Quoting system called ReceiveCreateSalesOrderRequests. We now need a Receive Location for this Receive Port called ReceiveCreateSalesOrderRequestsFromQuotingSystem that will use the FILE Adapter, the BizTalkServerApplication Receive handler, and the XMLReceive Receive pipeline. Since we are sharing a hot folder with the previous example, we need to provide a file mask of CreateSales*Copy*.xml.
We now
need to create our Send ports. The first Send port that we will create
will be used to communicate with SAP. The Send port that we will create
is called SendCreateSalesOrdersToSAP
and is responsible for sending the BAPI_SALESORDER_CREATEFROMDAT2,
BAPI_TRANSACTION_COMMIT, and BAPI_TRANSACTION_ROLLBACK messages. This Send port will use the WCF-SAP adapter, the BizTalkServerApplication Send handler, the XMLTransmit Send pipeline, and the XMLReceive Receive pipeline.
Click on the Configure button to edit the SAP specific properties. Click the Configure button again to edit the SAP URI. If you are unsure of the values for your organization, please contact your BASIS administrator.
Click the OK button to close this dialog. We now need to update the SOAP Action header
with the names of the operations that were created in our
Orchestration. Since this Send port is responsible for Sending the
Create Sales Order, Commit, and Rollback messages, we will need three
entries in this text box: <BtsActionMappingxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Operation Name="Operation_SendCreateSalesOrderCommit" Action="http://Microsoft.LobServices.Sap/2007/03/Bapi/BUS2032/BAPI_TRANSACTION_COMMIT/BAPI_TRANSACTION_COMMIT" />
<Operation Name="Operation_SendCreateSalesOrderRollback" Action="http://Microsoft.LobServices.Sap/2007/03/Bapi/BUS2032/BAPI_TRANSACTION_ROLLBACK/BAPI_TRANSACTION_ROLLBACK" />
<Operation Name="Operation_SendSalesOrderRequestsToSAP" Action="http://Microsoft.LobServices.Sap/2007/03/Bapi/BUS2032/CREATEFROMDAT2/BAPI_SALESORDER_CREATEFROMDAT2" />
</BtsActionMapping>
On the Binding tab, we want to ensure that EnableBizTalkCompatibilityMode and EnableSafeTyping are set to True.
On the Credentials tab, we need to provide our SAP credentials. In this scenario, we are using Username/Password credentials.
The
final Send port that we need to create will take care of sending our
Sales Order status back to the Quoting System. The Send port is called SendCreateSalesOrderResponsesToQuotingSystem, and uses the FILE Adapter, the BizTalkServerApplication Send handler, and the PassThruTransmit Send Pipeline. Lastly, we need to bind our ProcessCreateSalesOrder orchestration to the physical Receive and Send Ports that we just created.
We can now bounce our BizTalkServerApplication Host instance and start our application.
|