I’ve had the fortune to create two different Invoice routing applications in BizTalk. Lesson learned we made some improvements to the solution when it was time for #2 :)
Here I´m going to try and explain all the pitfalls and “good-to-know” which will hopefully save you a couple of hours of head scratching.
Some clarification before we start. I presume that you have already handled the invoice mapping from your sending invoice system, and the invoice lay outing is already done so that you are left with one or two files that you need to route to the appropriate customer. Often when talking about invoicing there are two types of files involved. One xml file with the raw data, and one pdf or image file that visualizes the data from the xml invoice.
Xml invoice is used to send to brokers that can send the invoice electronic to customers and the pdf/image file is used for email or printing and sending in a more traditional way; by mail. In the example below I use an xml message of the type E2B.
Step 1: Pair the xml and pdf/image file with each other when BizTalk receive them. You can’t exactly know when you receive them both, or in which order. For this we have set up an orchestration with a scope containing a parallel action shape that waits for both files to be received from two different receive ports; one for the xml and one for the pdf.
We have a timeout set on the scope that times out after given time if we haven’t received both files. In this way we can take proactive action before the customer calls you and wonder where the invoice is. It could be stuck in BizTalk forever if you don’t tell BizTalk what to do.
For this receive scenario we use a correlation set on the filename. Let’s presume the filename is set in this following format. [SendingOrgNumber]_[ReceiverOrgNumber]_[InvoiceNumber].[FileType] We then need to match on everything except the [FileType]. For this we create a custom pipeline component, to be used on the receive pipeline, that strips the file extension and promotes the value as ReceivedFileName in the default context.
In this way we get two files that are named exactly the same; leading to BizTalk being able to correlate the two files into the same orchestration. Fortunately we receive the files on different ports, so even though we are inside the orchestration with two files that are named exactly the same we know which is the xml and which is the pdf/image file.
Step 2: Set up routing information. Paper, email or electronic Invoice? Here we have more than one way to get information on how to route the invoice. In the first solution I built we had masterdata information about a customer in a database and fetched routing information based on the organization number fetched from the message itself. In the second one we had the information in the xml file when we received it. Here it is up to you how to get this information.
The important thing is to promote this value so that we can filter on this value on the send ports in the last step. i.e. 1=paper invoice, 2=email, 3=eInvoice.
Step 3: Decide if message should be routed via email or not. If routing is email then there is a dynamic send port set up in the orchestration for this scenario.
The only thing we need to do is to construct the message, promote receive type and reset the filename with file extension as shown in picture above. Last step before sending the invoice through the dynamic email port is to set up SMTP settings. (Here we read settings from appsettings file which makes it easier to change values without the need to actually redeploy solution). Important is to set the outbound SMTP server and credentials inside the construct message shape and also the email address, which is set in an expression shape. Example could look like textbox below.
But if it wasn’t then we really need the routing information in the context of the message. This is where we send the file to the appropriate send port and out of BizTalk’s control. We could set up send ports for each scenario. I.e. one send port for eInvoice xml and one for eInvoice pdf file, then one more for printhouse pdf, and maybe we want archiving… Like that you would end up with an orchestration full of send ports and every time you need to add a scenario you need to redeploy the solution. Instead we set up a send port for the xml and one for the pdf file, to be sent to the messagebox.
From there we can set up send ports in BizTalk Admin Console and set filter on receive type and message type. Then we have a clean orchestration and all other configuration in the admin console, easily configurable and easy to add one more subscription.
One very important thing to keep in mind when sending xml and pdf to the messagebox and you want to be able to filter on custom context properties on pdf you have to set up a correlation set for the pdf file. To be able to make custom context values to show up as promoted in the message you first have to promote the BTS.MessageType on the PDF send port. Create a new correlation set. When in the Correlation Properties window, scroll down to BTS and choose MessageType. Also choose your custom context values from your own custom property schema. Set initializing correlation sets on the xml message to the correlation set you just created and then set following correlation sets to the same on the send pdf.
Step 5: Filtering on send ports. Last step is to set up the actual filter and send the invoice. Here it is up to you to choose how to send the files. In my scenario I have an xml namespace on the xml file and the pdf file, which is treated as a System.Xml.Document inside the orchestration, has no namespace.
So if I would like to send only the xml file to eInvoice broker then I can set up a filter like this. (In my scenario invoice receiveType is 3 for eInvoice).
If you only want to send the pdf all you have to do is to set up filter to say that MessageType is not like http://www.e2b.no/XMLSchema/Internal#Interchange. In this way you can set up arbitrarily send ports to subscribe on the same message without the need to change or redeploy the BizTalk application.
Hope you found this useful and good luck setting up your own SalesInvoice routing application in the future! :)