///<summary>Gets the message control ID of the message we are attempting to send, for TCP/IP acknowledgment.</summary> public static string GetControlId(HL7Msg msg) { string retval = ""; if (msg == null) { return(retval); } int controlIdOrder = 0; MessageHL7 msgHl7 = new MessageHL7(msg.MsgText); //creates the segments HL7Def def = HL7Defs.GetOneDeepEnabled(); if (def == null) { return(retval); } HL7DefMessage hl7defmsg = null; for (int i = 0; i < def.hl7DefMessages.Count; i++) { if (def.hl7DefMessages[i].MessageType == msgHl7.MsgType) { hl7defmsg = def.hl7DefMessages[i]; break; } } if (hl7defmsg == null) //No message definition for this type of message in the enabled def { return(retval); } for (int s = 0; s < hl7defmsg.hl7DefSegments.Count; s++) //get MSH segment { if (hl7defmsg.hl7DefSegments[s].SegmentName == SegmentNameHL7.MSH) { for (int f = 0; f < hl7defmsg.hl7DefSegments[s].hl7DefFields.Count; f++) //find messageControlId field in MSH segment def { if (hl7defmsg.hl7DefSegments[s].hl7DefFields[f].FieldName == "messageControlId") { controlIdOrder = hl7defmsg.hl7DefSegments[s].hl7DefFields[f].OrdinalPos; break; } } break; } } if (controlIdOrder == 0) //No messageControlId defined for this MSH segment { return(retval); } for (int i = 0; i < msgHl7.Segments.Count; i++) //get control ID from message located in MSH segment with field determined above { if (msgHl7.Segments[i].Name == SegmentNameHL7.MSH) { retval = msgHl7.Segments[i].Fields[controlIdOrder].ToString(); break; } } return(retval); }
private void EcwOldProcessMessage(string fullPath) { string msgtext = ""; int i = 0; while (i < 5) { try { msgtext = File.ReadAllText(fullPath); break; } catch { } Thread.Sleep(200); i++; if (i == 5) { EventLog.WriteEntry("Could not read text from file due to file locking issues.", EventLogEntryType.Error); return; } } try { MessageHL7 msg = new MessageHL7(msgtext); //this creates an entire heirarchy of objects. if (msg.MsgType == MessageTypeHL7.ADT) { if (IsVerboseLogging) { EventLog.WriteEntry("OpenDentHL7", "Processed ADT message", EventLogEntryType.Information); } EcwADT.ProcessMessage(msg, ecwOldIsStandalone, IsVerboseLogging); } else if (msg.MsgType == MessageTypeHL7.SIU && !ecwOldIsStandalone) //appointments don't get imported if standalone mode. { if (IsVerboseLogging) { EventLog.WriteEntry("OpenDentHL7", "Processed SUI message", EventLogEntryType.Information); } EcwSIU.ProcessMessage(msg, IsVerboseLogging); } } catch (Exception ex) { EventLog.WriteEntry(ex.Message + "\r\n" + ex.StackTrace, EventLogEntryType.Error); return; } //we won't be processing DFT messages. //else if(msg.MsgType==MessageType.DFT) { //ADT.ProcessMessage(msg); //} try { File.Delete(fullPath); } catch (Exception ex) { EventLog.WriteEntry("Delete failed for " + fullPath + "\r\n" + ex.Message, EventLogEntryType.Error); } }
/// <summary>Helper method to send given appt to the unscheduled list. /// Creates SecurityLogs and considers HL7.</summary> public static void SetApptUnschedHelper(Appointment appt, Patient pat = null, bool doFireApptEvent = true) { DateTime datePrevious = appt.DateTStamp; Appointments.SetAptStatus(appt, ApptStatus.UnschedList); //Appointments S-Class handles Signalods #region SecurityLogs if (appt.AptStatus != ApptStatus.Complete) //seperate log entry for editing completed appts. { SecurityLogs.MakeLogEntry(Permissions.AppointmentMove, appt.PatNum, appt.ProcDescript + ", " + appt.AptDateTime.ToString() + ", Sent to Unscheduled List", appt.AptNum, datePrevious); } else { SecurityLogs.MakeLogEntry(Permissions.AppointmentCompleteEdit, appt.PatNum, appt.ProcDescript + ", " + appt.AptDateTime.ToString() + ", Sent to Unscheduled List", appt.AptNum, datePrevious); } #endregion #region HL7 //If there is an existing HL7 def enabled, send a SIU message if there is an outbound SIU message defined if (HL7Defs.IsExistingHL7Enabled()) { if (pat == null) { pat = Patients.GetPat(appt.PatNum); } //S15 - Appt Cancellation event MessageHL7 messageHL7 = MessageConstructor.GenerateSIU(pat, Patients.GetPat(pat.Guarantor), EventTypeHL7.S15, appt); //Will be null if there is no outbound SIU message defined, so do nothing if (messageHL7 != null) { HL7Msg hl7Msg = new HL7Msg(); hl7Msg.AptNum = appt.AptNum; hl7Msg.HL7Status = HL7MessageStatus.OutPending; //it will be marked outSent by the HL7 service. hl7Msg.MsgText = messageHL7.ToString(); hl7Msg.PatNum = pat.PatNum; HL7Msgs.Insert(hl7Msg); #if DEBUG MessageBox.Show("Appointments", messageHL7.ToString()); #endif } } #endregion if (doFireApptEvent) { AppointmentEvent.Fire(ODEventType.AppointmentEdited, appt); } Recalls.SynchScheduledApptFull(appt.PatNum); }
///<summary>Reprocess the original HL7 msgs for any MedLabs with PatNum 0, creates the embedded PDF files from the base64 text in the ZEF segments ///<para>The old method used when parsing MedLab HL7 msgs was to wait to extract these files until the msg was manually associated with a patient. ///Associating the MedLabs to a patient and reprocessing the HL7 messages using middle tier was very slow.</para> ///<para>The new method is to create the PDF files and save them in the image folder in a subdirectory called "MedLabEmbeddedFiles" if a patient ///isn't located from the details in the PID segment of the message. Associating the MedLabs to a pat is now just a matter of moving the files to ///the pat's image folder and updating the PatNum columns. All files are now extracted and stored, either in a pat's folder or in the ///"MedLabEmbeddedFiles" folder, by the HL7 service.</para> ///<para>This will reprocess all HL7 messages for MedLabs with PatNum=0 and replace the MedLab, MedLabResult, MedLabSpecimen, and MedLabFacAttach ///rows as well as create any embedded files and insert document table rows. The document table rows will have PatNum=0, just like the MedLabs, ///if a pat is still not located with the details in the PID segment. Once the user manually attaches the MedLab to a patient, all rows will be ///updated with the correct PatNum and the embedded PDFs will be moved to the pat's image folder. The document.FileName column will contain the ///name of the file, regardless of where it is located. The file name will be updated to a relevant name for the folder in which it is located. ///i.e. in the MedLabEmbeddedFiles directory it may be named 3YG8Z420150909100527.pdf, but once moved to a pat's folder it will be renamed to ///something like PatientAustin375.pdf and the document.FileName column will be the current name.</para> ///<para>If storing images in the db, the document table rows will contain the base64 text version of the PDFs with PatNum=0 and will be updated ///with the correct PatNum once associated. The FileName will be just the extension ".pdf" until it is associated with a patient at which time it ///will be updated to something like PatientAustin375.pdf.</para></summary> public static int Reconcile() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetInt(MethodBase.GetCurrentMethod())); } string command = "SELECT * FROM medlab WHERE PatNum=0"; List <MedLab> listMedLabs = Crud.MedLabCrud.SelectMany(command); if (listMedLabs.Count < 1) { return(0); } List <long> listMedLabNumsNew = new List <long>(); //used to delete old MedLab objects after creating these new ones from the HL7 message text int failedCount = 0; foreach (string relativePath in listMedLabs.Select(x => x.FileName).Distinct().ToList()) { string fileTextCur = ""; try { if (PrefC.AtoZfolderUsed != DataStorageType.InDatabase) { fileTextCur = FileAtoZ.ReadAllText(FileAtoZ.CombinePaths(ImageStore.GetPreferredAtoZpath(), relativePath)); } } catch (Exception ex) { ex.DoNothing(); //To avoid a warning message. The ex is needed to ensure all exceptions are caught. failedCount++; continue; } MessageHL7 msg = new MessageHL7(fileTextCur); List <long> listMedLabNumsCur = MessageParserMedLab.Process(msg, relativePath, false); //re-creates the documents from the ZEF segments if (listMedLabNumsCur == null || listMedLabNumsCur.Count < 1) { failedCount++; continue; //not sure what to do, just move on? } listMedLabNumsNew.AddRange(listMedLabNumsCur); MedLabs.UpdateFileNames(listMedLabNumsCur, relativePath); } //Delete all MedLabs, MedLabResults, MedLabSpecimens, and MedLabFacAttaches except the ones just created //Don't delete until we successfully process the messages and have valid new MedLab objects foreach (MedLab medLab in listMedLabs) { failedCount += DeleteLabsAndResults(medLab, listMedLabNumsNew); } return(failedCount); }
private void textHL7Raw_TextChanged(object sender, EventArgs e) { textPatName.Text = ""; textPatIDNum.Text = ""; textPatAccountNum.Text = ""; textDateTimeTest.Text = ""; textServiceID.Text = ""; textServiceName.Text = ""; try { //ORU-R01 MessageHL7 msg = new MessageHL7(textHL7Raw.Text); SegmentHL7 segPID = msg.GetSegment(SegmentNameHL7.PID, false); patNum = 0; if (segPID != null) { fName = segPID.GetFieldComponent(5, 1); lName = segPID.GetFieldComponent(5, 0); //F M L ? textPatName.Text = segPID.GetFieldComponent(5, 1) + " " + segPID.GetFieldComponent(5, 2) + " " + segPID.GetFieldComponent(5, 0); textPatIDNum.Text = segPID.GetFieldFullText(2); patNum = Patients.GetPatNumByName(lName, fName); //could be 0 //patNum=PIn.Long(segPID.GetFieldFullText(2)); textPatAccountNum.Text = segPID.GetFieldFullText(18); } SegmentHL7 segOBR = msg.GetSegment(SegmentNameHL7.OBR, false); if (segOBR != null) { textServiceID.Text = segOBR.GetFieldComponent(4, 0); textServiceName.Text = segOBR.GetFieldComponent(4, 1); } SegmentHL7 segOBX = msg.GetSegment(SegmentNameHL7.OBX, false); if (segOBX != null) { DateTime dt = segOBX.GetDateTime(14); if (dt.Year > 1880) { textDateTimeTest.Text = dt.ToShortDateString(); // +" "+dt.ToShortTimeString(); } } FillPatAndGrid(); } catch { patNum = 0; FillPatAndGrid(); MessageBox.Show("Error parsing HL7."); } }
private void CreateLabPanel() { MedicalOrder order = listLabOrders[gridMain.GetSelectedIndex()]; MessageHL7 msg = new MessageHL7(textHL7Raw.Text); //SegmentHL7 segOBR=null; //SegmentHL7 segOBX=null; //int idxPanel=0; //int idxResult=0; LabPanel panel = null; LabResult result = null; //loop through all message segments. for (int i = 0; i < msg.Segments.Count; i++) { if (msg.Segments[i].Name == SegmentNameHL7.OBR) //if this is the start of a new panel { panel = new LabPanel(); panel.PatNum = order.PatNum; panel.MedicalOrderNum = order.MedicalOrderNum; panel.RawMessage = textHL7Raw.Text; panel.LabNameAddress = msg.Segments[i].GetFieldFullText(20); panel.SpecimenSource = msg.Segments[i].GetFieldFullText(15); panel.SpecimenCondition = msg.Segments[i].GetFieldFullText(13); panel.ServiceId = msg.Segments[i].GetFieldComponent(4, 0); panel.ServiceName = msg.Segments[i].GetFieldComponent(4, 1); LabPanels.Insert(panel); } if (msg.Segments[i].Name == SegmentNameHL7.OBX) //if this is a result within a panel { result = new LabResult(); result.LabPanelNum = panel.LabPanelNum; result.DateTimeTest = msg.Segments[i].GetDateTime(14); result.TestID = msg.Segments[i].GetFieldComponent(3, 0); result.TestName = msg.Segments[i].GetFieldComponent(3, 1); result.ObsValue = msg.Segments[i].GetFieldFullText(5); result.ObsUnits = msg.Segments[i].GetFieldFullText(6); result.ObsRange = msg.Segments[i].GetFieldFullText(7); LabResults.Insert(result); } //any other kind of segment, continue. } //order.IsLabPending=false; //MedicalOrders.Update(order); //return true;//I guess it's always true? }
private void ProcessMessageFile(string fullPath) { string msgtext = ""; int i = 0; while (i < 5) { try { msgtext = File.ReadAllText(fullPath); break; } catch { } Thread.Sleep(200); i++; if (i == 5) { EventLog.WriteEntry("Could not read text from file due to file locking issues.", EventLogEntryType.Error); return; } } try { MessageHL7 msg = new MessageHL7(msgtext); //this creates an entire heirarchy of objects. MessageParser.Process(msg, IsVerboseLogging); if (IsVerboseLogging) { EventLog.WriteEntry("OpenDentHL7", "Processed message " + msg.MsgType.ToString(), EventLogEntryType.Information); } } catch (Exception ex) { EventLog.WriteEntry(ex.Message + "\r\n" + ex.StackTrace, EventLogEntryType.Error); return; } try { File.Delete(fullPath); } catch (Exception ex) { EventLog.WriteEntry("Delete failed for " + fullPath + "\r\n" + ex.Message, EventLogEntryType.Error); } }
///<summary>Creates a single recall appointment. If it's from a double click, then it will end up on that spot in the Appts module. If not, it will end up on the pinboard with StringDateJumpTo as due date to jump to. ListAptNumsSelected will contain the AptNum of the new appointment.</summary> public void MakeRecallAppointment() { List <InsSub> listInsSubs = InsSubs.RefreshForFam(_famCur); List <InsPlan> listInsPlans = InsPlans.RefreshForSubList(listInsSubs); Appointment apt = null; DateTime dateTimeApt = DateTime.MinValue; if (this.IsInitialDoubleClick) { dateTimeApt = DateTimeClicked; } try{ apt = AppointmentL.CreateRecallApt(_patCur, listInsPlans, -1, listInsSubs, dateTimeApt); } catch (Exception ex) { MessageBox.Show(ex.Message); return; } DateTime datePrevious = apt.DateTStamp; ListAptNumsSelected.Add(apt.AptNum); if (IsInitialDoubleClick) { Appointment oldApt = apt.Copy(); if (_patCur.AskToArriveEarly > 0) { apt.DateTimeAskedToArrive = apt.AptDateTime.AddMinutes(-_patCur.AskToArriveEarly); MessageBox.Show(Lan.g(this, "Ask patient to arrive") + " " + _patCur.AskToArriveEarly + " " + Lan.g(this, "minutes early at") + " " + apt.DateTimeAskedToArrive.ToShortTimeString() + "."); } apt.AptStatus = ApptStatus.Scheduled; apt.ClinicNum = _patCur.ClinicNum; apt.Op = OpNumClicked; apt = Appointments.AssignFieldsForOperatory(apt); //Use apt.ClinicNum because it was just set based on Op.ClinicNum in AssignFieldsForOperatory(). if (!AppointmentL.IsSpecialtyMismatchAllowed(_patCur.PatNum, apt.ClinicNum)) { return; } Appointments.Update(apt, oldApt); _otherResult = OtherResult.CreateNew; SecurityLogs.MakeLogEntry(Permissions.AppointmentCreate, apt.PatNum, apt.AptDateTime.ToString(), apt.AptNum, datePrevious); //If there is an existing HL7 def enabled, send a SIU message if there is an outbound SIU message defined if (HL7Defs.IsExistingHL7Enabled()) { //S12 - New Appt Booking event MessageHL7 messageHL7 = MessageConstructor.GenerateSIU(_patCur, _famCur.GetPatient(_patCur.Guarantor), EventTypeHL7.S12, apt); //Will be null if there is no outbound SIU message defined, so do nothing if (messageHL7 != null) { HL7Msg hl7Msg = new HL7Msg(); hl7Msg.AptNum = apt.AptNum; hl7Msg.HL7Status = HL7MessageStatus.OutPending; //it will be marked outSent by the HL7 service. hl7Msg.MsgText = messageHL7.ToString(); hl7Msg.PatNum = _patCur.PatNum; HL7Msgs.Insert(hl7Msg); #if DEBUG MessageBox.Show(this, messageHL7.ToString()); #endif } } DialogResult = DialogResult.OK; return; } //not initialClick _otherResult = OtherResult.PinboardAndSearch; Recall recall = Recalls.GetRecallProphyOrPerio(_patCur.PatNum); //shouldn't return null. if (recall.DateDue < DateTime.Today) { StringDateJumpTo = DateTime.Today.ToShortDateString(); //they are overdue } else { StringDateJumpTo = recall.DateDue.ToShortDateString(); } //no securitylog entry needed here. That will happen when it's dragged off pinboard. DialogResult = DialogResult.OK; }
///<summary>Sets given appt.AptStatus to broken. ///Provide procCode that should be charted, can be null but will not chart a broken procedure. ///Also considers various broken procedure based prefs. ///Makes its own securitylog entries.</summary> public static void BreakApptHelper(Appointment appt, Patient pat, ProcedureCode procCode) { //suppressHistory is true due to below logic creating a log with a specific HistAppointmentAction instead of the generic changed. DateTime datePrevious = appt.DateTStamp; bool suppressHistory = false; if (procCode != null) { suppressHistory = (procCode.ProcCode.In("D9986", "D9987")); } Appointments.SetAptStatus(appt, ApptStatus.Broken, suppressHistory); //Appointments S-Class handles Signalods if (appt.AptStatus != ApptStatus.Complete) //seperate log entry for completed appointments. { SecurityLogs.MakeLogEntry(Permissions.AppointmentEdit, pat.PatNum, appt.ProcDescript + ", " + appt.AptDateTime.ToString() + ", Broken from the Appts module.", appt.AptNum, datePrevious); } else { SecurityLogs.MakeLogEntry(Permissions.AppointmentCompleteEdit, pat.PatNum, appt.ProcDescript + ", " + appt.AptDateTime.ToString() + ", Broken from the Appts module.", appt.AptNum, datePrevious); } #region HL7 //If there is an existing HL7 def enabled, send a SIU message if there is an outbound SIU message defined if (HL7Defs.IsExistingHL7Enabled()) { //S15 - Appt Cancellation event MessageHL7 messageHL7 = MessageConstructor.GenerateSIU(pat, Patients.GetPat(pat.Guarantor), EventTypeHL7.S15, appt); //Will be null if there is no outbound SIU message defined, so do nothing if (messageHL7 != null) { HL7Msg hl7Msg = new HL7Msg(); hl7Msg.AptNum = appt.AptNum; hl7Msg.HL7Status = HL7MessageStatus.OutPending; //it will be marked outSent by the HL7 service. hl7Msg.MsgText = messageHL7.ToString(); hl7Msg.PatNum = pat.PatNum; HL7Msgs.Insert(hl7Msg); #if DEBUG MessageBox.Show("Appointments", messageHL7.ToString()); #endif } } #endregion #region Charting the proc if (procCode != null) { switch (procCode.ProcCode) { case "D9986": //Missed HistAppointments.CreateHistoryEntry(appt.AptNum, HistAppointmentAction.Missed); break; case "D9987": //Cancelled HistAppointments.CreateHistoryEntry(appt.AptNum, HistAppointmentAction.Cancelled); break; } Procedure procedureCur = new Procedure(); procedureCur.PatNum = pat.PatNum; procedureCur.ProvNum = (procCode.ProvNumDefault > 0 ? procCode.ProvNumDefault : appt.ProvNum); procedureCur.CodeNum = procCode.CodeNum; procedureCur.ProcDate = DateTime.Today; procedureCur.DateEntryC = DateTime.Now; procedureCur.ProcStatus = ProcStat.C; procedureCur.ClinicNum = appt.ClinicNum; procedureCur.UserNum = Security.CurUser.UserNum; procedureCur.Note = Lans.g("AppointmentEdit", "Appt BROKEN for") + " " + appt.ProcDescript + " " + appt.AptDateTime.ToString(); procedureCur.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService); //Default proc place of service for the Practice is used. List <InsSub> listInsSubs = InsSubs.RefreshForFam(Patients.GetFamily(pat.PatNum)); List <InsPlan> listInsPlans = InsPlans.RefreshForSubList(listInsSubs); List <PatPlan> listPatPlans = PatPlans.Refresh(pat.PatNum); InsPlan insPlanPrimary = null; InsSub insSubPrimary = null; if (listPatPlans.Count > 0) { insSubPrimary = InsSubs.GetSub(listPatPlans[0].InsSubNum, listInsSubs); insPlanPrimary = InsPlans.GetPlan(insSubPrimary.PlanNum, listInsPlans); } double procFee; long feeSch; if (insPlanPrimary == null || procCode.NoBillIns) { feeSch = FeeScheds.GetFeeSched(0, pat.FeeSched, procedureCur.ProvNum); } else //Only take into account the patient's insurance fee schedule if the D9986 procedure is not marked as NoBillIns { feeSch = FeeScheds.GetFeeSched(insPlanPrimary.FeeSched, pat.FeeSched, procedureCur.ProvNum); } procFee = Fees.GetAmount0(procedureCur.CodeNum, feeSch, procedureCur.ClinicNum, procedureCur.ProvNum); if (insPlanPrimary != null && insPlanPrimary.PlanType == "p" && !insPlanPrimary.IsMedical) //PPO { double provFee = Fees.GetAmount0(procedureCur.CodeNum, Providers.GetProv(procedureCur.ProvNum).FeeSched, procedureCur.ClinicNum, procedureCur.ProvNum); procedureCur.ProcFee = Math.Max(provFee, procFee); } else { procedureCur.ProcFee = procFee; } if (!PrefC.GetBool(PrefName.EasyHidePublicHealth)) { procedureCur.SiteNum = pat.SiteNum; } Procedures.Insert(procedureCur); //Now make a claimproc if the patient has insurance. We do this now for consistency because a claimproc could get created in the future. List <Benefit> listBenefits = Benefits.Refresh(listPatPlans, listInsSubs); List <ClaimProc> listClaimProcsForProc = ClaimProcs.RefreshForProc(procedureCur.ProcNum); Procedures.ComputeEstimates(procedureCur, pat.PatNum, listClaimProcsForProc, false, listInsPlans, listPatPlans, listBenefits, pat.Age, listInsSubs); FormProcBroken FormPB = new FormProcBroken(procedureCur); FormPB.IsNew = true; FormPB.ShowDialog(); } #endregion #region BrokenApptAdjustment if (PrefC.GetBool(PrefName.BrokenApptAdjustment)) { Adjustment AdjustmentCur = new Adjustment(); AdjustmentCur.DateEntry = DateTime.Today; AdjustmentCur.AdjDate = DateTime.Today; AdjustmentCur.ProcDate = DateTime.Today; AdjustmentCur.ProvNum = appt.ProvNum; AdjustmentCur.PatNum = pat.PatNum; AdjustmentCur.AdjType = PrefC.GetLong(PrefName.BrokenAppointmentAdjustmentType); AdjustmentCur.ClinicNum = appt.ClinicNum; FormAdjust FormA = new FormAdjust(pat, AdjustmentCur); FormA.IsNew = true; FormA.ShowDialog(); } #endregion #region BrokenApptCommLog if (PrefC.GetBool(PrefName.BrokenApptCommLog)) { Commlog CommlogCur = new Commlog(); CommlogCur.PatNum = pat.PatNum; CommlogCur.CommDateTime = DateTime.Now; CommlogCur.CommType = Commlogs.GetTypeAuto(CommItemTypeAuto.APPT); CommlogCur.Note = Lan.g("Appointment", "Appt BROKEN for") + " " + appt.ProcDescript + " " + appt.AptDateTime.ToString(); CommlogCur.Mode_ = CommItemMode.None; CommlogCur.UserNum = Security.CurUser.UserNum; FormCommItem FormCI = new FormCommItem(); FormCI.ShowDialog(new CommItemModel() { CommlogCur = CommlogCur }, new CommItemController(FormCI) { IsNew = true }); } #endregion AutomationL.Trigger(AutomationTrigger.BreakAppointment, null, pat.PatNum); Recalls.SynchScheduledApptFull(appt.PatNum); }
///<summary>Sets given appt.AptStatus to broken. ///Provide procCode that should be charted, can be null but will not chart a broken procedure. ///Also considers various broken procedure based prefs. ///Makes its own securitylog entries.</summary> public static void BreakApptHelper(Appointment appt, Patient pat, ProcedureCode procCode) { //suppressHistory is true due to below logic creating a log with a specific HistAppointmentAction instead of the generic changed. DateTime datePrevious = appt.DateTStamp; bool suppressHistory = false; if (procCode != null) { suppressHistory = (procCode.ProcCode.In("D9986", "D9987")); } Appointments.SetAptStatus(appt, ApptStatus.Broken, suppressHistory); //Appointments S-Class handles Signalods if (appt.AptStatus != ApptStatus.Complete) //seperate log entry for completed appointments. { SecurityLogs.MakeLogEntry(Permissions.AppointmentEdit, pat.PatNum, appt.ProcDescript + ", " + appt.AptDateTime.ToString() + ", Broken from the Appts module.", appt.AptNum, datePrevious); } else { SecurityLogs.MakeLogEntry(Permissions.AppointmentCompleteEdit, pat.PatNum, appt.ProcDescript + ", " + appt.AptDateTime.ToString() + ", Broken from the Appts module.", appt.AptNum, datePrevious); } #region HL7 //If there is an existing HL7 def enabled, send a SIU message if there is an outbound SIU message defined if (HL7Defs.IsExistingHL7Enabled()) { //S15 - Appt Cancellation event MessageHL7 messageHL7 = MessageConstructor.GenerateSIU(pat, Patients.GetPat(pat.Guarantor), EventTypeHL7.S15, appt); //Will be null if there is no outbound SIU message defined, so do nothing if (messageHL7 != null) { HL7Msg hl7Msg = new HL7Msg(); hl7Msg.AptNum = appt.AptNum; hl7Msg.HL7Status = HL7MessageStatus.OutPending; //it will be marked outSent by the HL7 service. hl7Msg.MsgText = messageHL7.ToString(); hl7Msg.PatNum = pat.PatNum; HL7Msgs.Insert(hl7Msg); #if DEBUG MessageBox.Show("Appointments", messageHL7.ToString()); #endif } } #endregion List <Procedure> listProcedures = new List <Procedure>(); //splits should only exist on procs if they are using tp pre-payments List <PaySplit> listSplitsForApptProcs = new List <PaySplit>(); bool isNonRefundable = false; double brokenProcAmount = 0; Procedure brokenProcedure = new Procedure(); bool wasBrokenProcDeleted = false; if (PrefC.GetYN(PrefName.PrePayAllowedForTpProcs)) { listProcedures = Procedures.GetProcsForSingle(appt.AptNum, false); if (listProcedures.Count > 0) { listSplitsForApptProcs = PaySplits.GetPaySplitsFromProcs(listProcedures.Select(x => x.ProcNum).ToList()); } } #region Charting the proc if (procCode != null) { switch (procCode.ProcCode) { case "D9986": //Missed HistAppointments.CreateHistoryEntry(appt.AptNum, HistAppointmentAction.Missed); break; case "D9987": //Cancelled HistAppointments.CreateHistoryEntry(appt.AptNum, HistAppointmentAction.Cancelled); break; } brokenProcedure.PatNum = pat.PatNum; brokenProcedure.ProvNum = (procCode.ProvNumDefault > 0 ? procCode.ProvNumDefault : appt.ProvNum); brokenProcedure.CodeNum = procCode.CodeNum; brokenProcedure.ProcDate = DateTime.Today; brokenProcedure.DateEntryC = DateTime.Now; brokenProcedure.ProcStatus = ProcStat.C; brokenProcedure.ClinicNum = appt.ClinicNum; brokenProcedure.UserNum = Security.CurUser.UserNum; brokenProcedure.Note = Lans.g("AppointmentEdit", "Appt BROKEN for") + " " + appt.ProcDescript + " " + appt.AptDateTime.ToString(); brokenProcedure.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService); //Default proc place of service for the Practice is used. List <InsSub> listInsSubs = InsSubs.RefreshForFam(Patients.GetFamily(pat.PatNum)); List <InsPlan> listInsPlans = InsPlans.RefreshForSubList(listInsSubs); List <PatPlan> listPatPlans = PatPlans.Refresh(pat.PatNum); InsPlan insPlanPrimary = null; InsSub insSubPrimary = null; if (listPatPlans.Count > 0) { insSubPrimary = InsSubs.GetSub(listPatPlans[0].InsSubNum, listInsSubs); insPlanPrimary = InsPlans.GetPlan(insSubPrimary.PlanNum, listInsPlans); } double procFee; long feeSch; if (insPlanPrimary == null || procCode.NoBillIns) { feeSch = FeeScheds.GetFeeSched(0, pat.FeeSched, brokenProcedure.ProvNum); } else //Only take into account the patient's insurance fee schedule if the D9986 procedure is not marked as NoBillIns { feeSch = FeeScheds.GetFeeSched(insPlanPrimary.FeeSched, pat.FeeSched, brokenProcedure.ProvNum); } procFee = Fees.GetAmount0(brokenProcedure.CodeNum, feeSch, brokenProcedure.ClinicNum, brokenProcedure.ProvNum); if (insPlanPrimary != null && insPlanPrimary.PlanType == "p" && !insPlanPrimary.IsMedical) //PPO { double provFee = Fees.GetAmount0(brokenProcedure.CodeNum, Providers.GetProv(brokenProcedure.ProvNum).FeeSched, brokenProcedure.ClinicNum, brokenProcedure.ProvNum); brokenProcedure.ProcFee = Math.Max(provFee, procFee); } else if (listSplitsForApptProcs.Count > 0 && PrefC.GetBool(PrefName.TpPrePayIsNonRefundable) && procCode.ProcCode == "D9986") { //if there are pre-payments, non-refundable pre-payments is turned on, and the broken appointment is a missed code then auto-fill //the window with the sum of the procs for the appointment. Transfer money below after broken procedure is confirmed by the user. brokenProcedure.ProcFee = listSplitsForApptProcs.Sum(x => x.SplitAmt); isNonRefundable = true; } else { brokenProcedure.ProcFee = procFee; } if (!PrefC.GetBool(PrefName.EasyHidePublicHealth)) { brokenProcedure.SiteNum = pat.SiteNum; } Procedures.Insert(brokenProcedure); //Now make a claimproc if the patient has insurance. We do this now for consistency because a claimproc could get created in the future. List <Benefit> listBenefits = Benefits.Refresh(listPatPlans, listInsSubs); List <ClaimProc> listClaimProcsForProc = ClaimProcs.RefreshForProc(brokenProcedure.ProcNum); Procedures.ComputeEstimates(brokenProcedure, pat.PatNum, listClaimProcsForProc, false, listInsPlans, listPatPlans, listBenefits, pat.Age, listInsSubs); FormProcBroken FormPB = new FormProcBroken(brokenProcedure, isNonRefundable); FormPB.IsNew = true; FormPB.ShowDialog(); brokenProcAmount = FormPB.AmountTotal; wasBrokenProcDeleted = FormPB.IsProcDeleted; } #endregion #region BrokenApptAdjustment if (PrefC.GetBool(PrefName.BrokenApptAdjustment)) { Adjustment AdjustmentCur = new Adjustment(); AdjustmentCur.DateEntry = DateTime.Today; AdjustmentCur.AdjDate = DateTime.Today; AdjustmentCur.ProcDate = DateTime.Today; AdjustmentCur.ProvNum = appt.ProvNum; AdjustmentCur.PatNum = pat.PatNum; AdjustmentCur.AdjType = PrefC.GetLong(PrefName.BrokenAppointmentAdjustmentType); AdjustmentCur.ClinicNum = appt.ClinicNum; FormAdjust FormA = new FormAdjust(pat, AdjustmentCur); FormA.IsNew = true; FormA.ShowDialog(); } #endregion #region BrokenApptCommLog if (PrefC.GetBool(PrefName.BrokenApptCommLog)) { Commlog commlogCur = new Commlog(); commlogCur.PatNum = pat.PatNum; commlogCur.CommDateTime = DateTime.Now; commlogCur.CommType = Commlogs.GetTypeAuto(CommItemTypeAuto.APPT); commlogCur.Note = Lan.g("Appointment", "Appt BROKEN for") + " " + appt.ProcDescript + " " + appt.AptDateTime.ToString(); commlogCur.Mode_ = CommItemMode.None; commlogCur.UserNum = Security.CurUser.UserNum; commlogCur.IsNew = true; FormCommItem FormCI = new FormCommItem(commlogCur); FormCI.ShowDialog(); } #endregion #region Transfer money from TP Procedures if necessary //Note this MUST come after FormProcBroken since clicking cancel in that window will delete the procedure. if (isNonRefundable && !wasBrokenProcDeleted && listSplitsForApptProcs.Count > 0) { //transfer what the user specified in the broken appointment window. //transfer up to the amount specified by the user foreach (Procedure proc in listProcedures) { if (brokenProcAmount == 0) { break; } List <PaySplit> listSplitsForAppointmentProcedure = listSplitsForApptProcs.FindAll(x => x.ProcNum == proc.ProcNum); foreach (PaySplit split in listSplitsForAppointmentProcedure) { if (brokenProcAmount == 0) { break; } double amt = Math.Min(brokenProcAmount, split.SplitAmt); Payments.CreateTransferForTpProcs(proc, new List <PaySplit> { split }, brokenProcedure, amt); double amtPaidOnApt = listSplitsForApptProcs.Sum(x => x.SplitAmt); if (amtPaidOnApt > amt) { //If the original prepayment amount is greater than the amt being specified for the appointment break, transfer //the difference to an Unallocated Unearned Paysplit on the account. double remainingAmt = amtPaidOnApt - amt; //We have to create a new transfer payment here to correlate to the split. Payment txfrPayment = new Payment(); txfrPayment.PayAmt = 0; txfrPayment.PayDate = DateTime.Today; txfrPayment.ClinicNum = split.ClinicNum; txfrPayment.PayNote = "Automatic transfer from treatment planned procedure prepayment."; txfrPayment.PatNum = split.PatNum; //ultimately where the payment ends up. txfrPayment.PayType = 0; Payments.Insert(txfrPayment); PaymentEdit.IncomeTransferData transferData = PaymentEdit.IncomeTransferData.CreateTransfer(split, txfrPayment.PayNum, true, remainingAmt); PaySplit offset = transferData.ListSplitsCur.FirstOrDefault(x => x.FSplitNum != 0); long offsetSplitNum = PaySplits.Insert(offset); //Get the FSplitNum from the offset PaySplit allocation = transferData.ListSplitsCur.FirstOrDefault(x => x.FSplitNum == 0); allocation.FSplitNum = offsetSplitNum; PaySplits.Insert(allocation); //Insert so the split is now up to date SecurityLogs.MakeLogEntry(Permissions.PaymentCreate, txfrPayment.PatNum, "Automatic transfer of funds for treatment plan procedure pre-payments."); } brokenProcAmount -= amt; } } } //if broken appointment procedure was deleted (user cancelled out of the window) just keep money on the original procedure. #endregion AppointmentEvent.Fire(ODEventType.AppointmentEdited, appt); AutomationL.Trigger(AutomationTrigger.BreakAppointment, null, pat.PatNum); Recalls.SynchScheduledApptFull(appt.PatNum); }
/// <summary> /// </summary> private Patient CreatePatient(String LastName, String FirstName, DateTime birthDate, WebSheets.SheetAndSheetField sAnds) { Patient newPat = new Patient(); newPat.LName = LastName; newPat.FName = FirstName; newPat.Birthdate = birthDate; newPat.ClinicNum = sAnds.web_sheet.ClinicNum; if (PrefC.GetBool(PrefName.EasyNoClinics)) { //Set the patients primary provider to the practice default provider. newPat.PriProv = Providers.GetDefaultProvider().ProvNum; } else //Using clinics. //Set the patients primary provider to the clinic default provider. { newPat.PriProv = Providers.GetDefaultProvider(Clinics.ClinicNum).ProvNum; } Type t = newPat.GetType(); FieldInfo[] fi = t.GetFields(); foreach (FieldInfo field in fi) { // find match for fields in Patients in the web_sheetfieldlist var WebSheetFieldList = sAnds.web_sheetfieldlist.Where(sf => sf.FieldName.ToLower() == field.Name.ToLower()); if (WebSheetFieldList.Count() > 0) { // this loop is used to fill a field that may generate mutiple values for a single field in the patient. //for example the field gender has 2 eqivalent sheet fields in the web_sheetfieldlist for (int i = 0; i < WebSheetFieldList.Count(); i++) { WebSheets.webforms_sheetfield sf = WebSheetFieldList.ElementAt(i); String SheetWebFieldValue = sf.FieldValue; String RadioButtonValue = sf.RadioButtonValue; FillPatientFields(newPat, field, SheetWebFieldValue, RadioButtonValue); } } } try{ Patients.Insert(newPat, false); SecurityLogs.MakeLogEntry(Permissions.PatientCreate, newPat.PatNum, "Created from Web Forms."); //set Guarantor field the same as PatNum Patient patOld = newPat.Copy(); newPat.Guarantor = newPat.PatNum; Patients.Update(newPat, patOld); //If there is an existing HL7 def enabled, send an ADT message if there is an outbound ADT message defined if (HL7Defs.IsExistingHL7Enabled()) { MessageHL7 messageHL7 = MessageConstructor.GenerateADT(newPat, newPat, EventTypeHL7.A04); //patient is guarantor //Will be null if there is no outbound ADT message defined, so do nothing if (messageHL7 != null) { HL7Msg hl7Msg = new HL7Msg(); hl7Msg.AptNum = 0; hl7Msg.HL7Status = HL7MessageStatus.OutPending; //it will be marked outSent by the HL7 service. hl7Msg.MsgText = messageHL7.ToString(); hl7Msg.PatNum = newPat.PatNum; HL7Msgs.Insert(hl7Msg); #if DEBUG MessageBox.Show(this, messageHL7.ToString()); #endif } } } catch (Exception e) { gridMain.EndUpdate(); MessageBox.Show(e.Message); } return(newPat); }
private void TimerCallbackSendTCP(Object stateInfo) { List <HL7Msg> list = HL7Msgs.GetOnePending(); for (int i = 0; i < list.Count; i++) //Right now, there will only be 0 or 1 item in the list. { string sendMsgControlId = HL7Msgs.GetControlId(list[i]); //could be empty string Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); string[] strIpPort = HL7DefEnabled.OutgoingIpPort.Split(':'); //this was already validated in the HL7DefEdit window. IPAddress ipaddress = IPAddress.Parse(strIpPort[0]); //already validated int port = int.Parse(strIpPort[1]); //already validated IPEndPoint endpoint = new IPEndPoint(ipaddress, port); try { socket.Connect(endpoint); if (!IsSendTCPConnected) //Previous run failed to connect. This time connected so make log entry that connection was successful { EventLog.WriteEntry("OpenDentHL7", "The HL7 send TCP/IP socket connection failed to connect previously and was successful this time.", EventLogEntryType.Information); IsSendTCPConnected = true; } } catch (SocketException ex) { if (IsSendTCPConnected) //Previous run connected fine, make log entry and set bool to false { EventLog.WriteEntry("OpenDentHL7", "The HL7 send TCP/IP socket connection failed to connect.\r\nException: " + ex.Message, EventLogEntryType.Warning); IsSendTCPConnected = false; } return; } string data = MLLP_START_CHAR + list[i].MsgText + MLLP_END_CHAR + MLLP_ENDMSG_CHAR; try { byte[] byteData = Encoding.ASCII.GetBytes(data); socket.Send(byteData); //this is a blocking call //For MLLP V2, do a blocking Receive here, along with a timeout. byte[] ackBuffer = new byte[256]; //plenty big enough to receive the entire ack/nack response socket.ReceiveTimeout = 5000; //5 second timeout. Database is polled every 6 seconds for a new message to send, 5 second wait for acknowledgment int byteCountReceived = socket.Receive(ackBuffer); //blocking Receive char[] chars = new char[byteCountReceived]; Encoding.UTF8.GetDecoder().GetChars(ackBuffer, 0, byteCountReceived, chars, 0); StringBuilder strbAckMsg = new StringBuilder(); strbAckMsg.Append(chars); if (strbAckMsg.Length > 0 && strbAckMsg[0] != MLLP_START_CHAR) { list[i].Note = list[i].Note + "Malformed acknowledgment.\r\n"; HL7Msgs.Update(list[i]); throw new Exception("Malformed acknowledgment."); } else if (strbAckMsg.Length >= 3 && strbAckMsg[strbAckMsg.Length - 1] == MLLP_ENDMSG_CHAR && //last char is the endmsg char. strbAckMsg[strbAckMsg.Length - 2] == MLLP_END_CHAR) //the second-to-the-last char is the end char. { //we have a complete message strbAckMsg.Remove(0, 1); //strip off the start char strbAckMsg.Remove(strbAckMsg.Length - 2, 2); //strip off the end chars } else if (strbAckMsg.Length >= 2 && //so that the next line won't crash strbAckMsg[strbAckMsg.Length - 1] == MLLP_END_CHAR) //the last char is the end char. { //we will treat this as a complete message, because the endmsg char is optional. strbAckMsg.Remove(0, 1); //strip off the start char strbAckMsg.Remove(strbFullMsg.Length - 1, 1); //strip off the end char } else { list[i].Note = list[i].Note + "Malformed acknowledgment.\r\n"; HL7Msgs.Update(list[i]); throw new Exception("Malformed acknowledgment."); } MessageHL7 ackMsg = new MessageHL7(strbAckMsg.ToString()); try { MessageParser.ProcessAck(ackMsg, IsVerboseLogging); } catch (Exception ex) { list[i].Note = list[i].Note + ackMsg.ToString() + "\r\nError processing acknowledgment.\r\n"; HL7Msgs.Update(list[i]); throw new Exception("Error processing acknowledgment.\r\n" + ex.Message); } if (ackMsg.AckCode == "" || ackMsg.ControlId == "") { list[i].Note = list[i].Note + ackMsg.ToString() + "\r\nInvalid ACK message. Attempt to resend.\r\n"; HL7Msgs.Update(list[i]); throw new Exception("Invalid ACK message received."); } if (ackMsg.ControlId == sendMsgControlId && ackMsg.AckCode == "AA") //acknowledged received (Application acknowledgment: Accept) { list[i].Note = list[i].Note + ackMsg.ToString() + "\r\nMessage ACK (acknowledgment) received.\r\n"; } else if (ackMsg.ControlId == sendMsgControlId && ackMsg.AckCode != "AA") //ACK received for this message, but ack code was not acknowledgment accepted { if (list[i].Note.Contains("NACK4")) //this is the 5th negative acknowledgment, don't try again { list[i].Note = list[i].Note + "Ack code: " + ackMsg.AckCode + "\r\nThis is NACK5, the message status has been changed to OutFailed. We will not attempt to send again.\r\n"; list[i].HL7Status = HL7MessageStatus.OutFailed; } else if (list[i].Note.Contains("NACK")) //failed sending at least once already { list[i].Note = list[i].Note + "Ack code: " + ackMsg.AckCode + "\r\nNACK" + list[i].Note.Split(new string[] { "NACK" }, StringSplitOptions.None).Length + "\r\n"; } else { list[i].Note = list[i].Note + "Ack code: " + ackMsg.AckCode + "\r\nMessage NACK (negative acknowlegment) received. We will try to send again.\r\n"; } HL7Msgs.Update(list[i]); //Add NACK note to hl7msg table entry return; //socket closed in finally } else //ack received for control ID that does not match the control ID of message just sent { list[i].Note = list[i].Note + "Sent message control ID: " + sendMsgControlId + "\r\nAck message control ID: " + ackMsg.ControlId + "\r\nAck received for message other than message just sent. We will try to send again.\r\n"; HL7Msgs.Update(list[i]); return; } } catch (SocketException ex) { EventLog.WriteEntry("OpenDentHL7", "The HL7 send TCP/IP socket encountered an error when sending message or receiving acknowledgment.\r\nSocket Exception: " + ex.Message, EventLogEntryType.Warning); return; //Try again in 3 seconds. socket closed in finally } catch (Exception ex) { EventLog.WriteEntry("OpenDentHL7", "The HL7 send TCP/IP encountered an error when sending message or receiving acknowledgment.\r\nException: " + ex.Message, EventLogEntryType.Warning); return; //socket closed in finally } finally { if (socket != null) { socket.Shutdown(SocketShutdown.Both); socket.Close(); } } list[i].HL7Status = HL7MessageStatus.OutSent; HL7Msgs.Update(list[i]); //set the status to sent and save ack message in Note field. HL7Msgs.DeleteOldMsgText(); //This is inside the loop so that it happens less frequently. To clean up incoming messages, we may move this someday. } }
///<summary>Runs in a separate thread</summary> private void OnDataReceived(IAsyncResult asyncResult) { int byteCountReceived = socketIncomingWorker.EndReceive(asyncResult); //blocks until data is recieved. char[] chars = new char[byteCountReceived]; Decoder decoder = Encoding.UTF8.GetDecoder(); decoder.GetChars(dataBufferIncoming, 0, byteCountReceived, chars, 0); //doesn't necessarily get all bytes from the buffer because buffer could be half full. strbFullMsg.Append(chars); //strbFullMsg might already have partial data //I think we are guaranteed to have received at least one char. bool isFullMsg = false; bool isMalformed = false; if (strbFullMsg.Length == 1 && strbFullMsg[0] == MLLP_ENDMSG_CHAR) //the only char in the message is the end char { strbFullMsg.Clear(); //this must be the very end of a previously processed message. Discard. isFullMsg = false; } //else if(strbFullMsg[0]!=MLLP_START_CHAR) { else if (strbFullMsg.Length > 0 && strbFullMsg[0] != MLLP_START_CHAR) { //Malformed message. isFullMsg = true; //we're going to do this so that the error gets saved in the database further down. isMalformed = true; } else if (strbFullMsg.Length >= 3 && //so that the next two lines won't crash strbFullMsg[strbFullMsg.Length - 1] == MLLP_ENDMSG_CHAR && //last char is the endmsg char. strbFullMsg[strbFullMsg.Length - 2] == MLLP_END_CHAR) //the second-to-the-last char is the end char. { //we have a complete message strbFullMsg.Remove(0, 1); //strip off the start char strbFullMsg.Remove(strbFullMsg.Length - 2, 2); //strip off the end chars isFullMsg = true; } else if (strbFullMsg.Length >= 2 && //so that the next line won't crash strbFullMsg[strbFullMsg.Length - 1] == MLLP_END_CHAR) //the last char is the end char. { //we will treat this as a complete message, because the endmsg char is optional. //if the endmsg char gets sent in a subsequent block, the code above will discard it. strbFullMsg.Remove(0, 1); //strip off the start char strbFullMsg.Remove(strbFullMsg.Length - 1, 1); //strip off the end char isFullMsg = true; } else { isFullMsg = false; //this is an incomplete message. Continue to receive more blocks. } //end of big if statement------------------------------------------------- if (!isFullMsg) { dataBufferIncoming = new byte[8]; //clear the buffer socketIncomingWorker.BeginReceive(dataBufferIncoming, 0, dataBufferIncoming.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), null); return; //get another block } //Prepare to save message to database if malformed and not processed HL7Msg hl7Msg = new HL7Msg(); hl7Msg.MsgText = strbFullMsg.ToString(); strbFullMsg.Clear(); //ready for the next message bool isProcessed = true; string messageControlId = ""; string ackEvent = ""; if (isMalformed) { hl7Msg.HL7Status = HL7MessageStatus.InFailed; hl7Msg.Note = "This message is malformed so it was not processed."; HL7Msgs.Insert(hl7Msg); isProcessed = false; } else { MessageHL7 messageHl7Object = new MessageHL7(hl7Msg.MsgText); //this creates an entire heirarchy of objects. try { MessageParser.Process(messageHl7Object, IsVerboseLogging); //also saves the message to the db messageControlId = messageHl7Object.ControlId; ackEvent = messageHl7Object.AckEvent; } catch (Exception ex) { EventLog.WriteEntry("OpenDentHL7", "Error in OnDataRecieved when processing message:\r\n" + ex.Message + "\r\n" + ex.StackTrace, EventLogEntryType.Error); isProcessed = false; } } MessageHL7 hl7Ack = MessageConstructor.GenerateACK(messageControlId, isProcessed, ackEvent); if (hl7Ack == null) { EventLog.WriteEntry("OpenDentHL7", "No ACK defined for the enabled HL7 definition or no HL7 definition enabled.", EventLogEntryType.Information); return; } byte[] ackByteOutgoing = Encoding.ASCII.GetBytes(MLLP_START_CHAR + hl7Ack.ToString() + MLLP_END_CHAR + MLLP_ENDMSG_CHAR); if (IsVerboseLogging) { EventLog.WriteEntry("OpenDentHL7", "Beginning to send ACK.\r\n" + MLLP_START_CHAR + hl7Ack.ToString() + MLLP_END_CHAR + MLLP_ENDMSG_CHAR, EventLogEntryType.Information); } socketIncomingWorker.Send(ackByteOutgoing); //this is a locking call //eCW uses the same worker socket to send the next message. Without this call to BeginReceive, they would attempt to send again //and the send would fail since we were no longer listening in this thread. eCW would timeout after 30 seconds of waiting for their //acknowledgement, then they would close their end and create a new socket for the next message. With this call, we can accept message //after message without waiting for a new connection. dataBufferIncoming = new byte[8]; //clear the buffer socketIncomingWorker.BeginReceive(dataBufferIncoming, 0, dataBufferIncoming.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), null); }
/// <summary> private static Patient CreatePatient(String LastName, String FirstName, DateTime birthDate, WebForms_Sheet webFormSheet, Sheet sheet, string cultureName) { bool isWebForm = webFormSheet != null; Patient newPat = new Patient(); newPat.LName = LastName; newPat.FName = FirstName; newPat.Birthdate = birthDate; if (isWebForm) { newPat.ClinicNum = webFormSheet.ClinicNum; } else { newPat.ClinicNum = sheet.ClinicNum; } if (!PrefC.HasClinicsEnabled) { //Set the patients primary provider to the practice default provider. newPat.PriProv = Providers.GetDefaultProvider().ProvNum; } else //Using clinics. //Set the patients primary provider to the clinic default provider. { newPat.PriProv = Providers.GetDefaultProvider(Clinics.ClinicNum).ProvNum; } Type t = newPat.GetType(); FieldInfo[] fi = t.GetFields(); foreach (FieldInfo field in fi) { // find match for fields in Patients in the SheetFields if (isWebForm) { List <WebForms_SheetField> listWebFormsSheetFields = webFormSheet.SheetFields.FindAll(x => x.FieldName.ToLower() == field.Name.ToLower()); if (listWebFormsSheetFields.Count() > 0) { // this loop is used to fill a field that may generate mutiple values for a single field in the patient. //for example the field gender has 2 eqivalent sheet fields in the SheetFields foreach (WebForms_SheetField webFormsSheetField in listWebFormsSheetFields) { FillPatientFields(newPat, field, webFormsSheetField.FieldValue, webFormsSheetField.RadioButtonValue, cultureName, isWebForm, false); } } } else { List <SheetField> listSheetFields = sheet.SheetFields.FindAll(x => x.FieldName.ToLower() == field.Name.ToLower()); if (listSheetFields.Count() > 0) { // this loop is used to fill a field that may generate mutiple values for a single field in the patient. //for example the field gender has 2 eqivalent sheet fields in the SheetFields foreach (SheetField sheetField in listSheetFields) { FillPatientFields(newPat, field, sheetField.FieldValue, sheetField.RadioButtonValue, "", isWebForm, sheet.IsCemtTransfer); } } } } try { Patients.Insert(newPat, false); SecurityLogs.MakeLogEntry(Permissions.PatientCreate, newPat.PatNum, isWebForm ? "Created from Web Forms." : "Created from CEMT transfer."); //set Guarantor field the same as PatNum Patient patOld = newPat.Copy(); newPat.Guarantor = newPat.PatNum; Patients.Update(newPat, patOld); //If there is an existing HL7 def enabled, send an ADT message if there is an outbound ADT message defined if (HL7Defs.IsExistingHL7Enabled()) { MessageHL7 messageHL7 = MessageConstructor.GenerateADT(newPat, newPat, EventTypeHL7.A04); //patient is guarantor //Will be null if there is no outbound ADT message defined, so do nothing if (messageHL7 != null) { HL7Msg hl7Msg = new HL7Msg(); hl7Msg.AptNum = 0; hl7Msg.HL7Status = HL7MessageStatus.OutPending; //it will be marked outSent by the HL7 service. hl7Msg.MsgText = messageHL7.ToString(); hl7Msg.PatNum = newPat.PatNum; HL7Msgs.Insert(hl7Msg); #if DEBUG MessageBox.Show("FormWebForms", messageHL7.ToString()); #endif } } } catch (Exception e) { MessageBox.Show(e.Message); } return(newPat); }