ORM^O01 .validate() and .parse_message() issues
Hi everyone
I build a hl7 ORM^O01 message:
msh = "MSH|^~\&|GHH_ADT||||20080115153000||ORM^O01|0123456789|P|2.5||||AL"
pid = "PID|1||566-554-3423^^^GHH^MR||EVERYMAN^ADAM^A|||M|||2222 HOME STREET^^ANN ARBOR^MI^^USA||555-555-2004~444-333-222|||M"
pv1 = "PV1|1|I|GHH PATIENT WARD|U||||^SENDER^SAM^^MD|^PUMP^PATRICK^P|CAR||||2|A0|||||||||||||||||||||||||||||2008"
in1 = "IN1|1|HCID-GL^GLOBAL|HCID-23432|HC PAYOR, INC.|5555 INSURERS CIRCLE^^ANN ARBOR^MI^99999^USA||||||||||||||||||||||||||||||||||||||||||||444-33-3333"
orc = "ORC|1||||||1||20150414120000"
obr = "OBR|1|1|1100|1||||||||||20150414110000|||||||||||||1"
hl7_msg = Message(name='ORM_O01', version='2.3')
hl7_msg.msh=msh
hl7_msg.add_segment("PID")
hl7_msg.pid=pid
hl7_msg.add_segment("PV1")
hl7_msg.pv1=pv1
hl7_msg.add_segment("IN1")
hl7_msg.in1=in1
hl7_msg.add_segment("ORC")
hl7_msg.orc=orc
hl7_msg.add_segment("OBR")
hl7_msg.obr=obr
After that, I have got:
hl7_msg.value -> 'MSH|^~\\&|GHH_ADT||||20080115153000||ORM^O01|0123456789|P|2.5||||AL\rPID|1||566-554-3423^^^GHH^MR||EVERYMAN^ADAM^A|||M|||2222 HOME STREET^^ANN ARBOR^MI^^USA||555-555-2004~444-333-222|||M\rPV1|1|I|GHH PATIENT WARD|U||||^SENDER^SAM^^MD|^PUMP^PATRICK^P|CAR||||2|A0|||||||||||||||||||||||||||||2008\rIN1|1|HCID-GL^GLOBAL|HCID-23432|HC PAYOR, INC.|5555 INSURERS CIRCLE^^ANN ARBOR^MI^99999^USA||||||||||||||||||||||||||||||||||||||||||||444-33-3333\rORC|1||||||1||20150414120000\rOBR|1|1|1100|1||||||||||20150414110000|||||||||||||1'
Q1:
When I test each segment, everything seems to be OK:
hl7_msg.msh.validate() -> True
hl7_msg.pid.validate() -> True
hl7_msg.pv1.validate() -> True
hl7_msg.in1.validate() -> True
hl7_msg.orc.validate() -> True
hl7_msg.obr.validate() -> True
But when I try to test hl7_msg.validate(), I got the error:
Traceback (most recent call last):
File "<pyshell#352>", line 1, in
What's the problem?
Q2:
Then, I try to parse the value of the communicate:
orm = parser.parse_message(hl7_msg.value)
orm -> <Message ORM_O01>
orm.value -> 'MSH|^~\\&|GHH_ADT||||20080115153000||ORM^O01|0123456789|P|2.5||||AL\rPID|1||566-554-3423^^^GHH^MR||EVERYMAN^ADAM^A|||M|||2222 HOME STREET^^ANN ARBOR^MI^^USA||555-555-2004~444-333-222|||M\rPV1|1|I|GHH PATIENT WARD|U||||^SENDER^SAM^^MD|^PUMP^PATRICK^P|CAR||||2|A0|||||||||||||||||||||||||||||2008\rIN1|1|HCID-GL^GLOBAL|HCID-23432|HC PAYOR, INC.|5555 INSURERS CIRCLE^^ANN ARBOR^MI^99999^USA||||||||||||||||||||||||||||||||||||||||||||444-33-3333\rORC|1||||||1||20150414120000\rOBR|1|1|1100|1||||||||||20150414110000|||||||||||||1'
orm.msh.value -> 'MSH|^~\\&|GHH_ADT||||20080115153000||ORM^O01|0123456789|P|2.5||||AL'
Everything seems to be OK, but:
orm.pid.validate
Traceback (most recent call last):
File "<pyshell#367>", line 1, in
I checked the value of the pid segment, but it is empty:
orm.pid.value -> 'PID'
The rest of the segments are also empty. The same happens, when I want to parse another way:
msg = msh + '\r' + pid + '\r' + pv1 + '\r' + in1 + '\r' + orc + '\r' + obr
What is the problem?
For Q1: The individual segments are valid, but the overall message structure is not. In an ORM_O01 message the HL7 standard (and HL7apy’s ORM_O01 profile) expects that after the MSH segment you have an optional NTE segment, followed by groups (like the ORM_O01_PATIENT group and the ORM_O01_ORDER group) rather than having segments like PID, PV1, IN1, ORC, and OBR directly at the message level.
In other words, you are adding segments directly to the message when they should be nested inside the proper groups. That is why the message-level validation fails with an error about “Invalid children detected.” Proper initialization would look like this:
hl7_msg = Message("ORM_O01", version="2.3")
hl7_msg.msh = msh
patient_group = hl7_msg.add_group("ORM_O01_PATIENT")
patient_group.add_segment("PID")
patient_group.pid = pid
patient_group.add_segment("PV1")
patient_group.pv1 = pv1
patient_group.add_segment("IN1")
patient_group.in1 = in1
order_group = hl7_msg.add_group("ORM_O01_ORDER")
order_group.add_segment("ORC")
order_group.orc = orc
order_group.add_segment("OBR")
order_group.obr = obr
And for Q2, after you'll have message properly initialized, your parsing will work good:
msg_str = hl7_msg.value
orm = parser.parse_message(msg_str)
the parser will recognize the proper group structure. Consequently, segments like orm.pid will have their fields populated (for example, PID-3 will be present) and validation will succeed
Reference of docs: https://hl7-definition.caristix.com/v2/HL7v2.3/TriggerEvents/ORM_O01
Thank You for reply and explanation - I think I now understand how walidation works. In reality, however, the process of building a message should look like this:
hl7_msg = Message(name='ORM_O01', version='2.3') hl7_msg.msh=msh patient_group = hl7_msg.add_group("ORM_O01_PATIENT") patient_group.add_segment("PID") patient_group.pid = pid patient_visit_group = patient_group.add_group("ORM_O01_PATIENT_VISIT") patient_visit_group.add_segment("PV1") patient_visit_group.pv1 = pv1 patient_insurance_group = patient_group.add_group("ORM_O01_INSURANCE") patient_insurance_group.add_segment("IN1") patient_insurance_group.in1=in1 order_group = hl7_msg.add_group("ORM_O01_ORDER") order_group.add_segment("ORC") order_group.orc = orc order_detail_group = order_group.add_group("ORM_O01_ORDER_DETAIL") order_detail_choice_group = order_detail_group.add_segment("ORM_O01_CHOICE") order_detail_choice_group.add_segment("OBR") order_detail_choice_group.obr = obr order_detail_choice_group.add_segment("RQD") order_detail_choice_group.add_segment("RQ1") order_detail_choice_group.add_segment("RXO") order_detail_choice_group.rxo = rxo order_detail_choice_group.add_segment("ODS") order_detail_choice_group.ods = ods order_detail_choice_group.add_segment("ODT") order_detail_choice_group.odt = odt
And indeed, validation does not return errors.
print(hl7_msg.validate()) -> True
As you can see, the building process of the message is complicated, and I still don't fully understand the intention of this approach to the subject. Maybe I'm misunderstanding something, but wouldn't it be simpler to only check the message itself, just only presence of necessary segments and fields, without taking into account the structure of the object that generates it? This would simplify message parsing and the end result would be the same - a plain text message.
That's how for example an online HL7 validator / parser works: https://freeonlineformatter.com/hl7-validator
Assuming that hl7_msg is a valid hl7 ORM^O01 message object, the one we created above:
with open('test.hl7', 'a') as f:
f.write(hl7_msg.value)
with open('test.hl7', 'r') as f:
hl7 = f.read()
msg = parser.parse_message(hl7)
try:
print(msg.validate())
except Exception as e:
print(e)
Now I get an error "Invalid children detected for <Segment MSH>: [None]" even though the message content is correct and an online validator accepts it without errors.