public static string RunOne(bool showForms) { string retVal = ""; long provNum = ProviderC.ListShort[0].ProvNum; //dentist #1 Patient pat = Patients.GetPat(PatientTC.PatNum1); //patient#1 if (pat.PriProv != provNum) { Patient oldPat = pat.Copy(); pat.PriProv = provNum; //this script uses the primary provider for the patient Patients.Update(pat, oldPat); } PatPlan patplan = PatPlans.GetPatPlan(pat.PatNum, 1); InsSub sub = InsSubs.GetOne(patplan.InsSubNum); InsPlan plan = InsPlans.GetPlan(sub.PlanNum, new List <InsPlan>()); //the UI would block this due to carrier not supporting this transaction type. Clearinghouse clearinghouseHq = Clearinghouses.GetDefaultDental(); Clearinghouse clearinghouseClin = Clearinghouses.OverrideFields(clearinghouseHq, Clinics.ClinicNum); long etransNum = CanadianOutput.SendElegibility(clearinghouseClin, pat.PatNum, plan, new DateTime(1999, 1, 1), patplan.Relationship, patplan.PatID, showForms, sub); Etrans etrans = Etranss.GetEtrans(etransNum); string message = EtransMessageTexts.GetMessageText(etrans.EtransMessageTextNum); CCDFieldInputter formData = new CCDFieldInputter(message); string responseStatus = formData.GetValue("G05"); if (responseStatus != "R") { throw new Exception("Should be R"); } retVal += "Eligibility #1 successful.\r\n"; return(retVal); }
public static string RunFour(bool showForms) { string retVal = ""; long provNum = ProviderC.ListShort[1].ProvNum; //dentist #2 Patient pat = Patients.GetPat(PatientTC.PatNum6); //patient#6 if (pat.PriProv != provNum) { Patient oldPat = pat.Copy(); pat.PriProv = provNum; //this script uses the primary provider for the patient Patients.Update(pat, oldPat); } PatPlan patplan = PatPlans.GetPatPlan(pat.PatNum, 1); InsSub sub = InsSubs.GetOne(patplan.InsSubNum); InsPlan plan = InsPlans.GetPlan(sub.PlanNum, new List <InsPlan>()); long etransNum = CanadianOutput.SendElegibility(pat.PatNum, plan, new DateTime(1999, 1, 1), patplan.Relationship, patplan.PatID, showForms, sub); Etrans etrans = Etranss.GetEtrans(etransNum); string message = EtransMessageTexts.GetMessageText(etrans.EtransMessageTextNum); CCDFieldInputter formData = new CCDFieldInputter(message); string responseStatus = formData.GetValue("G05"); if (responseStatus != "M") { throw new Exception("Should be M"); } retVal += "Eligibility #4 successful.\r\n"; return(retVal); }
///<summary></summary> public static Etrans Insert835Etrans(string etransMessageText, DateTime dateTimeTrans) { Etrans etrans835 = Etranss.CreateEtrans(DateTime.Now, 0, etransMessageText, 0); //Todo: T create class. etrans835.Etype = EtransType.ERA_835; Etranss.Insert(etrans835); etrans835.DateTimeTrans = dateTimeTrans; return(etrans835); }
public static string Run(int scriptNum, string responseExpected, Claim claim) { string retVal = ""; InsPlan insPlan = InsPlans.GetPlan(claim.PlanNum, null); InsSub insSub = InsSubs.GetOne(claim.InsSubNum); long etransNum = CanadianOutput.SendClaimReversal(claim, insPlan, insSub); Etrans etrans = Etranss.GetEtrans(etransNum); string message = EtransMessageTexts.GetMessageText(etrans.EtransMessageTextNum); CCDFieldInputter formData = new CCDFieldInputter(message); string responseStatus = formData.GetValue("G05"); if (responseStatus != responseExpected) { return("G05 should be " + responseExpected + "\r\n"); } retVal += "Reversal #" + scriptNum.ToString() + " successful.\r\n"; return(retVal); }
public static string Run(int scriptNum, string responseExpected, string responseTypeExpected, Claim claim, bool showForms, int pageNumber, int lastPageNumber, double firstExamFee, double diagnosticPhaseFee) { string retVal = ""; ClaimSendQueueItem queueItem = Claims.GetQueueList(claim.ClaimNum, claim.ClinicNum, 0)[0]; Clearinghouse clearinghouseHq = ClearinghouseL.GetClearinghouseHq(queueItem.ClearinghouseNum); Clearinghouse clearinghouseClin = Clearinghouses.OverrideFields(clearinghouseHq, Clinics.ClinicNum); Eclaims.GetMissingData(clearinghouseClin, queueItem); //,out warnings); if (queueItem.MissingData != "") { return("Cannot send predetermination until missing data is fixed:\r\n" + queueItem.MissingData + "\r\n"); } #if DEBUG Canadian.testNumber = scriptNum; claim.PreAuthString = "" + pageNumber + "," + lastPageNumber + "," + firstExamFee + "," + diagnosticPhaseFee; #endif long etransNum = Canadian.SendClaim(clearinghouseClin, queueItem, showForms); Etrans etrans = Etranss.GetEtrans(etransNum); string message = EtransMessageTexts.GetMessageText(etrans.EtransMessageTextNum); CCDFieldInputter formData = new CCDFieldInputter(message); string responseType = formData.GetValue("A04"); if (responseType != responseTypeExpected) { return("Form type is '" + responseType + "' but should be '" + responseTypeExpected + "'\r\n"); } string responseStatus = formData.GetValue("G05"); if (responseStatus != responseExpected) { return("G05 is '" + responseStatus + "' but should be '" + responseExpected + "'\r\n"); } if (responseExpected == "R" && responseTypeExpected == "11") { //so far, only for #6. We need some other way to test if successful transaction string errorMsgCount = formData.GetValue("G06"); if (errorMsgCount == "00") { return("Wrong message count.\r\n"); } } retVal += "Predetermination #" + scriptNum + " page " + pageNumber + " of " + lastPageNumber + " successful.\r\n"; return(retVal); }
public static string Run(int scriptNum, string responseExpected, string responseTypeExpected, Claim claim, bool showForms) { string retVal = ""; ClaimSendQueueItem queueItem = Claims.GetQueueList(claim.ClaimNum, claim.ClinicNum, 0)[0]; Clearinghouse clearinghouseHq = ClearinghouseL.GetClearinghouseHq(queueItem.ClearinghouseNum); Clearinghouse clearinghouseClin = Clearinghouses.OverrideFields(clearinghouseHq, Clinics.ClinicNum); Eclaims.GetMissingData(clearinghouseClin, queueItem); //,out warnings); if (queueItem.MissingData != "") { return("Cannot send claim until missing data is fixed:\r\n" + queueItem.MissingData + "\r\n"); } #if DEBUG Canadian.testNumber = scriptNum; #endif long etransNum = Canadian.SendClaim(clearinghouseClin, queueItem, showForms); Etrans etrans = Etranss.GetEtrans(etransNum); string message = EtransMessageTexts.GetMessageText(etrans.EtransMessageTextNum); CCDFieldInputter formData = new CCDFieldInputter(message); string responseType = formData.GetValue("A04"); if (responseType != responseTypeExpected) { return("Form type should be " + responseTypeExpected + "\r\n"); } string responseStatus = formData.GetValue("G05"); if (responseStatus != responseExpected) { return("G05 should be " + responseExpected + "\r\n"); } if (responseExpected == "R" && responseTypeExpected == "11") { //so far, only for #6. We need some other way to test if successful transaction string errorMsgCount = formData.GetValue("G06"); if (errorMsgCount == "00") { return("Wrong message count.\r\n"); } } retVal += "Claim #" + scriptNum.ToString() + " successful.\r\n"; return(retVal); }
public static string Run(int scriptNum, string responseExpected, Claim claim) { string retVal = ""; InsPlan insPlan = InsPlans.GetPlan(claim.PlanNum, null); InsSub insSub = InsSubs.GetOne(claim.InsSubNum); Carrier carrier = Carriers.GetCarrier(insPlan.CarrierNum); Clearinghouse clearinghouseHq = Clearinghouses.GetClearinghouse(Clearinghouses.AutomateClearinghouseHqSelection(carrier.ElectID, claim.MedType)); Clearinghouse clearinghouseClin = Clearinghouses.OverrideFields(clearinghouseHq, Clinics.ClinicNum); long etransNum = CanadianOutput.SendClaimReversal(clearinghouseClin, claim, insPlan, insSub); Etrans etrans = Etranss.GetEtrans(etransNum); string message = EtransMessageTexts.GetMessageText(etrans.EtransMessageTextNum); CCDFieldInputter formData = new CCDFieldInputter(message); string responseStatus = formData.GetValue("G05"); if (responseStatus != responseExpected) { return("G05 should be " + responseExpected + "\r\n"); } retVal += "Reversal #" + scriptNum.ToString() + " successful.\r\n"; return(retVal); }
///<summary>Sends an X12 270 request and returns X12 271 response or an error message.</summary> public static string Benefits270(Clearinghouse clearinghouseClin, string x12message, out Etrans etransHtml) //called from x270Controller. Clinic-level clearinghouse passed in. { string retVal = ""; etransHtml = null; try { HttpWebRequest webReq; WebResponse webResponseXml; //Production URL. For testing, set username to 'test' and password to 'test'. //When the username and password are both set to 'test', the X12 270 request will be ignored and just the transmission will be verified. webReq = (HttpWebRequest)WebRequest.Create("https://web2.edsedi.com/eds/Transmit_Request"); webReq.KeepAlive = false; webReq.Method = "POST"; webReq.ContentType = "text/xml"; string postDataXml = "<?xml version=\"1.0\" encoding=\"us-ascii\"?>" + "<content>" + "<header>" + "<userId>" + clearinghouseClin.LoginID + "</userId>" + "<pass>" + clearinghouseClin.Password + "</pass>" + "<process>transmitEligibility</process>" + "<version>1</version>" + "</header>" + "<body>" + "<type>EDI</type>" //Can only be EDI + "<data><![CDATA[" + x12message.Replace("\r\n", "").Replace("\n", "") + "]]></data>" + "<returnType>EDI</returnType>" //Can be EDI, HTML, or EDI.HTML, but should mimic the above type + "</body>" + "</content>"; ASCIIEncoding encoding = new ASCIIEncoding(); byte[] arrayXmlBytes = encoding.GetBytes(postDataXml); Stream streamOut = webReq.GetRequestStream(); streamOut.Write(arrayXmlBytes, 0, arrayXmlBytes.Length); streamOut.Close(); webResponseXml = webReq.GetResponse(); //Process the response StreamReader readStream = new StreamReader(webResponseXml.GetResponseStream(), Encoding.ASCII); string responseXml = readStream.ReadToEnd(); readStream.Close(); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(responseXml); XmlNode nodeErrorCode = xmlDoc.SelectSingleNode(@"content/body/ERROR_CODE"); if (nodeErrorCode != null && nodeErrorCode.InnerText.ToString() != "0") { throw new Exception("Error Code: " + nodeErrorCode.InnerText + " - " + xmlDoc.SelectSingleNode(@"content/body/ERROR_MSG").InnerText.ToString()); } nodeErrorCode = xmlDoc.SelectSingleNode(@"content/error/code"); if (nodeErrorCode != null && nodeErrorCode.InnerText != "0") { throw new Exception("Error Code: " + nodeErrorCode.InnerText + " - " + xmlDoc.SelectSingleNode(@"content/error/description").InnerText); } string htmlMessage = xmlDoc.SelectSingleNode(@"content/body/htmlData")?.InnerText.ToString(); //can be null if (!string.IsNullOrEmpty(htmlMessage)) { etransHtml = Etranss.CreateEtrans(DateTime.Now, clearinghouseClin.HqClearinghouseNum, htmlMessage, Security.CurUser.UserNum); etransHtml.Etype = EtransType.HTML; Etranss.Insert(etransHtml); } retVal = xmlDoc.SelectSingleNode(@"content/body/ediData").InnerText.ToString(); } catch (Exception e) { retVal = e.Message; } return(retVal); }
private void butShowEtrans_Click(object sender, EventArgs e) { if (!checkClaims.Checked) { MessageBox.Show("Only works for claims right now."); return; } //In case the form was just opened DatabaseTools.SetDbConnection(dbname); int scriptNum = PIn.Int(textSingleScript.Text); long patNum = 0; double claimFee = 0; string predeterm = ""; switch (scriptNum) { case 1: patNum = Patients.GetPatNumByNameAndBirthday("Fête", "Lisa", new DateTime(1960, 4, 12)); claimFee = 222.35; break; case 2: patNum = Patients.GetPatNumByNameAndBirthday("Fête", "Lisa", new DateTime(1960, 4, 12)); claimFee = 1254.85; break; case 3: patNum = Patients.GetPatNumByNameAndBirthday("Smith", "John", new DateTime(1948, 3, 2)); claimFee = 439.55; break; case 4: patNum = Patients.GetPatNumByNameAndBirthday("Smith", "John", new DateTime(1988, 11, 2)); claimFee = 222.35; break; case 5: patNum = Patients.GetPatNumByNameAndBirthday("Howard", "Bob", new DateTime(1964, 5, 16)); claimFee = 222.35; break; case 6: patNum = Patients.GetPatNumByNameAndBirthday("Howard", "Bob", new DateTime(1964, 5, 16)); claimFee = 232.35; break; case 7: patNum = Patients.GetPatNumByNameAndBirthday("Howard", "Bob", new DateTime(1964, 5, 16)); claimFee = 232.35; predeterm = "PD78901234"; break; case 8: patNum = Patients.GetPatNumByNameAndBirthday("West", "Martha", new DateTime(1954, 12, 25)); claimFee = 565.35; break; case 9: patNum = Patients.GetPatNumByNameAndBirthday("Arpège", "Madeleine", new DateTime(1940, 5, 1)); claimFee = 527.35; break; } List <Claim> claimList = Claims.Refresh(patNum); Claim claim = null; for (int i = 0; i < claimList.Count; i++) { if (claimList[i].ClaimFee == claimFee && claimList[i].PreAuthString == predeterm) { claim = claimList[i]; } } if (claim == null) { MessageBox.Show("Claim not found."); return; } List <Etrans> etransList = Etranss.GetHistoryOneClaim(claim.ClaimNum); if (etransList.Count == 0) { MessageBox.Show("No history found of sent e-claim."); return; } FormEtransEdit FormE = new FormEtransEdit(); FormE.EtransCur = etransList[0]; FormE.ShowDialog(); }
///<summary>Called from Eclaims and includes multiple claims.</summary> public static string SendBatch(Clearinghouse clearinghouseClin, List <ClaimSendQueueItem> queueItems, int batchNum) { //STEP 1 - Build XML output. List <DP_RACINDP> listDps = new List <DP_RACINDP>(); List <ProcedureCode> listProcCodes = ProcedureCodes.GetAllCodes(); List <Etrans> listEtrans = new List <Etrans>(); foreach (ClaimSendQueueItem queueItem in queueItems) { Etrans etrans = Etranss.SetClaimSentOrPrinted(queueItem.ClaimNum, queueItem.PatNum, clearinghouseClin.HqClearinghouseNum, EtransType.Claim_Ramq, batchNum, Security.CurUser.UserNum); listEtrans.Add(etrans); //Now we need to update our cache of claims to reflect the change that took place in the database above in Etranss.SetClaimSentOrPrinted() queueItem.ClaimStatus = "S"; Claim claim = Claims.GetClaim(queueItem.ClaimNum); Provider provClaimTreat = Providers.GetProv(claim.ProvTreat); DP_RACINDP dp = new DP_RACINDP(); #region Header dp.CHN = DP_RACINDPCHN.Item06; dp.CHNSpecified = true; dp.ENRG = DP_RACINDPENRG.Item1; dp.ENRGSpecified = true; //We hijack the TaxID number for the TRNSM field. The TRNSM is a office identifying number. Test range for developers is 18000 to 18999. dp.TRNSM = clearinghouseClin.SenderTIN; dp.DISP = provClaimTreat.NationalProvID; //dp.CPTE_ADMN=;//Administrative account number. Not currently used. JulianCalendar calendar = new JulianCalendar(); dp.ATTES = (DateTime.Now.Year % 10).ToString() //One digit for year + calendar.GetDayOfYear(DateTime.Now).ToString().PadLeft(3, '0') //3 digits for Julian day of year. + (etrans.CarrierTransCounter % 1000).ToString().PadLeft(3, '0'); //3 digits for sequence number. dp.NCE = (etrans.CarrierTransCounter % 10000).ToString().PadLeft(4, '0'); dp.DISP_REFNT = claim.CanadianReferralProviderNum.Trim(); //dp.DIAGN=;//Diagnostic code. Not currently used. dp.ETAB = provClaimTreat.CanadianOfficeNum; //Usually empty. //dp.ADMIS=;//Date of patient admission. Not currently used. This would be the same as the date of service for dental claims anyway. //dp.SORTI=;//Date patient discharged. Not currently used. This would be the same as the date of service for dental claims anyway. dp.TOT_DEM = claim.ClaimFee.ToString().Replace(".", "").PadLeft(6, '0'); dp.COMPL = TidyStr(claim.ClaimNote, 200); //dp.CS=;//Not sure what this is. Not currently used. //dp.AUTOR=claim.PreAuthString;//Authorization number when invoicing acrylic prostheses. Required if DAT_AUTOR is present. Not currently used. //dp.DAT_AUTOR=claim.CanadianDateInitialLower;//Date of authorization when invoicing acrylic prostheses. Format YYMMDD. Not currently used. dp.SERV = claim.DateService.ToString("yyMMdd"); #endregion Header #region Insurance //Most fields in the insuranace section are optional. InsSub insSub = InsSubs.GetOne(claim.InsSubNum); dp.PERS_ASSU = new DP_RACINDPPERS_ASSU(); dp.PERS_ASSU.NAM = insSub.SubscriberID; Patient pat = Patients.GetPat(claim.PatNum); dp.PERS_ASSU.PRE = TidyStr(pat.FName, 20); dp.PERS_ASSU.NOM = TidyStr(pat.LName, 30); if (pat.Birthdate.Year > 1880) { dp.PERS_ASSU.NAISS = pat.Birthdate.ToString("yyyyMMdd"); } if (pat.Gender == PatientGender.Male) { dp.PERS_ASSU.SEXE = DP_RACINDPPERS_ASSUSEXE.M; } else if (pat.Gender == PatientGender.Female) { dp.PERS_ASSU.SEXE = DP_RACINDPPERS_ASSUSEXE.F; } else { //There is no value for UNKNOWN. This field is optional if the subscriber ID is present anyway. } List <PatPlan> listPatPlans = PatPlans.Refresh(claim.PatNum); PatPlan patPlan = PatPlans.GetByInsSubNum(listPatPlans, insSub.InsSubNum); dp.PERS_ASSU.CAM = patPlan.PatID; if (insSub.DateTerm.Year > 1880) { dp.PERS_ASSU.EXPIR_CAM = insSub.DateTerm.ToString("yyMM"); } InsPlan insPlan = InsPlans.RefreshOne(claim.PlanNum); InsPlan insPlan2 = InsPlans.RefreshOne(claim.PlanNum2); Carrier carrier = null; if (claim.ClaimType == "S") { carrier = Carriers.GetCarrier(insPlan2.CarrierNum); } else { carrier = Carriers.GetCarrier(insPlan.CarrierNum); } if (carrier.Address.Trim() != "") { dp.PERS_ASSU.ADR_1 = carrier.Address; dp.PERS_ASSU.ADR_2 = carrier.Address2; dp.PERS_ASSU.CP = carrier.Zip; } #endregion Insurance #region Procedures List <ClaimProc> listClaimProcsForPat = ClaimProcs.Refresh(claim.PatNum); List <ClaimProc> listClaimProcsForClaim = ClaimProcs.GetForSendClaim(listClaimProcsForPat, claim.ClaimNum); //Excludes labs. List <Procedure> listProcsForPat = Procedures.Refresh(claim.PatNum); List <DP_RACINDPACTE> listProcs = new List <DP_RACINDPACTE>(); foreach (ClaimProc claimProc in listClaimProcsForClaim) { Procedure proc = Procedures.GetProcFromList(listProcsForPat, claimProc.ProcNum); if (proc.ProcFee == 0) { continue; } ProcedureCode procCode = ProcedureCodes.GetProcCode(proc.CodeNum, listProcCodes); if (procCode.NoBillIns) { continue; } DP_RACINDPACTE acteProc = new DP_RACINDPACTE(); acteProc.ACTE = procCode.ProcCode; if (procCode.ProcCode.Length > 5) { acteProc.ACTE = procCode.ProcCode.Substring(0, 5); } acteProc.ROLE = "1"; //1 for principal role and 2 for assistant role. //acte.MODIF=;//Optional. Not sure what to put here, so leaving blank for now. acteProc.UNIT = proc.UnitQty.ToString().PadLeft(3, '0'); acteProc.MNT = proc.ProcFee.ToString("F").Replace(".", "").PadLeft(6, '0'); acteProc.DENT = proc.ToothNum.ToString().PadLeft(2, '0'); acteProc.SURF = proc.Surf.ToString().PadLeft(2, '0'); listProcs.Add(acteProc); List <Procedure> listLabProcs = Procedures.GetCanadianLabFees(proc.ProcNum, listProcsForPat); foreach (Procedure labProc in listLabProcs) { if (labProc.ProcFee == 0) { continue; } ProcedureCode labProcCode = ProcedureCodes.GetProcCode(labProc.CodeNum, listProcCodes); DP_RACINDPACTE acteLab = new DP_RACINDPACTE(); acteLab.ACTE = labProcCode.ProcCode; if (labProcCode.ProcCode.Length > 5) { acteLab.ACTE = labProcCode.ProcCode.Substring(0, 5); } acteLab.ROLE = "1"; //1 for principal role and 2 for assistant role. acteLab.MNT = labProc.ProcFee.ToString("F").Replace(".", "").PadLeft(6, '0'); listProcs.Add(acteLab); } } dp.ACTE = listProcs.ToArray(); #endregion Procedures listDps.Add(dp); } DP_RACIN batch = new DP_RACIN(); batch.DP = listDps.ToArray(); StringWriter sw = new StringWriter(); XmlSerializer serializer = new XmlSerializer(typeof(DP_RACIN)); serializer.Serialize(sw, batch); string xml = sw.ToString(); //Save a copy of the batch xml to each etrans entry (one per claim). EtransMessageText etransMsgText = new EtransMessageText(); etransMsgText.MessageText = xml; EtransMessageTexts.Insert(etransMsgText); foreach (Etrans etrans in listEtrans) { etrans.EtransMessageTextNum = etransMsgText.EtransMessageTextNum; Etranss.Update(etrans); } //Step 2 - ZIP XML and save to report path. The zip file name and file name within the zip file do not matter. string zipFilePath = CodeBase.ODFileUtils.CreateRandomFile(clearinghouseClin.ExportPath, ".zip", "claims"); ZipFile zip = null; try { zip = new ZipFile(); zip.UseZip64WhenSaving = Zip64Option.Always; zip.AddEntry("claims" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xml", xml); zip.Save(zipFilePath); zip.Dispose(); } catch (Exception ex) { ex.ToString(); if (zip != null) { zip.Dispose(); } if (File.Exists(zipFilePath)) { try { File.Delete(zipFilePath); } catch (Exception ex2) { ex2.ToString(); } } } return(xml); }
///<summary>The insplan that's passed in need not be properly updated to the database first.</summary> public static void RequestBenefits(Clearinghouse clearhouse, InsPlan plan, long patNum, Carrier carrier, List <Benefit> benList, long patPlanNum, InsSub insSub) { Patient pat = Patients.GetPat(patNum); Patient subsc = Patients.GetPat(insSub.Subscriber); Clinic clinic = Clinics.GetClinic(pat.ClinicNum); Provider billProv = Providers.GetProv(Providers.GetBillingProvNum(pat.PriProv, pat.ClinicNum)); //validation. Throw exception if missing info---------------------------------------- string validationResult = X270.Validate(clearhouse, carrier, billProv, clinic, plan, subsc, insSub); if (validationResult != "") { throw new Exception(Lan.g("FormInsPlan", "Please fix the following errors first:") + "\r\n" + validationResult); } //create a 270 message--------------------------------------------------------------- string x12message = X270.GenerateMessageText(clearhouse, carrier, billProv, clinic, plan, subsc, insSub); EtransMessageText etransMessageText = new EtransMessageText(); etransMessageText.MessageText = x12message; EtransMessageTexts.Insert(etransMessageText); //attach it to an etrans------------------------------------------------------------- Etrans etrans = new Etrans(); etrans.DateTimeTrans = DateTime.Now; etrans.ClearingHouseNum = clearhouse.ClearinghouseNum; etrans.Etype = EtransType.BenefitInquiry270; etrans.PlanNum = plan.PlanNum; etrans.InsSubNum = insSub.InsSubNum; etrans.EtransMessageTextNum = etransMessageText.EtransMessageTextNum; Etranss.Insert(etrans); //send the 270---------------------------------------------------------------------- string x12response = ""; //a connection error here needs to bubble up try { if (clearhouse.CommBridge == EclaimsCommBridge.ClaimConnect) { x12response = ClaimConnect.Benefits270(clearhouse, x12message); } } catch (Exception ex) { EtransMessageTexts.Delete(etrans.EtransMessageTextNum); Etranss.Delete(etrans.EtransNum); throw new ApplicationException(Lan.g("FormInsPlan", "Connection Error:") + "\r\n" + ex.GetType().Name + "\r\n" + ex.Message); } //start to process the 271---------------------------------------------------------- X271 x271 = null; if (X12object.IsX12(x12response)) { X12object x12obj = new X12object(x12response); if (x12obj.Is271()) { x271 = new X271(x12response); } } else //neither a 997 nor a 271 { EtransMessageTexts.Delete(etrans.EtransMessageTextNum); Etranss.Delete(etrans.EtransNum); throw new ApplicationException(Lan.g("FormInsPlan", "Error:") + "\r\n" + x12response); } /* * //In realtime mode, X12 limits the request to one patient. * //We will always use the subscriber. * //So all EB segments are for the subscriber. * List<EB271> listEB=new List<EB271>(); * EB271 eb; * if(x271 != null) { * for(int i=0;i<x271.Segments.Count;i++) { * if(x271.Segments[i].SegmentID != "EB") { * continue; * } * eb=new EB271(x271.Segments[i]); * listEB.Add(eb); * } * }*/ //create an etrans for the 271------------------------------------------------------ etransMessageText = new EtransMessageText(); etransMessageText.MessageText = x12response; EtransMessageTexts.Insert(etransMessageText); Etrans etrans271 = new Etrans(); etrans271.DateTimeTrans = DateTime.Now; etrans271.ClearingHouseNum = clearhouse.ClearinghouseNum; etrans271.Etype = EtransType.TextReport; if (X12object.IsX12(x12response)) //this shouldn't need to be tested because it was tested above. { if (x271 == null) { etrans271.Etype = EtransType.Acknowledge_997; } else { etrans271.Etype = EtransType.BenefitResponse271; } } etrans271.PlanNum = plan.PlanNum; etrans271.InsSubNum = insSub.InsSubNum; etrans271.EtransMessageTextNum = etransMessageText.EtransMessageTextNum; Etranss.Insert(etrans271); etrans.AckEtransNum = etrans271.EtransNum; if (etrans271.Etype == EtransType.Acknowledge_997) { X997 x997 = new X997(x12response); string error997 = x997.GetHumanReadable(); etrans.Note = "Error: " + error997; //"Malformed document sent. 997 error returned."; Etranss.Update(etrans); MessageBox.Show(etrans.Note); //CodeBase.MsgBoxCopyPaste msgbox=new CodeBase.MsgBoxCopyPaste(etrans.Note); //msgbox.ShowDialog(); //don't show the 270 interface. return; } else { string processingerror = x271.GetProcessingError(); if (processingerror != "") { etrans.Note = processingerror; Etranss.Update(etrans); MessageBox.Show(etrans.Note); //CodeBase.MsgBoxCopyPaste msgbox=new CodeBase.MsgBoxCopyPaste(etrans.Note); //msgbox.ShowDialog(); //don't show the 270 interface. return; } else { etrans.Note = "Normal 271 response."; //change this later to be explanatory of content. } } Etranss.Update(etrans); //show the user a list of benefits to pick from for import-------------------------- FormEtrans270Edit formE = new FormEtrans270Edit(patPlanNum, plan.PlanNum, insSub.InsSubNum); formE.EtransCur = etrans; formE.IsInitialResponse = true; formE.benList = benList; formE.ShowDialog(); }
///<summary>Throws exceptions. The insplan that's passed in need not be properly updated to the database first.</summary> ///<returns>The Etrans created from the request. Will be null if the request failed in any way.</returns> public static Etrans RequestBenefits(Clearinghouse clearinghouseClin, InsPlan plan, long patNum, Carrier carrier, InsSub insSub, out string error) { error = ""; Patient pat = Patients.GetPat(patNum); Patient subsc = Patients.GetPat(insSub.Subscriber); Clinic clinic = Clinics.GetClinic(pat.ClinicNum); Provider billProv = Providers.GetProv(Providers.GetBillingProvNum(pat.PriProv, pat.ClinicNum)); //validation. Throw exception if missing info---------------------------------------- string validationResult = X270.Validate(clearinghouseClin, carrier, billProv, clinic, plan, subsc, insSub, pat); if (validationResult != "") { throw new Exception(Lans.g("FormInsPlan", "Please fix the following errors first:") + "\r\n" + validationResult); } //create a 270 message--------------------------------------------------------------- string x12message = X270.GenerateMessageText(clearinghouseClin, carrier, billProv, clinic, plan, subsc, insSub, pat); EtransMessageText etransMessageText = new EtransMessageText(); etransMessageText.MessageText = x12message; EtransMessageTexts.Insert(etransMessageText); //attach it to an etrans------------------------------------------------------------- Etrans etrans = new Etrans(); etrans.PatNum = patNum; etrans.DateTimeTrans = DateTime.Now; etrans.ClearingHouseNum = clearinghouseClin.HqClearinghouseNum; etrans.Etype = EtransType.BenefitInquiry270; etrans.PlanNum = plan.PlanNum; etrans.InsSubNum = insSub.InsSubNum; etrans.EtransMessageTextNum = etransMessageText.EtransMessageTextNum; Etranss.Insert(etrans); //send the 270---------------------------------------------------------------------- string x12response = ""; Etrans etransHtml = null; //a connection error here needs to bubble up try { if (!String.IsNullOrWhiteSpace(FakeResponseOverride271)) { x12response = FakeResponseOverride271; } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.ClaimConnect) { x12response = ClaimConnect.Benefits270(clearinghouseClin, x12message); } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.EDS) { x12response = EDS.Benefits270(clearinghouseClin, x12message, out etransHtml); } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.WebMD) { x12response = WebMD.Benefits270(clearinghouseClin, x12message); } } catch (Exception ex) { EtransMessageTexts.Delete(etrans.EtransMessageTextNum); Etranss.Delete(etrans.EtransNum); throw new ApplicationException(Lans.g("FormInsPlan", "Connection Error:") + "\r\n" + ex.GetType().Name + "\r\n" + ex.Message); } //start to process the 271---------------------------------------------------------- X271 x271 = null; if (X12object.IsX12(x12response)) { X12object x12obj = new X12object(x12response); if (x12obj.Is271()) { x271 = new X271(x12response); } } else //not a 997, 999, 277 or 271 { EtransMessageTexts.Delete(etrans.EtransMessageTextNum); Etranss.Delete(etrans.EtransNum); throw new ApplicationException(Lans.g("FormInsPlan", "Error:") + "\r\n" + x12response); } /* * //In realtime mode, X12 limits the request to one patient. * //We will always use the subscriber. * //So all EB segments are for the subscriber. * List<EB271> listEB=new List<EB271>(); * EB271 eb; * if(x271 != null) { * for(int i=0;i<x271.Segments.Count;i++) { * if(x271.Segments[i].SegmentID != "EB") { * continue; * } * eb=new EB271(x271.Segments[i]); * listEB.Add(eb); * } * }*/ //create an etrans for the 271------------------------------------------------------ etransMessageText = new EtransMessageText(); etransMessageText.MessageText = x12response; EtransMessageTexts.Insert(etransMessageText); Etrans etrans271 = new Etrans(); etrans271.PatNum = patNum; etrans271.DateTimeTrans = DateTime.Now; etrans271.ClearingHouseNum = clearinghouseClin.HqClearinghouseNum; etrans271.Etype = EtransType.TextReport; if (X12object.IsX12(x12response)) //this shouldn't need to be tested because it was tested above. { if (x271 == null) { X12object Xobj = new X12object(x12response); if (Xobj.Is997()) { etrans271.Etype = EtransType.Acknowledge_997; } else if (Xobj.Is999()) { etrans271.Etype = EtransType.Acknowledge_999; } else if (X277.Is277(Xobj)) { etrans271.Etype = EtransType.StatusNotify_277; } else if (X835.Is835(Xobj)) { etrans271.Etype = EtransType.ERA_835; } else if (Xobj.IsAckInterchange()) { etrans271.Etype = EtransType.Ack_Interchange; } } else { etrans271.Etype = EtransType.BenefitResponse271; } } etrans271.PlanNum = plan.PlanNum; etrans271.InsSubNum = insSub.InsSubNum; etrans271.EtransMessageTextNum = etransMessageText.EtransMessageTextNum; etrans271.MessageText = etransMessageText.MessageText; //Not a DB column, used to save queries for some calling methods (OpenDentalService). if (etransHtml != null) { etrans271.AckEtransNum = etransHtml.EtransNum; } Etranss.Insert(etrans271); etrans.AckEtransNum = etrans271.EtransNum; etrans.AckEtrans = etrans271; //Not a DB column, used to save queries for some calling methods (OpenDentalService). if (etrans271.Etype == EtransType.Acknowledge_997) { X997 x997 = new X997(x12response); string error997 = x997.GetHumanReadable(); etrans.Note = "Error: " + error997; //"Malformed document sent. 997 error returned."; Etranss.Update(etrans); error = etrans.Note; return(null); } else if (etrans271.Etype == EtransType.Acknowledge_999) { X999 x999 = new X999(x12response); string error999 = x999.GetHumanReadable(); etrans.Note = "Error: " + error999; //"Malformed document sent. 999 error returned."; Etranss.Update(etrans); error = etrans.Note; return(null); } else if (etrans271.Etype == EtransType.StatusNotify_277) { X277 x277 = new X277(x12response); string error277 = x277.GetHumanReadable(); etrans.Note = "Error: " + error277; //"Malformed document sent. 277 error returned."; Etranss.Update(etrans); error = etrans.Note; return(null); } else if (etrans271.Etype == EtransType.ERA_835) { X835 x835 = new X835(etrans271, x12response, ""); string error835 = x835.GetHumanReadable(); etrans.Note = "Error: " + error835; //"Malformed document sent. 835 error returned."; Etranss.Update(etrans); error = etrans.Note; return(null); } else if (etrans271.Etype == EtransType.BenefitResponse271) //271 { string processingerror = x271.GetProcessingError(); if (processingerror != "") { etrans.Note = processingerror; Etranss.Update(etrans); error = etrans.Note; return(null); } else { etrans.Note = "Normal 271 response."; //change this later to be explanatory of content. } } else if (etrans271.Etype == EtransType.Ack_Interchange) //See document "X092 Elig 270-271.pdf" pages 388 and 401. { X12object xobj = new X12object(x12response); X12Segment segTa1 = xobj.GetNextSegmentById(0, "TA1"); if (segTa1.Get(4) == "A") { etrans.Note = "The request was accepted, but the response is empty."; } else { if (segTa1.Get(4) == "E") { etrans.Note = "The request was accepted with errors: "; } else if (segTa1.Get(4) == "R") { etrans.Note = "The request was rejected with errors: "; } switch (segTa1.Get(5)) { case "000": etrans.Note += "No error"; break; case "001": etrans.Note += "The Interchange Control Number in the Header and Trailer Do Not Match. " + "The Value From the Header is Used in the Acknowledgment."; break; case "002": etrans.Note += "This Standard as Noted in the Control Standards Identifier is Not Supported."; break; case "003": etrans.Note += "This Version of the Controls is Not Supported"; break; case "004": etrans.Note += "The Segment Terminator is Invalid"; break; case "005": etrans.Note += "Invalid Interchange ID Qualifier for Sender"; break; case "006": etrans.Note += "Invalid Interchange Sender ID"; break; case "007": etrans.Note += "Invalid Interchange ID Qualifier for Receiver"; break; case "008": etrans.Note += "Invalid Interchange Receiver ID"; break; case "009": etrans.Note += "Unknown Interchange Receiver ID"; break; case "010": etrans.Note += "Invalid Authorization Information Qualifier Value"; break; case "011": etrans.Note += "Invalid Authorization Information Value"; break; case "012": etrans.Note += "Invalid Security Information Qualifier Value"; break; case "013": etrans.Note += "Invalid Security Information Value"; break; case "014": etrans.Note += "Invalid Interchange Date Value"; break; case "015": etrans.Note += "Invalid Interchange Time Value"; break; case "016": etrans.Note += "Invalid Interchange Standards Identifier Value"; break; case "017": etrans.Note += "Invalid Interchange Version ID Value"; break; case "018": etrans.Note += "Invalid Interchange Control Number Value"; break; case "019": etrans.Note += "Invalid Acknowledgment Requested Value"; break; case "020": etrans.Note += "Invalid Test Indicator Value"; break; case "021": etrans.Note += "Invalid Number of Included Groups Value"; break; case "022": etrans.Note += "Invalid Control Structure"; break; case "023": etrans.Note += "Improper (Premature) End-of-File (Transmission)"; break; case "024": etrans.Note += "Invalid Interchange Content (e.g., Invalid GS Segment)"; break; case "025": etrans.Note += "Duplicate Interchange Control Number"; break; case "026": etrans.Note += "Invalid Data Element Separator"; break; case "027": etrans.Note += "Invalid Component Element Separator"; break; case "028": etrans.Note += "Invalid Delivery Date in Deferred Delivery Request"; break; case "029": etrans.Note += "Invalid Delivery Time in Deferred Delivery Request"; break; case "030": etrans.Note += "Invalid Delivery Time Code in Deferred Delivery Request"; break; case "031": etrans.Note += "Invalid Grade of Service Code"; break; } } } else { throw new Exception("Unknown response"); } Etranss.Update(etrans); return(etrans); }
///<summary>Supply a list of ClaimSendQueueItems. Called from FormClaimSend. Can only send to one clearinghouse at a time. ///The queueItems must contain at least one item. Each item in queueItems must have the same ClinicNum. Cannot include Canadian.</summary> public static void SendBatch(Clearinghouse clearinghouseClin, List <ClaimSendQueueItem> queueItems, EnumClaimMedType medType, IFormClaimFormItemEdit formClaimFormItemEdit, Renaissance.FillRenaissanceDelegate fillRenaissance, ITerminalConnector terminalConnector) { string messageText = ""; if (clearinghouseClin.Eformat == ElectronicClaimFormat.Canadian) { MessageBox.Show(Lans.g("Eclaims", "Cannot send Canadian claims as part of Eclaims.SendBatch.")); return; } //get next batch number for this clearinghouse int batchNum = Clearinghouses.GetNextBatchNumber(clearinghouseClin); //--------------------------------------------------------------------------------------- //Create the claim file for this clearinghouse if (clearinghouseClin.Eformat == ElectronicClaimFormat.x837D_4010 || clearinghouseClin.Eformat == ElectronicClaimFormat.x837D_5010_dental || clearinghouseClin.Eformat == ElectronicClaimFormat.x837_5010_med_inst) { messageText = x837Controller.SendBatch(clearinghouseClin, queueItems, batchNum, medType, false); } else if (clearinghouseClin.Eformat == ElectronicClaimFormat.Renaissance) { messageText = Renaissance.SendBatch(clearinghouseClin, queueItems, batchNum, formClaimFormItemEdit, fillRenaissance); } else if (clearinghouseClin.Eformat == ElectronicClaimFormat.Dutch) { messageText = Dutch.SendBatch(clearinghouseClin, queueItems, batchNum); } else if (clearinghouseClin.Eformat == ElectronicClaimFormat.Ramq) { messageText = Ramq.SendBatch(clearinghouseClin, queueItems, batchNum); } else { messageText = ""; //(ElectronicClaimFormat.None does not get sent) } if (messageText == "") //if failed to create claim file properly, { return; //don't launch program or change claim status } //---------------------------------------------------------------------------------------- //Launch Client Program for this clearinghouse if applicable if (clearinghouseClin.CommBridge == EclaimsCommBridge.None) { AttemptLaunch(clearinghouseClin, batchNum); } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.WebMD) { if (!WebMD.Launch(clearinghouseClin, batchNum)) { MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + WebMD.ErrorMessage); return; } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.BCBSGA) { if (!BCBSGA.Launch(clearinghouseClin, batchNum, terminalConnector)) { MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + BCBSGA.ErrorMessage); return; } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.Renaissance) { AttemptLaunch(clearinghouseClin, batchNum); } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.ClaimConnect) { if (ClaimConnect.Launch(clearinghouseClin, batchNum)) { MessageBox.Show("Upload successful."); } else { MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + ClaimConnect.ErrorMessage); return; } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.RECS) { if (!RECS.Launch(clearinghouseClin, batchNum)) { MessageBox.Show(Lans.g("Eclaims", "Claim file created, but could not launch RECS client.") + "\r\n" + RECS.ErrorMessage); //continue; } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.Inmediata) { if (!Inmediata.Launch(clearinghouseClin, batchNum)) { MessageBox.Show(Lans.g("Eclaims", "Claim file created, but could not launch Inmediata client.") + "\r\n" + Inmediata.ErrorMessage); //continue; } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.AOS) // added by SPK 7/13/05 { if (!AOS.Launch(clearinghouseClin, batchNum)) { MessageBox.Show(Lans.g("Eclaims", "Claim file created, but could not launch AOS Communicator.") + "\r\n" + AOS.ErrorMessage); //continue; } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.PostnTrack) { AttemptLaunch(clearinghouseClin, batchNum); } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.MercuryDE) { if (!MercuryDE.Launch(clearinghouseClin, batchNum)) { MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + MercuryDE.ErrorMessage); return; } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.ClaimX) { if (!ClaimX.Launch(clearinghouseClin, batchNum)) { MessageBox.Show(Lans.g("Eclaims", "Claim file created, but encountered an error while launching ClaimX Client.") + ":\r\n" + ClaimX.ErrorMessage); } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.EmdeonMedical) { if (!EmdeonMedical.Launch(clearinghouseClin, batchNum, medType)) { MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + EmdeonMedical.ErrorMessage); return; } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.DentiCal) { if (!DentiCal.Launch(clearinghouseClin, batchNum)) { MessageBox.Show(Lans.g("Eclaims", "Error sending.") + DentiCal.ErrorMessage); return; } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.NHS) { if (!NHS.Launch(clearinghouseClin, batchNum)) { MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + NHS.ErrorMessage); return; } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.EDS) { if (!EDS.Launch(clearinghouseClin, messageText)) { MessageBox.Show(Lans.g("Eclaims", "Error sending.") + "\r\n" + EDS.ErrorMessage); return; } } else if (clearinghouseClin.CommBridge == EclaimsCommBridge.Ramq) { if (!Ramq.Launch(clearinghouseClin, batchNum)) { MessageBox.Show(Lans.g("Eclaims", "Error sending.") + Ramq.ErrorMessage); return; } } //---------------------------------------------------------------------------------------- //finally, mark the claims sent. (only if not Canadian) EtransType etype = EtransType.ClaimSent; if (clearinghouseClin.Eformat == ElectronicClaimFormat.Renaissance) { etype = EtransType.Claim_Ren; } //Canadians cannot send in batches (see above). RAMQ is performing a similar algorithm but the steps are in a different order in Ramq.cs. if (clearinghouseClin.Eformat != ElectronicClaimFormat.Canadian && clearinghouseClin.Eformat != ElectronicClaimFormat.Ramq) { //Create the etransmessagetext that all claims in the batch will point to. EtransMessageText etransMsgText = new EtransMessageText(); etransMsgText.MessageText = messageText; EtransMessageTexts.Insert(etransMsgText); for (int j = 0; j < queueItems.Count; j++) { Etrans etrans = Etranss.SetClaimSentOrPrinted(queueItems[j].ClaimNum, queueItems[j].PatNum, clearinghouseClin.HqClearinghouseNum, etype, batchNum, Security.CurUser.UserNum); etrans.EtransMessageTextNum = etransMsgText.EtransMessageTextNum; Etranss.Update(etrans); //Now we need to update our cache of claims to reflect the change that took place in the database above in Etranss.SetClaimSentOrPrinted() queueItems[j].ClaimStatus = "S"; } } }
///<summary>Supply a list of ClaimSendQueueItems. Called from FormClaimSend. Can only send to one clearinghouse at a time. Able to send just send one claim. Cannot include Canadian.</summary> public static void SendBatch(List <ClaimSendQueueItem> queueItems, Clearinghouse clearhouse, EnumClaimMedType medType) { string messageText = ""; if (clearhouse.Eformat == ElectronicClaimFormat.Canadian) { MsgBox.Show("Eclaims", "Cannot send Canadian claims as part of Eclaims.SendBatch."); return; } //get next batch number for this clearinghouse int batchNum = Clearinghouses.GetNextBatchNumber(clearhouse); //--------------------------------------------------------------------------------------- //Create the claim file for this clearinghouse if (clearhouse.Eformat == ElectronicClaimFormat.x837D_4010 || clearhouse.Eformat == ElectronicClaimFormat.x837D_5010_dental || clearhouse.Eformat == ElectronicClaimFormat.x837_5010_med_inst) { messageText = x837Controller.SendBatch(queueItems, batchNum, clearhouse, medType); } else if (clearhouse.Eformat == ElectronicClaimFormat.Renaissance) { messageText = Renaissance.SendBatch(queueItems, batchNum); } else if (clearhouse.Eformat == ElectronicClaimFormat.Dutch) { messageText = Dutch.SendBatch(queueItems, batchNum); } else { messageText = ""; //(ElectronicClaimFormat.None does not get sent) } if (messageText == "") //if failed to create claim file properly, { return; //don't launch program or change claim status } //---------------------------------------------------------------------------------------- //Launch Client Program for this clearinghouse if applicable if (clearhouse.CommBridge == EclaimsCommBridge.None) { AttemptLaunch(clearhouse, batchNum); } else if (clearhouse.CommBridge == EclaimsCommBridge.WebMD) { if (!WebMD.Launch(clearhouse, batchNum)) { MessageBox.Show(Lan.g("Eclaims", "Error sending.")); return; } } else if (clearhouse.CommBridge == EclaimsCommBridge.BCBSGA) { if (!BCBSGA.Launch(clearhouse, batchNum)) { MessageBox.Show(Lan.g("Eclaims", "Error sending.")); return; } } else if (clearhouse.CommBridge == EclaimsCommBridge.Renaissance) { AttemptLaunch(clearhouse, batchNum); } else if (clearhouse.CommBridge == EclaimsCommBridge.ClaimConnect) { if (!ClaimConnect.Launch(clearhouse, batchNum)) { MessageBox.Show(Lan.g("Eclaims", "Error sending.")); return; } } else if (clearhouse.CommBridge == EclaimsCommBridge.RECS) { if (!RECS.Launch(clearhouse, batchNum)) { MessageBox.Show("Claim file created, but could not launch RECS client."); //continue; } } else if (clearhouse.CommBridge == EclaimsCommBridge.Inmediata) { if (!Inmediata.Launch(clearhouse, batchNum)) { MessageBox.Show("Claim file created, but could not launch Inmediata client."); //continue; } } else if (clearhouse.CommBridge == EclaimsCommBridge.AOS) // added by SPK 7/13/05 { if (!AOS.Launch(clearhouse, batchNum)) { MessageBox.Show("Claim file created, but could not launch AOS Communicator."); //continue; } } else if (clearhouse.CommBridge == EclaimsCommBridge.PostnTrack) { AttemptLaunch(clearhouse, batchNum); } else if (clearhouse.CommBridge == EclaimsCommBridge.MercuryDE) { if (!MercuryDE.Launch(clearhouse, batchNum)) { MsgBox.Show("Eclaims", "Error sending."); return; } } else if (clearhouse.CommBridge == EclaimsCommBridge.ClaimX) { if (!ClaimX.Launch(clearhouse, batchNum)) { MessageBox.Show("Claim file created, but encountered an error while launching ClaimX Client."); } } else if (clearhouse.CommBridge == EclaimsCommBridge.EmdeonMedical) { if (!EmdeonMedical.Launch(clearhouse, batchNum, medType)) { MessageBox.Show(Lan.g("Eclaims", "Error sending.")); return; } } //---------------------------------------------------------------------------------------- //finally, mark the claims sent. (only if not Canadian) EtransType etype = EtransType.ClaimSent; if (clearhouse.Eformat == ElectronicClaimFormat.Renaissance) { etype = EtransType.Claim_Ren; } if (clearhouse.Eformat != ElectronicClaimFormat.Canadian) { for (int j = 0; j < queueItems.Count; j++) { Etrans etrans = Etranss.SetClaimSentOrPrinted(queueItems[j].ClaimNum, queueItems[j].PatNum, clearhouse.ClearinghouseNum, etype, batchNum); Etranss.SetMessage(etrans.EtransNum, messageText); } } }
///<summary>Supply an arrayList of type ClaimSendQueueItem. Called from FormClaimSend. Can send to multiple clearinghouses simultaneously.</summary> public static void SendBatches(ArrayList queueItems) { //claimsByCHouse is of type ClaimSendQueueItem ArrayList[] claimsByCHouse = new ArrayList[Clearinghouses.List.Length]; for (int i = 0; i < claimsByCHouse.Length; i++) { claimsByCHouse[i] = new ArrayList(); } //divide the items by clearinghouse: for (int i = 0; i < queueItems.Count; i++) { claimsByCHouse[Clearinghouses.GetIndex(((ClaimSendQueueItem)queueItems[i]).ClearinghouseNum)] .Add(queueItems[i]); } //for any clearinghouses with claims, send them: int batchNum; bool result = true; for (int i = 0; i < claimsByCHouse.Length; i++) { if (claimsByCHouse[i].Count == 0) { continue; } //get next batch number for this clearinghouse batchNum = Clearinghouses.GetNextBatchNumber(Clearinghouses.List[i]); //--------------------------------------------------------------------------------------- //Create the claim file(s) for this clearinghouse if (Clearinghouses.List[i].Eformat == ElectronicClaimFormat.X12) { result = X12.SendBatch(claimsByCHouse[i], batchNum); } else if (Clearinghouses.List[i].Eformat == ElectronicClaimFormat.Renaissance) { result = Renaissance.SendBatch(claimsByCHouse[i], batchNum); } else if (Clearinghouses.List[i].Eformat == ElectronicClaimFormat.Canadian) { //Canadian is a little different because we need the sequence numbers. //So all programs are launched and statuses changed from within Canadian.SendBatch() //We don't care what the result is. Canadian.SendBatch(claimsByCHouse[i], batchNum); continue; } else { result = false; //(ElectronicClaimFormat.None does not get sent) } if (!result) //if failed to create claim file properly, { continue; //don't launch program or change claim status } //---------------------------------------------------------------------------------------- //Launch Client Program for this clearinghouse if applicable if (Clearinghouses.List[i].CommBridge == EclaimsCommBridge.None) { AttemptLaunch(Clearinghouses.List[i], batchNum); } else if (Clearinghouses.List[i].CommBridge == EclaimsCommBridge.WebMD) { if (!WebMD.Launch(Clearinghouses.List[i], batchNum)) { MessageBox.Show(Lan.g("Eclaims", "Error sending.")); continue; } } else if (Clearinghouses.List[i].CommBridge == EclaimsCommBridge.BCBSGA) { if (!BCBSGA.Launch(Clearinghouses.List[i], batchNum)) { MessageBox.Show(Lan.g("Eclaims", "Error sending.")); continue; } } else if (Clearinghouses.List[i].CommBridge == EclaimsCommBridge.Renaissance) { AttemptLaunch(Clearinghouses.List[i], batchNum); } else if (Clearinghouses.List[i].CommBridge == EclaimsCommBridge.ClaimConnect) { if (!WebClaim.Launch(Clearinghouses.List[i], batchNum)) { MessageBox.Show(Lan.g("Eclaims", "Error sending.")); continue; } } else if (Clearinghouses.List[i].CommBridge == EclaimsCommBridge.RECS) { if (!RECS.Launch(Clearinghouses.List[i], batchNum)) { MessageBox.Show("Claim file created, but could not launch RECS client."); //continue; } } else if (Clearinghouses.List[i].CommBridge == EclaimsCommBridge.Inmediata) { if (!Inmediata.Launch(Clearinghouses.List[i], batchNum)) { MessageBox.Show("Claim file created, but could not launch Inmediata client."); //continue; } } else if (Clearinghouses.List[i].CommBridge == EclaimsCommBridge.AOS) // added by SPK 7/13/05 { if (!AOS.Launch(Clearinghouses.List[i], batchNum)) { MessageBox.Show("Claim file created, but could not launch AOS Communicator."); //continue; } } else if (Clearinghouses.List[i].CommBridge == EclaimsCommBridge.PostnTrack) { AttemptLaunch(Clearinghouses.List[i], batchNum); //if(!PostnTrack.Launch(Clearinghouses.List[i],batchNum)){ // MessageBox.Show("Claim file created, but could not launch AOS Communicator."); //continue; //} } //---------------------------------------------------------------------------------------- //finally, mark the claims sent. (only if not Canadian) EtransType etype = EtransType.ClaimSent; if (Clearinghouses.List[i].Eformat == ElectronicClaimFormat.Renaissance) { etype = EtransType.Claim_Ren; } if (Clearinghouses.List[i].Eformat != ElectronicClaimFormat.Canadian) { for (int j = 0; j < claimsByCHouse[i].Count; j++) { Etranss.SetClaimSentOrPrinted(((ClaimSendQueueItem)claimsByCHouse[i][j]).ClaimNum, ((ClaimSendQueueItem)claimsByCHouse[i][j]).PatNum, Clearinghouses.List[i].ClearinghouseNum, etype); } } } //for(int i=0;i<claimsByCHouse.Length;i++){ }
///<summary>The result is a string which can be dropped into the insplan.BenefitNotes. Or it might throw an exception if invalid data. This class is also responsible for saving the returned message to the etrans table and printing out the required form.</summary> public static string SendElegibility(string electID, int patNum, string groupNumber, string divisionNo, string subscriberID, string patID, Relat patRelat, int subscNum, string dentaideCardSequence) { //Note: This might be the only class of this kind that returns a string. It's a special situation. //We are simply not going to bother with language translation here. //determine carrier. Carrier carrier = Carriers.GetCanadian(electID); //this also happens to validate missing or short value if (carrier == null) { throw new ApplicationException("Invalid carrier EDI code."); } Clearinghouse clearhouse = Canadian.GetClearinghouse(); if (clearhouse == null) { throw new ApplicationException("Canadian clearinghouse not found."); } string saveFolder = clearhouse.ExportPath; if (!Directory.Exists(saveFolder)) { throw new ApplicationException(saveFolder + " not found."); } //Initialize objects----------------------------------------------------------------------------------------------- Patient patient = Patients.GetPat(patNum); Patient subscriber = Patients.GetPat(subscNum); Provider treatProv = Providers.GetProv(Patients.GetProvNum(patient)); Provider billProv = Providers.GetProv(Providers.GetBillingProvNum(treatProv.ProvNum)); //I had to use a dialog box to get the eligibility code. //validate any missing info---------------------------------------------------------------------------------- string error = ""; if (carrier.CanadianNetworkNum == 0) { if (error != "") { error += ", "; } error += "Carrier does not have network specified"; } if (!Regex.IsMatch(carrier.ElectID, @"^[0-9]{6}$")) //not necessary, but nice { if (error != "") { error += ", "; } error += "CarrierId 6 digits"; } if (treatProv.NationalProvID.Length != 9) { if (error != "") { error += ", "; } error += "TreatingProv CDA num 9 digits"; } if (treatProv.CanadianOfficeNum.Length != 4) { if (error != "") { error += ", "; } error += "TreatingProv office num 4 char"; } if (billProv.NationalProvID.Length != 9) { if (error != "") { error += ", "; } error += "BillingProv CDA num 9 digits"; } if (groupNumber.Length == 0 || groupNumber.Length > 12 || groupNumber.Contains(" ")) { if (error != "") { error += ", "; } error += "Plan Number"; } if (subscriberID == "") { if (error != "") { error += ", "; } error += "SubscriberID"; } if (patNum != subscNum && patRelat == Relat.Self) //if patient is not subscriber, and relat is self { if (error != "") { error += ", "; } error += "Relationship cannot be self"; } if (patient.Gender == PatientGender.Unknown) { if (error != "") { error += ", "; } error += "Patient gender"; } if (patient.Birthdate.Year < 1880 || patient.Birthdate > DateTime.Today) { if (error != "") { error += ", "; } error += "Patient birthdate"; } if (patient.LName == "") { if (error != "") { error += ", "; } error += "Patient lastname"; } if (patient.FName == "") { if (error != "") { error += ", "; } error += "Patient firstname"; } if (subscriber.Birthdate.Year < 1880 || subscriber.Birthdate > DateTime.Today) { if (error != "") { error += ", "; } error += "Subscriber birthdate"; } if (subscriber.LName == "") { if (error != "") { error += ", "; } error += "Subscriber lastname"; } if (subscriber.FName == "") { if (error != "") { error += ", "; } error += "Subscriber firstname"; } if (error != "") { throw new ApplicationException(error); } FormCanadianEligibility FormElig = new FormCanadianEligibility(); FormElig.ShowDialog(); if (FormElig.DialogResult != DialogResult.OK) { throw new ApplicationException("Eligibility Code or Date missing."); } //eligiblity code guaranteed to not be 0 at this point. Also date will be between 1980 and 10 years from now. Etrans etrans = Etranss.CreateCanadianOutput(patNum, carrier.CarrierNum, carrier.CanadianNetworkNum, clearhouse.ClearinghouseNum, EtransType.Eligibility_CA); string txt = ""; //create message---------------------------------------------------------------------------------------------- //A01 transaction prefix 12 AN //todo txt += "123456789012"; //To be later provided by the individual network. //A02 office sequence number 6 N txt += Canadian.TidyN(etrans.OfficeSequenceNumber, 6); //A03 format version number 2 N txt += "04"; //A04 transaction code 2 N txt += "08"; //eligibility //A05 carrier id number 6 N txt += carrier.ElectID; //already validated as 6 digit number. //A06 software system id 3 AN The third character is for version of OD. //todo txt += "OD1"; //To be later supplied by CDAnet staff to uniquely identify OD. //A10 encryption method 1 N //todo txt += "1"; //A07 message length 5 N int len = 214; //todo does not account for C19. Possibly 30 more. //if(C19 is used, Plan Record){ //len+=30; //} txt += Canadian.TidyN(len, 5); //A09 carrier transaction counter 5 N txt += Canadian.TidyN(etrans.CarrierTransCounter, 5); //B01 CDA provider number 9 AN txt += Canadian.TidyAN(treatProv.NationalProvID, 9); //already validated //B02 (treating) provider office number 4 AN txt += Canadian.TidyAN(treatProv.CanadianOfficeNum, 4); //already validated //B03 billing provider number 9 AN //todo, need to account for possible 5 digit prov id assigned by carrier txt += Canadian.TidyAN(billProv.NationalProvID, 9); //already validated //C01 primary policy/plan number 12 AN (group number) //only validated to ensure that it's not blank and is less than 12. Also that no spaces. txt += Canadian.TidyAN(groupNumber, 12); //C11 primary division/section number 10 AN txt += Canadian.TidyAN(divisionNo, 10); //C02 subscriber id number 12 AN txt += Canadian.TidyAN(subscriberID.Replace("-", ""), 12); //validated //C17 primary dependant code 2 N. Optional txt += Canadian.TidyN(patID, 2); //C03 relationship code 1 N //User interface does not only show Canadian options, but all options are handled. txt += Canadian.GetRelationshipCode(patRelat); //C04 patient's sex 1 A //validated to not include "unknown" if (patient.Gender == PatientGender.Male) { txt += "M"; } else { txt += "F"; } //C05 patient birthday 8 N txt += patient.Birthdate.ToString("yyyyMMdd"); //validated //C06 patient last name 25 AE txt += Canadian.TidyAE(patient.LName, 25, true); //validated //C07 patient first name 15 AE txt += Canadian.TidyAE(patient.FName, 15, true); //validated //C08 patient middle initial 1 AE txt += Canadian.TidyAE(patient.MiddleI, 1); //C09 eligibility exception code 1 N txt += Canadian.TidyN(FormElig.EligibilityCode, 1); //validated //C12 plan flag 1 A //todo //might not be carrier.IsPMP. Might have to do with plan, not carrier. See F17. txt += " "; //C18 plan record count 1 N //todo txt += "0"; //C16 Eligibility date. 8 N. txt += FormElig.AsOfDate.ToString("yyyyMMdd"); //validated //D01 subscriber birthday 8 N txt += subscriber.Birthdate.ToString("yyyyMMdd"); //validated //D02 subscriber last name 25 AE txt += Canadian.TidyAE(subscriber.LName, 25, true); //validated //D03 subscriber first name 15 AE txt += Canadian.TidyAE(subscriber.FName, 15, true); //validated //D04 subscriber middle initial 1 AE txt += Canadian.TidyAE(subscriber.MiddleI, 1); //D10 language of insured 1 A if (subscriber.Language == "fr") { txt += "F"; } else { txt += "E"; } //D11 card sequence/version number 2 N //todo: Not validated against type of carrier yet. Need to check if Dentaide. txt += Canadian.TidyN(dentaideCardSequence, 2); //todo If C18=1, then the following field would appear //C19 plan record 30 AN string result = ""; try { result = Canadian.PassToCCD(txt, carrier.CanadianNetworkNum, clearhouse); } catch (ApplicationException ex) { Etranss.Delete(etrans.EtransNum); throw new ApplicationException(ex.Message); } Etranss.SetMessage(etrans.EtransNum, txt); etrans.MessageText = txt; FormCCDPrint FormP = new FormCCDPrint(etrans); //Print the form. FormP.ShowDialog(); //Now we will process the 'result' here to extract the important data. Basically Yes or No on the eligibility. //We might not do this for any other trans type besides eligibility. string retVal = "Eligibility check on " + DateTime.Today.ToShortDateString() + "\r\n"; CCDFieldInputter fieldInputter = new CCDFieldInputter(result); CCDField field = fieldInputter.GetFieldById("G05");//response status //CCDFieldInputter could really use a GetValue(string fieldId) method so I don't have to use a field object. switch (field.valuestr) { case "E": retVal += "Patient is eligible."; break; case "R": retVal += "Patient not eligible, or error in data."; break; case "M": retVal += "Manual claimform should be submitted for employer certified plan."; break; } CCDField[] fields = fieldInputter.GetFieldsById("G08"); //Error Codes for (int i = 0; i < fields.Length; i++) { retVal += "\r\n"; retVal += fields[i].valuestr; //todo: need to turn this into a readable string. } fields = fieldInputter.GetFieldsById("G32"); //Display messages for (int i = 0; i < fields.Length; i++) { retVal += "\r\n"; retVal += fields[i].valuestr; } return(retVal); }