Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ORM^O01 .validate() and .parse_message() issues #142

Open
paw-bor opened this issue Feb 13, 2025 · 2 comments
Open

ORM^O01 .validate() and .parse_message() issues #142

paw-bor opened this issue Feb 13, 2025 · 2 comments

Comments

@paw-bor
Copy link

paw-bor commented Feb 13, 2025

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
hl7_msg.validate()
File "C:\Projects\LIStoLIS\venv\Lib\site-packages\hl7apy\core.py", line 751, in validate
return Validator.validate(self, reference=self.reference, report_file=report_file)
File "C:\Projects\LIStoLIS\venv\Lib\site-packages\hl7apy\validation.py", line 207, in validate
raise errors[0]
hl7apy.exceptions.ValidationError: Invalid children detected for : ['PID', 'IN1', 'OBR', 'PV1', 'ORC']

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
orm.pid.validate()
File "C:\Projects\LIStoLIS\venv\Lib\site-packages\hl7apy\core.py", line 751, in validate
return Validator.validate(self, reference=self.reference, report_file=report_file)
File "C:\Projects\LIStoLIS\venv\Lib\site-packages\hl7apy\validation.py", line 207, in validate
raise errors[0]
hl7apy.exceptions.ValidationError: Missing required child PID.PID_3

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?

@germiBest
Copy link

germiBest commented Feb 14, 2025

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

@paw-bor
Copy link
Author

paw-bor commented Feb 17, 2025

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 : [None]" even though the message content is correct and an online validator accepts it without errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants