Example #1
0
        //Open \\SERVERFILES\storage\OPEN DENTAL\Programmers Documents\Standards (X12, ADA, etc)\HL7\Version2.6\V26_CH02_Control_M4_JAN2007.doc
        //At the top of page 33, there are rules for the recipient.
        //Basically, they state that parsing should not fail just because there are extra unexpected items.
        //And parsing should also not fail if expected items are missing.

        public static void Process(MessageHL7 msg, bool isVerboseLogging)
        {
            HL7MsgCur           = new HL7Msg();
            HL7MsgCur.HL7Status = HL7MessageStatus.InFailed;          //it will be marked InProcessed once data is inserted.
            HL7MsgCur.MsgText   = msg.ToString();
            HL7MsgCur.PatNum    = 0;
            HL7MsgCur.AptNum    = 0;
            List <HL7Msg> hl7Existing = HL7Msgs.GetOneExisting(HL7MsgCur);

            if (hl7Existing.Count > 0)           //This message is already in the db
            {
                HL7MsgCur.HL7MsgNum = hl7Existing[0].HL7MsgNum;
                HL7Msgs.UpdateDateTStamp(HL7MsgCur);
                msg.ControlId = HL7Msgs.GetControlId(HL7MsgCur);
                return;
            }
            else
            {
                //Insert as InFailed until processing is complete.  Update once complete, PatNum will have correct value, AptNum will have correct value if SIU message or 0 if ADT, and status changed to InProcessed
                HL7Msgs.Insert(HL7MsgCur);
            }
            IsVerboseLogging = isVerboseLogging;
            IsNewPat         = false;
            HL7Def def = HL7Defs.GetOneDeepEnabled();

            if (def == null)
            {
                HL7MsgCur.Note = "Could not process HL7 message.  No HL7 definition is enabled.";
                HL7Msgs.Update(HL7MsgCur);
                throw new Exception("Could not process HL7 message.  No HL7 definition is enabled.");
            }
            HL7DefMessage hl7defmsg = null;

            for (int i = 0; i < def.hl7DefMessages.Count; i++)
            {
                if (def.hl7DefMessages[i].MessageType == msg.MsgType)               //&& def.hl7DefMessages[i].EventType==msg.EventType) { //Ignoring event type for now, we will treat all ADT's and SIU's the same
                {
                    hl7defmsg = def.hl7DefMessages[i];
                }
            }
            if (hl7defmsg == null)           //No message definition matches this message's MessageType and EventType
            {
                HL7MsgCur.Note = "Could not process HL7 message.  No definition for this type of message in the enabled HL7Def.";
                HL7Msgs.Update(HL7MsgCur);
                throw new Exception("Could not process HL7 message.  No definition for this type of message in the enabled HL7Def.");
            }
            string   chartNum      = null;
            long     patNum        = 0;
            DateTime birthdate     = DateTime.MinValue;
            string   patLName      = null;
            string   patFName      = null;
            bool     isExistingPID = false;      //Needed to add note to hl7msg table if there isn't a PID segment in the message.

            //Get patient in question, incoming messages must have a PID segment so use that to find the pat in question
            for (int s = 0; s < hl7defmsg.hl7DefSegments.Count; s++)
            {
                if (hl7defmsg.hl7DefSegments[s].SegmentName != SegmentNameHL7.PID)
                {
                    continue;
                }
                int pidOrder = hl7defmsg.hl7DefSegments[s].ItemOrder;
                //we found the PID segment in the def, make sure it exists in the msg
                if (msg.Segments.Count <= pidOrder ||           //If the number of segments in the message is less than the item order of the PID segment
                    msg.Segments[pidOrder].GetField(0).ToString() != "PID"                      //Or if the segment we expect to be the PID segment is not the PID segment
                    )
                {
                    break;
                }
                isExistingPID = true;
                for (int f = 0; f < hl7defmsg.hl7DefSegments[s].hl7DefFields.Count; f++)           //Go through fields of PID segment and get patnum, chartnum, patient name, and/or birthdate to locate patient
                {
                    if (hl7defmsg.hl7DefSegments[s].hl7DefFields[f].FieldName == "pat.ChartNumber")
                    {
                        int chartNumOrdinal = hl7defmsg.hl7DefSegments[s].hl7DefFields[f].OrdinalPos;
                        chartNum = msg.Segments[pidOrder].Fields[chartNumOrdinal].ToString();
                    }
                    else if (hl7defmsg.hl7DefSegments[s].hl7DefFields[f].FieldName == "pat.PatNum")
                    {
                        int patNumOrdinal = hl7defmsg.hl7DefSegments[s].hl7DefFields[f].OrdinalPos;
                        patNum = PIn.Long(msg.Segments[pidOrder].Fields[patNumOrdinal].ToString());
                    }
                    else if (hl7defmsg.hl7DefSegments[s].hl7DefFields[f].FieldName == "pat.birthdateTime")
                    {
                        int patBdayOrdinal = hl7defmsg.hl7DefSegments[s].hl7DefFields[f].OrdinalPos;
                        birthdate = FieldParser.DateTimeParse(msg.Segments[pidOrder].Fields[patBdayOrdinal].ToString());
                    }
                    else if (hl7defmsg.hl7DefSegments[s].hl7DefFields[f].FieldName == "pat.nameLFM")
                    {
                        int patNameOrdinal = hl7defmsg.hl7DefSegments[s].hl7DefFields[f].OrdinalPos;
                        patLName = msg.Segments[pidOrder].GetFieldComponent(patNameOrdinal, 0);
                        patFName = msg.Segments[pidOrder].GetFieldComponent(patNameOrdinal, 1);
                    }
                }
            }
            if (!isExistingPID)
            {
                HL7MsgCur.Note = "Could not process the HL7 message due to missing PID segment.";
                HL7Msgs.Update(HL7MsgCur);
                throw new Exception("Could not process HL7 message.  Could not process the HL7 message due to missing PID segment.");
            }
            //We now have patnum, chartnum, patname, and/or birthdate so locate pat
            Patient pat    = null;
            Patient patOld = null;

            if (patNum != 0)
            {
                pat = Patients.GetPat(patNum);
            }
            if (def.InternalType != "eCWStandalone" && pat == null)
            {
                IsNewPat = true;
            }
            //In eCWstandalone integration, if we couldn't locate patient by patNum or patNum was 0 then pat will still be null so try to locate by chartNum if chartNum is not null
            if (def.InternalType == "eCWStandalone" && chartNum != null)
            {
                pat = Patients.GetPatByChartNumber(chartNum);
            }
            //In eCWstandalone integration, if pat is still null we need to try to locate patient by name and birthdate
            if (def.InternalType == "eCWStandalone" && pat == null)
            {
                long patNumByName = Patients.GetPatNumByNameAndBirthday(patLName, patFName, birthdate);
                //If patNumByName is 0 we couldn't locate by patNum, chartNum or name and birthdate so this message must be for a new patient
                if (patNumByName == 0)
                {
                    IsNewPat = true;
                }
                else
                {
                    pat             = Patients.GetPat(patNumByName);
                    patOld          = pat.Copy();
                    pat.ChartNumber = chartNum;                  //from now on, we will be able to find pat by chartNumber
                    Patients.Update(pat, patOld);
                }
            }
            if (IsNewPat)
            {
                pat = new Patient();
                if (chartNum != null)
                {
                    pat.ChartNumber = chartNum;
                }
                if (patNum != 0)
                {
                    pat.PatNum    = patNum;
                    pat.Guarantor = patNum;
                }
                pat.PriProv     = PrefC.GetLong(PrefName.PracticeDefaultProv);
                pat.BillingType = PrefC.GetLong(PrefName.PracticeDefaultBillType);
            }
            else
            {
                patOld = pat.Copy();
            }
            //Update hl7msg table with correct PatNum for this message
            HL7MsgCur.PatNum = pat.PatNum;
            HL7Msgs.Update(HL7MsgCur);
            //If this is a message that contains an SCH segment, loop through to find the AptNum.  Pass it to the other segments that will need it.
            long aptNum = 0;

            for (int s = 0; s < hl7defmsg.hl7DefSegments.Count; s++)
            {
                if (hl7defmsg.hl7DefSegments[s].SegmentName != SegmentNameHL7.SCH)
                {
                    continue;
                }
                //we found the SCH segment
                int schOrder = hl7defmsg.hl7DefSegments[s].ItemOrder;
                for (int f = 0; f < hl7defmsg.hl7DefSegments[s].hl7DefFields.Count; f++)           //Go through fields of SCH segment and get AptNum
                {
                    if (hl7defmsg.hl7DefSegments[s].hl7DefFields[f].FieldName == "apt.AptNum")
                    {
                        int aptNumOrdinal = hl7defmsg.hl7DefSegments[s].hl7DefFields[f].OrdinalPos;
                        aptNum = PIn.Long(msg.Segments[schOrder].Fields[aptNumOrdinal].ToString());
                    }
                }
            }
            //We now have a patient object , either loaded from the db or new, and aptNum so process this message for this patient
            //We need to insert the pat to get a patnum so we can compare to guar patnum to see if relationship to guar is self
            if (IsNewPat)
            {
                if (isVerboseLogging)
                {
                    EventLog.WriteEntry("OpenDentHL7", "Inserted patient: " + pat.FName + " " + pat.LName, EventLogEntryType.Information);
                }
                if (pat.PatNum == 0)
                {
                    pat.PatNum = Patients.Insert(pat, false);
                }
                else
                {
                    pat.PatNum = Patients.Insert(pat, true);
                }
                patOld = pat.Copy();
            }
            for (int i = 0; i < hl7defmsg.hl7DefSegments.Count; i++)
            {
                try {
                    SegmentHL7 seg = msg.GetSegment(hl7defmsg.hl7DefSegments[i].SegmentName, !hl7defmsg.hl7DefSegments[i].IsOptional);
                    if (seg != null)                   //null if segment was not found but is optional
                    {
                        ProcessSeg(pat, aptNum, hl7defmsg.hl7DefSegments[i], seg, msg);
                    }
                }
                catch (ApplicationException ex) {               //Required segment was missing, or other error.
                    HL7MsgCur.Note = "Could not process this HL7 message.  " + ex;
                    HL7Msgs.Update(HL7MsgCur);
                    throw new Exception("Could not process HL7 message.  " + ex);
                }
            }
            //We have processed the message so now update or insert the patient
            if (pat.FName == "" || pat.LName == "")
            {
                EventLog.WriteEntry("OpenDentHL7", "Patient demographics not processed due to missing first or last name. PatNum:" + pat.PatNum.ToString()
                                    , EventLogEntryType.Information);
                HL7MsgCur.Note = "Patient demographics not processed due to missing first or last name. PatNum:" + pat.PatNum.ToString();
                HL7Msgs.Update(HL7MsgCur);
                return;
            }
            if (IsNewPat)
            {
                if (pat.Guarantor == 0)
                {
                    pat.Guarantor = pat.PatNum;
                    Patients.Update(pat, patOld);
                }
                else
                {
                    Patients.Update(pat, patOld);
                }
            }
            else
            {
                if (isVerboseLogging)
                {
                    EventLog.WriteEntry("OpenDentHL7", "Updated patient: " + pat.FName + " " + pat.LName, EventLogEntryType.Information);
                }
                Patients.Update(pat, patOld);
            }
            HL7MsgCur.HL7Status = HL7MessageStatus.InProcessed;
            HL7Msgs.Update(HL7MsgCur);
        }