Article
· Jun 9, 2023 15m read

EMPI installation and customization in Standalone - Customization of patient data

As we said yesterday... our EMPI can receive data from multiple sources, REST, HL7 messaging, etc. But it is possible that the standard fields are not enough and we want to expand the patient information to help discriminate and uniquely identify them. How could we customize patient data? Modifying the standard classes to our liking? NOOOOO!!!! Well, a little yes, but not like crazy, because if we modify standard classes carelessly we may find that in a future update we lose all these modifications.

Customization of patient data

Muy bien, continuemos con la configuración de nuestro EMPI en el que hemos introducido unos cuantos pacientes. Imaginad que hemos decidido incluir el grupo sanguíneo como un criterio para ayudar en el proceso del cálculo de pesos. Recordemos que clases definían los datos del paciente.

Por un lado tenemos el objeto que vamos a persistir y que lo encontramos en el Definition Designer:

On the other hand, we have the object that we are going to return in the searches and that corresponds to the "Composite Record" previously configured from the Configuration Registry option.

 

Let's take a look at HSPI.Data.Patient, specifically the class declaration:

Class HSPI.Data.Patient Extends (%Persistent, HSPI.Data.Type.Patient, %MPRL.Linkage.Base) 

We can see that its properties are inherited from HSPI.Data.Type.Patient, if we access to this class we will see that we have a series of values corresponding to the properties of the patient object. As we have said, we could add the fields here that we need... but that is NOT RECOMMENDED, we have a better option that will not be affected by version updates. If we go to the end of the HSPI.Data.Type.Patient class we find the following property:

Property Extension As HS.Local.SDA3.PatientExtension;

This property is what will allow us to add as many fields as we want to our patient object. As you can see, belonging to the Local will prevent this information from being lost in future version changes. Let's open HS.Local.SDA3.PatientExtension and include the BloodType property as a simple String:

Class HS.Local.SDA3.PatientExtension Extends HS.SDA3.DataType
{

Parameter HSDEPLOY = 0;
Parameter STREAMLETCLASS = "HS.SDA3.Streamlet.Patient";
Property BloodType As %String;
}

Perfect, our object is prepared to receive this information. How can we send this new information to our system? As we saw in the previous article, our EMPI has a default configuration that can receive HL7 messages and that we have already used to add patients.

Create new HL7 schema

In our example we will use an A28 message to which we will add a new segment with the blood type information. To do this we are going to create a new schema based on the 2.5.1 standard schema and we are going to create a new DocType for the A28 message type.

Here we have our new HealthShare_2.5 schema that, as you can see, extends the 2.5.1 standard and we have created a new message structure of type A28. To add a new segment we will first create said segment that we will call ZBT and add the field that will contain the blood type:

With the segment created, we only need to include it in the message structure and we can start working with these personalized messages:

Perfect, message set up with our ZBT segment. Now let's see an example of the type of message that we will receive with the new segment:

MSH|^~\&|HIS|HULP|EMPI||20230329085239||ADT^A28|72104|P|HealthShare_2.5
EVN|A28|20230329085239|20230329085239|1
PID|||1502935519^^^SERMAS^SN~424392^^^HULP^PI||CABEZUELA SANZ^PEDRO^^^||20160627|M|||PASEO JULIA ÁLVAREZ^395 3 E^MADRID^MADRID^28909^SPAIN||555710791^PRN^^PEDRO.CABEZUELA@GMAIL.COM|||||||||||||||||N|
PV1||N
ZBT|A-

In our example, the patient Pedro Cabezuela Sanz has a blood type A-.

EMPI Production Configuration:

As we saw in the previous EMPI configuration article, we have a production configured by default that allows us to immediately operate with our EMPI.

In our example we are using the Business Service EnsLib.HL7.Service.FileService that will capture files with HL7 messages from the specified route. To adapt it to the new type of messages that we are going to receive, we will modify the Message Schema Category to refer to the new schema created. Let's take a look at one of the examples of the messages that we sent in the example of the previous article to identify the Business Components through which our messages pass and to be able to identify them:

Our message enters through EnsLib.HL7.Service.FileService and it is redirected to HS.Hub.Standalone.HL7.Operation, here we have the configuration of said Business Operation:

We notice that we have an attribute called HL7ToSDA3Class configured with the class HS.Hub.Standalone.HL7.HL7ToSDA3. Let's open the class and check what its functionality is.

 
HS.Hub.Standaline.HL7.HL7ToSDA3

This class belongs to the standard and we have no interest in modifying anything in it, so we are going to create a new Local that will extend the standard class:

Class Local.Hub.Standalone.HL7.HL7ToSDA3 Extends HS.Hub.Standalone.HL7.HL7ToSDA3
{

ClassMethod GetTransformClass(msgType As %String, ByRef pTransformClass As %String) As %Status
{
	set tSC=$$$OK
	set pTransformClass=..OnGetTransformClass() 
	quit:pTransformClass'=""
	set pTransformClass = $CASE(msgType,
              "ADT_A01":"ADTA01ToSDA3", "ADT_A02":"ADTA02ToSDA3", "ADT_A03":"ADTA03ToSDA3",
              "ADT_A04":"ADTA01ToSDA3", "ADT_A05":"ADTA05ToSDA3", "ADT_A06":"ADTA01ToSDA3",
              "ADT_A07":"ADTA01ToSDA3", "ADT_A08":"ADTA01ToSDA3", "ADT_A09":"ADTA01ToSDA3",
              "ADT_A10":"ADTA01ToSDA3", "ADT_A11":"ADTA09ToSDA3", "ADT_A12":"ADTA01ToSDA3",
              "ADT_A13":"ADTA01ToSDA3", "ADT_A16":"ADTA01ToSDA3", "ADT_A17":"ADTA01ToSDA3",
              "ADT_A18":"ADTA18ToSDA3", "ADT_A23":"ADTA21ToSDA3", "ADT_A25":"ADTA01ToSDA3",
              "ADT_A27":"ADTA01ToSDA3", "ADT_A28":"ADTA28ToSDA3", "ADT_A29":"ADTA21ToSDA3",
              "ADT_A30":"ADTA30ToSDA3", "ADT_A31":"ADTA05ToSDA3", "ADT_A34":"ADTA30ToSDA3",
              "ADT_A36":"ADTA30ToSDA3", "ADT_A39":"ADTA40ToSDA3", "ADT_A40":"ADTA40ToSDA3",
              "ADT_A45":"ADTA45ToSDA3", "ADT_A47":"ADTA30ToSDA3", "ADT_A50":"ADTA50ToSDA3",
              "ADT_A60":"ADTA60ToSDA3", "BAR_P12":"BARP12ToSDA3", "MDM_T02":"MDMT02ToSDA3",
              "MDM_T04":"MDMT02ToSDA3", "MDM_T08":"MDMT02ToSDA3", "MDM_T11":"MDMT01ToSDA3",
              "OMP_O09":"OMPO09ToSDA3", "ORM_O01":"ORMO01ToSDA3", "ORU_R01":"ORUR01ToSDA3",
              "PPR_PC1":"PPRPC1ToSDA3", "PPR_PC2":"PPRPC1ToSDA3", "PPR_PC3":"PPRPC1ToSDA3",
              "RDE_O11":"RDEO11ToSDA3", "SIU_S12":"SIUS12ToSDA3", "SIU_S13":"SIUS12ToSDA3",
              "SIU_S14":"SIUS12ToSDA3", "SIU_S15":"SIUS12ToSDA3", "SIU_S16":"SIUS12ToSDA3",
              "SIU_S17":"SIUS12ToSDA3", "SIU_S26":"SIUS12ToSDA3", "VXU_V04":"VXUV04ToSDA3",
              :"Unsupported HL7 Message Type")

	set:pTransformClass="Unsupported HL7 Message Type" tSC = $$$HSError($$$HSErrUnsupportedHL7MessageType,msgType)
 	if $$$ISERR(tSC) quit tSC
 	if (msgType = "ADT_A28") {
 		set tTransformPackage = "Local.Hub.Standalone.HL7.DTL"
 	}
 	else {
 		set tTransformPackage = "HS.Hub.Standalone.HL7.DTL"
 	}
 	set pTransformClass = tTransformPackage_"."_pTransformClass
	
	quit tSC
}

}

Of all its classes, the one that interests us the most is GetTransformClass, which will indicate which transformation we must carry out depending on the type of message received. As in our case we have chosen the A28 message as the carrier of the new segment with the blood group information, we must find said transformation within the $CASE command:

"ADT_A28":"ADTA05ToSDA3"

Here we have our initial transformation, as we can see, the structure of the ADT_A28 message is that of ADT_A05, therefore it has said transformation configured by default, in our case we are going to create a new transformation copying the ADTA05ToSDA3 and we will call it ADTA28ToSDA3, replacing the value that had in the $CASE a:

"ADT_A28":"ADTA28ToSDA3"

As you can see from Local.Hub.Standalone.HL7.HL7ToSDA3 we have included an if to apply the proper transformation depending on the type of HL7 message received if the message is an ADT_A28 the package to be use is Local.Hub.Standalone.HL7.DTL.

With the class Local.Hub.Standalone.HL7.HL7ToSDA3 compiled we will open our production again and define the value of the HL7ToSDA3Class parameter in the Business Operation HS.Hub.Standalone.HL7.Operation with the newly implemented class Local.Hub.Standalone.HL7. HL7ToSDA3

Perfect, we have finished the configuration of our production. We only have one small detail left...we haven't created our ADTA28ToSDA3 transformation yet!

Creating custom transformation:

From the list of transformations menu we will look for the ADTA05ToSDA3.

Here we have it, let's open it and proceed to save it with another name to create a copy of it.

With the new class created we can start the transformation, we must perform the following tasks:

  • Change the Source Doc Type from 2.5.1:ADT_A05 to HealthShare_2.5:ADT_A28. Remember that we have created a new message structure A28.
  • Assign the value of the BloodType field of the ZBT segment of our message to the BloodType field that we find inside the Extension property included in Patient. This BloodType field is available by adding the BloodType property to the HS.Local.SDA3.PatientExtension class.

The transformation would be like this:

Alright, let's review what we've done so far:

  • Creating the BloodType field in the HS.Local.SDA3.PatientExtension class to store the custom information.
  • Extension of HL7 2.5.1 schema to add a custom Z segment to A28 messages.
  • Extension of the HS.Hub.Standalone.HL7.HL7ToSDA3 class to indicate the transformation to perform when receiving the A28.
  • Creating the ADTA28ToSDA3 transformation.

With all of the above we can now send messages with the blood group in the new segment and store it with the patient's data as an extension. What would we need to complete the customization? The Local.CompositeRecord.Transient.Definition! We are saving the data correctly but we have not modified the class used to load blood group in the relevant patient data.

CompositeRecord Setup

Let's see how the data is displayed in the CompositeRecord:

<propertyGroup name="Gender" trustBlock="base" description="Gender - base: all tier 5">
<property>Gender</property>
</propertyGroup>

 We define the group to which the new data will belong and its ownership in the patient object. In our case the BloodType property is hanging from the Extension property, so our new pool will be like this:

<propertyGroup name="Extension" trustBlock="base" description="Extension - base: all tier 5">
<property name='Blood Type'>Extension.BloodType</property>
</propertyGroup>

In our case we have called it Extension, but it could be any other name.

Once our Local.CompositeRecord.Transient.Definition class has been edited, we can launch tests with our custom A28 messages starting production.

Testing

Let's check the trace of one of the messages entered:

There we have our ZBT segment with the value B+. Let's see how it is mapped to the object:

There we have our Extension field with the new BloodType property. Let's launch a search for that patient registered with MPIID 100000350.

Here is the Extension field and its B+ value. We could rename the tag and call it Blood Type without any problem.

Well, this would be all, we have configured our EMPI to receive personalized fields, to register them as patient data and to return them.

If you have any questions or suggestions, do not hesitate to write a comment about it.

Discussion (0)1
Log in or sign up to continue