Mapping Data - BizTalk 2013 EDI for Health Care: HIPAA-Compliant 834 (Enrollment) and 837 (Claims) Solutions (2014) (2014)

BizTalk 2013 EDI for Health Care: HIPAA-Compliant 834 (Enrollment) and 837 (Claims) Solutions (2014)

Chapter 4. Mapping Data

Constructing and deconstructing the data in the various EDI formats associated with health care is a task that requires both analysis and development skills. There are people within claims management who specialize in working with data as it is defined in the various formats, and someone acting as an EDI analyst will be critical during initial inbound and outbound BizTalk map implementations.

It is possible to look at an implementation guide and make intelligent decisions about how data should be mapped, but without the EDI analyst testing and reviewing the data, the chances of getting a fully compliant document that your trading partner will be able to consume is unlikely. To improve your chances for a compliant EDI document early in the development process, make sure to take the following steps:

· Whenever possible, get access to an actual EDI document that is being used for the specific trading partner you are working with. Implementation guides are good for reference, but as a developer, having access to the actual file is of immense value. It allows for side-by-side comparisons between what you are creating in BizTalk and what you know is a valid format.

· There are many alternative ways to populate data in the 837 Professional, Institutional, and Dental formats, and in the 834 enrollment, maintenance, reconciliation, and effectuation formats, and it is common to have mapping requirements that are unique to a trading partner. Be prepared to have maps that are very different between partners, whether inbound or outbound.

· Different trading partners require different levels of validation on data delivered to them. BizTalk officially supports level 1 and level 2 of HIPAA compliance validation (though it is arguable that levels 3 and 4 are met unofficially). If more levels of compliance are required, you will need to create your level 2 compliant document in BizTalk and then deliver the final file (individual or batched) to another application that will perform the additional levels of validation.

· The work of creating an outbound 834 or 837 document from scratch will likely require both a developer and an EDI Analyst. The developer will be focused on the BizTalk map implementation while the EDI Analyst will need to work with the developer to unit test the data. The testing portion of mapping health care EDI data, especially when dealing with the 837 formats, will take as much time as the actual development. Don’t underestimate the need for this resource - only rarely will you find someone who can do both development and full analysis and testing of this type of data.

· In some cases, mapping is best done in multiple stages. It is always nice to be able to map a source document to the target EDI document (or vice versa) in a single map, but it does not always allow for the easiest or most maintainable solution. When developing your maps, think about the next person who may have to take these maps over from you at a later time. Will they be able to interpret what you have done and make modifications to it, if needed? When planning your mapping, think about ways to simplify your logic, and determine if creating several maps that take the data through several phases of transformation could ease your development.

The topics in this chapter will cover how to approach mapping the 834 and 837 formats (and mapping solutions in general) with several development techniques. While it isn’t possible to demonstrate how to map either format in its entirety, it is possible to cover some key foundational information, and with some patience and (ideally) access to an EDI analyst, you will be able to create maps that are well architected and use the most appropriate mapping technologies.

image Note When building outbound maps where you have control over the source data you are mapping from, try to pre-format as much data as possible (in the source flat file or database result set) so that once it gets to the BizTalk map, there is as little additional mapping needed as possible. The less complex your map is, the easier your solution will be to develop, test, and maintain.

BizTalk Mapping Technologies

There are several technologies that you will need to be very comfortable with in order to have the tools available in BizTalk to handle the complex mapping that is associated with working on 834 and 837 document implementations. The BizTalk Visual Studio map is the canvas for development, but there are numerous options for mapping the data. These mapping technologies are as follows:

· Functoids. There are many functoids available to you, and it is possible to implement almost all of the 834 and 837 mapping requirements without the use of externals scripts. However, trying to implement an 837 map without the use of external scripts is a mistake, and will lead to an enormously complex map. Trying to support outbound 834 effectuation and reconciliation for integration with some trading partners without the use of external scripts is virtually impossible in many scenarios.

· Inline .NET code. The Scripting functoid in the mapper allows for a variety of script languages. You can accomplish quite a bit within these scripts, but you have limited access to libraries. Only those libraries available to XLANG can be used within a Scripting functoid, which is a subset of the overall .NET framework.

· External .NET Assemblies. When you need the power of the full .NET engine and associated libraries, you’ll want to develop an actual assembly with methods that can be called from maps. Some tasks, such as interactions with a database, are often best done in external assemblies (as opposed to adapters).

· Inline XSLT. This is a very important skill to develop, and should not be overlooked or avoided. Tasks that could take many functoids or complex external .NET scripts can be done quickly using XSLT. Some mapping issues in more complex documents can’t even be solved without the use of XSLT. While there will be some ramp up in learning this scripting language, it will be worth your time investment.

· External XSLT. In most cases, you will use the functoids and mapping options available in the map to complete your solution. In other cases, you may want to simply shell out to an external XSLT file to handle the mapping.

· SQL Stored Procedures. When dealing with business rules, data level transformations, or lookups, you may want to create stored procedures and deal with logic there. Calling a stored procedure through an external .NET assembly from a map is an easy architecture to build, and can be of great benefit.

Looking at actual examples of mapping technologies is what the rest of this chapter is devoted to. With these specific examples in front of you, you should be able to jump into the development of your 834 and 837 health care maps with a solid direction as to how to implement. You’ll look at several examples - data being mapped to an outbound 837 and data being mapped from an inbound 834 and 837. Chapter 9, “Advanced 834 Mapping” covers how to map to an advanced form of the outbound 834.

Mapping to an Outbound 837

Mapping to an 837 from an internal data structure is required whenever you are sending outbound data. The solution outlined in Chapter 3 (“Solution: Sending 837P Data”) discusses creating the internal data structure from an SQL Server stored procedure. However, source data can come from a variety of sources, including flat files, internal 837 documents, and various database structures, just to name a few. In the end, you will always be mapping from a source structure to the target 837 schema, and the mapping requirements will be similar regardless of the actual source of data.

Formatting Dates using an External .NET Assembly

There are a large number of date fields in an 837 document that have to be populated. Take the scenario where the source data was generated by SQL Server and all dates are in the format similar to 2012-10-21T04:00:20.043. The target date fields (such as BHT04) need to have this format converted to 20121021. This formatting must be applied to many fields, and the code used to convert from the SQL format to the EDI format needs to be used each time.

There are many options for implementation, including using standard functoids, but the most appropriate solution that uses the least amount of components is an external .NET assembly. If standard functoids were used, you would have to use several string functoids in a pattern, and this pattern would have to be applied over and over in the map. With the external .NET assembly, the code is written once, and a Scripting functoid is dropped wherever the conversion needs to take place. If the conversion logic needs to be changed for whatever reason (such as the source data format changes) then it only has to be changed in one place (the referenced DLL) and not everywhere the conversion is taking place (which would be the case with the functoid pattern).

In order to build this using an external .NET assembly, take the following steps.

MAPPING WITH AN EXTERNAL .NET ASSEMBLY

This exercise will walk through calling an external assembly to format dates in EDI compliant formats.

1. Create a .NET class library. Give it a namespace of Maps.Helper, and a class name of Helper.

2. Create a method called FormatDate which has one input parameter in string format. Write the code to convert from the source format to the target EDI format. An example of this code is shown in Listing 4-1.

3. Compile the assembly and reference it in your Visual Studio map project.

4. In the map, drop a Scripting functoid on the map surface. Drag the input from the source document’s date field, and drop it on the target document’s date field.

5. Open the Scripting functoid and click on the Script Functoid Configuration tab. Set the script type to External Assembly, then select your Script assembly, class, and method from the dropdowns. If your assembly is not shown, try closing Visual Studio and reopening. In some cases, you may have to install the DLL to the Global Assembly Cache (GAC - see next step) in order to be able to see it.

6. Test the map. This requires that the assembly be deployed to the GAC. Chapter 2, “Solution: Receiving 837P Data” discusses how to deploy assemblies via the BizTalk Administration Console, which places them in the GAC.

An example of the functoid being used on the BHT04 field is shown in Figure 4-1.

image

Figure 4-1. Calling an External Assembly from a Map

Listing 4-1. Formatting a Date

public string FormatDate(string dateString)
{
if (string.IsNullOrEmpty(dateString) == false)
{
try
{
DateTime date = XmlConvert.ToDateTime(dateString,
XmlDateTimeSerializationMode.Local);
return date.ToString("yyyyMMdd");
}
catch
{
return string.Empty;
}
}
else
{
return string.Empty;
}
}

Creating HI Records using Inline XSLT

837 documents have a long list of HI records that can be populated, code nodes that can be populated. These HI records include diagnosis codes, condition information, and other repeating data types. This example will look at one option for mapping the diagnosis codes (referred to as the HI_HealthCareDiagnosisCode in the 837P BizTalk schema) - using Inline XSLT. The Inline XSLT looks at the source data and creates the target data XML based on what is present. Assuming that the source data structure for Diagnosis code is that shown in Figure 4-2, the XSLT in Listing 4-2 can be used to populate the HI node structure in the target 837 Schema shown in the map in Figure 4-3. Note that there is no input to the Scripting functoid that contains the Inline XSLT.

image

Figure 4-2. Diagnosis Code Structure in the Source Data

Listing 4-2. Inline XSLT for Diagnosis Code Creation

<xsl:element name="ns0:HI_HealthCareDiagnosisCode">
<xsl:for-each select="//*[local-name()='DiagnosisCode']">
<xsl:if test="./@SequenceNumber = '1'">
<xsl:element name="ns0:C022_HealthCareCodeInformation">
<xsl:element name="C02201_DiagnosisTypeCode">BK</xsl:element>
<xsl:element name="C02202_DiagnosisCode"><xsl:value-of
select="translate(.,'.','')"/></xsl:element>
</xsl:element>
</xsl:if>

<xsl:if test="./@SequenceNumber = '2'">
<xsl:element name="ns0:C022_HealthCareCodeInformation_2">
<xsl:element name="C02201_DiagnosisTypeCode">BF</xsl:element>
<xsl:element name="C02202_DiagnosisCode"><xsl:value-of
select="translate(.,'.','')"/></xsl:element>
</xsl:element>
</xsl:if>

<xsl:if test="./@SequenceNumber = '3'">
<xsl:element name="ns0:C022_HealthCareCodeInformation_3">
<xsl:element name="C02201_DiagnosisTypeCode">BF</xsl:element>
<xsl:element name="C02202_DiagnosisCode"><xsl:value-of
select="translate(.,'.','')"/></xsl:element>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:element>

image

Figure 4-3. Mapping to the HI_HealthCareDiagnosisCode using Inline XSLT

What the XSLT is doing is looping through all of the source diagnosis codes that are available in the source data and creating target codes in the 837 EDI document in the exact XML structure that matches the schema. Depending on the SequenceNumber of the source code, the appropriate target code is created in the EDI document. The translate() method in the XSLT is used to remove periods from the source data before placing it in the target data.

Inline XSLT is amazingly useful with BizTalk mapping, and 837 data in particular. It gives the level of control over parsing and manipulating data that is essential. The ability to look throughout the source data, regardless of where data lies in the overall hierarchy and node structure, allows for building the logic that may be required without having to build ridiculously complex functoid pattern solutions.

Service Line Mapping using Inline XSLT Call Template

In the previous example, you looked at Inline XSLT, which does not require any inputs to the Scripting functoid. Inline XSLT can parse through the source data without reference to anything. However, in some cases you may need to pass in one or more parameters. A great of example of this is in the case of Service Line mapping, which can be very involved. You may decide that the entire Service Line detail, from the TS837_2400_Loop down, is best created using XSLT. In the case at hand, the source data contains many claims, and each claim contains one or more service lines. In order to successfully map the target loop, the Transaction ID of the source claim data needs to be passed into the Inline XSLT Call Template so that only those service lines associated with the specific claim being mapped at this specific time in the map are copied over.

The code in Listing 4-3 shows a snippet of how a parameter can be passed, and how the Service Line in the target schema can be created. The TID parameter is passed in from the source. The xsl:if then checks to see if that TID matches the current data’s TID (each would have a unique ID). If so, the service line gets mapped, otherwise it is ignored, as it belongs to some other claim.

Listing 4-3. Passing a Parameter into Inline XSLT Call Template Code

<xsl:template name="ServiceLine">
<xsl:param name="TID" />
<xsl:for-each select="//*[local-name()='ServiceLine']">
<xsl:if test="../../../*/*[local-name()='TransactionID'] = $TID">

<xsl:element name="ns0:TS837_2400_Loop">
<xsl:element name="ns0:LX_ServiceLineNumber">
<LX01_AssignedNumber>
<xsl:number /> <!-- will create numeric for this line, ordered -->
</LX01_AssignedNumber>
</xsl:element>
. . . . . . .

</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>

HL Hierarchy Mapping with Functoids

Setting the HL01 and HL02 values can be a little daunting when creating an outbound 837 document from a source document that doesn’t contain hierarchy relations. The best way to set your hierarchy values accurately is through the use of a Loop functoid (which you will likely have in order to loop through all of the source data to get it into the target data) and two Scripting functoid shapes. Assuming that the Loop functoid is mapped to your target TS837Q1_2000A_Loop, all HL hierarchy nodes in the target document can be set using the same two functoids. The first functoid sets the value of the HL01, and the second functoid sets the value of the HL02. Every HL01 in the target schema should have its source as the HL01 functoid, and every HL02 should have its source as the HL02 functoid. This means both of them will have many outputs. Neither has an input. Instead, the HL01 functoid declares a global variable that is available to other functoids within the map, and the HL02 functoid has access to this global variable.

The code for the HL01 functoid is shown in Listing 4-4, and the code for the HL02 functoid is shown in Listing 4-5. This code is added as Inline C# into the respective functoids. Figure 4-4 shows the functoid configuration in the map.

Listing 4-4. The HL01 Functoid

// global variable
int intHL01;

// this gets executed on every HL01 mapped to
public int getHL01()
{
intHL01++;
return intHL01;
}

Listing 4-5. The HL02 Functoid

// references global variable set and declared in HL01 script
public int getHL02()
{
return intHL01 - 1;
}

image

Figure 4-4. Mapping HL Segments

Mapping from an Inbound 837

Mapping from an inbound 837 to a flat file or other format required by systems within your company requires some analysis. You want to ensure that your maps are as simple, efficient, and easily maintainable as possible. This may require that you use several maps to split out the mapping into logical steps, rather than trying to force everything into a single map. It may also mean you rely heavily on XSLT in the map, and don’t depend too heavily on standard functoids. Given the complexity of the 837 formats, it is extremely easy to end up with a map that is completely unusable and unsupportable. What you do not want to end up with is a map that looks like that shown in Figure 4-5.

image

Figure 4-5. An Unsupportable and Unacceptable Mapping of Inbound 837P Data

In order to avoid ending up in a scenario like that shown in Figure 4-5, take the following steps:

· Plan your architecture - wait to start development. It is easy and tempting to just start mapping. 80% of the mapping you’ll do with an inbound 837 is straightforward, and you’ll find that you make quick progress with much of the implementation. Given the size of it, 80% of the mapping will be hours’ worth of work. Then, as you begin on the final 20%, you’ll start to run into hurdles that are very difficult to overcome, especially if you haven’t built the rest of your map to support this 20%. You’ll find that loops you’ve built and nodes you’ve mapped have to be rewritten to support your requirements, and the initial hours of work has now turned into days or weeks. So, in short, plan your mapping before you start development.

· Start with the most complex nodes first. Assess what the most complicated aspect of mapping is, and deal with that first. It will ensure that you are developing with the right approach, and if you find that you have to rethink your approach, you haven’t wasted a lot of time on other mappings.

· Use XSLT. There are so many complexities in mapping the 837 that are reduced and simplified by using XSLT that it is a mistake not to plan on using it extensively in your maps.

The technologies used for mapping are outlined in the earlier section on outbound mapping, and are the same for inbound. Here are several examples of mapping inbound data that will be of use to you.

Using More than One Map to Handle a Single Map Case

There are times when it is critical that you use multiple maps in order to map a single inbound 837 document to an internal format. The case of the ECSIF format was mentioned in Chapter 2. This format is nearly as complex in nature as the 837, and contains virtually all of the same information. Like the 837, the ECSIF format is also a flat file format. In order to use two maps, you’ll need three schemas. You will need access two of the schemas regardless: the schema that matches the 837 and the schema that matches the ECSIF flat file format. The third schema is an intermediary schema that is a halfway structure between the 837 and the final ECSIF, formed in such a way as to aid in the transformation.

An example of using three schemas and two maps for mapping the Inbound 837 to a flat ECSIF file structure is shown in the following figures. The first figure (Figure 4-6) shows a partial shot of the map from the 837P structure to the intermediary ECSIF schema. Figure 4-7shows a shot of the mapping between the intermediary structure and the final ECSIF flat file structure.

image

Figure 4-6. The First Map - 837P to ECSIF Intermediary

image

Figure 4-7. The Second Map - ECSIF Intermediary to ECSIF Flat File

When using two or more maps for a single mapping requirement, you will most likely want to incorporate an orchestration. The orchestration will allow you to stack your maps one after the other. If you were just using one map, an orchestration would not be required, as the mapping could be done directly on the ports. Figure 4-8 shows the pattern for developing an orchestration with the two maps.

image

Figure 4-8. An Orchestration with the Two Maps for ECSIF Transformation

Using an External XSLT File for Mapping

There were two examples of using Inline XSLT earlier in this chapter, both of which could be used in conjunction with traditional mapping. There is one other type of mapping that can be used when things are simply unmanageable within a map. This option is to shell out to an external XSLT solution and skip the BizTalk mapper completely. Look at Figure 4-7 and notice that there are no mappings showing in it. This is an example of a map that uses external XSLT. In order to use external XSLT, take these steps:

· Open up a text editor and create your XSLT. An example of an XSLT file that can be used as a template in your development is shown in Listing 4-6.

image Note Using an external XSLT file for mapping means that you do not have to use the BizTalk mapper interface in Visual Studio to test your maps. There are a number of free tools available on the internet that allow you to specify a source XML document to map from and an XSLT file to use in order to generate test output data.

· Create a new BizTalk map. Click anywhere on the map surface and select properties. Set the Custom XSL Path to the location of the XSLT you just created. For simplicity, add the XSLT file to the Visual Studio project at the same level as this map. The file can then be referenced as .\CustomXSLT.xslt.

Listing 4-6. Template for an External XSLT File

<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var"
exclude-result-prefixes="msxsl var s0" version="1.0"
xmlns:ns0="http://Company.BizTalk.Schemas.ECSIFOB_FF"
xmlns:s0="http://Company.BizTalk.Schemas.ClaimsIB_ECSIF_XML">

<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<xsl:apply-templates select="/s0:ECSIFIB_XML" />
</xsl:template>

<xsl:template match="/s0:ECSIFIB_XML">
<ns0:ECSIF_FF>

<!-- Your XSLT Code Goes Here -->

</ns0:ECSIF_FF>
</xsl:template>
</xsl:stylesheet>

Mapping from an Inbound 834

Most of the concepts are the same between an 837 and an 834; dates have to be transformed, loops have to be structured. In this section, you’ll look at mapping an 834 to a canonical structure, which is an intermediary structure that represents the internal structure of an 834. Canonical schema structures are somewhat controversial. Some organizations simply require that all inbound data that may have two or more trading partners delivering the same document types must map to a common canonical structure. Other organizations are more open to allowing for thought and good architecture to dictate when a canonical is used, and when it is not. Some of the key items to consider when deciding whether to incorporate a canonical view of the data in your BizTalk solution are described in the following sections.

Creating Global Inline C# Variables and Methods

There are frequent occasions in mapping data when there is a need to reuse a method, or to have access to a variable from multiple Scripting functoids within a map. Creating a single global inline C# Scripting functoid is an ideal way to allow for the reuse of methods and variables. The approach is simple: you can add a Scripting functoid to your map, and include the variables and methods you want to be globally accessible within it. The functoid itself should have no inputs and no outputs; it should be left orphaned somewhere on your mapping surface, and should be commented appropriately on the Label property of the functoid. An example of a functoid used for storing global methods and variables is shown in Figure 4-9, while an example of some global methods are shown in Listing 4-7.

image

Figure 4-9. A Scripting Functoid for Globally Accessible Variables and Methods

Listing 4-7. Globally Accessible Function Examples

public string GetDate()
{
System.DateTime date = new System.DateTime();

return date.ToString("yyyy-MM-dd");
}

public string SetGender(string gender)
{
string result = "N/A";
if (gender.Equals("M"))
result = "Male";
else if (gender.Equals("F"))
result = "Female";

return result;
}

public string RemoveBadChars(string input)
{
string result = System.Text.RegularExpressions.Regex.
Replace(input, @"[^0-9]+", string.Empty, System.Text.
RegularExpressions.RegexOptions.None);
return result;
}

image Note A good example of needing to use a common variable is outlined in the HL mapping earlier in this chapter. Often, you will need to be able to increment a common variable from multiple locations within a map for summing and comparison purposes.

Calling Inline C# Method from within Inline XSLT

XSLT is powerful, but there are quite a few things that are challenging (or impossible) to do directly from XSLT (such as database lookups). Being able to call out to C# methods from within XSLT opens up infinite options for coding, and allows you complete freedom in how you develop your maps. In Listing 4-8, you will see a method that returns the maintenance reason based on the reason code that is passed in as a parameter. This reason code comes from the INS04_MaintenanceReasonCode element within the 834, but is passed in directly from Inline XSLT, shown in this code snippet (note the userCSharp directive):

<xsl:when test="current()/*[local-name()='INS_
MemberLevelDetail']/*[local-name()='INS04_
MaintenanceReasonCode']!=''">
<xsl:element name="ns0:MaintenanceReason">
<xsl:value-of select="userCSharp:GetMaintenanceReason
(current()/*[local-name()='INS_MemberLevelDetail']/*
[local-name()='INS04_MaintenanceReasonCode'])" />
</xsl:element>
</xsl:when>

Listing 4-8. Maintenance Reason

public string GetMaintenanceReason(string reasonCode)
{
string reason="";
switch (reasonCode)
{
case "01":reason = "Divorce"; break;
case "02":reason = "Birth"; break;
case "03":reason = "Death"; break;
case "05":reason = "Adoption"; break;
case "07":reason = "TermOfBenefits"; break;
case "08":reason = "TermOfEmployment"; break;
case "14":reason = "VoluntaryCancel"; break;
case "22":reason = "PlanChange"; break;
case "25":reason = "ChangeOfInformation"; break;
case "28":reason = "Effectuation"; break;
case "EC":reason = "BenefitSelection"; break;
case "32":reason = "Marriage"; break;
case "41":reason = "Re-enrollment"; break;
case "43":reason = "LocationChange"; break;
case "59":reason = "NonPayment"; break;
case "AI":reason = "NoReason"; break;
case "33":reason = "PersonnelData"; break;
case "XN":reason = "NotificationOnly"; break;
case "XT":reason = "Transfer"; break;
default:reason = "N/A"; break;
}
return reason;
}

Mapping the Transaction Type for SHOP and Individual

SHOP and Individual 834 files will often be processed through the same maps. The data is almost identical between the two, and most of the code you write will be reusable between the two. In cases where you are mapping both through the same map, you’ll have several code paths that must return different results depending on the type. Figure 4-10 shows the map for one example of this - mapping the transaction types - while Listing 4-9 shows the code behind the Scripting functoid.

image

Figure 4-10. A Scripting Functoid for Mapping Transaction Type

Listing 4-9. Mapping the Transaction Type

public string GetTransactionType(string BGN08, string N103)
{
string result = null;
if (BGN08 == "2")
{
if (N103=="24")
result = "SHOP Enrollment";
else
result = "Individual Enrollment";
}
if (BGN08 == "4")
{
if (N103=="24")
result = "SHOP Reconciliation";
else
result = "Individual Reconciliation";
}
return result;
}

Conclusion

This chapter gives an overview of how to be successful with your mapping solutions. It also gives specific examples around mapping several elements in both the 837 and 834 document types, and provides direction on how to implement inline scripts for more complex maps. With the proper use of the techniques outlined – and especially through the use of XSLT – you will be able to solve any mapping problem that may arise. Chapter 9, “Advanced 834 Mapping” covers a complex outbound 834 pattern that introduces more concepts around mapping that you may want to incorporate into your own solutions.