///<summary>Removes the assigned user from the InsVerify of the InsPlan that is associated to the PatPlan passed in. ///Will only unassign if the user assigned to the patplan matches the user assigned to the insplan.</summary> private static void RemoveAssignedUser(PatPlan patPlanCur) { //No Remoting check; no call to db. //Get the insurance verified assigned to the PatPlan. InsVerify insVerifyForPatPlan = InsVerifies.GetOneByFKey(patPlanCur.PatPlanNum, VerifyTypes.PatientEnrollment); if (insVerifyForPatPlan != null && insVerifyForPatPlan.UserNum > 0) { //Get the insplan associated to the PatPlan. InsSub inssub = null; if (patPlanCur != null) { inssub = InsSubs.GetOne(patPlanCur.InsSubNum); } InsPlan insPlan = null; if (inssub != null) { insPlan = InsPlans.RefreshOne(inssub.PlanNum); } if (insPlan != null) { //Get the insVerify for the insplan associated to the patplan we are about to delete. InsVerify insVerifyForInsPlan = InsVerifies.GetOneByFKey(insPlan.PlanNum, VerifyTypes.InsuranceBenefit); //Only unassign the user for the insplan if it matches the user for the patplan being dropped if (insVerifyForInsPlan != null && insVerifyForInsPlan.UserNum == insVerifyForPatPlan.UserNum) { //Remove user and set DateLastVerified to MinValue. insVerifyForInsPlan.UserNum = 0; insVerifyForInsPlan.DateLastVerified = DateTime.MinValue; InsVerifies.Update(insVerifyForInsPlan); } } } }
///<summary>It's fastest if you supply a sub list that contains the sub, but it also works just fine if it can't initally locate the sub in the list. You can supply an empty list. If still not found, returns a new InsSub. The reason for the new InsSub is because it is common to immediately get an insplan using inssub.InsSubNum. And, of course, that would fail if inssub was null.</summary> public static InsSub GetSub(long insSubNum, List <InsSub> subList) { //No need to check RemotingRole; no call to db. InsSub retVal = new InsSub(); if (insSubNum == 0) { return(new InsSub()); } if (subList == null) { subList = new List <InsSub>(); } bool found = false; for (int i = 0; i < subList.Count; i++) { if (subList[i].InsSubNum == insSubNum) { found = true; retVal = subList[i]; } } if (!found) { retVal = GetOne(insSubNum); //retVal will now be null if not found } if (retVal == null) { //MessageBox.Show(Lans.g("InsPlans","Database is inconsistent. Please run the database maintenance tool.")); return(new InsSub()); } return(retVal); }
///<summary>Returns true if the inssub has valid fkey references and no changes were needed. ///Returns false if changes were needed. doFixIfInvalid dictates if changes were actually made, separate from the return value. ///If doFixIfInvalid is true, we attempt to delete an inssub with an invalid PlanNum. ///If unable to delete, we set the PlanNum to a new insplan associated to a carrier with the CarrierName of "UNKNOWN CARRIER" (this matches DBM logic)</summary> public static bool ValidatePlanNum(long insSubNum, bool doFixIfInvalid = true, List <InsSub> listInsSubs = null) { //No need to check RemotingRole; no call to db. List <InsPlan> listInsPlan = new List <InsPlan>(); InsSub sub = InsSubs.GetSub(insSubNum, listInsSubs); long subscriberNum = sub.Subscriber; InsPlan plan = InsPlans.GetPlan(sub.PlanNum, listInsPlan); if (plan != null) //Plan exists. This means the reference from the inssub is intact. { return(true); } if (!doFixIfInvalid) { //There is an invalid PlanNum reference. //Don't automatically fix the reference if the caller doesn't want it fixed. return(false); } try { //The inssub points to an invalid plan, attempt to delete sub InsSubs.Delete(sub.InsSubNum); SecurityLogs.MakeLogEntry(Permissions.InsPlanEditSub, subscriberNum, "Deleted inssub with invalid insplan attached."); } catch (Exception ex) { ex.DoNothing(); //Create blank insplan and attach to inssub InsSubs.AssignBlankPlanToInsSub(sub); SecurityLogs.MakeLogEntry(Permissions.InsPlanEditSub, subscriberNum, "Inssub with invalid insplan found, attached blank insplan."); } //Return false because the plan wasn't valid when entering the method, although it is now valid. return(false); }
///<summary>This will assign all PlanNums to new value when Create New Plan If Needed is selected and there are multiple subscribers to a plan and an inssub object has been updated to point at a new PlanNum. The PlanNum values need to be reflected in the claim, claimproc, payplan, and etrans tables, since those all both store inssub.InsSubNum and insplan.PlanNum.</summary> public static void SynchPlanNumsForNewPlan(InsSub SubCur) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), SubCur); return; } //claim.PlanNum string command = "UPDATE claim SET claim.PlanNum=" + POut.Long(SubCur.PlanNum) + " " + "WHERE claim.InsSubNum=" + POut.Long(SubCur.InsSubNum) + " AND claim.PlanNum!=" + POut.Long(SubCur.PlanNum); Db.NonQ(command); //claim.PlanNum2 command = "UPDATE claim SET claim.PlanNum2=" + POut.Long(SubCur.PlanNum) + " " + "WHERE claim.InsSubNum2=" + POut.Long(SubCur.InsSubNum) + " AND claim.PlanNum2!=" + POut.Long(SubCur.PlanNum); Db.NonQ(command); //claimproc.PlanNum command = "UPDATE claimproc SET claimproc.PlanNum=" + POut.Long(SubCur.PlanNum) + " " + "WHERE claimproc.InsSubNum=" + POut.Long(SubCur.InsSubNum) + " AND claimproc.PlanNum!=" + POut.Long(SubCur.PlanNum); Db.NonQ(command); //payplan.PlanNum command = "UPDATE payplan SET payplan.PlanNum=" + POut.Long(SubCur.PlanNum) + " " + "WHERE payplan.InsSubNum=" + POut.Long(SubCur.InsSubNum) + " AND payplan.PlanNum!=" + POut.Long(SubCur.PlanNum); Db.NonQ(command); //etrans.PlanNum, only used if EtransType.BenefitInquiry270 and BenefitResponse271 and Eligibility_CA. command = "UPDATE etrans SET etrans.PlanNum=" + POut.Long(SubCur.PlanNum) + " " + "WHERE etrans.InsSubNum!=0 AND etrans.InsSubNum=" + POut.Long(SubCur.InsSubNum) + " AND etrans.PlanNum!=" + POut.Long(SubCur.PlanNum); Db.NonQ(command); }
///<summary></summary> public static long Insert(InsSub insSub,bool useExistingPK){ if(RemotingClient.RemotingRole==RemotingRole.ClientWeb){ insSub.InsSubNum=Meth.GetLong(MethodBase.GetCurrentMethod(),insSub,useExistingPK); return insSub.InsSubNum; } return Crud.InsSubCrud.Insert(insSub,useExistingPK); }
///<summary>Returns the data needed for ProcFeeHelper. Does not get ListFees.</summary> public static ProcFeeHelper GetData(long patNum, ProcFeeHelper procFeeHelper) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { //Not passing procFeeHelper because the null lists will get turned into empty lists which messes things up. return(Meth.GetObject <ProcFeeHelper>(MethodBase.GetCurrentMethod(), patNum, null)); } procFeeHelper = procFeeHelper ?? new ProcFeeHelper(patNum); procFeeHelper.Pat = procFeeHelper.Pat ?? Patients.GetPat(patNum); procFeeHelper.ListPatPlans = procFeeHelper.ListPatPlans ?? PatPlans.GetPatPlansForPat(patNum); procFeeHelper.ListInsSubs = procFeeHelper.ListInsSubs ?? InsSubs.GetMany(procFeeHelper.ListPatPlans.Select(x => x.InsSubNum).ToList()); procFeeHelper.ListInsPlans = procFeeHelper.ListInsPlans ?? InsPlans.GetPlans(procFeeHelper.ListInsSubs.Select(x => x.PlanNum).ToList()); if (procFeeHelper.ListPatPlans.Count > 0) { PatPlan priPatPlan = procFeeHelper.ListPatPlans[0]; InsSub priInsSub = InsSubs.GetSub(priPatPlan.InsSubNum, procFeeHelper.ListInsSubs); InsPlan priInsPlan = InsPlans.GetPlan(priInsSub.PlanNum, procFeeHelper.ListInsPlans); procFeeHelper.ListBenefitsPrimary = procFeeHelper.ListBenefitsPrimary ?? Benefits.RefreshForPlan(priInsPlan.PlanNum, priPatPlan.PatPlanNum); } else { procFeeHelper.ListBenefitsPrimary = new List <Benefit>(); } return(procFeeHelper); }
///<summary>It's fastest if you supply a sub list that contains the sub, but it also works just fine if it can't initally locate the sub in the list. You can supply an empty list. If still not found, returns a new InsSub. The reason for the new InsSub is because it is common to immediately get an insplan using inssub.InsSubNum. And, of course, that would fail if inssub was null.</summary> public static InsSub GetSub(long insSubNum,List<InsSub> subList) { //No need to check RemotingRole; no call to db. InsSub retVal=new InsSub(); if(insSubNum==0) { return new InsSub(); } if(subList==null) { subList=new List<InsSub>(); } bool found=false; for(int i=0;i<subList.Count;i++) { if(subList[i].InsSubNum==insSubNum) { found=true; retVal=subList[i]; } } if(!found) { retVal=GetOne(insSubNum);//retVal will now be null if not found } if(retVal==null) { //MessageBox.Show(Lans.g("InsPlans","Database is inconsistent. Please run the database maintenance tool.")); return new InsSub(); } return retVal; }
///<summary></summary> public static InsSub CreateInsSub(long subscriberNum,long planNum){ InsSub sub=new InsSub(); sub.Subscriber=subscriberNum; sub.PlanNum=planNum; sub.SubscriberID="1234"; InsSubs.Insert(sub); return sub; }
///<summary>This will replace the currently attached InsPlan with an "UNKNOWN CARRIER" InsPlan.</summary> public static void AssignBlankPlanToInsSub(InsSub subCur) { //No need to check RemotingRole; no call to db. //Will get the plan if it exists, or create a new one and insert if it does not. InsPlan plan = InsPlans.GetByCarrierName("UNKNOWN CARRIER"); subCur.PlanNum = plan.PlanNum; Update(subCur); }
///<summary></summary> public static void Update(InsSub insSub) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), insSub); return; } Crud.InsSubCrud.Update(insSub); }
///<summary></summary> public static long Insert(InsSub insSub, bool useExistingPK) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { insSub.InsSubNum = Meth.GetLong(MethodBase.GetCurrentMethod(), insSub, useExistingPK); return(insSub.InsSubNum); } return(Crud.InsSubCrud.Insert(insSub, useExistingPK)); }
///<summary></summary> public static long Insert(InsSub insSub,bool useExistingPK){ if(RemotingClient.RemotingRole==RemotingRole.ClientWeb){ insSub.InsSubNum=Meth.GetLong(MethodBase.GetCurrentMethod(),insSub,useExistingPK); return insSub.InsSubNum; } if(DataConnection.DBtype==DatabaseType.Oracle) { return Crud.InsSubCrud.Insert(insSub);//Oracle ALWAYS uses existing PKs because they do not support auto-incrementing. } return Crud.InsSubCrud.Insert(insSub,useExistingPK); }
///<summary>Throws exception if dependencies. Doesn't delete anything else.</summary> public static void Delete(InsSub insSub) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),insSub); return; } long subNum=insSub.InsSubNum; try { ValidateNoKeys(subNum,true); } catch(ApplicationException ex){ throw new ApplicationException(Lans.g("FormInsPlan","Not allowed to delete: ")+ex.Message); } Crud.InsSubCrud.Delete(insSub.InsSubNum); }
///<summary></summary> public static long Insert(InsSub insSub, bool useExistingPK) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { insSub.InsSubNum = Meth.GetLong(MethodBase.GetCurrentMethod(), insSub, useExistingPK); return(insSub.InsSubNum); } //Security.CurUser.UserNum gets set on MT by the DtoProcessor so it matches the user from the client WS. insSub.SecUserNumEntry = Security.CurUser.UserNum; if (DataConnection.DBtype == DatabaseType.Oracle) { return(Crud.InsSubCrud.Insert(insSub)); //Oracle ALWAYS uses existing PKs because they do not support auto-incrementing. } return(Crud.InsSubCrud.Insert(insSub, useExistingPK)); }
///<summary>Throws exception if dependencies. Doesn't delete anything else.</summary> public static void Delete(InsSub insSub) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), insSub); return; } long subNum = insSub.InsSubNum; try { ValidateNoKeys(subNum, true); } catch (ApplicationException ex) { throw new ApplicationException(Lans.g("FormInsPlan", "Not allowed to delete: ") + ex.Message); } Crud.InsSubCrud.Delete(insSub.InsSubNum); }
///<summary></summary> public static long Insert(InsSub insSub, bool useExistingPK) { if (RemotingClient.RemotingRole != RemotingRole.ServerWeb) { insSub.SecUserNumEntry = Security.CurUser.UserNum; //must be before normal remoting role check to get user at workstation } if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { insSub.InsSubNum = Meth.GetLong(MethodBase.GetCurrentMethod(), insSub, useExistingPK); return(insSub.InsSubNum); } if (DataConnection.DBtype == DatabaseType.Oracle) { return(Crud.InsSubCrud.Insert(insSub)); //Oracle ALWAYS uses existing PKs because they do not support auto-incrementing. } return(Crud.InsSubCrud.Insert(insSub, useExistingPK)); }
///<summary>This will replace the currently attached InsPlan with an "UNKNOWN CARRIER" InsPlan.</summary> public static void AssignBlankPlanToInsSub(InsSub subCur) { //No need to check RemotingRole; no call to db. //Will get the plan if it exists, or create a new one and insert if it does not. string strCarrierUnknownName = "UNKNOWN CARRIER"; InsPlan plan = InsPlans.GetByCarrierName(strCarrierUnknownName).FirstOrDefault(); //If an UNKNOWN CARRIER plan doesn't exist in the database, we will create it if (plan == null) { //Will create a new UNKNOWN CARRIER carrier if it doesn't already exist Carrier carrier = Carriers.GetByNameAndPhone(strCarrierUnknownName, ""); plan = new InsPlan(); plan.CarrierNum = carrier.CarrierNum; //Security.CurUser.UserNum gets set on MT by the DtoProcessor so it matches the user from the client WS. plan.SecUserNumEntry = Security.CurUser.UserNum; InsPlans.Insert(plan); //log taken care of in a subfunction. } subCur.PlanNum = plan.PlanNum; Update(subCur); }
///<summary>Gets the fee schedule from the first insplan, the patient, or the provider in that order. Either returns a fee schedule (fk to definition.DefNum) or 0.</summary> public static long GetFeeSched(Patient pat, List <InsPlan> planList, List <PatPlan> patPlans, List <InsSub> subList) { //No need to check RemotingRole; no call to db. //there's not really a good place to put this function, so it's here. long retVal = 0; if (PatPlans.GetInsSubNum(patPlans, 1) != 0) { InsSub SubCur = InsSubs.GetSub(PatPlans.GetInsSubNum(patPlans, 1), subList); InsPlan PlanCur = InsPlans.GetPlan(SubCur.PlanNum, planList); if (PlanCur == null) { retVal = 0; } else { retVal = PlanCur.FeeSched; } } if (retVal == 0) { if (pat.FeeSched != 0) { retVal = pat.FeeSched; } else { if (pat.PriProv == 0) { retVal = ProviderC.ListShort[0].FeeSched; } else { //MessageBox.Show(Providers.GetIndex(Patients.Cur.PriProv).ToString()); retVal = ProviderC.ListLong[Providers.GetIndexLong(pat.PriProv)].FeeSched; } } } return(retVal); }
///<summary>Returns the ordinal (1-based) for the patplan matching the given PriSecMed. Returns 0 if no match.</summary> public static int GetOrdinal(PriSecMed priSecMed, List <PatPlan> PatPlanList, List <InsPlan> planList, List <InsSub> subList) { //No need to check RemotingRole; no call to db. int dentalOrdinal = 0; for (int i = 0; i < PatPlanList.Count; i++) { InsSub sub = InsSubs.GetSub(PatPlanList[i].InsSubNum, subList); InsPlan plan = InsPlans.GetPlan(sub.PlanNum, planList); if (plan.IsMedical) { if (priSecMed == PriSecMed.Medical) { return(PatPlanList[i].Ordinal); } } else //dental { dentalOrdinal++; if (dentalOrdinal == 1) { if (priSecMed == PriSecMed.Primary) { return(PatPlanList[i].Ordinal); } } else if (dentalOrdinal == 2) { if (priSecMed == PriSecMed.Secondary) { return(PatPlanList[i].Ordinal); } } } } return(0); }
///<summary>The result is the etransNum of the response message. Or it might throw an exception if invalid data. This class is also responsible for saving the returned message to the etrans table, and for printing out the required form.</summary> public static long SendElegibility(long patNum,InsPlan plan,DateTime date,Relat relat,string patID,bool doPrint,InsSub insSub) { //string electID,long patNum,string groupNumber,string divisionNo, //string subscriberID,string patID,Relat patRelat,long 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. Carrier carrier=Carriers.GetCarrier(plan.CarrierNum); if(carrier==null) { throw new ApplicationException("Invalid carrier."); } if((carrier.CanadianSupportedTypes&CanSupTransTypes.EligibilityTransaction_08)!=CanSupTransTypes.EligibilityTransaction_08) { throw new ApplicationException("The carrier does not support eligibility transactions."); } if(carrier.CanadianNetworkNum==0) { throw new ApplicationException("Carrier network not set."); } CanadianNetwork network=CanadianNetworks.GetNetwork(carrier.CanadianNetworkNum); Patient patient=Patients.GetPat(patNum); Patient subscriber=Patients.GetPat(insSub.Subscriber); Provider provDefaultTreat=Providers.GetProv(PrefC.GetLong(PrefName.PracticeDefaultProv)); 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."); } //validate---------------------------------------------------------------------------------------------------- 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(!provDefaultTreat.IsCDAnet) { error+="Prov not setup as CDA provider"; } if(provDefaultTreat.NationalProvID.Length!=9) { if(error!="") error+=", "; error+="Prov CDA num 9 digits"; } if(provDefaultTreat.CanadianOfficeNum.Length!=4) { if(error!="") error+=", "; error+="Prov office num 4 char"; } //if(plan.GroupNum.Length==0 || groupNumber.Length>12 || groupNumber.Contains(" ")){ // if(error!="") error+=", "; // error+="Plan Number"; //} //if(subscriberID==""){//already validated. And it's allowed to be blank sometimes // if(error!="") error+=", "; // error+="SubscriberID"; //} if(patNum != insSub.Subscriber && relat==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(patient.CanadianEligibilityCode==0) { if(error!="") error+=", "; error+="Patient eligibility exception code"; } 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); } Etrans etrans=Etranss.CreateCanadianOutput(patNum,carrier.CarrierNum,0, clearhouse.ClearinghouseNum,EtransType.Eligibility_CA,plan.PlanNum,insSub.InsSubNum); StringBuilder strb=new StringBuilder(); //create message---------------------------------------------------------------------------------------------- //A01 transaction prefix 12 AN strb.Append(Canadian.TidyAN(network.CanadianTransactionPrefix,12)); //A02 office sequence number 6 N strb.Append(Canadian.TidyN(etrans.OfficeSequenceNumber,6)); //A03 format version number 2 N strb.Append(carrier.CDAnetVersion);//eg. "04", validated in UI //A04 transaction code 2 N if(carrier.CDAnetVersion=="02"){ strb.Append("00");//eligibility } else{ strb.Append("08");//eligibility } //A05 carrier id number 6 N strb.Append(carrier.ElectID);//already validated as 6 digit number. //A06 software system id 3 AN strb.Append(Canadian.SoftwareSystemId()); if(carrier.CDAnetVersion=="04") { //A10 encryption method 1 N strb.Append(carrier.CanadianEncryptionMethod);//validated in UI } //A07 message length 5 N int len; bool C19PlanRecordPresent=false; if(carrier.CDAnetVersion=="02"){ len=178; strb.Append(Canadian.TidyN(len,4)); } else{ len=214; if(plan.CanadianPlanFlag=="A"){// || plan.CanadianPlanFlag=="N"){ C19PlanRecordPresent=true; } if(C19PlanRecordPresent){ len+=30; } strb.Append(Canadian.TidyN(len,5)); //A09 carrier transaction counter 5 N, only version 04 strb.Append(Canadian.TidyN(etrans.CarrierTransCounter,5)); } //B01 CDA provider number 9 AN strb.Append(Canadian.TidyAN(provDefaultTreat.NationalProvID,9));//already validated //B02 provider office number 4 AN strb.Append(Canadian.TidyAN(provDefaultTreat.CanadianOfficeNum,4));//already validated if(carrier.CDAnetVersion=="04"){ //B03 billing provider number 9 AN Provider provBilling=Providers.GetProv(Providers.GetBillingProvNum(provDefaultTreat.ProvNum,patient.ClinicNum)); strb.Append(Canadian.TidyAN(provBilling.NationalProvID,9));//already validated } if(carrier.CDAnetVersion=="02") { //C01 primary policy/plan number 8 AN (group number) //No special validation for version 02 strb.Append(Canadian.TidyAN(plan.GroupNum,8)); } else { //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. strb.Append(Canadian.TidyAN(plan.GroupNum,12)); } //C11 primary division/section number 10 AN strb.Append(Canadian.TidyAN(plan.DivisionNo,10)); if(carrier.CDAnetVersion=="02") { //C02 subscriber id number 11 AN strb.Append(Canadian.TidyAN(insSub.SubscriberID.Replace("-",""),11));//no extra validation for version 02 } else{ //C02 subscriber id number 12 AN strb.Append(Canadian.TidyAN(insSub.SubscriberID.Replace("-",""),12));//validated } if(carrier.CDAnetVersion=="04") { //C17 primary dependant code 2 N. Optional strb.Append(Canadian.TidyN(patID,2)); } //C03 relationship code 1 N //User interface does not only show Canadian options, but all options are handled. strb.Append(Canadian.GetRelationshipCode(relat)); //C04 patient's sex 1 A //validated to not include "unknown" if(patient.Gender==PatientGender.Male) { strb.Append("M"); } else { strb.Append("F"); } //C05 patient birthday 8 N strb.Append(patient.Birthdate.ToString("yyyyMMdd"));//validated //C06 patient last name 25 AE strb.Append(Canadian.TidyAE(patient.LName,25,true));//validated //C07 patient first name 15 AE strb.Append(Canadian.TidyAE(patient.FName,15,true));//validated //C08 patient middle initial 1 AE strb.Append(Canadian.TidyAE(patient.MiddleI,1)); //C09 eligibility exception code 1 N strb.Append(Canadian.GetEligibilityCode(patient.CanadianEligibilityCode,carrier.CDAnetVersion=="02"));//validated if(carrier.CDAnetVersion=="04") { //C12 plan flag 1 A strb.Append(Canadian.GetPlanFlag(plan.CanadianPlanFlag)); //C18 plan record count 1 N if(C19PlanRecordPresent) { strb.Append("1"); } else { strb.Append("0"); } //C16 Eligibility date. 8 N. strb.Append(date.ToString("yyyyMMdd")); } //D01 subscriber birthday 8 N strb.Append(subscriber.Birthdate.ToString("yyyyMMdd"));//validated //D02 subscriber last name 25 AE strb.Append(Canadian.TidyAE(subscriber.LName,25,true));//validated //D03 subscriber first name 15 AE strb.Append(Canadian.TidyAE(subscriber.FName,15,true));//validated //D04 subscriber middle initial 1 AE strb.Append(Canadian.TidyAE(subscriber.MiddleI,1)); if(carrier.CDAnetVersion=="04") { //D10 language of insured 1 A if(subscriber.Language=="fr") { strb.Append("F"); } else { strb.Append("E"); } //D11 card sequence/version number 2 N //Not validated against type of carrier. Might need to check if Dentaide. strb.Append(Canadian.TidyN(plan.DentaideCardSequence,2)); //C19 plan record 30 AN if(C19PlanRecordPresent) { //todo: what text goes here? Not documented strb.Append(Canadian.TidyAN("",30)); } } string result=""; bool resultIsError=false; try { result=Canadian.PassToIca(strb.ToString(),clearhouse); } catch(ApplicationException ex) { result=ex.Message; resultIsError=true; //Etranss.Delete(etrans.EtransNum);//we don't want to do this, because we want the incremented etrans.OfficeSequenceNumber to be saved //Attach an ack indicating failure. } //Attach an ack to the etrans Etrans etransAck=new Etrans(); etransAck.PatNum=etrans.PatNum; etransAck.PlanNum=etrans.PlanNum; etransAck.InsSubNum=etrans.InsSubNum; etransAck.CarrierNum=etrans.CarrierNum; etransAck.DateTimeTrans=DateTime.Now; CCDFieldInputter fieldInputter=null; if(resultIsError){ etransAck.Etype=EtransType.AckError; etrans.Note="failed"; } else{ fieldInputter=new CCDFieldInputter(result); CCDField fieldG05=fieldInputter.GetFieldById("G05"); if(fieldG05!=null) { etransAck.AckCode=fieldG05.valuestr; } etransAck.Etype=fieldInputter.GetEtransType(); } Etranss.Insert(etransAck); Etranss.SetMessage(etransAck.EtransNum,result); etrans.AckEtransNum=etransAck.EtransNum; Etranss.Update(etrans); Etranss.SetMessage(etrans.EtransNum,strb.ToString()); if(resultIsError){ throw new ApplicationException(result); } if(doPrint) { new FormCCDPrint(etrans,result,true);//Print the form. } //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 strResponse="";//"Eligibility check on "+DateTime.Today.ToShortDateString()+"\r\n"; //CCDField field=fieldInputter.GetFieldById("G05");//response status string valuestr=fieldInputter.GetValue("G05");//response status switch(valuestr){ case "E": strResponse+="Patient is eligible."; break; case "R": strResponse+="Patient not eligible, or error in data."; break; case "M": strResponse+="Manual claimform should be submitted for employer certified plan."; break; } etrans=Etranss.GetEtrans(etrans.EtransNum); etrans.Note=strResponse; Etranss.Update(etrans); return etransAck.EtransNum; /* 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;*/ }
private void gridMain_CellDoubleClick(object sender,OpenDental.UI.ODGridClickEventArgs e) { if(ViewRelat && listRelat.SelectedIndex==-1) { MessageBox.Show(Lan.g(this,"Please select a relationship first.")); return; } if(ViewRelat) { PatRelat=(Relat)listRelat.SelectedIndex; } SelectedSub=SubList[e.Row]; SelectedPlan=InsPlans.GetPlan(SubList[e.Row].PlanNum,PlanList); DialogResult=DialogResult.OK; }
private void Init(){ InitializeComponent(); breakLinePen.Width=2; if(etrans.PatNum!=0) { //Some transactions are not patient specific. patient=Patients.GetPat(etrans.PatNum); patPlansForPat=PatPlans.Refresh(etrans.PatNum); claim=Claims.GetClaim(etrans.ClaimNum); primaryCarrier=Carriers.GetCarrier(etrans.CarrierNum); if(claim==null) {//for eligibility //Get primary info insSub=InsSubs.GetSub(etrans.InsSubNum,new List<InsSub>()); subscriber=Patients.GetPat(insSub.Subscriber); insplan=InsPlans.GetPlan(etrans.PlanNum,new List<InsPlan>()); patPlanPri=PatPlans.GetFromList(patPlansForPat,insSub.InsSubNum); } else { //Get primary info insSub=InsSubs.GetSub(claim.InsSubNum,new List<InsSub>()); subscriber=Patients.GetPat(insSub.Subscriber); insplan=InsPlans.GetPlan(claim.PlanNum,new List<InsPlan>()); patPlanPri=PatPlans.GetFromList(patPlansForPat,insSub.InsSubNum); //Get secondary info if(claim.InsSubNum2!=0) { patPlanSec=PatPlans.GetFromList(patPlansForPat,claim.InsSubNum2); insSub2=InsSubs.GetSub(claim.InsSubNum2,new List<InsSub>()); subscriber2=Patients.GetPat(insSub2.Subscriber); insplan2=InsPlans.GetPlan(claim.PlanNum2,new List<InsPlan>()); secondaryCarrier=Carriers.GetCarrier(insplan2.CarrierNum); } //Provider info provTreat=Providers.GetProv(claim.ProvTreat); provBill=Providers.GetProv(claim.ProvBill); //Claim related info claimprocs=ClaimProcs.RefreshForClaim(claim.ClaimNum); long clinicNum=0; for(int i=0;i<claimprocs.Count;i++) { if(claimprocs[i].ClinicNum!=0) { clinicNum=claimprocs[i].ClinicNum; break; } } if(clinicNum!=0) { clinic=Clinics.GetClinic(clinicNum); } else if(!PrefC.GetBool(PrefName.EasyNoClinics) && Clinics.List.Length>0) { clinic=Clinics.List[0]; } } if(provTreat==null) { provTreat=Providers.GetProv(Patients.GetProvNum(patient)); } if(provBill==null) { provBill=Providers.GetProv(Patients.GetProvNum(patient)); } List<Procedure> procsAll=Procedures.Refresh(etrans.PatNum); extracted=Procedures.GetCanadianExtractedTeeth(procsAll); } if(MessageText==null || MessageText.Length<23) { throw new Exception("CCD message format too short: "+MessageText); } formData=new CCDFieldInputter(MessageText);//Input the fields of the given message. CCDField languageOfInsured=formData.GetFieldById("G27"); if(languageOfInsured!=null) { if(languageOfInsured.valuestr=="F") { isFrench=true; } } else if(subscriber!=null && subscriber.Language=="fr") { isFrench=true; } formatVersionNumber=formData.GetFieldById("A03").valuestr;//Must always exist so no error checking here. transactionCode=formData.GetFieldById("A04").valuestr;//Must always exist so no error checking here. if(formatVersionNumber=="04") {//FormId field does not exist in version 02 in any of the message texts. CCDField formIdField=formData.GetFieldById("G42");//Usually exists in version 04 response messages. //Only a few response transactions don't define field G42. So far, those are transactions 15 (Summary Reconciliation), 16 (Payment Reconciliation) and 24 (Email). //In these cases, we simply do not use the formId field later on in the display code. if(formIdField!=null) { formId=formIdField.valuestr; } } else {//Version 02 //Since there is no FormID field in version 02, we figure out what the formId should be based on the transaction type. if(transactionCode=="10") {//Eligibility Response. formId="08";//Eligibility Form } else if(transactionCode=="11") {//Claim Response. formId="03";//Claim Acknowledgement Form } else if(transactionCode=="21") {//EOB formId="01";//EOB Form CCDField g02=formData.GetFieldById("G02"); if(g02!=null && g02.valuestr=="Y") { formId="04";//Employer Certified. } } else if(transactionCode=="13") {//Response to Pre-Determination. formId="06";//Pre-Determination Acknowledgement Form } else if(transactionCode=="12") { //Reversal response //There is no standard form for a reversal response, but we print the reversal response later on based on the transactioncode so we don't need to do anything here. } else { throw new Exception("Unhandled transactionCode '"+transactionCode+"' for version 02 message."); } } CCDField status=formData.GetFieldById("G05"); if(status!=null && status.valuestr!=null) { responseStatus=status.valuestr.ToUpper(); } transactionCode=formData.GetFieldById("A04").valuestr; predetermination=(transactionCode=="23"||transactionCode=="13");//Be sure to list all predetermination response types here! if(copiesToPrint<=0) { //Show the form on screen if there are no copies to print. ShowDisplayMessages(); CCDField fieldPayTo=formData.GetFieldById("F01"); if(fieldPayTo!=null) { bool paySubscriber=(fieldPayTo.valuestr=="1");//same for version 02 and version 04 //Typically, insurance companies in Canada prefer to pay the subscriber instead of the dentist. if(AssignmentOfBenefits()) {//The insurance plan is set to pay the dentist if(paySubscriber) {//The carrier has decided to pay the subscriber. MsgBox.Show("Canadian","INFORMATION: The carrier changed the payee from the dentist to the subscriber.");//This check was required for certification. } } else {//The insurance plan is set to pay the subscriber if(!paySubscriber) {//The carrier has decided to pay the dentist. MsgBox.Show("Canadian","INFORMATION: The carrier changed the payee from the subscriber to the dentist.");//This check was required for certification. } } } CCDField paymentAdjustmentAmount=formData.GetFieldById("G33"); if(paymentAdjustmentAmount!=null) { if(paymentAdjustmentAmount.valuestr.Substring(1)!="000000") { MessageBox.Show(Lan.g(this,"Payment adjustment amount")+": "+RawMoneyStrToDisplayMoney(paymentAdjustmentAmount.valuestr)); } } if(autoPrint) { if(responseStatus!="R") { //We are not required to automatically print rejection notices. //Automatically print a patient copy only. We are never required to autoprint a dentist copy, but it can be done manually instead. new FormCCDPrint(etrans.Copy(),MessageText,1,false,true); } } if(formId=="05") { //Manual claim form Canadian.ShowManualClaimForm(claim); Close(); } else { pd=CreatePrintDocument(); printPreviewControl1.Document=pd;//Setting the document causes system to call pd_PrintPage, which will print the document in the preview window. ShowDialog(); } } else { pd=CreatePrintDocument(); if(formId=="05") { //Manual claim form #if DEBUG Canadian.ShowManualClaimForm(claim); #else Canadian.PrintManualClaimForm(claim);//Send the print job to the physical printer. #endif } else { #if DEBUG new FormCCDPrint(etrans.Copy(),MessageText,0,false,patientCopy);//Show the form on the screen. #else pd.Print();//Send the print job to the physical printer. #endif } //Print the remaining copies recursively. if(copiesToPrint>=2) { new FormCCDPrint(etrans.Copy(),MessageText,copiesToPrint-1,false,patientCopy); } } CCDField embeddedTransaction=formData.GetFieldById("G40"); if(embeddedTransaction!=null) { new FormCCDPrint(etrans.Copy(),embeddedTransaction.valuestr,copiesToPrint,autoPrint,patientCopy); } }
///<summary></summary> public static long Insert(InsSub insSub) { return(Insert(insSub, false)); }
private void ToolButIns_Click(){ DialogResult result=MessageBox.Show(Lan.g(this,"Is this patient the subscriber?"),"",MessageBoxButtons.YesNoCancel); if(result==DialogResult.Cancel){ return; } //Pick a subscriber------------------------------------------------------------------------------------------------ Patient subscriber; if(result==DialogResult.Yes){//current patient is subscriber subscriber=PatCur.Copy(); } else{//patient is not subscriber //show list of patients in this family FormSubscriberSelect FormS=new FormSubscriberSelect(FamCur); FormS.ShowDialog(); if(FormS.DialogResult==DialogResult.Cancel){ return; } subscriber=Patients.GetPat(FormS.SelectedPatNum); } //Subscriber has been chosen. Now, pick a plan------------------------------------------------------------------- InsPlan plan=null; InsSub sub=null; bool planIsNew=false; List<InsSub> subList=InsSubs.GetListForSubscriber(subscriber.PatNum); if(subList.Count==0){ planIsNew=true; } else{ FormInsSelectSubscr FormISS=new FormInsSelectSubscr(subscriber.PatNum); FormISS.ShowDialog(); if(FormISS.DialogResult==DialogResult.Cancel) { return; } if(FormISS.SelectedInsSubNum==0){//'New' option selected. planIsNew=true; } else{ sub=InsSubs.GetSub(FormISS.SelectedInsSubNum,subList); plan=InsPlans.GetPlan(sub.PlanNum,new List<InsPlan>()); } } //New plan was selected instead of an existing plan. Create the plan-------------------------------------------- if(planIsNew){ plan=new InsPlan(); plan.EmployerNum=subscriber.EmployerNum; plan.PlanType=""; InsPlans.Insert(plan); sub=new InsSub(); sub.PlanNum=plan.PlanNum; sub.Subscriber=subscriber.PatNum; if(subscriber.MedicaidID==""){ sub.SubscriberID=subscriber.SSN; } else{ sub.SubscriberID=subscriber.MedicaidID; } sub.ReleaseInfo=true; sub.AssignBen=true; InsSubs.Insert(sub); Benefit ben; for(int i=0;i<CovCatC.ListShort.Count;i++){ if(CovCatC.ListShort[i].DefaultPercent==-1){ continue; } ben=new Benefit(); ben.BenefitType=InsBenefitType.CoInsurance; ben.CovCatNum=CovCatC.ListShort[i].CovCatNum; ben.PlanNum=plan.PlanNum; ben.Percent=CovCatC.ListShort[i].DefaultPercent; ben.TimePeriod=BenefitTimePeriod.CalendarYear; ben.CodeNum=0; Benefits.Insert(ben); } //Zero deductible diagnostic if(CovCats.GetForEbenCat(EbenefitCategory.Diagnostic)!=null) { ben=new Benefit(); ben.CodeNum=0; ben.BenefitType=InsBenefitType.Deductible; ben.CovCatNum=CovCats.GetForEbenCat(EbenefitCategory.Diagnostic).CovCatNum; ben.PlanNum=plan.PlanNum; ben.TimePeriod=BenefitTimePeriod.CalendarYear; ben.MonetaryAmt=0; ben.Percent=-1; ben.CoverageLevel=BenefitCoverageLevel.Individual; Benefits.Insert(ben); } //Zero deductible preventive if(CovCats.GetForEbenCat(EbenefitCategory.RoutinePreventive)!=null) { ben=new Benefit(); ben.CodeNum=0; ben.BenefitType=InsBenefitType.Deductible; ben.CovCatNum=CovCats.GetForEbenCat(EbenefitCategory.RoutinePreventive).CovCatNum; ben.PlanNum=plan.PlanNum; ben.TimePeriod=BenefitTimePeriod.CalendarYear; ben.MonetaryAmt=0; ben.Percent=-1; ben.CoverageLevel=BenefitCoverageLevel.Individual; Benefits.Insert(ben); } } //Then attach plan------------------------------------------------------------------------------------------------ PatPlan patplan=new PatPlan(); patplan.Ordinal=(byte)(PatPlanList.Count+1);//so the ordinal of the first entry will be 1, NOT 0. patplan.PatNum=PatCur.PatNum; patplan.InsSubNum=sub.InsSubNum; patplan.Relationship=Relat.Self; PatPlans.Insert(patplan); //Then, display insPlanEdit to user------------------------------------------------------------------------------- FormInsPlan FormI=new FormInsPlan(plan,patplan,sub); FormI.IsNewPlan=planIsNew; FormI.IsNewPatPlan=true; FormI.ShowDialog();//this updates estimates also. //if cancel, then patplan is deleted from within that dialog. //if cancel, and planIsNew, then plan and benefits are also deleted. ModuleSelected(PatCur.PatNum); }
public static string Validate(Clearinghouse clearhouse,Carrier carrier,Provider billProv,Clinic clinic,InsPlan insPlan,Patient subscriber,InsSub insSub) { StringBuilder strb=new StringBuilder(); X12Validate.ISA(clearhouse,strb); X12Validate.Carrier(carrier,strb); if(carrier.ElectID.Length<2) { if(strb.Length!=0) { strb.Append(","); } strb.Append("Electronic ID"); } if(billProv.SSN.Length!=9) { if(strb.Length!=0) { strb.Append(","); } strb.Append("Prov TIN 9 digits"); } X12Validate.BillProv(billProv,strb); if(clinic==null) { X12Validate.PracticeAddress(strb); } else { X12Validate.Clinic(clinic,strb); } if(insSub.SubscriberID.Length<2) { if(strb.Length!=0) { strb.Append(","); } strb.Append("SubscriberID"); } if(subscriber.Birthdate.Year<1880) { if(strb.Length!=0) { strb.Append(","); } strb.Append("Subscriber Birthdate"); } if(insPlan.GroupNum=="") { if(strb.Length!=0) { strb.Append(","); } strb.Append("Group Number"); } return strb.ToString(); }
///<summary>The only validation that's been done is just to make sure that only procedures are selected. All validation on the procedures selected is done here. Creates and saves claim initially, attaching all selected procedures. But it does not refresh any data. Does not do a final update of the new claim. Does not enter fee amounts. claimType=P,S,Med,or Other</summary> private Claim CreateClaim(string claimType,List <PatPlan> PatPlanList,List <InsPlan> planList,List<ClaimProc> ClaimProcList,List<Procedure> procsForPat,List<InsSub> subList){ long claimFormNum = 0; InsPlan PlanCur=new InsPlan(); InsSub SubCur=new InsSub(); Relat relatOther=Relat.Self; switch(claimType){ case "P": SubCur=InsSubs.GetSub(PatPlans.GetInsSubNum(PatPlanList,PatPlans.GetOrdinal(PriSecMed.Primary,PatPlanList,planList,subList)),subList); PlanCur=InsPlans.GetPlan(SubCur.PlanNum,planList); break; case "S": SubCur=InsSubs.GetSub(PatPlans.GetInsSubNum(PatPlanList,PatPlans.GetOrdinal(PriSecMed.Secondary,PatPlanList,planList,subList)),subList); PlanCur=InsPlans.GetPlan(SubCur.PlanNum,planList); break; case "Med": //It's already been verified that a med plan exists SubCur=InsSubs.GetSub(PatPlans.GetInsSubNum(PatPlanList,PatPlans.GetOrdinal(PriSecMed.Medical,PatPlanList,planList,subList)),subList); PlanCur=InsPlans.GetPlan(SubCur.PlanNum,planList); break; case "Other": FormClaimCreate FormCC=new FormClaimCreate(PatCur.PatNum); FormCC.ShowDialog(); if(FormCC.DialogResult!=DialogResult.OK){ return new Claim(); } PlanCur=FormCC.SelectedPlan; SubCur=FormCC.SelectedSub; relatOther=FormCC.PatRelat; break; } DataTable table=DataSetMain.Tables["account"]; Procedure proc; for(int i=0;i<gridAccount.SelectedIndices.Length;i++){ proc=Procedures.GetProcFromList(procsForPat,PIn.Long(table.Rows[gridAccount.SelectedIndices[i]]["ProcNum"].ToString())); if(Procedures.NoBillIns(proc,ClaimProcList,PlanCur.PlanNum)){ MsgBox.Show(this,"Not allowed to send procedures to insurance that are marked 'Do not bill to ins'."); return new Claim(); } } for(int i=0;i<gridAccount.SelectedIndices.Length;i++){ proc=Procedures.GetProcFromList(procsForPat,PIn.Long(table.Rows[gridAccount.SelectedIndices[i]]["ProcNum"].ToString())); if(Procedures.IsAlreadyAttachedToClaim(proc,ClaimProcList,SubCur.InsSubNum)){ MsgBox.Show(this,"Not allowed to send a procedure to the same insurance company twice."); return new Claim(); } } proc=Procedures.GetProcFromList(procsForPat,PIn.Long(table.Rows[gridAccount.SelectedIndices[0]]["ProcNum"].ToString())); long clinicNum=proc.ClinicNum; PlaceOfService placeService=proc.PlaceService; for(int i=1;i<gridAccount.SelectedIndices.Length;i++){//skips 0 proc=Procedures.GetProcFromList(procsForPat,PIn.Long(table.Rows[gridAccount.SelectedIndices[i]]["ProcNum"].ToString())); if(clinicNum!=proc.ClinicNum){ MsgBox.Show(this,"All procedures do not have the same clinic."); return new Claim(); } if(proc.PlaceService!=placeService) { MsgBox.Show(this,"All procedures do not have the same place of service."); return new Claim(); } } ClaimProc[] claimProcs=new ClaimProc[gridAccount.SelectedIndices.Length];//1:1 with selectedIndices long procNum; for(int i=0;i<gridAccount.SelectedIndices.Length;i++){//loop through selected procs //and try to find an estimate that can be used procNum=PIn.Long(table.Rows[gridAccount.SelectedIndices[i]]["ProcNum"].ToString()); claimProcs[i]=Procedures.GetClaimProcEstimate(procNum,ClaimProcList,PlanCur,SubCur.InsSubNum); } for(int i=0;i<claimProcs.Length;i++){//loop through each claimProc //and create any missing estimates. This handles claims to 3rd and 4th ins co's. if(claimProcs[i]==null){ claimProcs[i]=new ClaimProc(); proc=Procedures.GetProcFromList(procsForPat,PIn.Long(table.Rows[gridAccount.SelectedIndices[i]]["ProcNum"].ToString()));//1:1 ClaimProcs.CreateEst(claimProcs[i],proc,PlanCur,SubCur); } } Claim ClaimCur=new Claim(); Claims.Insert(ClaimCur);//to retreive a key for new Claim.ClaimNum //now, all claimProcs have a valid value //for any CapComplete, need to make a copy so that original doesn't get attached. for(int i=0;i<claimProcs.Length;i++){ if(claimProcs[i].Status==ClaimProcStatus.CapComplete){ claimProcs[i].ClaimNum=ClaimCur.ClaimNum; claimProcs[i]=claimProcs[i].Copy(); claimProcs[i].WriteOff=0; claimProcs[i].CopayAmt=-1; claimProcs[i].CopayOverride=-1; //status will get changed down below ClaimProcs.Insert(claimProcs[i]);//this makes a duplicate in db with different claimProcNum } } ClaimCur.PatNum=PatCur.PatNum; ClaimCur.DateService=claimProcs[claimProcs.Length-1].ProcDate; ClaimCur.ClinicNum=clinicNum; ClaimCur.PlaceService=proc.PlaceService; //datesent ClaimCur.ClaimStatus="U"; //datereceived InsSub sub; ClaimCur.PlanNum=PlanCur.PlanNum; ClaimCur.InsSubNum=SubCur.InsSubNum; switch(claimType){ case "P": ClaimCur.PatRelat=PatPlans.GetRelat(PatPlanList,PatPlans.GetOrdinal(PriSecMed.Primary,PatPlanList,planList,subList)); ClaimCur.ClaimType="P"; ClaimCur.InsSubNum2=PatPlans.GetInsSubNum(PatPlanList,PatPlans.GetOrdinal(PriSecMed.Secondary,PatPlanList,planList,subList)); sub=InsSubs.GetSub(ClaimCur.InsSubNum2,subList); if(sub.PlanNum>0 && InsPlans.RefreshOne(sub.PlanNum).IsMedical) { ClaimCur.PlanNum2=0;//no sec ins ClaimCur.PatRelat2=Relat.Self; } else { ClaimCur.PlanNum2=sub.PlanNum;//might be 0 if no sec ins ClaimCur.PatRelat2=PatPlans.GetRelat(PatPlanList,PatPlans.GetOrdinal(PriSecMed.Secondary,PatPlanList,planList,subList)); } break; case "S": ClaimCur.PatRelat=PatPlans.GetRelat(PatPlanList,PatPlans.GetOrdinal(PriSecMed.Secondary,PatPlanList,planList,subList)); ClaimCur.ClaimType="S"; ClaimCur.InsSubNum2=PatPlans.GetInsSubNum(PatPlanList,PatPlans.GetOrdinal(PriSecMed.Primary,PatPlanList,planList,subList)); sub=InsSubs.GetSub(ClaimCur.InsSubNum2,subList); ClaimCur.PlanNum2=sub.PlanNum; ClaimCur.PatRelat2=PatPlans.GetRelat(PatPlanList,PatPlans.GetOrdinal(PriSecMed.Primary,PatPlanList,planList,subList)); break; case "Med": ClaimCur.PatRelat=PatPlans.GetFromList(PatPlanList,SubCur.InsSubNum).Relationship; ClaimCur.ClaimType="Other"; if(PrefC.GetBool(PrefName.ClaimMedTypeIsInstWhenInsPlanIsMedical)){ ClaimCur.MedType=EnumClaimMedType.Institutional; } else{ ClaimCur.MedType=EnumClaimMedType.Medical; } break; case "Other": ClaimCur.PatRelat=relatOther; ClaimCur.ClaimType="Other"; //plannum2 is not automatically filled in. ClaimCur.ClaimForm=claimFormNum; if(PlanCur.IsMedical){ if(PrefC.GetBool(PrefName.ClaimMedTypeIsInstWhenInsPlanIsMedical)){ ClaimCur.MedType=EnumClaimMedType.Institutional; } else{ ClaimCur.MedType=EnumClaimMedType.Medical; } } break; } if(PlanCur.PlanType=="c"){//if capitation ClaimCur.ClaimType="Cap"; } ClaimCur.ProvTreat=Procedures.GetProcFromList(procsForPat,PIn.Long(table.Rows[gridAccount.SelectedIndices[0]]["ProcNum"].ToString())).ProvNum; for(int i=0;i<gridAccount.SelectedIndices.Length;i++){ proc=Procedures.GetProcFromList(procsForPat,PIn.Long(table.Rows[gridAccount.SelectedIndices[i]]["ProcNum"].ToString())); if(!Providers.GetIsSec(proc.ProvNum)){//if not a hygienist ClaimCur.ProvTreat=proc.ProvNum; } } if(Providers.GetIsSec(ClaimCur.ProvTreat)){ ClaimCur.ProvTreat=PatCur.PriProv; //OK if 0, because auto select first in list when open claim } //claimfee calcs in ClaimEdit //inspayest '' //inspayamt //ClaimCur.DedApplied=0;//calcs in ClaimEdit. //preauthstring, etc, etc ClaimCur.IsProsthesis="N"; //int clinicInsBillingProv=0; //bool useClinic=false; //if(ClaimCur.ClinicNum>0){ // useClinic=true; // clinicInsBillingProv=Clinics.GetClinic(ClaimCur.ClinicNum).InsBillingProv; //} ClaimCur.ProvBill=Providers.GetBillingProvNum(ClaimCur.ProvTreat,ClaimCur.ClinicNum);//,useClinic,clinicInsBillingProv);//OK if zero, because it will get fixed in claim ClaimCur.EmployRelated=YN.No; ClaimCur.ClaimForm=PlanCur.ClaimFormNum; //attach procedures Procedure ProcCur; //for(int i=0;i<tbAccount.SelectedIndices.Length;i++){ for(int i=0;i<claimProcs.Length;i++){ ProcCur=Procedures.GetProcFromList(procsForPat,PIn.Long(table.Rows[gridAccount.SelectedIndices[i]]["ProcNum"].ToString()));//1:1 //ClaimProc ClaimProcCur=new ClaimProc(); //ClaimProcCur.ProcNum=ProcCur.ProcNum; claimProcs[i].ClaimNum=ClaimCur.ClaimNum; //ClaimProcCur.PatNum=Patients.Cur.PatNum; //ClaimProcCur.ProvNum=ProcCur.ProvNum; //ClaimProcs.Cur.FeeBilled=;//handle in call to ClaimL.CalculateAndUpdate() //inspayest '' //dedapplied '' if(PlanCur.PlanType=="c")//if capitation claimProcs[i].Status=ClaimProcStatus.CapClaim; else claimProcs[i].Status=ClaimProcStatus.NotReceived; //inspayamt=0 //remarks //claimpaymentnum=0 //ClaimProcCur.PlanNum=Claims.Cur.PlanNum; //ClaimProcCur.DateCP=ProcCur.ProcDate; //writeoff handled in ClaimL.CalculateAndUpdate() if(PlanCur.UseAltCode && (ProcedureCodes.GetProcCode(ProcCur.CodeNum).AlternateCode1!="")){ claimProcs[i].CodeSent=ProcedureCodes.GetProcCode(ProcCur.CodeNum).AlternateCode1; } else if(PlanCur.IsMedical && ProcCur.MedicalCode!=""){ claimProcs[i].CodeSent=ProcCur.MedicalCode; } else{ claimProcs[i].CodeSent=ProcedureCodes.GetProcCode(ProcCur.CodeNum).ProcCode; if(claimProcs[i].CodeSent.Length>5 && claimProcs[i].CodeSent.Substring(0,1)=="D"){ claimProcs[i].CodeSent=claimProcs[i].CodeSent.Substring(0,5); } if(CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Canadian. en-CA or fr-CA if(claimProcs[i].CodeSent.Length>5) { //In Canadian electronic claims, codes can contain letters or numbers and cannot be longer than 5 characters. claimProcs[i].CodeSent=claimProcs[i].CodeSent.Substring(0,5); } } } claimProcs[i].LineNumber=(byte)(i+1); ClaimProcs.Update(claimProcs[i]); }//for claimProc return ClaimCur; //return null; }
///<summary></summary> public static long Insert(InsSub insSub){ return Insert(insSub,false); }
public static string InsSubNumMismatchPlanNum(bool verbose,bool isCheck) { //Checks for situations where there are valid InsSubNums, but mismatched PlanNums. if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { return Meth.GetString(MethodBase.GetCurrentMethod(),verbose,isCheck); } string log=""; if(isCheck) { int numFound=0; //Can't do the following because no inssubnum: appointmentx2, benefit. //Can't do inssub because that's what we're comparing against. That's the one that's assumed to be correct. //claim.PlanNum ----------------------------------------------------------------------------------------------------- command="SELECT COUNT(*) FROM claim " +"WHERE PlanNum NOT IN (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=claim.InsSubNum) "; numFound=PIn.Int(Db.GetCount(command)); if(numFound>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Mismatched claim InsSubNum/PlanNum values: ")+numFound+"\r\n"; } //claim.PlanNum2--------------------------------------------------------------------------------------------------- command="SELECT COUNT(*) FROM claim WHERE PlanNum2 != 0 "//not really necessary; just a reminder +"AND PlanNum2 NOT IN (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=claim.InsSubNum2)"; numFound=PIn.Int(Db.GetCount(command)); if(numFound>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Mismatched claim InsSubNum2/PlanNum2 values: ")+numFound+"\r\n"; } //claimproc--------------------------------------------------------------------------------------------------- command="SELECT COUNT(*) FROM claimproc " +"WHERE PlanNum NOT IN (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=claimproc.InsSubNum)"; numFound=PIn.Int(Db.GetCount(command)); if(numFound>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Mismatched claimproc InsSubNum/PlanNum values: ")+numFound+"\r\n"; } //etrans--------------------------------------------------------------------------------------------------- command="SELECT COUNT(*) FROM etrans " +"WHERE PlanNum!=0 AND PlanNum NOT IN (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=etrans.InsSubNum)"; numFound=PIn.Int(Db.GetCount(command)); if(numFound>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Mismatched etrans InsSubNum/PlanNum values: ")+numFound+"\r\n"; } //payplan--------------------------------------------------------------------------------------------------- command="SELECT COUNT(*) FROM payplan " +"WHERE PlanNum NOT IN (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=payplan.InsSubNum)"; numFound=PIn.Int(Db.GetCount(command)); if(numFound>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Mismatched payplan InsSubNum/PlanNum values: ")+numFound+"\r\n"; } } else {//fix long numFixed=0; //claim.PlanNum (1/3) Mismatch------------------------------------------------------------------------------------------------------ command="UPDATE claim SET PlanNum = (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=claim.InsSubNum) " +"WHERE PlanNum != (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=claim.InsSubNum)"; numFixed=Db.NonQ(command); if(numFixed>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Mismatched claim InsSubNum/PlanNum fixed: ")+numFixed.ToString()+"\r\n"; } numFixed=0; //claim.PlanNum (2/3) PlanNum zero, invalid InsSubNum-------------------------------------------------------------------------------- //Will leave orphaned claimprocs. No finanicals to check. command="DELETE FROM claim WHERE PlanNum=0 AND ClaimStatus IN ('PreAuth','W','U') AND NOT EXISTS(SELECT * FROM inssub WHERE inssub.InsSubNum=claim.InsSubNum)"; numFixed=Db.NonQ(command); if(numFixed>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Claims deleted with invalid InsSubNum and PlanNum=0: ")+numFixed.ToString()+"\r\n"; } numFixed=0; //claim.PlanNum (3/3) PlanNum invalid, and claim.InsSubNum invalid------------------------------------------------------------------- command="SELECT claim.PatNum,claim.PlanNum,claim.InsSubNum FROM claim " +"WHERE PlanNum NOT IN (SELECT insplan.PlanNum FROM insplan) " +"AND InsSubNum NOT IN (SELECT inssub.InsSubNum FROM inssub) "; table=Db.GetTable(command); if(table.Rows.Count>0) { log+=Lans.g("FormDatabaseMaintenance","List of patients who will need insurance information reentered:")+"\r\n"; } for(int i=0;i<table.Rows.Count;i++) {//Create simple InsPlans and InsSubs for each claim to replace the missing ones. //make sure a plan does not exist from a previous insert in this loop command="SELECT COUNT(*) FROM insplan WHERE PlanNum = " + table.Rows[i]["PlanNum"].ToString(); if(Db.GetCount(command)=="0") { InsPlan plan=new InsPlan(); plan.PlanNum=PIn.Long(table.Rows[i]["PlanNum"].ToString());//reuse the existing FK plan.IsHidden=true; plan.CarrierNum=Carriers.GetByNameAndPhone("UNKNOWN CARRIER","").CarrierNum; InsPlans.Insert(plan,true); } long patNum=PIn.Long(table.Rows[i]["PatNum"].ToString()); //make sure an inssub does not exist from a previous insert in this loop command="SELECT COUNT(*) FROM inssub WHERE InsSubNum = " + table.Rows[i]["InsSubNum"].ToString(); if(Db.GetCount(command)=="0") { InsSub sub=new InsSub(); sub.InsSubNum=PIn.Long(table.Rows[i]["InsSubNum"].ToString());//reuse the existing FK sub.PlanNum=PIn.Long(table.Rows[i]["PlanNum"].ToString()); sub.Subscriber=patNum;//if this sub was created on a previous loop, this may be some other patient. sub.SubscriberID="unknown"; InsSubs.Insert(sub,true); } Patient pat=Patients.GetLim(patNum); log+="PatNum: "+pat.PatNum+" - "+Patients.GetNameFL(pat.LName,pat.FName,pat.Preferred,pat.MiddleI)+"\r\n"; } numFixed=table.Rows.Count; if(numFixed>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Claims with invalid PlanNums and invalid InsSubNums fixed: ")+numFixed.ToString()+"\r\n"; } numFixed=0; //claim.PlanNum2--------------------------------------------------------------------------------------------------- command="UPDATE claim SET PlanNum2 = (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=claim.InsSubNum2) " +"WHERE PlanNum2 != 0 " +"AND PlanNum2 NOT IN (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=claim.InsSubNum2)"; //if InsSubNum2 was completely invalid, then PlanNum2 gets set to zero here. numFixed=Db.NonQ(command); if(numFixed>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Mismatched claim InsSubNum2/PlanNum2 fixed: ")+numFixed.ToString()+"\r\n"; } numFixed=0; //claimproc--------------------------------------------------------------------------------------------------- command="UPDATE claimproc SET PlanNum = (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=claimproc.InsSubNum) " +"WHERE PlanNum != (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=claimproc.InsSubNum)"; numFixed=Db.NonQ(command); if(numFixed>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Mismatched claimproc InsSubNum/PlanNum fixed: ")+numFixed.ToString()+"\r\n"; } numFixed=0; //claimproc.PlanNum zero, invalid InsSubNum-------------------------------------------------------------------------------- command="DELETE FROM claimproc WHERE PlanNum=0 AND NOT EXISTS(SELECT * FROM inssub WHERE inssub.InsSubNum=claimproc.InsSubNum)" +" AND InsPayAmt=0 AND WriteOff=0"//Make sure this deletion will not affect financials. +" AND Status IN (6,2)";//OK to delete because no claim and just an estimate (6) or preauth (2) claimproc numFixed=Db.NonQ(command); if(numFixed>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Claimprocs deleted with invalid InsSubNum and PlanNum=0: ")+numFixed.ToString()+"\r\n"; } numFixed=0; //etrans--------------------------------------------------------------------------------------------------- command="UPDATE etrans SET PlanNum = (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=etrans.InsSubNum) " +"WHERE PlanNum!=0 AND PlanNum != (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=etrans.InsSubNum)"; numFixed=Db.NonQ(command); if(numFixed>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Mismatched etrans InsSubNum/PlanNum fixed: ")+numFixed.ToString()+"\r\n"; } numFixed=0; //payplan--------------------------------------------------------------------------------------------------- command="UPDATE payplan SET PlanNum = (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=payplan.InsSubNum) " +"WHERE PlanNum != (SELECT inssub.PlanNum FROM inssub WHERE inssub.InsSubNum=payplan.InsSubNum)"; numFixed=Db.NonQ(command); if(numFixed>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Mismatched payplan InsSubNum/PlanNum fixed: ")+numFixed.ToString()+"\r\n"; } numFixed=0; } return log; }
public static string Validate(Clearinghouse clearinghouseClin, Carrier carrier, Provider billProv, Clinic clinic, InsPlan insPlan, Patient subscriber, InsSub insSub, Patient patForRequest) { StringBuilder strb = new StringBuilder(); X12Validate.ISA(clearinghouseClin, strb); X12Validate.Carrier(carrier, strb); if (carrier.ElectID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Electronic ID"); } if (billProv.SSN.Length != 9) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Prov TIN 9 digits"); } X12Validate.BillProv(billProv, strb); if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { X12Validate.BillingAddress(strb); } else if (clinic == null) { X12Validate.PracticeAddress(strb); } else { X12Validate.Clinic(clinic, strb); } if (insSub.SubscriberID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("SubscriberID"); } if (subscriber.Birthdate.Year < 1880) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Subscriber Birthdate"); } if (patForRequest.PatNum != subscriber.PatNum) //Dependent validation. { if (patForRequest.Birthdate.Year < 1880) //Dependent level validation. { if (strb.Length != 0) { strb.Append(","); } strb.Append("Dependent Birthdate"); } } ElectID eID = ElectIDs.GetID(carrier.ElectID); //Medicaid uses the patient First/Last/DOB to get benefits, not group number, so skip this validation if this is medicaid bool isMedicaid = (eID != null && eID.IsMedicaid) || carrier.CarrierName.ToLower().Contains("medicaid"); if (!isMedicaid) { if (insPlan.GroupNum == "") { if (strb.Length != 0) { strb.Append(","); } strb.Append("Group Number"); } } //Darien at Dentalxchange helped us resolve one issue where the Group Number included a dash and was failing. //The fix suggested by Darien was to only include the numbers before the dash... See task #705773 if (IsClaimConnect(clearinghouseClin) && insPlan.GroupNum.Contains("-")) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Group Number: Only include the group number prior to the '-'"); } return(strb.ToString()); }
///<summary>This will assign all PlanNums to new value when Create New Plan If Needed is selected and there are multiple subscribers to a plan and an inssub object has been updated to point at a new PlanNum. The PlanNum values need to be reflected in the claim, claimproc, payplan, and etrans tables, since those all both store inssub.InsSubNum and insplan.PlanNum.</summary> public static void SynchPlanNumsForNewPlan(InsSub SubCur) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),SubCur); return; } //claim.PlanNum string command="UPDATE claim SET claim.PlanNum="+POut.Long(SubCur.PlanNum)+" " +"WHERE claim.InsSubNum="+POut.Long(SubCur.InsSubNum)+" AND claim.PlanNum!="+POut.Long(SubCur.PlanNum); Db.NonQ(command); //claim.PlanNum2 command="UPDATE claim SET claim.PlanNum2="+POut.Long(SubCur.PlanNum)+" " +"WHERE claim.InsSubNum2="+POut.Long(SubCur.InsSubNum)+" AND claim.PlanNum2!="+POut.Long(SubCur.PlanNum); Db.NonQ(command); //claimproc.PlanNum command="UPDATE claimproc SET claimproc.PlanNum="+POut.Long(SubCur.PlanNum)+" " +"WHERE claimproc.InsSubNum="+POut.Long(SubCur.InsSubNum)+" AND claimproc.PlanNum!="+POut.Long(SubCur.PlanNum); Db.NonQ(command); //payplan.PlanNum command="UPDATE payplan SET payplan.PlanNum="+POut.Long(SubCur.PlanNum)+" " +"WHERE payplan.InsSubNum="+POut.Long(SubCur.InsSubNum)+" AND payplan.PlanNum!="+POut.Long(SubCur.PlanNum); Db.NonQ(command); //etrans.PlanNum, only used if EtransType.BenefitInquiry270 and BenefitResponse271 and Eligibility_CA. command="UPDATE etrans SET etrans.PlanNum="+POut.Long(SubCur.PlanNum)+" " +"WHERE etrans.InsSubNum!=0 AND etrans.InsSubNum="+POut.Long(SubCur.InsSubNum)+" AND etrans.PlanNum!="+POut.Long(SubCur.PlanNum); Db.NonQ(command); }
private Claim CreateClaim(string claimType,List<PatPlan> patPlanList,List<InsPlan> planList,List<ClaimProc> claimProcList,Procedure proc,List<InsSub> subList) { long claimFormNum=0; InsPlan planCur=new InsPlan(); InsSub subCur=new InsSub(); Relat relatOther=Relat.Self; long clinicNum=proc.ClinicNum; PlaceOfService placeService=proc.PlaceService; switch(claimType) { case "P": subCur=InsSubs.GetSub(PatPlans.GetInsSubNum(patPlanList,PatPlans.GetOrdinal(PriSecMed.Primary,patPlanList,planList,subList)),subList); planCur=InsPlans.GetPlan(subCur.PlanNum,planList); break; case "S": subCur=InsSubs.GetSub(PatPlans.GetInsSubNum(patPlanList,PatPlans.GetOrdinal(PriSecMed.Secondary,patPlanList,planList,subList)),subList); planCur=InsPlans.GetPlan(subCur.PlanNum,planList); break; case "Med": //It's already been verified that a med plan exists subCur=InsSubs.GetSub(PatPlans.GetInsSubNum(patPlanList,PatPlans.GetOrdinal(PriSecMed.Medical,patPlanList,planList,subList)),subList); planCur=InsPlans.GetPlan(subCur.PlanNum,planList); break; } ClaimProc claimProcCur=Procedures.GetClaimProcEstimate(proc.ProcNum,claimProcList,planCur,subCur.InsSubNum); if(claimProcCur==null) { claimProcCur=new ClaimProc(); ClaimProcs.CreateEst(claimProcCur,proc,planCur,subCur); } Claim claimCur=new Claim(); claimCur.PatNum=proc.PatNum; claimCur.DateService=proc.ProcDate; claimCur.ClinicNum=proc.ClinicNum; claimCur.PlaceService=proc.PlaceService; claimCur.ClaimStatus="W"; claimCur.DateSent=DateTimeOD.Today; claimCur.PlanNum=planCur.PlanNum; claimCur.InsSubNum=subCur.InsSubNum; InsSub sub; switch(claimType) { case "P": claimCur.PatRelat=PatPlans.GetRelat(patPlanList,PatPlans.GetOrdinal(PriSecMed.Primary,patPlanList,planList,subList)); claimCur.ClaimType="P"; claimCur.InsSubNum2=PatPlans.GetInsSubNum(patPlanList,PatPlans.GetOrdinal(PriSecMed.Secondary,patPlanList,planList,subList)); sub=InsSubs.GetSub(claimCur.InsSubNum2,subList); if(sub.PlanNum>0 && InsPlans.RefreshOne(sub.PlanNum).IsMedical) { claimCur.PlanNum2=0;//no sec ins claimCur.PatRelat2=Relat.Self; } else { claimCur.PlanNum2=sub.PlanNum;//might be 0 if no sec ins claimCur.PatRelat2=PatPlans.GetRelat(patPlanList,PatPlans.GetOrdinal(PriSecMed.Secondary,patPlanList,planList,subList)); } break; case "S": claimCur.PatRelat=PatPlans.GetRelat(patPlanList,PatPlans.GetOrdinal(PriSecMed.Secondary,patPlanList,planList,subList)); claimCur.ClaimType="S"; claimCur.InsSubNum2=PatPlans.GetInsSubNum(patPlanList,PatPlans.GetOrdinal(PriSecMed.Primary,patPlanList,planList,subList)); sub=InsSubs.GetSub(claimCur.InsSubNum2,subList); claimCur.PlanNum2=sub.PlanNum; claimCur.PatRelat2=PatPlans.GetRelat(patPlanList,PatPlans.GetOrdinal(PriSecMed.Primary,patPlanList,planList,subList)); break; case "Med": claimCur.PatRelat=PatPlans.GetFromList(patPlanList,subCur.InsSubNum).Relationship; claimCur.ClaimType="Other"; if(PrefC.GetBool(PrefName.ClaimMedTypeIsInstWhenInsPlanIsMedical)){ claimCur.MedType=EnumClaimMedType.Institutional; } else{ claimCur.MedType=EnumClaimMedType.Medical; } break; case "Other": claimCur.PatRelat=relatOther; claimCur.ClaimType="Other"; //plannum2 is not automatically filled in. claimCur.ClaimForm=claimFormNum; if(planCur.IsMedical){ if(PrefC.GetBool(PrefName.ClaimMedTypeIsInstWhenInsPlanIsMedical)){ claimCur.MedType=EnumClaimMedType.Institutional; } else{ claimCur.MedType=EnumClaimMedType.Medical; } } break; } if(planCur.PlanType=="c"){//if capitation claimCur.ClaimType="Cap"; } claimCur.ProvTreat=proc.ProvNum; if(Providers.GetIsSec(proc.ProvNum)) { claimCur.ProvTreat=Patients.GetPat(proc.PatNum).PriProv; //OK if zero, because auto select first in list when open claim } claimCur.IsProsthesis="N"; claimCur.ProvBill=Providers.GetBillingProvNum(claimCur.ProvTreat,claimCur.ClinicNum);//OK if zero, because it will get fixed in claim claimCur.EmployRelated=YN.No; claimCur.ClaimForm=planCur.ClaimFormNum; Claims.Insert(claimCur); //attach procedure claimProcCur.ClaimNum=claimCur.ClaimNum; if(planCur.PlanType=="c") {//if capitation claimProcCur.Status=ClaimProcStatus.CapClaim; } else { claimProcCur.Status=ClaimProcStatus.NotReceived; } if(planCur.UseAltCode && (ProcedureCodes.GetProcCode(proc.CodeNum).AlternateCode1!="")) { claimProcCur.CodeSent=ProcedureCodes.GetProcCode(proc.CodeNum).AlternateCode1; } else if(planCur.IsMedical && proc.MedicalCode!="") { claimProcCur.CodeSent=proc.MedicalCode; } else { claimProcCur.CodeSent=ProcedureCodes.GetProcCode(proc.CodeNum).ProcCode; if(claimProcCur.CodeSent.Length>5 && claimProcCur.CodeSent.Substring(0,1)=="D") { claimProcCur.CodeSent=claimProcCur.CodeSent.Substring(0,5); } if(CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Canadian. en-CA or fr-CA if(claimProcCur.CodeSent.Length>5) {//In Canadian e-claims, codes can contain letters or numbers and cannot be longer than 5 characters. claimProcCur.CodeSent=claimProcCur.CodeSent.Substring(0,5); } } } claimProcCur.LineNumber=(byte)1; ClaimProcs.Update(claimProcCur); return claimCur; }
private static void WriteFunctionalGroup(StreamWriter sw,List<ClaimSendQueueItem> queueItems,int batchNum,Clearinghouse clearhouse,EnumClaimMedType medType) { #region Functional Group Header int transactionNum=1;//Gets incremented for each carrier. Can be reused in other functional groups and interchanges, so not persisted //Functional Group Header string groupControlNumber=batchNum.ToString();//Must be unique within file. We will use batchNum string industryIdentifierCode=""; if(medType==EnumClaimMedType.Medical) { industryIdentifierCode="005010X222A1"; } else if(medType==EnumClaimMedType.Institutional) { industryIdentifierCode="005010X223A2"; } else if(medType==EnumClaimMedType.Dental) { industryIdentifierCode="005010X224A2"; } sw.Write("GS"+s +"HC"+s//GS01 2/2 Functional Identifier Code: Health Care Claim. +X12Generator.GetGS02(clearhouse)+s//GS02 2/15 Application Sender's Code: Sometimes Jordan Sparks. Sometimes the sending clinic. +Sout(clearhouse.GS03,15,2)+s//GS03 2/15 Application Receiver's Code: +DateTime.Today.ToString("yyyyMMdd")+s//GS04 8/8 Date: today's date. +DateTime.Now.ToString("HHmm")+s//GS05 4/8 TIME: current time. +groupControlNumber+s//GS06 1/9 Group Control Number: No padding necessary. +"X"+s//GS07 1/2 Responsible Agency Code: X=Accredited Standards Committee X12. +industryIdentifierCode//GS08 1/12 Version/Release/Industry Identifier Code: +endSegment); #endregion Functional Group Header #region Define Variables int HLcount=1; int parentProv=0;//the HL sequence # of the current provider. int parentSubsc=0;//the HL sequence # of the current subscriber. string hasSubord="";//0 if no subordinate, 1 if at least one subordinate Claim claim; InsPlan insPlan; InsPlan otherPlan=null; InsSub sub; InsSub otherSub=new InsSub(); Patient patient; Patient subscriber; Patient otherSubsc=new Patient(); Carrier carrier; Carrier otherCarrier=new Carrier(); List<ClaimProc> claimProcList;//all claimProcs for a patient. List<ClaimProc> claimProcs; List<Procedure> procList; List<ToothInitial> initialList; List<PatPlan> patPlans; Procedure proc; ProcedureCode procCode; Provider provTreat;//claim level treating provider. Provider billProv=null; Clinic clinic=null; seg=0; #endregion Define Variables #region Transaction Set Header //if(i==0//if this is the first claim // || claimItems[i].PayorId0 != claimItems[i-1].PayorId0)//or the payorID has changed //{ // newTrans=true; // seg=0; //} //else newTrans=false; //if(newTrans) { //Transaction Set Header (one for each carrier) //transactionNum gets incremented in SE section //ST02 Transact. control #. Must be unique within ISA //NO: So we used combination of transaction and group, eg 00011 sw.Write("ST"+s +"837"+s//ST01 3/3 Transaction Set Identifier Code: +transactionNum.ToString().PadLeft(4,'0')+s//ST02 4/9 Transaction Set Control Number: +industryIdentifierCode);//ST03 1/35 Implementation Convention Reference: EndSegment(sw); sw.Write("BHT"+s +"0019"+s//BHT01 4/4 Hierarchical Structure Code: 0019=Information Source, Subscriber, Dependant. +"00"+s//BHT02 2/2 Transaction Set Purpose Code: 00=Original transmissions are transmissions which have never been sent to the reciever. +transactionNum.ToString().PadLeft(4,'0')+s//BHT03 1/50 Reference Identification: Can be same as ST02. +DateTime.Now.ToString("yyyyMMdd")+s//BHT04 8/8 Date: +DateTime.Now.ToString("HHmmss")+s//BHT05 4/8 Time: +"CH");//BHT06 2/2 Transaction Type Code: CH=Chargable. EndSegment(sw); //1000A Submitter is OPEN DENTAL and sometimes it's the practice //(depends on clearinghouse and Partnership agreements) //See 2010AA PER (after REF) for the new billing provider contact phone number //1000A NM1: 41 (medical,institutional,dental) Submitter Name. Write1000A_NM1(sw,clearhouse); //1000A PER: IC (medical,institutional,dental) Submitter EDI Contact Information. Contact number. Write1000A_PER(sw,clearhouse); //1000B NM1: 40 (medical,institutional,dental) Receiver Name. Always the Clearinghouse. sw.Write("NM1"+s +"40"+s//NM101 2/3 Entity Identifier Code: 40=Receiver. +"2"+s);//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity. if(IsClaimConnect(clearhouse)) { sw.Write("CLAIMCONNECT"+s);//NM103 1/60 Name Last or Organization Name: Receiver Name. } else if(IsDentiCal(clearhouse)) { sw.Write("DENTICAL"+s);//NM103 1/60 Name Last or Organization Name: Receiver Name. } else { sw.Write(Sout(clearhouse.Description,60)+s);//NM103 1/60 Name Last or Organization Name: Receiver Name. } sw.Write(s//NM104 1/35 Name First: Not Used. +s//NM105 1/25 Name Middle: Not Used. +s//NM106 1/10 Name Prefix: Not Used. +s//NM107 1/10 Name Suffix: Not Used. +"46"+s);//NM108 1/2 Identification Code Qualifier: 46=Electronic Transmitter Identification Number (ETIN). if(IsDentiCal(clearhouse)) { sw.Write("1941461312");//NM109 2/80 Identification Code: Receiver ID Code. aka ETIN#. } else { sw.Write(Sout(clearhouse.ISA08,80,2));//NM109 2/80 Identification Code: Receiver ID Code. aka ETIN#. } EndSegment(sw);//NM110 through NM112 are not used. HLcount=1; parentProv=0;//the HL sequence # of the current provider. parentSubsc=0;//the HL sequence # of the current subscriber. hasSubord="";//0 if no subordinate, 1 if at least one subordinate //} #endregion for(int i=0;i<queueItems.Count;i++) { #region Initialize Variables claim=Claims.GetClaim(queueItems[i].ClaimNum); insPlan=InsPlans.GetPlan(claim.PlanNum,new List<InsPlan>()); sub=InsSubs.GetSub(claim.InsSubNum,null); //insPlan could be null if db corruption. No error checking for that otherPlan=null;//Must be reset each time through because if otherPlan!=null below then we assume the current claim has a secondary plan. if(claim.PlanNum2>0) { otherPlan=InsPlans.GetPlan(claim.PlanNum2,new List<InsPlan>()); otherSub=InsSubs.GetSub(claim.InsSubNum2,null); otherSubsc=Patients.GetPat(otherSub.Subscriber); otherCarrier=Carriers.GetCarrier(otherPlan.CarrierNum); } patient=Patients.GetPat(claim.PatNum); subscriber=Patients.GetPat(sub.Subscriber); carrier=Carriers.GetCarrier(insPlan.CarrierNum); claimProcList=ClaimProcs.Refresh(patient.PatNum); claimProcs=ClaimProcs.GetForSendClaim(claimProcList,claim.ClaimNum); procList=Procedures.Refresh(claim.PatNum); initialList=ToothInitials.Refresh(claim.PatNum); patPlans=PatPlans.Refresh(patient.PatNum); #endregion Initialize Variables #region Billing Provider //Billing address is based on clinic, not provider. All claims in a batch are guaranteed to be from a single clinic. That validation is done in FormClaimSend. //Although, now that we have a separate loop for each claim, we might be able to allow a batch with mixed clinics. if(!PrefC.GetBool(PrefName.EasyNoClinics)) {//if using clinics clinic=Clinics.GetClinic(claim.ClinicNum);//might be null } //2000A HL: (medical,instituational,dental) Billing Provider Hierarchical Level. sw.Write("HL"+s+HLcount.ToString()+s//HL01 1/12 Heirarchical ID Number: +s//HL02 1/12 Hierarchical Parent ID Number: Not used. +"20"+s//HL03 1/2 Heirarchical Level Code: 20=Information Source. +"1");//HL04 1/1 Heirarchical Child Code. 1=Additional Subordinate HL Data Segment in This Hierarchical Structure. EndSegment(sw); //billProv=ProviderC.ListLong[Providers.GetIndexLong(claimItems[i].ProvBill1)]; billProv=Providers.GetProv(claim.ProvBill); //2000A PRV: BI (medical,institutional,dental) Billing Provider Specialty Information. Situational. Required when billing provider is treating provider. bool usePrvBilling=false; if(claim.ProvBill==claim.ProvTreat) { usePrvBilling=true; } if(IsWashingtonMedicaid(clearhouse,carrier)) { usePrvBilling=true; } if(usePrvBilling) { sw.Write("PRV"+s +"BI"+s//PRV01 1/3 Provider Code: BI=Billing. +"PXC"+s//PRV02 2/3 Reference Identification Qualifier: PXC=Health Care Provider Taxonomy Code. +X12Generator.GetTaxonomy(billProv));//PRV03 1/50 Reference Identification: Provider Taxonomy Code. EndSegment(sw);//PRV04 through PRV06 are not used. } //2000A CUR: (medical,instituational,dental) Foreign Currency Information. Situational. We do not need to specify because united states dollars are default. //2010AA NM1: 85 (medical,institutional,dental) Billing Provider Name. if(medType==EnumClaimMedType.Institutional) { billProv.IsNotPerson=true;//Required by X12 specification. Cannot send a person as the billing provider. } WriteNM1Provider("85",sw,billProv); //2010AA N3: (medical,institutional,dental) Billing Provider Address. string billingAddress1=""; string billingAddress2=""; string billingCity=""; string billingState=""; string billingZip=""; if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { billingAddress1=PrefC.GetString(PrefName.PracticeBillingAddress); billingAddress2=PrefC.GetString(PrefName.PracticeBillingAddress2); billingCity=PrefC.GetString(PrefName.PracticeBillingCity); billingState=PrefC.GetString(PrefName.PracticeBillingST); billingZip=PrefC.GetString(PrefName.PracticeBillingZip); } else if(clinic==null) { billingAddress1=PrefC.GetString(PrefName.PracticeAddress); billingAddress2=PrefC.GetString(PrefName.PracticeAddress2); billingCity=PrefC.GetString(PrefName.PracticeCity); billingState=PrefC.GetString(PrefName.PracticeST); billingZip=PrefC.GetString(PrefName.PracticeZip); } else { billingAddress1=clinic.Address; billingAddress2=clinic.Address2; billingCity=clinic.City; billingState=clinic.State; billingZip=clinic.Zip; } sw.Write("N3"+s+Sout(billingAddress1,55));//N301 1/55 Address Information: if(billingAddress2!="") { sw.Write(s+Sout(billingAddress2,55));//N302 1/55 Address Information: } EndSegment(sw); //2010AA N4: (medical,institutional,dental) Billing Provider City, State, Zip Code. sw.Write("N4"+s+Sout(billingCity,30)+s//N401 2/30 City Name: +Sout(billingState,2,2)+s//N402 2/2 State or Province Code: +Sout(billingZip.Replace("-",""),15));//N403 3/15 Postal Code: EndSegment(sw);//NM404 through NM407 are either situational with United States as default, or not used, so we don't specify any of them. //2010AA REF: EI (medical,institutional,dental) Billing Provider Tax Identification. sw.Write("REF"+s); if(medType==EnumClaimMedType.Medical) { sw.Write((billProv.UsingTIN?"EI":"SY")+s);//REF01 2/3 Reference Identification Qualifier: EI=Employer's Identification Number (EIN). SY=Social Security Number (SSN). } else if(medType==EnumClaimMedType.Institutional) { sw.Write("EI"+s);//REF01 2/3 Reference Identification Qualifier: EI=Employer's Identification Number (EIN). } else if(medType==EnumClaimMedType.Dental) { sw.Write((billProv.UsingTIN?"EI":"SY")+s);//REF01 2/3 Reference Identification Qualifier: EI=Employer's Identification Number (EIN). SY=Social Security Number (SSN). } sw.Write(Sout(billProv.SSN,50));//REF02 1/50 Reference Identification. Tax ID #. EndSegment(sw);//REF03 and REF04 are not used. if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Dental) { //2010AA REF: (medical,dental) Billing Provider UIPN/License Information: Situational. We do not use. Max repeat 2. } if(medType==EnumClaimMedType.Dental) { //2010AA REF: (dental) State License Number: Required by RECS and Emdeon clearinghouses. We do NOT validate that it's entered because sending it with non-persons causes problems. //if(IsEmdeonDental(clearhouse) || clearhouse.CommBridge==EclaimsCommBridge.RECS) { if(!IsDentiCal(clearhouse)) { //Denti-Cal never wants this. if(billProv.StateLicense!="") { sw.Write("REF"+s +"0B"+s//REF01 2/3 Reference Identification Qualifier: 0B=State License Number. +Sout(billProv.StateLicense,50));//REF02 1/50 Reference Identification: EndSegment(sw);//REF03 and REF04 are not used. } } //2010AA REF G5 (dental) Site Identification Number: NOT IN X12 5010 STANDARD DOCUMENTATION. Only required by Emdeon. if(IsEmdeonDental(clearhouse)) { Write2010AASiteIDforEmdeon(sw,billProv,carrier.ElectID); } } //2010AA PER: IC (medical,institutional,dental) Billing Provider Contact Information: Probably required by a number of carriers and by Emdeon. sw.Write("PER"+s +"IC"+s//PER01 2/2 Contact Function Code: IC=Information Contact. +Sout(PrefC.GetString(PrefName.PracticeTitle),60)+s//PER02 1/60 Name: Practice Title. +"TE"+s);//PER03 2/2 Communication Number Qualifier: TE=Telephone. if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { sw.Write(Sout(PrefC.GetString(PrefName.PracticePhone),256));//PER04 1/256 Communication Number: Telephone number. } else if(clinic==null){ sw.Write(Sout(PrefC.GetString(PrefName.PracticePhone),256));//PER04 1/256 Communication Number: Telephone number. } else{ sw.Write(Sout(clinic.Phone,256));//PER04 1/256 Communication Number: Telephone number. } EndSegment(sw);//PER05 through PER08 are situational and PER09 is not used. We do not use. if(PrefC.GetString(PrefName.PracticePayToAddress)!="") { //2010AB NM1: 87 (medical,institutional,dental) Pay-To Address Name. sw.Write("NM1"+ s+"87"+s);//NM101 2/3 Entity Identifier Code: 87=Pay-to Provider. if(medType==EnumClaimMedType.Institutional) { sw.Write("2");//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity. } else { //(medical,dental) sw.Write((billProv.IsNotPerson?"2":"1"));//NM102 1/1 Entity Type Qualifier: 1=Person, 2=Non-Person Entity. } EndSegment(sw);//NM103 through NM112 are not used. //2010AB N3: (medical,institutional,dental) Pay-To Address. sw.Write("N3"+s+Sout(PrefC.GetString(PrefName.PracticePayToAddress),55));//N301 1/55 Address Information: if(PrefC.GetString(PrefName.PracticePayToAddress2)!="") { sw.Write(s+Sout(PrefC.GetString(PrefName.PracticePayToAddress2),55));//N302 1/55 Address Information: } EndSegment(sw); //2010AB N4: (medical,institutional,dental) Pay-To Address City, State, Zip Code. sw.Write("N4"+s+Sout(PrefC.GetString(PrefName.PracticePayToCity),30)+s//N401 2/30 City Name: +Sout(PrefC.GetString(PrefName.PracticePayToST),2,2)+s//N402 2/2 State or Province Code: +Sout(PrefC.GetString(PrefName.PracticePayToZip).Replace("-",""),15));//N403 3/15 Postal Code: EndSegment(sw);//NM404 through NM407 are either situational with United States as default, or not used, so we don't specify any of them. } //2010AC NM1: 98 (medical,institutional,dental) Pay-To Plan Name. We do not use. //2010AC N3: (medical,institutional,dental) Pay-To Plan Address. We do not use. //2010AC N4: (medical,institutional,dental) Pay-To Plan City, State, Zip Code. We do not use. //2010AC REF: (medical,institutional,dental) Pay-To Plan Secondary Identification. We do not use. //2010AC REF: (medical,institutional,dental) Pay-To Plan Tax Identification Number. We do not use. parentProv=HLcount; HLcount++; #endregion Billing Provider #region Attachments /*if(IsTesia(clearhouse) && claim.Attachments.Count>0){//If Tesia and has attachments claim.ClaimNote="TESIA#"+claim.ClaimNum.ToString()+" "+claim.ClaimNote; string saveFolder=clearhouse.ExportPath;//we've already tested to make sure this exists. string saveFile; string storedFile; for(int c=0;c<claim.Attachments.Count;c++){ saveFile=ODFileUtils.CombinePaths(saveFolder, claim.ClaimNum.ToString()+"_"+(c+1).ToString()+Path.GetExtension(claim.Attachments[c].DisplayedFileName)+".IMG"); storedFile=ODFileUtils.CombinePaths(FormEmailMessageEdit.GetAttachPath(),claim.Attachments[c].ActualFileName); File.Clone(storedFile,saveFile,true); } }*/ #endregion #region Subscriber if(patient.PatNum==subscriber.PatNum){//if patient is the subscriber hasSubord="0";//-claim level will follow //subordinate patients will not follow in this loop. The subscriber loop will be duplicated for them. } else {//patient is not the subscriber hasSubord="1";//-patient will always follow } //2000B HL: (medical,institutional,dental) Subscriber Hierarchical Level. sw.Write("HL"+s+HLcount.ToString()+s//HL01 1/12 Hierarchical ID Number: +parentProv.ToString()+s//HL02 1/12 Hierarchical Parent ID Number: parent HL is always the billing provider HL. +"22"+s//HL03 1/2 Hierarchical Level Code: 22=Subscriber. +hasSubord);//HL04 1/1 Hierarchical Child Code: 0=No subordinate HL segment in this hierarchical structure. 1=Additional subordinate HL data segment in this hierarchical structure. EndSegment(sw); //2000B SBR: (medical,institutional,dental) Subscriber Information. sw.Write("SBR"+s); bool claimIsPrimary=true;//we currently support only primary and secondary. Plan2, if present, must be the opposite. if(claim.ClaimType=="PreAuth") { if(otherPlan!=null && PatPlans.GetOrdinal(claim.InsSubNum2,patPlans) < PatPlans.GetOrdinal(claim.InsSubNum,patPlans)) { //When there are two plans and the secondary plan is in the primary ins position. claimIsPrimary=false; } } else if(otherPlan!=null && (otherPlan.IsMedical || insPlan.IsMedical)) { //When there are two plans and at least one plan is medical. if(PatPlans.GetOrdinal(claim.InsSubNum2,patPlans) < PatPlans.GetOrdinal(claim.InsSubNum,patPlans)) { //The insurance plan order is determined by patplan.ordinal claimIsPrimary=false; } } else if(claim.ClaimType=="P") { } else if(claim.ClaimType=="S") { //Verification ensures that there are two plans associated with the claim in this case. claimIsPrimary=false; } else if(claim.ClaimType=="Other") { //Also used for a medical claim with only one insurance. //We always send medical plans as primary. They are totally separate from the ordinals for dental. } else if(claim.ClaimType=="Cap") { //All captication claims are treated as primary claims. //todo: is secondary capitation possible? } sw.Write((claimIsPrimary?"P":"S")+s);//SBR01 1/1 Payer Responsibility Sequence Number Code: string relationshipCode="";//empty if patient is not subscriber. if(patient.PatNum==subscriber.PatNum) {//if patient is the subscriber relationshipCode="18"; } sw.Write(relationshipCode+s//SBR02 2/2 Individual Relationship Code: 18=Self (The only option besides blank). +Sout(insPlan.GroupNum,50)+s);//SBR03 1/50 Reference Identification: Does not need to be validated because group number is optional. //SBR04 1/60 Name: Situational. Required when SBR03 is not used. Does not need to be validated because group name is optional. if(insPlan.GroupNum!="") { sw.Write(s); } else { sw.Write(Sout(insPlan.GroupName,60)+s); } sw.Write(s//SBR05 1/3 Insurance Type Code. Situational. Skip because we don't support secondary Medicare. +s//SBR06 1/1 Coordination of Benefits Code: Not used. +s//SBR07 1/1 Yes/No Condition or Respose Code: Not used. +s//SBR08 2/2 Employment Status Code: Not used. +GetFilingCode(insPlan));//SBR09: 12=PPO,17=DMO,BL=BCBS,CI=CommercialIns,FI=FEP,HM=HMO. Will no longer be required when HIPPA National Plan ID is mandated. EndSegment(sw); if(medType==EnumClaimMedType.Medical) { //2000B PAT: (medical) Patient Information. Situational. Required when the patient is the subscriber or considered to be the subscriber and at least one of the element requirements are met. Element requirements include: when the patient is deceased and the date of death is available; or when the claim involves Medicare Durable Medical Equipment Regional Carriers Certificate of Medical Necessity (DMERC CMN) 02.03, 10.02, or DMA MAC 10.03; or when law requires to know if the patient is pregnant or not. We do not use, because we do not track death date, durable medical equipment information, nor do we know weather or not the patient is pregnant. Some of these fields may be necessary in the future, but not likely since our medical claims are usually pretty simple. } //2010BA NM1: IL (medical,institutional,dental) Subscriber Name. sw.Write("NM1"+s +"IL"+s//NM101 2/3 Entity Identifier Code: IL=Insured or Subscriber. +"1"+s//NM102 1/1 Entity Type Qualifier: 1=Person, 2=Non-Person Entity. +Sout(subscriber.LName,60)+s//NM103 1/60 Name Last or Organization Name: Never blank, because validated in the patient edit window when a patient is added/edited. +Sout(subscriber.FName,35)+s//NM104 1/35 Name First: +Sout(subscriber.MiddleI,25)+s//NM105 1/25 Name Middle: +s//NM106 1/10 Name Prefix: Not Used. +s//NM107 1/10 Name Suffix: Situational. Not present in Open Dental yet so we leave blank. +"MI"+s//NM108 1/2 Identification Code Qualifier: MI=Member Identification Number. +Sout(sub.SubscriberID.Replace("-",""),80,2));//NM109 2/80 Identification Code: Situational. Required when NM102=1. EndSegment(sw);//NM110 through NM112 are not used. //In 4010s, at the request of Emdeon, we always include N3,N4,and DMG even if patient is not subscriber. This did not make the transaction non-compliant, and they found it useful. //In 5010s, we will follow the X12 specification for most clearinghouses and only include subsc address when subscriber=patient. //But for any clearinghouse who requests it, we will always include, [js 3/14/13 even when subscriber!=patient]. List them here: //ClaimConnect, EmdeonMed, EmdeonDent, LindsayTechnicalConsultants, OfficeAlly: Always include. //PostNTrack, BCBSIdaho: Only include when subscriber=patient. bool subscIncludeAddressAndGender=false; if(IsClaimConnect(clearhouse) || IsEmdeonDental(clearhouse) || IsEmdeonMedical(clearhouse) || IsLindsayTechnicalConsultants(clearhouse) || IsOfficeAlly(clearhouse)) { subscIncludeAddressAndGender=true; } else {//X12 standard behavior for everyone else, including: BCBSIdaho, ColoradoMedicaid, Denti-Cal, PostNTrack, WashingtonMedicaid. if(subscriber.PatNum==patient.PatNum) {//[js 3/14/13 only include when subscriber==patient] subscIncludeAddressAndGender=true; } //[js 3/14/13 when subscriber!=patient, don't include address] } if(subscIncludeAddressAndGender) { //2010BA N3: (medical,institutional,dental) Subscriber Address. Situational. Required when the patient is the subscriber. sw.Write("N3"+s+Sout(subscriber.Address,55));//N301 1/55 Address Information: if(subscriber.Address2!="") { sw.Write(s+Sout(subscriber.Address2,55));//N302 1/55 Address Information: } EndSegment(sw); //2010BA N4: (medical,institutional,dental) Subscriber City, State, Zip Code. Situational. Required when the patient is the subscriber. sw.Write("N4"+s +Sout(subscriber.City,30)+s//N401 2/30 City Name: +Sout(subscriber.State,2,2)+s//N402 2/2 State or Provice Code: +Sout(subscriber.Zip.Replace("-",""),15));//N403 3/15 Postal Code: EndSegment(sw);//N404 through N407 either not used or required for addresses outside of the United States. //2010BA DMG: (medical,institutional,dental) Subscriber Demographic Information. Situational. Required when the patient is the subscriber. //Carriers tend to complain if the BD is missing for the subscriber even though it's not strictly required. So we will require it from users. sw.Write("DMG"+s +"D8"+s//DMG01 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD. +subscriber.Birthdate.ToString("yyyyMMdd")+s//DMG02 1/35 Date Time Period: Birthdate. The subscriber birtdate is validated. +GetGender(subscriber.Gender));//DMG03 1/1 Gender Code: F=Female, M=Male, U=Unknown. EndSegment(sw); } //2010BA REF: SY (medical,institutional,dental) Secondary Secondary Identification: Situational. Required when an additional identification number to that provided in NM109 of this loop is necessary. We do not use this. //2010BA REF: Y4 (medical,institutional,dental) Property and Casualty Claim Number: Required when the services included in this claim are to be considered as part of a property and casualty claim. We do not use this. //2010BA PER: IC (medical) Property and Casualty Subscriber Contact information: Situational. We do not use this. //2010BB NM1: PR (medical,institutional,dental) Payer Name. sw.Write("NM1"+s +"PR"+s//NM101 2/3 Entity Identifier Code: PR=Payer. +"2"+s);//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity. //NM103 1/60 Name Last or Organization Name: if(IsEMS(clearhouse)) { //This is a special situation requested by EMS. This tacks the employer onto the end of the carrier. sw.Write(Sout(carrier.CarrierName,30)+"|"+Sout(Employers.GetName(insPlan.EmployerNum),30)+s); } else if(IsDentiCal(clearhouse)) { sw.Write("DENTICAL"+s); } else { sw.Write(Sout(carrier.CarrierName,60)+s); } sw.Write(s//NM104 1/35 Name First: Not used. +s//NM105 1/25 Name Middle: Not used. +s//NM106 1/10 Name Prefix: Not used. +s//NM107 1/10 Name Suffix: Not used. +"PI"+s);//NM108 1/2 Identification Code Qualifier: PI=Payor Identification. sw.Write(Sout(GetCarrierElectID(carrier,clearhouse),80,2));//NM109 2/80 Identification Code: PayorID. EndSegment(sw);//NM110 through NM112 Not Used. //2010BB N3: (medical,institutional,dental) Payer Address. sw.Write("N3"+s+Sout(carrier.Address,55));//N301 1/55 Address Information: if(carrier.Address2!="") { sw.Write(s+Sout(carrier.Address2,55));//N302 1/55 Address Information: Required when there is a second address line. } EndSegment(sw); //2010BB N4: (medical,institutional,dental) Payer City, State, Zip Code. sw.Write("N4"+s +Sout(carrier.City,30)+s//N401 2/30 City Name: +Sout(carrier.State,2)+s//N402 2/2 State or Province Code: +Sout(carrier.Zip.Replace("-",""),15));//N403 3/15 Postal Code: EndSegment(sw);//N404 through N407 are either not used or are for addresses outside of the United States. //2010BB REF 2U,EI,FY,NF (dental) Payer Secondary Identificaiton. Situational. //2010BB REF G2,LU Billing Provider Secondary Identification. Situational. Not required because we always send NPI. if(!IsDentiCal(clearhouse)){//DentiCal complained that they don't usually want this (except for non-subparted NPIs, which we don't handle). So far, nobody else has complained. //Always required by Emdeon Dental. WriteProv_REFG2orLU(sw,billProv,carrier.ElectID); } parentSubsc=HLcount; HLcount++; #endregion #region Patient if(patient.PatNum!=subscriber.PatNum){//if patient is not the subscriber //2000C HL: (medical,institutional,dental) Patient Hierarchical Level. sw.Write("HL"+s+HLcount.ToString()+s//HL01 1/12 Hierarchical ID Number: +parentSubsc.ToString()+s//HL02 1/12 Hierarchical Parent ID Number: Parent is always the subscriber HL. +"23"+s//HL03 1/2 Hierarchical Level Code: 23=Dependent. +"0");//HL04 1/1 Hierarchical Child Code: 0=No subordinate HL segment in this hierarchical structure. EndSegment(sw); //2000C PAT: (medical,institutional,dental) Patient Information. if(IsEmdeonDental(clearhouse)) { sw.Write("PAT"+s +GetRelat(claim.PatRelat)+s//PAT01 2/2 Individual Relationship Code: +s//PAT02 1/1 Patient Location Code: Not used. +s//PAT03 2/2 Employment Status Code: Not used. +GetStudentEmdeon(patient.StudentStatus));//PAT04 1/1 Student Status Code: Not used. Emdeon wants us to sent this code corresponding to version 4010, even through it is not standard X12. EndSegment(sw);//PAT05 through PAT08 not used in institutional or dental, but is sometimes used in medical. We do not use. } else { sw.Write("PAT"+s +GetRelat(claim.PatRelat));//PAT01 2/2 Individual Relationship Code: EndSegment(sw);//PAT02 through PAT04 Not used. PAT05 through PAT08 not used in institutional or dental, but is sometimes used in medical. We do not use. } //2010CA NM1: QC (medical,institutional,dental) Patient Name. sw.Write("NM1"+s +"QC"+s//NM101 2/3 Entity Identifier Code: QC=Patient. +"1"+s//NM102 1/1 Entity Type Qualifier: 1=Person. +Sout(patient.LName,60)+s//NM103 1/60 Name Last or Organization Name: +Sout(patient.FName,35));//NM104 1/35 Name First: Never blank, because validated in the patient edit window when a patient is added/edited. if(patient.MiddleI!="") { sw.Write(s+Sout(patient.MiddleI,25));//NM105 1/25 Name Middle } EndSegment(sw); //NM106 not used. NM107, No suffix field in Open Dental. NM108 through NM112 not used. //2010CA N3: (medical,institutional,dental) Patient Address. sw.Write("N3"+s+ Sout(patient.Address,55));//N301 1/55 Address Information if(patient.Address2!="") { sw.Write(s+Sout(patient.Address2,55));//N302 1/55 Address Information: } EndSegment(sw); //2010CA N4: (medical,institutional,dental) Patient City, State, Zip Code. sw.Write("N4"+s +Sout(patient.City,30)+s//N401 2/30 City Name: +Sout(patient.State,2,2)+s//N402 2/2 State or Provice Code: +Sout(patient.Zip.Replace("-",""),15));//N403 3/15 Postal Code: EndSegment(sw);//N404 through N407 are either not used or only required for addresses outside the United States. //2010CA DMG: (medical,institutional,dental) Patient Demographic Information. sw.Write("DMG"+s +"D8"+s//DMG01 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD. +patient.Birthdate.ToString("yyyyMMdd")+s//DMG02 1/35 Date Time Period: +GetGender(patient.Gender));//DMG03 1/1 Gender Code: F=Female,M=Male,U=Unknown. EndSegment(sw);//DMG04 through DMG11 are not used. //2010CA REF: (medical,instituional,dental) Property and Casualty Claim Number. Situational. We do not use this. //2010CA REF: (medical,institutional) Property and Casualty Patient Identifier. Situational. We do not use. //2010CA PER: (medical) Property and Casualty Patient Contact Information. Situational. We do not use. HLcount++; } #endregion #region Claim CLM //2300 CLM: (medical,institutional,dental) Claim Information. string clm01=claim.ClaimIdentifier;//Typically PatNum/ClaimNum. Check for uniqueness is performed in UI. if(IsDentiCal(clearhouse)) { clm01=Sout(clm01,17);//Denti-Cal has a maximum of 17 chars here. This field is what Denti-Cal refers to as the PDCN. } else if(IsEmdeonMedical(clearhouse)) { clm01=clm01.Replace('/','-');//Emdeon Medical only allows letters, numbers, dashes, periods, spaces and asterisks. The claim identifier will contain / inside the claim edit window still. } string claimFrequencyTypeCode="1"; if(claim.CorrectionType==ClaimCorrectionType.Original) { claimFrequencyTypeCode="1"; } else if(claim.CorrectionType==ClaimCorrectionType.Replacement) { claimFrequencyTypeCode="7"; } else if(claim.CorrectionType==ClaimCorrectionType.Void) { claimFrequencyTypeCode="8"; } //the next 8 lines fix a rare bug where the total doesn't match the sum of the procs. This would result in invalid X12 decimal claimFeeBilled=0; for(int j=0;j<claimProcs.Count;j++) { claimFeeBilled+=(decimal)claimProcs[j].FeeBilled; } if(claimFeeBilled!=(decimal)claim.ClaimFee) { claim.ClaimFee=(double)claimFeeBilled; Claims.Update(claim); } sw.Write("CLM"+s +Sout(clm01,20)+s//CLM01 1/38 Claim Submitter's Identifier: A unique id. Carriers are not required to handle more than 20 char. +claimFeeBilled.ToString("f2")+s//CLM02 1/18 Monetary Amount: +s//CLM03 1/2 Claim Filing Indicator Code: Not used. +s);//CLM04 1/2 Non-Institutional Claim Type Code: Not used. //CLM05 (medical,institutional,dental) Health Care Services Location Information. if(medType==EnumClaimMedType.Medical) { sw.Write(GetPlaceService(claim.PlaceService)+isa16//CLM05-1 1/2 Facility Code Value: Place of Service. +"B"+isa16//CLM05-2 1/2 Facility Code Qualifier, B=Place of Service Codes. +claimFrequencyTypeCode+s);//CLM05-3 1/1 Claim Frequency Type Code: 1=original, 7=replacement, 8=void(in limited jurisdictions). } else if(medType==EnumClaimMedType.Institutional) { //claim.UniformBillType validated to be exactly 3 char //Example: 771: 7=clinic, 7=FQHC, 1=Only claim. 713: 7=clinic, 1=rural health clinic, 3=continuing claim. sw.Write(claim.UniformBillType.Substring(0,2)+isa16//CLM05-1 1/2 Facility Code Value: First and second position of UniformBillType. +"A"+isa16//CLM05-2 1/2 Facility Code Qualifier, A=Uniform Billing Claim Form Bill Type. +claim.UniformBillType.Substring(2,1)+s);//CLM05-3 1/1 Claim Frequency Type Code: Third position of UniformBillType. } else{//dental. sw.Write(GetPlaceService(claim.PlaceService)+isa16//CLM05-1 1/2 Facility Code Value: Place of Service. +"B"+isa16//CLM05-2 1/2 Facility Code Qualifier, B=Place of Service Codes. +claimFrequencyTypeCode+s);//CLM05-3 1/1 Claim Frequency Type Code: 1=original, 7=replacement, 8=void(in limited jurisdictions). } if(medType==EnumClaimMedType.Medical) { sw.Write("Y"+s);//CLM06 1/1 Yes/No Condition or Response Code: prov sig on file (always yes) } else if(medType==EnumClaimMedType.Institutional) { sw.Write(s);//CLM06 1/1 Yes/No Condition or Response Code: Not used. } else if(medType==EnumClaimMedType.Dental) { sw.Write("Y"+s);//CLM06 1/1 Yes/No Condition or Response Code: prov sig on file (always yes) } sw.Write("A"+s//CLM07 1/1 Provider Accept Assignment Code: Prov accepts medicaid assignment. OD has no field for this, so no choice. +(sub.AssignBen?"Y":"N")+s//CLM08 1/1 Yes/No Condition or Response Code: We do not support W. +(sub.ReleaseInfo?"Y":"I"));//CLM09 1/1 Release of Information Code: Y or I(which is equivalent to No) if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Dental) { if(claim.AccidentDate.Year>1880 || claim.SpecialProgramCode!=EnumClaimSpecialProgram.none || claim.ClaimType=="PreAuth") {//if val for 11,12, or 19 sw.Write(s+s//end of CLM09. CLM10 not used +GetRelatedCauses(claim));//CLM11 2/3:2/3:2/3:2/2:2/3 Related Causes Information: Situational. Accident related, including state. Might be blank. } if(claim.SpecialProgramCode!=EnumClaimSpecialProgram.none || claim.ClaimType=="PreAuth") {//if val for 12, or 19 sw.Write(s//nothing for CLM11. +GetSpecialProgramCode(claim.SpecialProgramCode));//CLM12 2/3 Special Program Code: Situational. Example EPSTD. } if(claim.ClaimType=="PreAuth") {//if val for 19 sw.Write(s//nothing for CLM12. +s+s+s+s+s+s//CLM13-18 not used +"PB");//CLM19 2/2 Claim Submission Reason Code: PB=Predetermination of Benefits. TODO: Not allowed in medical claims. What is the replacement?? //CLM20 1/2 Delay Reason Code: Situational. Required when claim is submitted late. Not supported. } } //CLM10-19 not used, 20 not supported for institutional. EndSegment(sw); #endregion Claim CLM #region Claim DTP if(medType==EnumClaimMedType.Medical) { //2300 DTP: 431 (medical) Date Onset of Current Illness or Symptom. Situational. We do not use. //2300 DTP: 454 (medical) Initial Treatment Date. Situational. We do not use. (spinal manipulation). //2300 DTP: 304 (medical) Date Last Seen. Situational. We do not use. (foot care) //2300 DTP: 453 (medical) Date Accute Manifestation. Situational. We do not use. (spinal manipulation) //2300 DTP: 439 (medical) Date Accident. Situational. if(claim.AccidentDate.Year>1880) { sw.Write("DTP"+s +"439"+s//DTP01 3/3 Date/Time Qualifier: 439=accident +"D8"+s//DTP02 2/3 Date Time Period Format Qualifer: D8=Date Expressed in Format CCYYMMDD. +claim.AccidentDate.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period: EndSegment(sw); } //2300 DTP: 484 (medical) Last Menstrual Period Date. Situational. We do not use. //2300 DTP: 455 (medical) Last X-ray Date. Situational. We do not use. //2300 DTP: 471 (medical) Hearing and Vision Prescription Date. Situational. We do not use. //2300 DTP: 314,360,361 (medical) Disability Dates. Situational. We do not use. //2300 DTP: 297 (medical) Date Last Worked. Situational. We do not use. //2300 DTP: 296 (medical) Date Authorized Return to Work. Situational. We do not use. //2300 DTP: 435 (medical) Date Admission. Situational. We do not use. Inpatient. Request #2843. //2300 DTP: 096 (medical) Date Discharge. Situational. We do not use. Inpatient. Request #2843. //2300 DTP: 090 (medical) Date Assumed and Relinquished Care Dates. Situational. We do not use. //2300 DTP: 444 (medical) Date Property and Casualty Date of First Contact. Situational. We do not use. //2300 DTP: 050 (medical) Repricer Received Date. Situational. We do not use. } else if(medType==EnumClaimMedType.Institutional) { //2300 DTP 096 (institutional) Discharge Hour. Situational. We do not use. Inpatient. //2300 DTP 434 (instititional) Statement Dates. //todo:how to handle preauths? if(claim.DateService.Year>1880) {//DateService validated sw.Write("DTP"+s +"434"+s//DTP01 3/3 Date/Time Qualifier: 434=Statement. +"RD8"+s//DTP02 2/3 Date Time Period Format Qualifier: RD8=Range of Dates Expressed in Format CCYYMMDD-CCYYMMDD. +claim.DateService.ToString("yyyyMMdd")+"-"+claim.DateService.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period: EndSegment(sw); } //2300 DTP 435 (institutional) Admission Date/Hour. Situational. We do not use. Inpatient. //For the UB04 we are using claim.DateService for this field. //2300 DTP 050 (institutional) Repricer Received Date. Situational. Not supported. } else if(medType==EnumClaimMedType.Dental) { //2300 DTP 439 (dental) Date accident. Situational. Required when there was an accident. if(claim.AccidentDate.Year>1880) { sw.Write("DTP"+s +"439"+s//DTP01 3/3 Date/Time Qualifier: 439=accident +"D8"+s//DTP02 2/3 Date Time Period Format Qualifer: D8=Date Expressed in Format CCYYMMDD. +claim.AccidentDate.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period: EndSegment(sw); } //2300 DTP 452 (dental) Date Appliance Placement. Situational. Values can be overriden in loop 2400 for individual service items, but we don't support that. if(claim.OrthoDate.Year>1880) { sw.Write("DTP"+s +"452"+s//DTP01 3/3 Date/Time Qualifier: 452=Appliance Placement. +"D8"+s//DTP02 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD. +claim.OrthoDate.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period: EndSegment(sw); } //2300 DTP 472 (dental) Service Date. Not used if predeterm. if(claim.ClaimType!="PreAuth") { if(claim.DateService.Year>1880) { sw.Write("DTP"+s +"472"+s//DTP01 3/3 Date/Time Qualifier: 472=Service. +"D8"+s//DTP02 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD. +claim.DateService.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period: EndSegment(sw); } } //2300 DTP 050 (dental) Repricer Received Date. Not supported. } #endregion Claim DTP #region Claim DN CL1 if(medType==EnumClaimMedType.Dental) { //2300 DN1: Orthodontic Total Months of Treatment. if(claim.IsOrtho) { sw.Write("DN1"+s +s//DN101 1/15 Quantity: Total months of orthodontic treatment. Not used because no field yet in OD. +claim.OrthoRemainM.ToString());//DN102 1/15 Quantity: Number of treatment months remaining. EndSegment(sw);//DN103 is not used and DN104 is situational but we do not use it. } //2300 DN2: Tooth Status. Missing teeth. List<string> missingTeeth=ToothInitials.GetMissingOrHiddenTeeth(initialList); bool doSkip; int countMissing=0; for(int j=0;j<missingTeeth.Count;j++) { //if the missing tooth is missing because of an extraction being billed here, then exclude it //still needed, even though missing teeth are not based on procedures any longer doSkip=false; for(int p=0;p<claimProcs.Count;p++) { proc=Procedures.GetProcFromList(procList,claimProcs[p].ProcNum); procCode=ProcedureCodes.GetProcCode(proc.CodeNum); if(procCode.PaintType==ToothPaintingType.Extraction && proc.ToothNum==missingTeeth[j]) { doSkip=true; break; } } if(doSkip) { continue; } countMissing++; if(countMissing>35) {//segment max use 35 continue; } sw.Write("DN2"+s +missingTeeth[j]+s//DN201 1/50 Reference Identification: Tooth number. +"M"+s//DN202: M=Missing, I=Impacted, E=To be extracted. +s//DN203 1/15 Quantity: Not used. +s//DN204 2/3 Date Time Period Format Qualifier: Not used. +s//DN205 1/35 Date Time Period: Not used. +"JP");//DN206 1/3 Code List Qualifier Code: Required. JP=JP Universal National Tooth Designation System. EndSegment(sw); } } if(medType==EnumClaimMedType.Institutional) { //2300 CL1: Institutional Claim Code. Required sw.Write("CL1"+s +claim.AdmissionTypeCode+s//CL101 1/1 Admission Type Code: Validated. +claim.AdmissionSourceCode+s//CL102 1/1 Admission Source Code: Required for inpatient services. Validated. +claim.PatientStatusCode);//CL103 1/2 Patient Status Code: Validated. EndSegment(sw);//CL104 1/1 Nursing Home Residential Status Code: Not used. } #endregion Claim DN CL1 #region Claim PWK //2300 PWK: (medical,institutional,dental) Claim Supplemental Information. Paperwork. Used to identify attachments. /*if(IsTesia(clearhouse) && claim.Attachments.Count>0) {//If Tesia and has attachments sw.Write("PWK"+s +"OZ"+s//PWK01: ReportTypeCode. OZ=Support data for claim. +"EL"+s//PWK02: Report Transmission Code. EL=Electronic +s+s//PWK03 and 04: not used +"AC"+s//PWK05: Identification Code Qualifier. AC=Attachment Control Number +"TES"+claim.ClaimNum.ToString());//PWK06: Identification Code. EndSegment(sw); }*/ //If Attachment ID # is present but no attachment flag, then sending is blocked. //No other validation is done. However, warnings are displayed if: //Warning if attachments are listed as Mail even though we are sending electronically. //Warning if any PWK segments are needed, and there is no ID code. //PWK can repeat max 10 times. However, we only write one PWK segment, because the user can only enter one Attachment Control Number. string pwk01=" ";//This double blank will never actually get sent because of the trim and if statement around the PWK creation. if(claim.AttachedFlags.Contains("EoB")) { pwk01="EB";//Explaination of Benefits } if(claim.AttachedFlags.Contains("Perio")) { if(medType==EnumClaimMedType.Dental) { pwk01="P6";//Periodontal Charts } else {//Medical and institutional pwk01="OZ";//Support Data for Claim. There is no "P6" nor a code for perio charts. } } if(claim.AttachedFlags.Contains("Misc") || claim.AttachedFlags.Contains("Note") || claim.AttachedImages>0) { pwk01="OZ";//Support Data for Claim } if(claim.Radiographs>0) { pwk01="RB";//Radiology Films } if(claim.AttachedModels>0) { pwk01="DA";//Dental Models } string pwk02=" "; if(IsDentiCal(clearhouse)) { pwk02="FT";//"File Transfer". Might be electronic or mail, but Denti-Cal requires a value of FT here. } else { if(claim.AttachedFlags.Contains("Mail")) { pwk02="BM";//By Mail } else { pwk02="EL";//Elect } } string pwk06=claim.AttachmentID; if(pwk02=="BM" && pwk06=="") {//If By Mail is checked, they will typically leave attachment ID blank, but X12 requires a value, so we make one up. pwk06="00"; } pwk06=Sout(pwk06,80,2); if(pwk01.Trim()!="" && pwk06!="") { sw.Write("PWK"+s +pwk01+s//PWK01 2/2 Report Type Code: +pwk02+s//PWK02 1/2 Report Transmission Code: EL=Electronically Only, BM=By Mail. +s+s//PWK03 and PWK04: Not Used. +"AC"+s//PWK05 1/2 Identification Code Qualifier: AC=Attachment Control Number. +pwk06);//PWK06 2/80 Identification Code: EndSegment(sw);//PWK07 through PWK09 are not used. } #endregion Claim PWK #region Claim CN1 AMT //2300 CN1: (medical,institutional,dental)Contract Information. Situational. We do not use this. //2300 AMT: (institutional) Patient Estimated Amount Due. //2300 AMT: (medical,dental) Patient Amount Paid. Situational. We do not use this. if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Dental) { //sw.Write("AMT"+s // +"F5"+s//AMT01 1/3 Amount Qualifier Code: F5=Patient Paid Amount. // +"0");//AMT02 1/18 Monetary Amount: We don't track this information very well so we always put zero. //EndSegment(sw);//AMT03 is not used. } #endregion Claim CN1 AMT #region Claim REF if(medType==EnumClaimMedType.Dental) { //2300 REF: G3 (dental) Predetermination Identification. Situational. Required when sending claim for previously predetermined services. Do not send prior authorization number here. if(claim.PreAuthString!="") {//validated to be empty for medical and inst sw.Write("REF"+s +"G3"+s//REF01 2/3 G3=Predetermination of Benefits Identification Number. +Sout(claim.PreAuthString,50));//REF02 1/50 Predeterm of Benfits Identifier. EndSegment(sw);//REF03 and REF04 are not used. } } //2300 REF: 4N (medical,institutional,dental) Service Authorization Exception Code. Situational. Required if services were performed without authorization. //todo: ServiceAuthException //2300 REF: F5 (medical) Mandatory Medicare (Section 4081) Crossover Indicator. Situational. Required when submitter is Medicare and the claim is a Medigap or COB crossover claim. We do not use. //2300 REF: EW (medical) Mammography Certification Number. Situational. We do not use. //2300 REF: F8 (medical,institutional,dental) Payer Claim Control Number: Situational. Required if this is a replacement or void claim. Might not be required for corrected, but we require anyway since it is required in 4010. //aka Original Document Control Number/Internal Control Number (DCN/ICN). //aka Transaction Control Number (TCN). //aka Claim Reference Number. //Seems to be required by Medicaid when voiding a claim or resubmitting a claim by setting the CLM05-3. if(claim.CorrectionType!=ClaimCorrectionType.Original || claim.UniformBillType.Length>2 && (claim.UniformBillType.Substring(2,1)=="6" || claim.UniformBillType.Substring(2,1)=="7" || claim.UniformBillType.Substring(2,1)=="8")) { //correction, replacement or void. sw.Write("REF"+s +"F8"+s//REF01 2/3 Reference Identification Qualifier: F8=Original Reference Number. +Sout(claim.OrigRefNum,50));//REF02 1/50 Reference Identification: Payer Claim Control Number. EndSegment(sw);//REF03 and REF04 are not used. } //2300 REF: 9F (medical,institutional,dental) Referral Number. Situational. Required when a referral number is assigned by the payer or Utilization Management Organization (UMO) AND a referral is involved. if(claim.RefNumString!="") { sw.Write("REF"+s +"9F"+s//REF01 2/3 Reference Identification Qualifier: 9F=Referral Number. +Sout(claim.RefNumString,30));//REF02 1/50 Reference Identification: EndSegment(sw);//REF03 and REF04 are not used. } //2300 REF: X4 (medical) Clinical Laboratory Improvement Amendment (CLIA) Number. Situational. We do not use. //2300 REF: G1 (medical,institutional,dental) Prior Authorization. Situational. Do not report predetermination of benefits id number here. G1 and G3 were muddled in 4010. if(claim.PriorAuthorizationNumber!="") { sw.Write("REF"+s +"G1"+s//REF01 2/3 Reference Identification Qualifier: G1=Prior Authorization Number. +Sout(claim.PriorAuthorizationNumber,50));//REF02 1/50 Reference Identification: Prior Authorization Number. EndSegment(sw);//REF03 and REF04 are not used. } //2300 REF: 9A (medical,institutional,dental) Repriced Claim Number. Situational. We do not use. //2300 REF: 9C (medical,institutional,dental) Adjusted Repriced Claim Number. Situational. We do not use. //2300 REF: D9 (medical,institutional,dental) Claim Identifier For Transmission Intermediaries. Situational. if(IsClaimConnect(clearhouse)) { //Since this information has only been requested by ClaimConnect and is optional in the specification, we should only add specific clearinghouses here when requested. sw.Write("REF"+s +"D9"+s//REF01 2/3 Reference Identification Qualifier: D9=Claim Number. +Sout(claim.ClaimIdentifier,20));//REF02 1/50 Reference Identification: Value Added Network Trace Number. From specification, maximum of 20 characters even though there is space for 50. EndSegment(sw);//REF03 and REF04 are not used. } //2300 REF: LX (medical,institutional) Investigational Device Exemption Number. Situational. Required for FDA IDE. //2300 REF: LU (institutional) Auto Accident State. Situational. Seems to me to be a duplicate of the info in CLM11. //2300 REF: EA (medical,institutional) Medical Record Number. Situational. We do not use. //2300 REF: P4 (medical,institutional) Demonstration Project Identifier. Situational. We do not use. Seems very unimportant. //2300 REF: G4 (institutional) Peer Review Organization (PRO) Approval Number. Situational. We do not use. //2300 REF: 1J (medical) Care Plan Oversight. Situational. We do not use. #endregion Claim REF #region Claim K3 NTE CRx //2300 K3: File info (medical,institutional,dental). Situational. We do not use this. //NTE loops------------------------------------------------------------------------------------------------------ //2300 NTE: (medical,institutional,dental) Claim Note. Situational. A number of NTE01 codes other than 'ADD', which we don't support. string note=""; if(claim.AttachmentID!="" && !claim.ClaimNote.StartsWith(claim.AttachmentID)) { note=claim.AttachmentID+" "; } note+=claim.ClaimNote; if(note!="") { sw.Write("NTE"+s +"ADD"+s//NTE01 3/3 Note Reference Code: ADD=Additional information. +Sout(note,80));//NTE02 1/80 Description: EndSegment(sw); } //2300 NTE: (institutional) Billing Note. Situational. We do not use. //CRx loops------------------------------------------------------------------------------------------------------ //2300 CR1: LB (medical) Ambulance Transport Information. Situational. We do not use. //2300 CR2: (medical) Spinal Manipulation Service Information. Situational. We do not use. //2300 CRC: (medical) Ambulance Certification. Situational. We do not use. //2300 CRC: (medical) Patient Condition Information Vision. Situational. We do not use. //2300 CRC: (medcial) Homebound Indicator. Situational. We do not use. //2300 CRC: (medical,institutional) EPSDT Referral. Situational. Required on EPSDT claims when the screening service is being billed in this claim. We do not use. #endregion Claim K3 NTE CRx #region Claim HI HCP //HI loops------------------------------------------------------------------------------------------------------- List<string> diagnosisList=new List<string>();//princDiag will always be the first element. if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Institutional){ for(int j=0;j<claimProcs.Count;j++) { proc=Procedures.GetProcFromList(procList,claimProcs[j].ProcNum); if(proc.DiagnosticCode=="") { continue; } if(proc.IsPrincDiag) { if(diagnosisList.Contains(proc.DiagnosticCode)) { diagnosisList.Remove(proc.DiagnosticCode); } diagnosisList.Insert(0,proc.DiagnosticCode);//princDiag always goes first. There will always be one. } else {//not princDiag if(!diagnosisList.Contains(proc.DiagnosticCode)) { diagnosisList.Add(proc.DiagnosticCode); } } } } //2300 HI: BK (medical,dental) Health Care Diagnosis Code. Situational. For OMS or anesthesiology. //todo: validate at least one diagnosis if(medType==EnumClaimMedType.Institutional) { sw.Write("HI"+s +"BK"+isa16//HI01-1 1/3 Code List Qualifier Code: BK=ICD-9 Principal Diagnosis. +Sout(diagnosisList[0].Replace(".",""),30));//HI01-2 1/30 Industry Code: Diagnosis code. No periods. EndSegment(sw); } else if(medType==EnumClaimMedType.Medical) { sw.Write("HI"+s +"BK"+isa16//HI01-1 1/3 Code List Qualifier Code: BK=ICD-9 Principal Diagnosis. +Sout(diagnosisList[0].Replace(".",""),30));//HI01-2 1/30 Industry Code: Diagnosis code. No periods. for(int j=1;j<diagnosisList.Count;j++) { if(j>11) {//maximum of 12 diagnoses break; } sw.Write(s//this is the separator from the _previous_ field. +"BF"+isa16//HI0#-1 1/3 Code List Qualifier Code: BF=ICD-9 Diagnosis +Sout(diagnosisList[j].Replace(".",""),30));//HI0#-2 1/30 Industry Code: Diagnosis code. No periods. } EndSegment(sw); } //2300 HI: BP (medical) Anesthesia Related Procedure. Situational. We do not use. //2300 HI: BJ (institutional) Admitting Diagnosis. Situational. Required for inpatient admission. We do not use. //2300 HI: PR (institutional) Patient's Reason for Visit. Situational. Required for outpatient visits. if(medType==EnumClaimMedType.Institutional) { sw.Write("HI"+s +"PR"+isa16//HI01-1 1/3 Code List Qualifier Code: PR=ICD-9 Patient's Reason for Visit. +Sout(diagnosisList[0].Replace(".",""),30));//HI01-2 1/30 Industry Code: No periods. This is not really principal diagnosis but is close to the same, so someday we will add this field to claim. EndSegment(sw); } //2300 HI: BN (institutional) External Cause of Injury. Situational. We do not use. //2300 HI: (institutional) Diagnosis Related Group (DRG) Information. Situational. We do not use. For inpatient hospital under DRG contract. //2300 HI: BF (institutional) Other Diagnosis Information. Situational. We do not use. When other conditions coexist or develop. //2300 HI: BR (institutional) Principal Procedure Information. Situational. We do not use. Required on inpatient claims when a procedure was performed. //2300 HI: BQ (institutional) Other Procedure Information. Situational. We do not use. Inpatient claims for additional procedures. //2300 HI: BI (institutional) Occurence Span Information. Situational. We do not use. For an occurence span code. //2300 HI: BH (institutional) Occurence Information. Situational. We do not use. For an occurence code. //2300 HI: BE (institutional) Value Information. Situational. We do not use. For a value code. //2300 HI: BG (medical,institutional) Condition Information. Situational. We do not use. For a condition code. //2300 HI: TC (institutional) Treatment Code Information. Situational. We do not use. When home health agencies need to report plan of treatment information under contracts. //2300 HCP: (medical,institutional,dental) Claim Pricing/Repricing Information. Situational. We do not use. #endregion Claim HI HCP bool sendFacilityNameAndAddress=false; if(medType==EnumClaimMedType.Medical) { //Code added to send the segment below, but no logic here for sending yet, so it is never sent. } else if(medType==EnumClaimMedType.Institutional) { //Code added to send the segment below, but no logic here for sending yet, so it is never sent. } else if(medType==EnumClaimMedType.Dental) { if(claim.PlaceService!=PlaceOfService.Office) { if(IsClaimConnect(clearhouse)) { //Osvaldo Ferrer, VIP account manager for DentalXChange, says we need the segment whenever the place of service is not office. sendFacilityNameAndAddress=true; } else {//for other clearinghouses, the X12 specs say that we don't send it if it's the same as the billing prov. //and since we always set it the same as the billing prov, we shouldn't send it. } } } Provider facilityProv=billProv;//If this provider changes in the future, then the validation section will also need to be updated. string facilityAddress1=billingAddress1; string facilityAddress2=billingAddress2; string facilityCity=billingCity; string facilityState=billingState; string facilityZip=billingZip; //For medical, instititional, and dental, sending facility NPI must be for an organization (non-person). if(!facilityProv.IsNotPerson) {//Validated also sendFacilityNameAndAddress=false; } provTreat=Providers.GetProv(claim.ProvTreat); #region 2310 Claim Providers (medical) //Since order might be important, we have to handle medical, institutional, and dental separately. if(medType==EnumClaimMedType.Medical) { //2310A NM1: DN/P3 (medical) Referring Provider Name. Situational. WriteNM1_DN(sw,claim.ReferringProv); //2310A REF: (medical) Referring Provider Secondary Identification. Situational. We do not use. //Always included for Emdeon Medical, because Emdeon Medical will automatically remove this segment if the payer does not want it //Some payers reject if not specified, even when the claim.ProvTreat=claim.ProvBill. For example, Texas Medicaid. //if(claim.ProvTreat!=claim.ProvBill || IsEmdeonMedical(clearhouse)) { //2310B NM1: 82 (medical) Rendering Provider Name. Required when treating provider is different from billing provider. WriteNM1Provider("82",sw,provTreat); //2310B PRV: PE (medical) Rendering Provider Specialty Information. Situational. WritePRV_PE(sw,provTreat); //2310B REF: (medical) Rendering Provider Secondary Identification. Situational. We do not use. //2310C NM1: 77 (medical) Service Facility Location Name. Conditions different than 4010. //Not supposed to send if same location as 2010AA Billing Provider, but some clearinghouses want this segment anyway. if(sendFacilityNameAndAddress) { sw.Write("NM1"+s +"77"+s//NM101 2/3 Entity Identifier Code: 77=Service Location. +"2"+s//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity. +Sout(facilityProv.LName,60)+s//NM103 1/60 Name Last or Organization Name: Laboratory or Facility Name. +s//NM104 1/35 Name First: Not used. +s//NM105 1/25 Name Middle: Not used. +s//NM106 1/10 Name Prefix: Not used. +s//NM107 1/10 Name Suffix: Not used. +"XX"+s//NM108 1/2 Identification Code Qualifier: XX=NPI. +Sout(facilityProv.NationalProvID,80));//NM109 2/80 Identification Code: Laboratory or Facility Identifier. Validated. EndSegment(sw);//NM110 through NM112 not used. //2310C N3: (medical) Service Facility Location Address. sw.Write("N3"+s+Sout(facilityAddress1,55));//N301 1/55 Address Information: Laboratory or Facility Address Line. if(facilityAddress2!="") { sw.Write(s+Sout(facilityAddress2,55));//N302 1/55 Address Information: Laboratory or Facility Address Line 2. Only required when there is a secondary address line. } EndSegment(sw); //2310C N4: (medical) Service Facility Location City, State, Zip Code. sw.Write("N4"+s +Sout(facilityCity,30)+s//N401 2/30 City Name: Laboratory or Facility City Name. +Sout(facilityState,2,2)+s//N402 2/2 State or Provice Code: Laboratory or Facility State or Province Code. +Sout(facilityZip.Replace("-",""),15));//N403 3/15 Postal Code: Laboratory or Facility Postal Zone or ZIP Code. EndSegment(sw);//N404 through N407 are either not used or only required when outside of the United States. //2310C REF: (medical) Service Facility Location Secondary Identification. Situational. We do not use this. //2310C PER: (medical) Service Facility Contact Information. Situational. Required for property and casualty claims. We do not use. } //2310D NM1: (medical) Supervising Provider Name. Situational. We do not use. //2310D REF: (medical) Supervising Provider Secondary Identification. Situational. We do not use. //2310E NM1: (medical) Ambulance Pick-up Location. Situational. We do not use. //2310E N3: (medical) Ambulance Pick-up Location Address. We do not use. //2310E N4: (medical) Ambulance Pick-up Location City, State, Zip Code. We do not use. //2310F NM1: (medical) Ambulance Drop-off Location. Situational. We do not use. //2310F N3: (medical) Ambulance Drop-off Location Address. We do not use. //2310F N4: (medical) Ambulance Drop-off Location City, State, Zip Code. We do not use. } #endregion 2310 Claim Providers (medical) #region 2310 Claim Providers (inst) if(medType==EnumClaimMedType.Institutional) { //2310A NM1: 71 (institutional) Attending Provider Name. Situational. Always a person according to the specification (cannot be non-person). WriteNM1Provider("71",sw,provTreat.FName,provTreat.MI,provTreat.LName,provTreat.NationalProvID,false); //2310A PRV: AT (institutional) Attending Provider Specialty Information. Situational. sw.Write("PRV"+s +"AT"+s//PRV01 1/3 Provider Code: AT=Attending. +"PXC"+s//PRV02 2/3 Reference Identification Qualifier: PXC=Health Care Provider Taxonomy Code. +X12Generator.GetTaxonomy(provTreat));//PRV03 1/50 Reference Identification: Provider Taxonomy Code. EndSegment(sw);//PRV04 through PRV06 are not used. //2310A REF: (institutional) Attending Provider Secondary Identification. Situational. //2310B NM1: 72 (institutional) Operating Physician Name. Situational. For surgical procedure codes. //2310C REF: ZZ (institutional) Secondary Physician Secondary Identification. Situational. //2310C NM1: ZZ (institutional) Other Operating Physician Name. Situational. //2310C REF: ZZ (institutional) Other Operating Physician Secondary Identification. Situational. //2310D NM1: 82 (institutional) Rendering Provider Name. Situational. If different from attending provider AND when regulations require both facility and professional components. //2310D REF: ZZ (institutional) Rendering Provider Secondary Identificaiton. Situational. //2310E NM1: 77 (institutional) Service Facility Location Name. Conditions different than 4010. //Not supposed to send if same location as 2010AA Billing Provider, but some clearinghouses want this segment anyway. if(sendFacilityNameAndAddress) { sw.Write("NM1"+s +"77"+s//NM101 2/3 Entity Identifier Code: 77=Service Location. +"2"+s//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity. +Sout(facilityProv.LName,60)+s//NM103 1/60 Name Last or Organization Name: Laboratory or Facility Name. +s//NM104 1/35 Name First: Not used. +s//NM105 1/25 Name Middle: Not used. +s//NM106 1/10 Name Prefix: Not used. +s//NM107 1/10 Name Suffix: Not used. +"XX"+s//NM108 1/2 Identification Code Qualifier: XX=NPI. +Sout(facilityProv.NationalProvID,80));//NM109 2/80 Identification Code: Laboratory or Facility Primary Identifier. Validated. EndSegment(sw);//NM110 through NM112 not used. //2310E N3: (institutional) Service Facility Location Address. sw.Write("N3"+s+Sout(facilityAddress1,55));//N301 1/55 Address Information: Laboratory or Facility Address Line. if(facilityAddress2!="") { sw.Write(s+Sout(facilityAddress2,55));//N302 1/55 Address Information: Laboratory or Facility Address Line 2. Only required when there is a secondary address line. } EndSegment(sw); //2310E N4: (institutional) Service Facility Location City, State, Zip Code. sw.Write("N4"+s +Sout(facilityCity,30)+s//N401 2/30 City Name: Laboratory or Facility City Name. +Sout(facilityState,2,2)+s//N402 2/2 State or Provice Code: Laboratory or Facility State or Province Code. +Sout(facilityZip.Replace("-",""),15));//N403 3/15 Postal Code: Laboratory or Facility Postal Zone or ZIP Code. EndSegment(sw);//N404 through N407 are either not used or only required when outside of the United States. //2310E REF: ZZ (institutional) Service Facility Location Secondary Identificiation. Situational. We do not use. } //2310F NM1: DN (institutional) Referring Provider Name. Situational. Required when referring provider is different from attending provider. if(claim.ReferringProv!=claim.ProvTreat) { WriteNM1_DN(sw,claim.ReferringProv); } //2310F REF: (institutional) Referring Provider Secondary Identification. Situational. } #endregion 2310 Claim Providers (inst) #region 2310 Claim Providers (dental) if(medType==EnumClaimMedType.Dental) { //2310A NM1: DN (dental) Referring Provider Name. Situational. WriteNM1_DN(sw,claim.ReferringProv); //2310A PRV: (dental) Referring Provider Specialty Information. Situational. //2310A REF: G2 (dental) Referring Provider Secondary Identification. Situational. bool sendClaimTreatProv=false; if(claim.ProvTreat!=claim.ProvBill) { //Emdeon will reject the claim if this segment is the same as the billing provider for all claims in the batch. sendClaimTreatProv=true;//Standard X12 behavior to only include the treating provider if it is different than the billing provider. } //The following clearinghouses always want the claim treating provider, even if it is the same as the billing provider. if(IsOfficeAlly(clearhouse)) { sendClaimTreatProv=true; } if(sendClaimTreatProv) { //2310B NM1: 82 (dental) Rendering Provider Name. Situational. Only required if different from the billing provider. WriteNM1Provider("82",sw,provTreat); //2310B PRV: PE (dental) Rendering Provider Specialty Information. WritePRV_PE(sw,provTreat); //2310B REF: (dental) Rendering Provider Secondary Identification. Situational. Not required because we always send NPI. Max repeat of 4. if(IsClaimConnect(clearhouse) || IsEmdeonDental(clearhouse)) { //The state licence number can be anywhere between 4 and 14 characters depending on state, and most states have more than one state license format. //Therefore, we only validate that the state license is present or not. if(provTreat.StateLicense!="") { sw.Write("REF"+s +"0B"+s//REF01 2/3 Reference Identification Qualifier: 0B=State License Number. +Sout(provTreat.StateLicense,50));//REF02 1/50 Reference Identification: EndSegment(sw);//REF03 and REF04 are not used. } } if(IsEmdeonDental(clearhouse)) { //Always required by Emdeon Dental. WriteProv_REFG2orLU(sw,provTreat,carrier.ElectID); } } //2310C NM1: 77 (dental) Service Facility Location Name. Conditions different than 4010. //Not supposed to send if same location as 2010AA Billing Provider, but ClaimConnect wants this segment anyway. if(sendFacilityNameAndAddress) { sw.Write("NM1"+s +"77"+s//NM101 2/3 Entity Identifier Code: 77=Service Location. +"2"+s//NM102 1/1 Entity Type Qualifier: 2=Non-Person Entity. +Sout(facilityProv.LName,60)+s//NM103 1/60 Name Last or Organization Name: Laboratory or Facility Name. +s//NM104 1/35 Name First: Not used. +s//NM105 1/25 Name Middle: Not used. +s//NM106 1/10 Name Prefix: Not used. +s//NM107 1/10 Name Suffix: Not used. +"XX"+s//NM108 1/2 Identification Code Qualifier: XX=NPI. +Sout(facilityProv.NationalProvID,80));//NM109 2/80 Identification Code: Laboratory or Facility Identifier. Validated. EndSegment(sw);//NM110 through NM112 not used. //2310C N3: (dental) Service Facility Location Address. sw.Write("N3"+s+Sout(facilityAddress1,55));//N301 1/55 Address Information: Laboratory or Facility Address Line. if(facilityAddress2!="") { sw.Write(s+Sout(facilityAddress2,55));//N302 1/55 Address Information: Laboratory or Facility Address Line 2. Only required when there is a secondary address line. } EndSegment(sw); //2310C N4: (dental) Service Facility Location City, State, Zip Code. sw.Write("N4"+s +Sout(facilityCity,30)+s//N401 2/30 City Name: Laboratory or Facility City Name. +Sout(facilityState,2,2)+s//N402 2/2 State or Provice Code: Laboratory or Facility State or Province Code. +Sout(facilityZip.Replace("-",""),15));//N403 3/15 Postal Code: Laboratory or Facility Postal Zone or ZIP Code. EndSegment(sw);//N404 through N407 are either not used or only required when outside of the United States. //2310C REF: (dental) Service Facility Location Secondary Identification. Situational. We do not use this. } //2310D NM1: (dental) Assistant Surgeon Name. Situational. We do not support. //2310D PRV: (dental) Assistant Surgeon Specialty Information. We do not support. //2310D REF: (dental) Assistant Surgeon Secondary Identification. We do not support. //2310E NM1: (dental) Supervising Provider Name. Situational. We do not support. //2310E REF: (dental) Supervising Provider Secondary Identification. Situational. We do not support. } #endregion 2310 Claim Providers (dental) #region 2320 Other subscriber information List<double> listProcWriteoffAmts=new List<double>(); List<double> listProcDeductibleAmts=new List<double>(); List<double> listProcPaidOtherInsAmts=new List<double>(); bool hasAdjForOtherPlans=false; //2320 Other subscriber------------------------------------------------------------------------------------------ if(otherPlan!=null) { //2320 SBR: Other Subscriber Information. Situational. sw.Write("SBR"+s); sw.Write((claimIsPrimary?"S":"P")+s);//SBR01 1/1 Payer Responsibility Sequence Number Code: When the claim is primary then the other insurance is secondary, and vice versa. sw.Write(GetRelat(claim.PatRelat2)+s//SBR02 2/2 Individual Relationship Code: +Sout(otherPlan.GroupNum,50)+s);//SBR03 1/50 Reference Identification: //SBR04 1/60 Name: Situational. Required when SBR03 is not specified. if(otherPlan.GroupNum!="") { sw.Write(s); } else { sw.Write(Sout(otherPlan.GroupName,60)+s); } sw.Write(s//SBR05 1/3 Insurance Type Code: Situational. Required when the payer in loop 2330B is Medicare and Medicare is not the primary payer. Medical and Dental only. TODO: implement. +s//SBR06 1/1 Coordination of Benefits Code: Not used. +s//SBR07 1/1 Yes/No Condition or Response Code: Not Used. +s//SBR08 2/2 Employment Status Code: Not Used. +GetFilingCode(otherPlan));//SBR09 1/2 Claim Filing Indicator Code: 12=PPO,17=DMO,BL=BCBS,CI=CommercialIns,FI=FEP,HM=HMO. Will no longer be required when HIPPA National Plan ID is mandated. EndSegment(sw); double claimWriteoffAmt=0; double claimDeductibleAmt=0; double claimPaidOtherInsAmt=0; double claimPatientPortionAmt=0; for(int j=0;j<claimProcs.Count;j++) {//Claim procs for this claim double procWriteoffAmt=0; double procDeductibleAmt=0; double procPaidOtherInsAmt=0; for(int k=0;k<claimProcList.Count;k++) {//All claim procs for patient if(ClaimProcs.IsValidClaimAdj(claimProcList[k],claimProcs[j].ProcNum,claimProcs[j].InsSubNum)) {//Adjustment due to other insurance plans. hasAdjForOtherPlans=true; claimWriteoffAmt+=claimProcList[k].WriteOff; claimDeductibleAmt+=claimProcList[k].DedApplied; claimPaidOtherInsAmt+=claimProcList[k].InsPayAmt; procWriteoffAmt+=claimProcList[k].WriteOff; procDeductibleAmt+=claimProcList[k].DedApplied; procPaidOtherInsAmt+=claimProcList[k].InsPayAmt; } } listProcWriteoffAmts.Add(procWriteoffAmt); listProcDeductibleAmts.Add(procDeductibleAmt); listProcPaidOtherInsAmts.Add(procPaidOtherInsAmt); double procPatientPortionAmt=Math.Max(0,claimProcs[j].FeeBilled-listProcWriteoffAmts[j]-listProcDeductibleAmts[j]-listProcPaidOtherInsAmts[j]); claimPatientPortionAmt+=procPatientPortionAmt; } //If sending the primary claim, then hasAdjForOtherPlans will be false, because all claimprocs for any other plans (secondary) will be estimates. //If sending the secondary claim, then hasAdjForOtherPlans will be true, because the primary claimprocs will be received. //This strategy works for dental and medical plans in any combination: D, M, DD, DM, MD, MM if(hasAdjForOtherPlans) { //2320 CAS: (medical,institutional,dental) Claim Level Adjustments. Situational. We use this to show patient responsibility, because the adjustments here plus AMT D below must equal claim amount in CLM02 for Emdeon. //Claim Adjustment Reason Codes can be found on the Washington Publishing Company website at: http://www.wpc-edi.com/reference/codelists/healthcare/claim-adjustment-reason-codes/ if(claimWriteoffAmt>0) { sw.Write("CAS"+s +"CO"+s//CAS01 1/2 Claim Adjustment Group Code: CO=Contractual Obligations. +"45"+s//CAS02 1/5 Claim Adjustment Reason Code: 45=Charge exceeds fee schedule/maximum allowable or contracted/legislated fee arrangement. +AmountToStrNoLeading(claimWriteoffAmt));//CAS03 1/18 Monetary Amount: EndSegment(sw); } if(claimDeductibleAmt>0 || claimPatientPortionAmt>0) { sw.Write("CAS"+s +"PR");//CAS01 1/2 Claim Adjustment Group Code: PR=Patient Responsibility. if(claimDeductibleAmt>0) { sw.Write(s//end of previous field +"1"+s//CAS02 1/5 Claim Adjustment Reason Code: 1=Deductible. +AmountToStrNoLeading(claimDeductibleAmt)+s//CAS03 1/18 Monetary Amount: +"1");//CAS04 1/15 Quantity: } if(claimPatientPortionAmt>0) { sw.Write(s//end of previous field +"3"+s//CAS02 or CAS05 1/5 Claim Adjustment Reason Code: 3=Co-payment Amount. +AmountToStrNoLeading(claimPatientPortionAmt));//CAS03 or CAS06 1/18 Monetary Amount: } EndSegment(sw); } //2320 AMT: D (medical,institutional,dental) COB Payer Paid Amount. Situational. Required when the claim has been adjudicated by payer in loop 2330B. sw.Write("AMT"+s +"D"+s//AMT01 1/3 Amount Qualifier Code: D=Payor Amount Paid. +AmountToStrNoLeading(claimPaidOtherInsAmt));//AMT02 1/18 Monetary Amount: EndSegment(sw);//AMT03 Not used. //2320 AMT: EAF (medical,institutional,dental) Remaining Patient Liability. Situational. Required when claim has been adjudicated by payer in loop 2330B. sw.Write("AMT"+s +"EAF"+s//AMT01 1/3 Amount Qualifier Code: EAF=Amount Owed. +AmountToStrNoLeading(claimPatientPortionAmt));//AMT02 1/18 Monetary Amount: EndSegment(sw);//AMT03 Not used. //2320 AMT: A8 (medical,institutional,dental) COB Total Non-Covered Amount. Situational. Can be set when primary claim was not adjudicated. We do not use. } if(IsClaimConnect(clearhouse)) { //2320 DMG: Other subscriber demographics. This segment is not allowed in X12. ClaimConnect requires this information anyway. They will fix their validator later. sw.Write("DMG"+s +"D8"+s//DMG01 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD. +otherSubsc.Birthdate.ToString("yyyyMMdd")+s//DMG02 1/35 Date Time Period: Birthdate. The othet subscriber birtdate is validated. +GetGender(otherSubsc.Gender));//DMG03 1/1 Gender Code: F=Female, M=Male, U=Unknown. EndSegment(sw); } //2320 OI: (medical,institutional,dental) Other Insurance Coverage Information. sw.Write("OI"+s +s//OI01 1/2 Claim Filing Indicator Code: Not used. +s//OI02 2/2 Claim Submission Reason Code: Not used. +(otherSub.AssignBen?"Y":"N")+s//OI03 1/1 Yes/No Condition or Response Code: +s//OI04 1/1 Patient Signature Source Code: Not used in institutional or dental. Situational in medical, but we do not support. +s//OI05 1/1 Provider Agreement Code: Not used. +(otherSub.ReleaseInfo?"Y":"I"));//OI06 1/1 Release of Information Code: EndSegment(sw); //2320 MIA: (institutional) Inpatient Adjudication Information. Situational. We do not support. //2320 MOA: (medical,institutional,dental) Outpatient Adjudication Information. Situational. For reporting remark codes from ERAs. We don't support. #endregion 2320 Other subscriber information #region 2330A Other subscriber Name //2330A NM1: IL (medical,institutional,dental) Other Subscriber Name. sw.Write("NM1"+s +"IL"+s//NM101 2/3 Entity Identifier Code: IL=Insured or Subscriber. +"1"+s//NM102 1/1 Entity Type Qualifier: 1=Person. +Sout(otherSubsc.LName,60)+s//NM103 1/60 Name Last or Organization Name: Never blank, because validated in the patient edit window when a patient is added/edited. +Sout(otherSubsc.FName,35)+s//NM104 1/35 Name First: +Sout(otherSubsc.MiddleI,25)+s//NM105 1/25 Middle Name: +s//NM106 1/10 Name Prefix: Not used. +s//NM107 1/10 Name Suffix: Situational. No corresponding field in OD. +"MI"+s//NM108 1/2 Identification Code Qualifier: MI=Member Identification Number. +Sout(otherSub.SubscriberID,80));//NM109 2/80 Identification Code: EndSegment(sw);//NM110 through NM112 are not used. //2330A N3: Other Subscriber Address. sw.Write("N3"+s+Sout(otherSubsc.Address,55));//N301 1/55 Address Information: if(otherSubsc.Address2!="") { sw.Write(s+Sout(otherSubsc.Address2,55)); } EndSegment(sw);//N302 1/55 Address Information: //2330A N4: (medical,institutional,dental) Other Subscriber City, State, Zip Code. sw.Write("N4"+s +Sout(otherSubsc.City,30)+s//N401 2/30 City Name: +Sout(otherSubsc.State,2,2)+s//N402 2/2 State or Province Code: +Sout(otherSubsc.Zip.Replace("-",""),15));//N403 3/15 Postal Code: EndSegment(sw);//N404 through N407 are either not required or are required when the address is outside of the United States. //2330A REF: (medical,institutional,dental) Other Subscriber Secondary Identification. Situational. Not supported. #endregion 2330A Other subscriber Name #region Other payer //2330B NM1: (medical,institutional,dental) Other Payer Name. sw.Write("NM1"+s +"PR"+s//NM101 2/3 Entity Code Identifier: PR=Payer. +"2"+s);//NM102 1/1 Entity Type Qualifier: 2=Non-Person. //NM103 1/60 Name Last or Organization Name: if(IsEMS(clearhouse)) { long employerNum=0; if(otherPlan!=null) { employerNum=otherPlan.EmployerNum; } //This is a special situation requested by EMS. This tacks the employer onto the end of the carrier. sw.Write(Sout(otherCarrier.CarrierName,30)+"|"+Sout(Employers.GetName(employerNum),30)+s); } else if(IsDentiCal(clearhouse)) { sw.Write("DENTICAL"+s); } else { sw.Write(Sout(otherCarrier.CarrierName,60)+s); } sw.Write(s//NM104 1/35 Name First: Not used. +s//NM105 1/25 Name Middle: Not used. +s//NM106 1/10 Name Prefix: Not used. +s//NM107 1/10 Name Suffix: Not used. +"PI"+s);//NM108 1/2 Identification Code Qualifier: PI=Payor Identification. XV must be used after national plan ID mandated. sw.Write(Sout(GetCarrierElectID(otherCarrier,clearhouse),80,2));//NM109 2/80 Identification Code: EndSegment(sw);//NM110 through NM112 not used. //2230B N3: (medical,institutional,dental) Other Payer Address. Situational. We don't support. //2330B N4: (medical,institutional,dental) Other Payer City, State, Zip Code. Situational. We don't support. //2330B DTP: 573 (medical,institutional,dental) Claim Check or Remittance Date. Situational. Claim Paid date. if(hasAdjForOtherPlans) { DateTime datePaidOtherIns=DateTime.Today; DateTime dtThisCP; for(int j=0;j<claimProcs.Count;j++) { dtThisCP=ClaimProcs.GetDatePaid(claimProcList,claimProcs[j].ProcNum,claimProcs[j].PlanNum); if(dtThisCP>datePaidOtherIns) { datePaidOtherIns=dtThisCP; } } //it's a required segment, so always include it. sw.Write("DTP"+s +"573"+s//DTP01 3/3 Date/Time Qualifier: 573=Date Claim Paid. +"D8"+s//DTP02 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD. +datePaidOtherIns.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period: EndSegment(sw); } //2330B REF: (medical,institutional,dental) Other Payer Secondary Identifier. Situational. We do not use. //2330B REF: G1 (medical,institutional,dental) Other Payer Prior Authorization Number. Situational. We do not use. //2330B REF: 9F (medical,institutional,dental) Other Payer Referral Number. Situational. We do not use. //2330B REF: T4 (medical,institutional,dental) Other Payer Claim Adjustment Indicator. Situational. We do not use. //2330B REF: G3 (dental) Other Payer Predetermination Identification. Situational. We do not use. //2230B REF: F8 (medical,institutional,dental) Other Payer Claim Control Number. Situational. We do not use. if(medType==EnumClaimMedType.Medical) { //2330C NM1: (medical) Other Payer Referring Provider. Situational. Only used in crosswalking COBs. We do not use. //2330C REF: (medical) Other Payer Referring Provider Secondary Identification. We do not use. //2330D NM1: 82 (medical) Other Payer Rendering Provider. Situational. Only used in crosswalking COBs. We do not use. //2330D REF: (medical) Other Payer Rendering Provider Secondary Identificaiton. We do not use. //2330E NM1: 77 (medical) Other Payer Service Facility Location. Situational. We do not use. //2330E REF: (medical) Other Payer Service Facility Location Secondary Identification. We do not use. //2330F NM1: DQ (medical) Other Payer Supervising Provider. Situational. We do not use. //2330F REF: (medical) Other Payer Supervising Provider Secondary Identificaiton. We do not use. //2330G NM1: 85 (medical) Other Payer Billing Provider. Situational. We do not use. //2330G REF: (medical) Other Payer Billing Provider Secondary Identification. We do not use. } else if(medType==EnumClaimMedType.Institutional) { //2330C NM1: 71 (institutional) Other Payer Attending Provider. Situational. Only used in crosswalking COBs. We do not use. //2330C REF: (institutional) Other Payer Attending Provider Secondary Identification. We do not use. //2330D NM1: 72 (institutional) Other Payer Operating Physician. Situational. //2330D REF: (institutional) Other Payer Operating Physician Secondary Identificaiton. We do not use. //2330E NM1: ZZ (institutional) Other Payer Other Operating Physician. Situational. We do not use. //2330E REF: (institutional) Other Payer Other Operating Physician Secondary Identificaiton. We do not use. //2330F NM1: 77 (institutional) Other Payer Service Facility Location. Situational. We do not use. //2330F REF: (institutional) Other Payer Service Facility Location Secondary Identification. We do not use. //2330G NM1: 82 (institutional) Other Payer Rendering Provider Name. Situatiuonal. We do not use. //2330G REF: (institutional) Other Payer Rendering Provider Secondary Identificaiton. We do not use. //2330H NM1: DN (institutional) Other Payer Referring Provider. Situational. We do not use. //2330H REF: (institutional) Other Payer Referring Provider Secondary Identificaiton. We do not use. //2330I NM1: 85 (institutional) Other Payer Billing Provider. Situational. We do not use. //2330I REF: (institutional) Other Payer Billing Provider Secondary Identification. We do not use. } else if(medType==EnumClaimMedType.Dental) { //2330C NM1: (dental) Other Payer Referring Provider. Situational. Only used in crosswalking COBs. We do not use. //2330C REF: (dental) Other Payer Referring Provider Secondary Identification. We do not use. //2330D NM1: 82 (dental) Other Payer Rendering Provider. Situational. Only used in crosswalking COBs. We do not use. //2330D REF: (dental) Other Payer Rendering Provider Secondary Identificaiton. We do not use. //2330E NM1: DQ (dental) Other Payer Supervising Provider. Situational. We do not use. //2330E REF: (dental) Other Payer Supervising Provider Secondary Identificaiton. We do not use. //2330F NM1: 85 (dental) Other Payer Billing Provider. Situational. We do not use. //2330F REF: (dental) Other Payer Billing Provider Secondary Identification. We do not use. //2330G NM1: 77 (dental) Other Payer Service Facility Location. Situational. We do not use. //2330G REF: (dental) Other Payer Service Facility Location Secondary Identification. We do not use. //2330H NM1: DD (dental) Other Payer Assistant Sugeon. Situational. We do not use. //2330H REF: (dental) Other Payer Assistant Surgeon Secondary Identifier. We do not use. } #endregion Other payer } for(int j=0;j<claimProcs.Count;j++) { #region Service Line proc=Procedures.GetProcFromList(procList,claimProcs[j].ProcNum); procCode=ProcedureCodes.GetProcCode(proc.CodeNum); //2400 LX: Service Line Number. sw.Write("LX"+s+(j+1).ToString());//LX01 1/6 Assigned Number: EndSegment(sw); if(medType==EnumClaimMedType.Medical) { //2400 SV1: Professional Service. sw.Write("SV1"+s //SV101 Composite Medical Procedure Identifier +"HC"+isa16//SV101-1 2/2 Product/Service ID Qualifier: HC=Health Care. +Sout(claimProcs[j].CodeSent));//SV101-2 1/48 Product/Service ID: Procedure code. The rest of SV101 is not supported. if(proc.CodeMod1!="" || proc.CodeMod2!="" || proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") { sw.Write(isa16+Sout(proc.CodeMod1));//SV101-3 2/2 Procedure Modifier: Situational. } if(proc.CodeMod2!="" || proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") { sw.Write(isa16+Sout(proc.CodeMod2));//SV101-4 2/2 Procedure Modifier: Situational. } if(proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") { sw.Write(isa16+Sout(proc.CodeMod3));//SV101-5 2/2 Procedure Modifier: Situational. } if(proc.CodeMod4!="" || proc.ClaimNote!="") { sw.Write(isa16+Sout(proc.CodeMod4));//SV101-6 2/2 Procedure Modifier: Situational. } if(proc.ClaimNote!="") { sw.Write(isa16+Sout(proc.ClaimNote,80));//SV101-7 1/80 Description: Situational. } sw.Write(s//SV101-8 is not used. +claimProcs[j].FeeBilled.ToString()+s);//SV102 1/18 Monetary Amount: Charge Amt. if(proc.UnitQtyType==ProcUnitQtyType.MinutesAnesth) { sw.Write("MJ"+s);//SV103 2/2 Unit or Basis for Measurement Code: MJ=minutes, UN=Unit. } else { sw.Write("UN"+s);//SV103 2/2 Unit or Basis for Measurement Code: MJ=minutes, UN=Unit. } sw.Write(proc.UnitQty+s);//SV104 1/15 Quantity: Service Unit Count or Anesthesia Minutes. if(proc.PlaceService!=claim.PlaceService) { sw.Write(GetPlaceService(proc.PlaceService)); } sw.Write(s//SV105 1/2 Facility Code Value: Place of Service Code if different from claim. +s);//SV106 1/2 Service Type Code: Not used. //SV107: Composite Diagnosis Code Pointer. Required when 2300HI(Health Care Diagnosis Code) is used (always). //SV107-1: Primary diagnosis. Only allowed pointers 1-8 even though 2300HI supports 12 diagnoses. //We don't validate that there are not more than 8 diagnoses on one claim. //If the diagnosis we need is not in the first 8, then we will use the primary. if(proc.DiagnosticCode=="") {//If the diagnosis is blank, we will use the primary. sw.Write("1");//use primary. } else { int diagI=1; for(int d=0;d<diagnosisList.Count;d++) { if(d>7) {//we can't point to any except first 8. continue; } if((string)diagnosisList[d]==proc.DiagnosticCode) { diagI=d+1; } } sw.Write(diagI.ToString()); } //SV107-2 through SV107-4: Other diagnoses, which we don't support yet. EndSegment(sw);//SV108 through SV121 are not used or situational. We do not use. } else if(medType==EnumClaimMedType.Institutional) { //2400 SV2: Institutional Service Line. sw.Write("SV2"+s +Sout(proc.RevCode,48)+s//SV201 1/48 Product/Service ID: Revenue Code, validated. //SV202 Composite Medical Procedure Identifier +"HC"+isa16//SV202-1 2/2 Product/Service ID Qualifier: HC=Health Care. Includes CPT codes. +Sout(claimProcs[j].CodeSent));//SV202-2 1/48 Product/Service ID: Procedure code. //mods validated to be exactly 2 char long or else blank. if(proc.CodeMod1!="" || proc.CodeMod2!="" || proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") { sw.Write(isa16+Sout(proc.CodeMod1));//SV202-3 2/2 Procedure Modifier: Situational. } if(proc.CodeMod2!="" || proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") { sw.Write(isa16+Sout(proc.CodeMod2));//SV202-4 2/2 Procedure Modifier: Situational. } if(proc.CodeMod3!="" || proc.CodeMod4!="" || proc.ClaimNote!="") { sw.Write(isa16+Sout(proc.CodeMod3));//SV202-5 2/2 Procedure Modifier: Situational. } if(proc.CodeMod4!="" || proc.ClaimNote!="") { sw.Write(isa16+Sout(proc.CodeMod4));//SV202-6 2/2 Procedure Modifier: Situational. } if(proc.ClaimNote!="") { sw.Write(isa16+Sout(proc.ClaimNote,80));//SV202-7 1/80 Description: Situational. } sw.Write(s//SV202-8 is not used. +claimProcs[j].FeeBilled.ToString()+s);//SV203 1/18 Monetary Amount: Charge Amt. if(proc.UnitQtyType==ProcUnitQtyType.Days) { sw.Write("DA"+s);//SV204 2/2 Unit or Basis for Measurement Code: DA=Days, UN=Unit. } else { sw.Write("UN"+s);//SV204 2/2 Unit or Basis for Measurement Code: DA=Days, UN=Unit. } sw.Write(proc.UnitQty.ToString());//SV205 1/15 Quantity: EndSegment(sw);//SV206,208,209 and 210 are not used, SV207 is situational but we do not use. } else if(medType==EnumClaimMedType.Dental) { //2400 SV3: Dental Service. sw.Write("SV3"+s +"AD"+isa16//SV301-1 2/2 Product/Service ID Qualifier: AD=American Dental Association Codes +Sout(claimProcs[j].CodeSent,5));//SV301-2 1/48 Product/Service ID: Procedure code if(proc.ClaimNote!="") { sw.Write(isa16//SV301-3 2/2 Procedure Modifier: Situational. We do not use. +isa16//SV301-4 2/2 Procedure Modifier: Situational. We do not use. +isa16//SV301-5 2/2 Procedure Modifier: Situational. We do not use. +isa16//SV301-6 2/2 Procedure Modifier: Situational. We do not use. +isa16+Sout(proc.ClaimNote,80));//SV301-7 1/80 Description: Situational. } sw.Write(s//SV301-8 is not used. +claimProcs[j].FeeBilled.ToString());//SV302 1/18 Monetary Amount: Charge Amount. string placeService=""; if(proc.PlaceService!=claim.PlaceService) { placeService=GetPlaceService(proc.PlaceService); } string area=GetArea(proc,procCode); int unitQty=Math.Max(proc.UnitQty,1);//Minimum of 1 bool includeUnits=false; if(unitQty>=2) {//Standard behavior based on the X12 guide. includeUnits=true; } //The following carriers always want to see the unit quantity, even if it is only 1. if(IsColoradoMedicaid(clearhouse) || IsWashingtonMedicaid(clearhouse,carrier)) { includeUnits=true; } if(placeService!="" || area!="" || proc.Prosthesis!="" || includeUnits) { sw.Write(s+placeService);//SV303 1/2 Facility Code Value: Location Code if different from claim. } if(area!="" || proc.Prosthesis!="" || includeUnits) { sw.Write(s+area);//SV304 Oral Cavity Designation: SV304-1 1/3 Oral Cavity Designation Code: Area. SV304-2 through SV304-5 are situational and we do not use. } if(proc.Prosthesis!="" || includeUnits) { sw.Write(s+proc.Prosthesis);//SV305 1/1 Prothesis, Crown or Inlay Code: I=Initial Placement. R=Replacement. } if(includeUnits) { sw.Write(s+unitQty.ToString());//SV306 1/15 Quantity: Situational. Procedure count. } EndSegment(sw);//SV307 throug SV311 are either not used or are situational and we do not use. //2400 TOO: Tooth Information. Number/Surface. Multiple iterations of the TOO segment are allowed only when the quantity reported in Loop ID-2400 SV306 is equal to one. if(procCode.TreatArea==TreatmentArea.Tooth) { sw.Write("TOO"+s +"JP"+s//TOO01 1/3 Code List Qualifier Code: JP=Universal National Tooth Designation System. +proc.ToothNum);//TOO02 1/30 Industry Code: Tooth number. EndSegment(sw);//TOO03 Tooth Surface: Situational. Not applicable. } else if(procCode.TreatArea==TreatmentArea.Surf) { sw.Write("TOO"+s +"JP"+s//TOO01 1/3 Code List Qualifier Code: JP=Universal National Tooth Designation System. +proc.ToothNum+s);//TOO02 1/30 Industry Code: Tooth number. string validSurfaces=Tooth.SurfTidyForClaims(proc.Surf,proc.ToothNum); for(int k=0;k<validSurfaces.Length;k++) { if(k>0) { sw.Write(isa16); } sw.Write(validSurfaces.Substring(k,1));//TOO03 Tooth Surface: TOO03-1 through TOO03-5 are for individual surfaces. } EndSegment(sw); } else if(procCode.TreatArea==TreatmentArea.ToothRange) { string[] individTeeth=proc.ToothRange.Split(','); for(int t=0;t<individTeeth.Length;t++) { sw.Write("TOO"+s +"JP"+s//TOO01 1/3 Code List Qualifier Code: JP=Universal National Tooth Designation System. +individTeeth[t]);//TOO02 1/30 Industry Code: Tooth number. EndSegment(sw);//TOO03 Tooth Surface: Situational. Not applicable. } } }//dental #endregion Service Line //2400 PWK: (institutional) Line Supplemental Information. Situational. We do not use. //2400 CRC: (medical) Condition Indicator/Durable Medical Equipment. Situational. We do not use. #region Service DTP //2400 DTP: 472 (medical,institutional,dental) Service Date. Situaitonal. Required for medical. Required if different from claim for dental and inst. if(claim.ClaimType!="PreAuth") { bool useProcDateService=false; //Always required for medical because there is no date of service at the claim level. if(medType==EnumClaimMedType.Medical) { useProcDateService=true; } else { //Institutional and dental. //Standard X12 behavior, preferred by the following clearinghouses: EmdeonDental. //Required for institutional and dental when procedure date of service is different from the claim date of service. if(proc.ProcDate!=claim.DateService) { useProcDateService=true; } } //The following clearinghouses always want this segment no matter what: Apex, Inmediata. if(IsApex(clearhouse) || IsInmediata(clearhouse)) { useProcDateService=true; } if(useProcDateService) { sw.Write("DTP"+s +"472"+s//DTP01 3/3 Date/Time Qualifier: 472=Service. +"D8"+s//DTP02 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD. +proc.ProcDate.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period: EndSegment(sw); } } //2400 DTP: 139/441 (dental) Date Prior Placement. Situational. Required when replacement. if(proc.Prosthesis=="R") {//already validated date sw.Write("DTP"+s +"441"+s//DTP01 3/3 Date/Time Qualifier: 441=Prior Placement. +"D8"+s//DTP02 2/3 Date Time Period Format Qualifier: D8=Date Expressed in Format CCYYMMDD. +proc.DateOriginalProsth.ToString("yyyyMMdd"));//DTP03 1/35 Date Time Period: EndSegment(sw); } //2400 DTP: 452 (dental) Date Appliance Placement. Situational. Ortho appliance placement. We do not use. //2400 DTP: 446 (dental) Date Replacement. Date ortho appliance replaced. We do not use. //2400 DTP: 196 (medical,dental) Date Treatment Start. Situational. Rx date. We do not use. //2400 DTP: 198 (dental) Date Treatment Completion. Situational. We do not use. //2400 DTP: 471 (medical) Prescription Date: Situational. We do not use. //2400 DTP: 607 (medical) Date Certification Revision/Recertification. Situational. Not supported. //2400 DTP: 463 (medical) Date Begin Therapy. Situational. Not supported. //2400 DTP: 461 (medical) Date Last Certification. Situational. Not supported. //2400 DTP: 304 (medical) Date Last Seen. Situational. Not supported. //2400 DTP: 738/739 (medical) Test Date. Situational. For Dialysis. Not supported. //2400 DTP: 011 (medical) Date Shipped. Situational. Not supported. //2400 DTP: 455 (medical) Date Last X-Ray. Situational. Not supported. //2400 DTP: 454 (medical) Date Initial Treatment. Situational. Not supported. #endregion Service DTP #region Service QTY MEA CN1 //2400 QTY: PT (medical) Ambulance Patient Count. Situational. Not supported. //2400 QTY: FL (medical) Obstetric Anesthesia Additional Units. Situational. Anesthesia quantity. We do not use. //2400 MEA: (medical) Test Result. Situational. We do not use. //2400 CN1: (medical,dental) Contract Information. Situational. We do not use. #endregion Service QTY MEA CN1 #region Service REF //2400 REF: G3 (dental) Service Predetermination Identification. Situational. Pretermination ID. We do not use. //2400 REF: G1 (medical,dental) Prior Authorization. Situational. We do not use. //2400 REF: 9F (medical,dental) Referral Number. Situational. We do not use. //2400 REF: 9A (dental) Repriced Claim Number. Situational. We do not use. //2400 REF: 9B (medical,institutional) Repriced Line Item Reference Number. Situational. We do not use. //2400 REF: 9C (dental) Adjusted Repriced claim Number. Situational. We do not use. //2400 REF: 9D (medical,instituitonal) Adjusted Repriced Line Item Reference Number. Situational. We do not use. //2400 REF: 6R (medical,institutional,dental) Line Item Control Number. ProcNum. Will later be used for ERAs. sw.Write("REF"+s +"6R"+s//REF01 2/3 Reference Identification Qualifier: 6R=Procedure Control Number. +proc.ProcNum.ToString());//REF02 1/50 Reference Identification: EndSegment(sw);//REF03 and REF04 are not used. //2400 REF: EW (medical) Mammography Certification Number. Situational. We do not use. //2400 REF: X4 (medical) Clinical Laboratory Improvement Amendment (CLIA) Number. Situational. We do not use. //2400 REF: F4 (medical) Referring Clinical Laboratory Improvement Amendment (CLIA) Facility Identification. Situational. We do not use. //2400 REF: BT (medical) Immunization Batch Number. Situational. We do not use. #endregion Service REF #region Service AMT K3 NTE PS1 HCP LIN CTP //2400 AMT: T (medical,dental) Sales Tax Amount. Situational. Not supported. //2400 AMT: F4 (medical) Postage Claimed Amount. Situational. We do not use. //2400 AMT GT (institutional) Service Tax Amount. Situational. Not supported. //2400 AMT N8 (institutional) Facility Tax Amount. Situational. Not supported. //2400 K3: (medical,dental) File Information. Situational. Not supported. //2400 NTE: ADD/DCP (medical) Line Note. Situational. We do not use. //2400 NTE: TPO (medical,institutional) Third Party Organization Notes. Situational. Not sent by providers. Not supported. //2400 PS1: (medical) Purchased Service Information. Situational. We do not use. //2400 HCP: (medical,institutional,dental) Line Pricing/Repricing Information. Situational. Not used by providers. Not supported. #endregion Service AMT K3 NTE PS1 HCP #region 2410 Service Drug Identification //2410 LIN,CTP,REF: (medical) ? if(medType==EnumClaimMedType.Medical || medType==EnumClaimMedType.Institutional) { //2410 LIN: (medical,institutional) Drug Identification if(procCode.DrugNDC!="" && proc.DrugQty>0){ sw.Write("LIN"+s+s//LIN01 1/20 Assigned Identification: Not used. +"N4"+s//LIN02 2/2 Product/Service ID Qualifier: N4=NDC code in 5-4-2 format, no dashes. +procCode.DrugNDC);//LIN03 1/48 Product/Service ID: NDC. EndSegment(sw);//LIN04 through LIN31 not used. //2410 CTP: (medical,institutional) Drug Quantity. sw.Write("CTP"+s+s+s+s//CTP01 through CTP03 not used. +proc.DrugQty.ToString()+s//CTP04 1/15 Quantity: +GetDrugUnitCode(proc.DrugUnit));//CTP05-1 2/2 Unit or Basis for Measurement Code: Code Qualifier, validated to not be None. EndSegment(sw);//CTP05-2 through CTP05-15 not used. CTP06 through CTP11 not used. //2410 REF (inst) Rx or compound drug association number. Not supported. } } #endregion 2410 Service Drug Identification Provider provTreatProc=provTreat;//procedure level treating provider. //2410 REF: VY/XZ (medical,institutional) Prescription or Compound Drug Association Number. Situational. We do not use. #region 2420 Service Providers (medical) if(medType==EnumClaimMedType.Medical) { if(claim.ProvTreat!=proc.ProvNum && PrefC.GetBool(PrefName.EclaimsSeparateTreatProv)) { //2420A NM1: 82 (medical) Rendering Provider Name. Only if different from the claim. provTreatProc=Providers.GetProv(proc.ProvNum); WriteNM1Provider("82",sw,provTreatProc); //2420A PRV: (medical) Rendering Provider Specialty Information. sw.Write("PRV"+s +"PE"+s//PRV01 1/3 Provider Code: PE=Performing. +"PXC"+s//PRV02 2/3 Reference Identification Qualifier: PXC=Health Care Provider Taxonomy Code. +X12Generator.GetTaxonomy(provTreatProc));//PRV03 1/50 Reference Identification: Taxonomy Code. EndSegment(sw);//PRV04 through PRV06 not used. //2420A REF: (medical) Rendering Provider Secondary Identification. sw.Write("REF"+s +"0B"+s//REF01 2/3 Reference Identification Qualifier: 0B=State License Number. +Sout(provTreatProc.StateLicense,50));//REF02 1/50 Reference Identification: EndSegment(sw);//REF03 1/80 Description: Not used. REF04 Reference Identifier: Situational. Not used when REF01 is 0B or 1G. } //2420B NM1: Purchased Service Provider Name. Situational. We do not use. //2420B REF: Purchased Service Provider Secondary Identificaiton. Situational. We do not use. //2420C NM1: 77 (medical) Service Facility Location Name. Situational. We enforce all procs on a claim being performed at the same location so we don't need this. //2420C N3: (medical) Service Facility Location Address. We do not use. //2420C N4: (medical) Service Facility Location City, State, Zip Code. We do not use. //2420C REF: (medical) Service Facility Location Secondary Identification. Situational. We do not use. //2420D NM1: DQ (medical) Supervising Provider Name. Situational. We do not support. //2420D REF: (medical) Supervising Provider Secondary Identification. Situational. We do not support. //Emdeon Medical requires loop 2420E when the claim is sent to DMERC (Medicaid) carriers. This loop can only be used for a provider that is a person, not an organization, so we don't send this loop if not a person. if(!provTreatProc.IsNotPerson) { //Treating provider is a person. //2420E NM1: DK (medical) Ordering Provider Name. Situational. Required to be a person. WriteNM1Provider("DK",sw,provTreatProc); //2420E N3: (medical) Ordering Provider Address. Situational. sw.Write("N3"+s+Sout(billingAddress1,55));//N301 1/55 Address Information: if(billingAddress2!="") { sw.Write(s+Sout(billingAddress2,55));//N302 1/55 Address Information: Only required when there is a secondary address line. } EndSegment(sw); //2420E N4: (medical) Ordering Provider City, State, Zip Code. Situational. sw.Write("N4"+s +Sout(billingCity,30)+s//N401 2/30 City Name: +Sout(billingState,2,2)+s//N402 2/2 State or Provice Code: +Sout(billingZip.Replace("-",""),15));//N403 3/15 Postal Code: EndSegment(sw);//N404 through N407 are either not used or only required when outside of the United States. //2420E REF: (medical) Ordering Provider Secondary Identification. Situational. Required before NPIs were in effect. We do not use this segment because we require NPI. //2420E PER: (medical) Ordering Provider Contact Information. Situational. sw.Write("PER"+s +"IC"+s//PER01 2/2 Contact Function Code: IC=Information Contact. +Sout(PrefC.GetString(PrefName.PracticeTitle),60)+s//PER02 1/60 Name: Practice Title. +"TE"+s);//PER03 2/2 Communication Number Qualifier: TE=Telephone. if(clinic==null) { sw.Write(Sout(PrefC.GetString(PrefName.PracticePhone),256));//PER04 1/256 Communication Number: Telephone number. } else { sw.Write(Sout(clinic.Phone,256));//PER04 1/256 Communication Number: Telephone number. } EndSegment(sw);//PER05 through PER08 are situational and PER09 is not used. We do not use. } //2420F NM1: (medical) Referring Provider Name. Situational. We do not use. //2420F REF: (medical) Referring Provider Secondary Identification. Situational. We do not use. //2420G NM1: PW (medical) Ambulance Pick-up Location. Situational. We do not use. //2420G N3: (medical) Ambulance Pick-up Location Address. We do not use. //2420G N4: (medical) Ambulance Pick-up Location City, State, Zip Code. We do not use. //2420H NM1: (medical) Ambulance Drop-off Location. Situational. We do not use. //2420H N3: (medical) Ambulance Drop-off Location Address. We do not use. //2420H N4: (medical) Ambulance Drop-off Location City, State, Zip Code. We do not use. } #endregion 2420 Service Providers (medical) #region 2420 Service Providers (inst) if(medType==EnumClaimMedType.Institutional) { //2420A NM1: 72 (institutional) Operating Physician Name. Situational. Only for surgical procedures. We don't support. //2420A REF: (instititional) Operating Physician Secondary Identification. Situational. Only for surgical procedures. We don't support. //2420B NM1: ZZ (institutional) Other Operating Physician Name. Situational. We don't support. //2420B REF: (institutional) Other Operating Physician Secondary Identification. Situational. We don't support. if(claim.ProvTreat!=proc.ProvNum && PrefC.GetBool(PrefName.EclaimsSeparateTreatProv)) { provTreatProc=Providers.GetProv(proc.ProvNum); //2420C NM1: 82 (institutional) Rendering Provider Name. Situational. Only if different than claim attending (treating) prov. Person only, non-person not allowed. WriteNM1Provider("82",sw,provTreatProc.FName,provTreatProc.MI,provTreatProc.LName,provTreatProc.NationalProvID,false); //2420C REF: Rendering Provider Secondary Identification. Situational. sw.Write("REF"+s +"0B"+s//REF01 2/3 Reference Identification Qualifier: 0B=State License Number. +Sout(provTreatProc.StateLicense,50));//REF02 1/50 Reference Identification: Valided to be present. EndSegment(sw);//REF03 through REF04 are not used or situational. } //2420D NM1: DN (institutional) Referring Provider Name. Situational. We do not use. //2420D REF: (institutional) Referring Provider Secondary Identification. Situational. We do not use. } #endregion 2420 Service Providers (inst) #region 2420 Service Providers (dental) if(medType==EnumClaimMedType.Dental) { if(claim.ProvTreat!=proc.ProvNum && PrefC.GetBool(PrefName.EclaimsSeparateTreatProv)) { //2420A NM1: 82 (dental) Rendering Provider Name. Only if different from the claim. provTreatProc=Providers.GetProv(proc.ProvNum); WriteNM1Provider("82",sw,provTreatProc); //2420A PRV: (dental) Rendering Provider Specialty Information. sw.Write("PRV"+s +"PE"+s//PRV01 1/3 Provider Code: PE=Performing. +"PXC"+s//PRV02 2/3 Reference Identification Qualifier: PXC=Health Care Provider Taxonomy Code. +X12Generator.GetTaxonomy(provTreatProc));//PRV03 1/50 Reference Identification: Taxonomy Code. EndSegment(sw);//PRV04 through PRV06 not used. //2420A REF: (dental) Rendering Provider Secondary Identification. Never required because we always send NPI (validated). if(!IsDentiCal(clearhouse)) { //Denti-Cal never wants this. if(provTreatProc.StateLicense!="") { sw.Write("REF"+s +"0B"+s//REF01 2/3 Reference Identification Qualifier: 0B=State License Number. +Sout(provTreatProc.StateLicense,50));//REF02 1/50 Reference Identification: EndSegment(sw);//REF03 1/80 Description: Not used. REF04 Reference Identifier: Situational. Not used when REF01 is 0B or 1G. } } } //2420B NM1: DD (dental) Assistant Surgeon Name. Situational. We do not support. //2420B PRV: AS (dental) Assistant Surgeon Specialty Information. Situational. We do not support. //2420B REF: (dental) Assistant Surgeon Secondary Identification. Situational. We do not support. //2420C NM1: DQ (dental) Supervising Provider Name. Situational. We do not support. //2420C REF: (dental) Supervising Provider Secondary Identification. Situational. We do not support. //2420D NM1: 77 (dental) Service Facility Location Name. Situational. We enforce all procs on a claim being performed at the same location so we don't need this. //2420D N3: (dental) Service Facility Location Address. We do not use. //2420D N4: (dental) Service Facility Location City, State, Zip Code. We do not use. //2420D REF: (dental) Service Facility Location Secondary Identification. Situational. We do not use. } #endregion 2420 Service Providers (dental) //2430 SVD: (medical,institutional,dental) Line Adjudication Information. Situational. We do not support. //2430 CAS: (medical,institutional,dental) Line Adjustment. Situational. Required when the payer identified in Loop 2330B made line level adjustments which caused the amount paid to differ from the amount originally charged. //These CAS segments at the procedure level should add up to their respective claim level 2320 CAS segments. //Claim Adjustment Reason Codes can be found on the Washington Publishing Company website at: http://www.wpc-edi.com/reference/codelists/healthcare/claim-adjustment-reason-codes/ if(hasAdjForOtherPlans && IsApex(clearhouse)) {//This section of code might work for other clearinghouses, but has not yet been tested, and nobody else has requested this information yet. double procPatientPortionAmt=Math.Max(0,claimProcs[j].FeeBilled-listProcWriteoffAmts[j]-listProcDeductibleAmts[j]-listProcPaidOtherInsAmts[j]); if(listProcWriteoffAmts[j]>0) { sw.Write("CAS"+s +"CO"+s//CAS01 1/2 Claim Adjustment Group Code: CO=Contractual Obligations. +"45"+s//CAS02 1/5 Claim Adjustment Reason Code: 45=Charge exceeds fee schedule/maximum allowable or contracted/legislated fee arrangement. +AmountToStrNoLeading(listProcWriteoffAmts[j]));//CAS03 1/18 Monetary Amount: EndSegment(sw); } if(listProcDeductibleAmts[j]>0 || procPatientPortionAmt>0) { sw.Write("CAS"+s +"PR");//CAS01 1/2 Claim Adjustment Group Code: PR=Patient Responsibility. if(listProcDeductibleAmts[j]>0) { sw.Write(s//end of previous field +"1"+s//CAS02 1/5 Claim Adjustment Reason Code: 1=Deductible. +AmountToStrNoLeading(listProcDeductibleAmts[j])+s//CAS03 1/18 Monetary Amount: +"1");//CAS04 1/15 Quantity: } if(procPatientPortionAmt>0) { sw.Write(s//end of previous field +"3"+s//CAS02 or CAS05 1/5 Claim Adjustment Reason Code: 3=Co-payment Amount. +AmountToStrNoLeading(procPatientPortionAmt));//CAS03 or CAS06 1/18 Monetary Amount: } EndSegment(sw); } } //2430 DTP: (medical,institutional,dental) Line Check or Remittance Date. We do not support. //2430 AMT: (medical,institutional,dental) Remaining Patient Liability. We do not support. //2440 LQ: (medical) Form Identification Code. Situational. We do not use. //2440 FRM: (medical) Supporting Documentation. We do not use. } } #region Trailers //Transaction Trailer sw.Write("SE"+s +(seg+1).ToString()+s//SE01 1/10 Number of Included Segments: Total segments, including ST & SE. We add 1 for this SE segment, since the seg variable is not incremented until after this segment is written. +transactionNum.ToString().PadLeft(4,'0'));//SE02 4/9 Transaction Set Control Number: EndSegment(sw); //Functional Group Trailer sw.Write("GE"+s+transactionNum.ToString()+s//GE01 1/6 Number of Transaction Sets Included. Always 1 for us. +groupControlNumber//GE02 1/9 Group Control Number: Must be identical to GS06. +endSegment); #endregion Trailers }
private void FormSheetImport_Load(object sender,EventArgs e) { if(SheetCur!=null) { pat=Patients.GetPat(SheetCur.PatNum); } else { throw new NotImplementedException();//js this broke with the move to dot net 4.0. /* pat=Patients.GetPat(DocCur.PatNum); CAcroApp acroApp=null; try { acroApp=new AcroAppClass();//Initialize Acrobat by creating App object } catch { MsgBox.Show(this,"Requires Acrobat 9 Pro to be installed on this computer."); DialogResult=DialogResult.Cancel; return; } //acroApp.Show();// Show Acrobat Viewer //acroApp.Hide();//This is annoying if Acrobat is already open for some other reason. CAcroAVDoc avDoc=new AcroAVDocClass(); string pathToPdf=CodeBase.ODFileUtils.CombinePaths(ImageStore.GetPatientFolder(pat),DocCur.FileName); if(!avDoc.Open(pathToPdf,"")){ MessageBox.Show(Lan.g(this,"Could not open")+" "+pathToPdf); DialogResult=DialogResult.Cancel; return; } IAFormApp formApp=new AFormAppClass();//Create a IAFormApp object so we can access the form fields in the open document IFields myFields=(IFields)formApp.Fields;// Get the IFields object associated with the form IEnumerator myEnumerator = myFields.GetEnumerator();// Get the IEnumerator object for myFields dictAcrobatFields=new Dictionary<string,string>(); IField myField; string nameClean; string valClean; while(myEnumerator.MoveNext()) { myField=(IField)myEnumerator.Current;// Get the IField object if(myField.Value==null){ continue; } //if the form was designed in LiveCycle, the names will look like this: topmostSubform[0].page1[0].SSN[0] //Whereas, if it was designed in Acrobat, the names will look like this: SSN //So... nameClean=myField.Name; if(nameClean.Contains("[") && nameClean.Contains(".")) { nameClean=nameClean.Substring(nameClean.LastIndexOf(".")+1); nameClean=nameClean.Substring(0,nameClean.IndexOf("[")); } if(nameClean=="misc") { int suffix=1; nameClean=nameClean+suffix.ToString(); while(dictAcrobatFields.ContainsKey(nameClean)) {//untested. suffix++; nameClean=nameClean+suffix.ToString(); } } valClean=myField.Value; if(valClean=="Off") { valClean=""; } //myField.Type//possible values include text,radiobutton,checkbox //MessageBox.Show("Raw:"+myField.Name+" Name:"+nameClean+" Value:"+myField.Value); if(dictAcrobatFields.ContainsKey(nameClean)) { continue; } dictAcrobatFields.Add(nameClean,valClean); //name:topmostSubform[0].page1[0].SSN[0] } //acroApp.Hide();//Doesn't work well enough //this.BringToFront();//Doesn't work //acroApp.Minimize(); acroApp.Exit(); acroApp=null; */ } fam=Patients.GetFamily(pat.PatNum); AddressSameForFam=true; for(int i=0;i<fam.ListPats.Length;i++) { if(pat.HmPhone!=fam.ListPats[i].HmPhone || pat.Address!=fam.ListPats[i].Address || pat.Address2!=fam.ListPats[i].Address2 || pat.City!=fam.ListPats[i].City || pat.State!=fam.ListPats[i].State || pat.Zip!=fam.ListPats[i].Zip) { AddressSameForFam=false; break; } } patPlanList=PatPlans.Refresh(pat.PatNum); subList=InsSubs.RefreshForFam(fam); planList=InsPlans.RefreshForSubList(subList); if(patPlanList.Count==0) { patPlan1=null; plan1=null; sub1=null; ins1Relat=null; carrier1=null; } else { patPlan1=patPlanList[0]; sub1=InsSubs.GetSub(patPlan1.InsSubNum,subList); plan1=InsPlans.GetPlan(sub1.PlanNum,planList); ins1Relat=patPlan1.Relationship; carrier1=Carriers.GetCarrier(plan1.CarrierNum); } if(patPlanList.Count<2) { patPlan2=null; plan2=null; sub2=null; ins2Relat=null; carrier2=null; } else { patPlan2=patPlanList[1]; sub2=InsSubs.GetSub(patPlan2.InsSubNum,subList); plan2=InsPlans.GetPlan(sub2.PlanNum,planList); ins2Relat=patPlan2.Relationship; carrier2=Carriers.GetCarrier(plan2.CarrierNum); } FillRows(); FillGrid(); }
/// <summary>claimType="P" or "S".</summary> public static Claim CreateClaim(string claimType,List<PatPlan> PatPlanList,List<InsPlan> InsPlanList,List<ClaimProc> ClaimProcList,List<Procedure> procsForPat,Patient pat,List<Procedure> procsForClaim,List<Benefit> benefitList,List<InsSub> SubList){ //Claim ClaimCur=CreateClaim("P",PatPlanList,InsPlanList,ClaimProcList,procsForPat); long claimFormNum = 0; EtransType eFormat = 0; InsPlan PlanCur1=new InsPlan(); InsSub SubCur1=new InsSub(); InsPlan PlanCur2=new InsPlan(); InsSub SubCur2=new InsSub(); Relat relatOther=Relat.Self; switch(claimType) { case "P": SubCur1=InsSubs.GetSub(PatPlans.GetInsSubNum(PatPlanList,1),SubList); PlanCur1=InsPlans.GetPlan(SubCur1.PlanNum,InsPlanList); SubCur2=InsSubs.GetSub(PatPlans.GetInsSubNum(PatPlanList,2),SubList); //PlanCur2=InsPlans.GetPlan(SubCur.PlanNum,InsPlanList);//can end up null break; case "S": SubCur1=InsSubs.GetSub(PatPlans.GetInsSubNum(PatPlanList,2),SubList); PlanCur1=InsPlans.GetPlan(SubCur1.PlanNum,InsPlanList); SubCur2=InsSubs.GetSub(PatPlans.GetInsSubNum(PatPlanList,1),SubList); //PlanCur2=InsPlans.GetPlan(SubCur.PlanNum,InsPlanList);//can end up null break; } //DataTable table=DataSetMain.Tables["account"]; Procedure proc; //proc=Procedures.GetProcFromList(procsForPat,PIn.Long(table.Rows[gridAccount.SelectedIndices[0]]["ProcNum"].ToString())); //long clinicNum=proc.ClinicNum; ClaimProc[] claimProcs=new ClaimProc[procsForClaim.Count];//1:1 with procs long procNum; for(int i=0;i<procsForClaim.Count;i++) {//loop through selected procs //and try to find an estimate that can be used procNum=procsForClaim[i].ProcNum; claimProcs[i]=Procedures.GetClaimProcEstimate(procNum,ClaimProcList,PlanCur1,SubCur1.InsSubNum); } for(int i=0;i<claimProcs.Length;i++) {//loop through each claimProc //and create any missing estimates. This handles claims to 3rd and 4th ins co's. if(claimProcs[i]==null) { claimProcs[i]=new ClaimProc(); proc=procsForClaim[i]; ClaimProcs.CreateEst(claimProcs[i],proc,PlanCur1,SubCur1); } } Claim claim=new Claim(); Claims.Insert(claim);//to retreive a key for new Claim.ClaimNum claim.PatNum=pat.PatNum; claim.DateService=claimProcs[claimProcs.Length-1].ProcDate; claim.ClinicNum=procsForClaim[0].ClinicNum; claim.DateSent=DateTime.Today; claim.ClaimStatus="S"; //datereceived switch(claimType) { case "P": claim.PlanNum=SubCur1.PlanNum; claim.InsSubNum=PatPlans.GetInsSubNum(PatPlanList,1); claim.PatRelat=PatPlans.GetRelat(PatPlanList,1); claim.ClaimType="P"; claim.PlanNum2=SubCur2.PlanNum;//might be 0 if no sec ins claim.InsSubNum2=PatPlans.GetInsSubNum(PatPlanList,2); claim.PatRelat2=PatPlans.GetRelat(PatPlanList,2); break; case "S": claim.PlanNum=SubCur1.PlanNum; claim.InsSubNum=PatPlans.GetInsSubNum(PatPlanList,2); claim.PatRelat=PatPlans.GetRelat(PatPlanList,2); claim.ClaimType="S"; claim.PlanNum2=SubCur2.PlanNum; claim.InsSubNum2=PatPlans.GetInsSubNum(PatPlanList,1); claim.PatRelat2=PatPlans.GetRelat(PatPlanList,1); break; } claim.ProvTreat=procsForClaim[0].ProvNum; claim.IsProsthesis="I"; claim.ProvBill=Providers.GetBillingProvNum(claim.ProvTreat,claim.ClinicNum); claim.EmployRelated=YN.No; //attach procedures Procedure ProcCur; for(int i=0;i<claimProcs.Length;i++) { ProcCur=procsForClaim[i]; claimProcs[i].ClaimNum=claim.ClaimNum; claimProcs[i].Status=ClaimProcStatus.NotReceived;//status for claims unsent or sent. //writeoff handled in ClaimL.CalculateAndUpdate() claimProcs[i].CodeSent=ProcedureCodes.GetProcCode(ProcCur.CodeNum).ProcCode; if(claimProcs[i].CodeSent.Length>5 && claimProcs[i].CodeSent.Substring(0,1)=="D") { claimProcs[i].CodeSent=claimProcs[i].CodeSent.Substring(0,5); } claimProcs[i].LineNumber=(byte)(i+1); ClaimProcs.Update(claimProcs[i]); } ClaimProcList=ClaimProcs.Refresh(pat.PatNum); ClaimL.CalculateAndUpdate(procsForPat,InsPlanList,claim,PatPlanList,benefitList,pat.Age,SubList); return claim; }
///<summary></summary> public static void Update(InsSub insSub) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),insSub); return; } Crud.InsSubCrud.Update(insSub); }
///<summary>In progress. Probably needs a different name. Info must be validated first.</summary> public static string GenerateMessageText(Clearinghouse clearhouse,Carrier carrier,Provider billProv,Clinic clinic,InsPlan insPlan,Patient subscriber,InsSub insSub) { int batchNum=Clearinghouses.GetNextBatchNumber(clearhouse); string groupControlNumber=batchNum.ToString();//Must be unique within file. We will use batchNum int transactionNum=1; StringBuilder strb=new StringBuilder(); //Interchange Control Header strb.AppendLine("ISA*00* *"//ISA01,ISA02: 00 + 10 spaces +"00* *"//ISA03,ISA04: 00 + 10 spaces +clearhouse.ISA05+"*"//ISA05: Sender ID type: ZZ=mutually defined. 30=TIN. Validated +X12Generator.GetISA06(clearhouse)+"*"//ISA06: Sender ID(TIN). Or might be TIN of Open Dental +clearhouse.ISA07+"*"//ISA07: Receiver ID type: ZZ=mutually defined. 30=TIN. Validated +Sout(clearhouse.ISA08,15,15)+"*"//ISA08: Receiver ID. Validated to make sure length is at least 2. +DateTime.Today.ToString("yyMMdd")+"*"//ISA09: today's date +DateTime.Now.ToString("HHmm")+"*"//ISA10: current time +"U*00401*"//ISA11 and ISA12. //ISA13: interchange control number, right aligned: +batchNum.ToString().PadLeft(9,'0')+"*" +"0*"//ISA14: no acknowledgment requested +clearhouse.ISA15+"*"//ISA15: T=Test P=Production. Validated. +":~");//ISA16: use ':' //Functional Group Header strb.AppendLine("GS*HS*"//GS01: HS for 270 benefit inquiry +X12Generator.GetGS02(clearhouse)+"*"//GS02: Senders Code. Sometimes Jordan Sparks. Sometimes the sending clinic. +Sout(clearhouse.GS03,15,2)+"*"//GS03: Application Receiver's Code +DateTime.Today.ToString("yyyyMMdd")+"*"//GS04: today's date +DateTime.Now.ToString("HHmm")+"*"//GS05: current time +groupControlNumber+"*"//GS06: Group control number. Max length 9. No padding necessary. +"X*"//GS07: X +"004010X092~");//GS08: Version //Beginning of transaction-------------------------------------------------------------------------------- int seg=0;//count segments for the ST-SE transaction //Transaction Set Header //ST02 Transact. control #. Must be unique within ISA seg++; strb.AppendLine("ST*270*"//ST01 +transactionNum.ToString().PadLeft(4,'0')+"~");//ST02 seg++; strb.AppendLine("BHT*0022*13*"//BHT02: 13=request +transactionNum.ToString().PadLeft(4,'0')+"*"//BHT03. Can be same as ST02 +DateTime.Now.ToString("yyyyMMdd")+"*"//BHT04: Date +DateTime.Now.ToString("HHmmss")+"~");//BHT05: Time, BHT06: not used //HL Loops----------------------------------------------------------------------------------------------- int HLcount=1; //2000A HL: Information Source-------------------------------------------------------------------------- seg++; strb.AppendLine("HL*"+HLcount.ToString()+"*"//HL01: Heirarchical ID. Here, it's always 1. +"*"//HL02: No parent. Not used +"20*"//HL03: Heirarchical level code. 20=Information source +"1~");//HL04: Heirarchical child code. 1=child HL present //2100A NM1 seg++; strb.AppendLine("NM1*PR*"//NM101: PR=Payer +"2*"//NM102: 2=Non person +Sout(carrier.CarrierName,35)+"*"//NM103: Name Last. +"****"//NM104-07 not used +"PI*"//NM108: PI=PayorID +Sout(carrier.ElectID,80,2)+"~");//NM109: PayorID. Validated to be at least length of 2. HLcount++; //2000B HL: Information Receiver------------------------------------------------------------------------ seg++; strb.AppendLine("HL*"+HLcount.ToString()+"*"//HL01: Heirarchical ID. Here, it's always 2. +"1*"//HL02: Heirarchical parent id number. 1 in this simple message. +"21*"//HL03: Heirarchical level code. 21=Information receiver +"1~");//HL04: Heirarchical child code. 1=child HL present seg++; //2100B NM1: Information Receiver Name strb.AppendLine("NM1*1P*"//NM101: 1P=Provider +(billProv.IsNotPerson?"2":"1")+"*"//NM102: 1=person,2=non-person +Sout(billProv.LName,35)+"*"//NM103: Last name +Sout(billProv.FName,25)+"*"//NM104: First name +Sout(billProv.MI,25,1)+"*"//NM105: Middle name +"*"//NM106: not used +"*"//NM107: Name suffix. not used +"XX*"//NM108: ID code qualifier. 24=EIN. 34=SSN, XX=NPI +Sout(billProv.NationalProvID,80)+"~");//NM109: ID code. NPI validated //2100B REF: Information Receiver ID seg++; strb.Append("REF*"); if(billProv.UsingTIN) { strb.Append("TJ*");//REF01: qualifier. TJ=Federal TIN } else {//SSN strb.Append("SY*");//REF01: qualifier. SY=SSN } strb.AppendLine(Sout(billProv.SSN,30)+"~");//REF02: ID //2100B N3: Information Receiver Address seg++; if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { strb.Append("N3*"+Sout(PrefC.GetString(PrefName.PracticeBillingAddress),55));//N301: Address } else if(clinic==null) { strb.Append("N3*"+Sout(PrefC.GetString(PrefName.PracticeAddress),55));//N301: Address } else { strb.Append("N3*"+Sout(clinic.Address,55));//N301: Address } if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { if(PrefC.GetString(PrefName.PracticeBillingAddress2)=="") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*"+Sout(PrefC.GetString(PrefName.PracticeBillingAddress2),55)+"~"); } } else if(clinic==null) { if(PrefC.GetString(PrefName.PracticeAddress2)=="") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*"+Sout(PrefC.GetString(PrefName.PracticeAddress2),55)+"~"); } } else { if(clinic.Address2=="") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*"+Sout(clinic.Address2,55)+"~"); } } //2100B N4: Information Receiver City/State/Zip seg++; if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { strb.AppendLine("N4*"+Sout(PrefC.GetString(PrefName.PracticeBillingCity),30)+"*"//N401: City +Sout(PrefC.GetString(PrefName.PracticeBillingST),2)+"*"//N402: State +Sout(PrefC.GetString(PrefName.PracticeBillingZip).Replace("-",""),15)+"~");//N403: Zip } else if(clinic==null) { strb.AppendLine("N4*"+Sout(PrefC.GetString(PrefName.PracticeCity),30)+"*"//N401: City +Sout(PrefC.GetString(PrefName.PracticeST),2)+"*"//N402: State +Sout(PrefC.GetString(PrefName.PracticeZip).Replace("-",""),15)+"~");//N403: Zip } else { strb.AppendLine("N4*"+Sout(clinic.City,30)+"*"//N401: City +Sout(clinic.State,2)+"*"//N402: State +Sout(clinic.Zip.Replace("-",""),15)+"~");//N403: Zip } //2100B PRV: Information Receiver Provider Info seg++; //PRV*PE*ZZ*1223G0001X~ strb.AppendLine("PRV*PE*"//PRV01: Provider Code. PE=Performing. There are many other choices. +"ZZ*"//PRV02: ZZ=Mutually defined = health care provider taxonomy code +X12Generator.GetTaxonomy(billProv)+"~");//PRV03: Specialty code HLcount++; //2000C HL: Subscriber----------------------------------------------------------------------------------- seg++; strb.AppendLine("HL*"+HLcount.ToString()+"*"//HL01: Heirarchical ID. Here, it's always 3. +"2*"//HL02: Heirarchical parent id number. 2 in this simple message. +"22*"//HL03: Heirarchical level code. 22=Subscriber +"0~");//HL04: Heirarchical child code. 0=no child HL present (no dependent) //2000C TRN: Subscriber Trace Number seg++; strb.AppendLine("TRN*1*"//TRN01: Trace Type Code. 1=Current Transaction Trace Numbers +"1*"//TRN02: Trace Number. We don't really have a good primary key yet. Keep it simple. Use 1. +"1"+billProv.SSN+"~");//TRN03: Entity Identifier. First digit is 1=EIN. Next 9 digits are EIN. Length validated. //2100C NM1: Subscriber Name seg++; strb.AppendLine("NM1*IL*"//NM101: IL=Insured or Subscriber +"1*"//NM102: 1=Person +Sout(subscriber.LName,35)+"*"//NM103: LName +Sout(subscriber.FName,25)+"*"//NM104: FName +Sout(subscriber.MiddleI,25)+"*"//NM105: MiddleName +"*"//NM106: not used +"*"//NM107: suffix. Not present in Open Dental yet. +"MI*"//NM108: MI=MemberID +Sout(insSub.SubscriberID.Replace("-",""),80)+"~");//NM109: Subscriber ID. Validated to be L>2. //2100C REF: Subscriber Additional Information. Without this, old plans seem to be frequently returned. seg++; strb.AppendLine("REF*6P*"//REF01: 6P=GroupNumber +Sout(insPlan.GroupNum,30)+"~");//REF02: Supplemental ID. Validated. //2100C DMG: Subscriber Demographic Information seg++; strb.AppendLine("DMG*D8*"//DMG01: Date Time Period Qualifier. D8=CCYYMMDD +subscriber.Birthdate.ToString("yyyyMMdd")+"~");//DMG02: Subscriber birthdate. Validated //DMG03: Gender code. Situational. F or M. Since this was left out in the example, //and since we don't want to send the wrong gender, we will not send this element. //2100C DTP: Subscriber Date. Deduced through trial and error that this is required by EHG even though not by X12 specs. seg++; strb.AppendLine("DTP*307*"//DTP01: Qualifier. 307=Eligibility +"D8*"//DTP02: Format Qualifier. +DateTime.Today.ToString("yyyyMMdd")+"~");//DTP03: Date //2110C EQ: Subscriber Eligibility or Benefit Enquiry Information //We can loop this 99 times to request very specific benefits. //strb.AppendLine("EQ*30~");//EQ01: 30=General Coverage seg++; strb.AppendLine("EQ*23~");//Diagnostic seg++; strb.AppendLine("EQ*4~");//Diagnostic Xray seg++; strb.AppendLine("EQ*41~");//Routine Preventive seg++; strb.AppendLine("EQ*25~");//Restorative seg++; strb.AppendLine("EQ*26~");//Endo seg++; strb.AppendLine("EQ*24~");//Perio seg++; strb.AppendLine("EQ*40~");//Oral Surgery seg++; strb.AppendLine("EQ*36~");//Crowns seg++; strb.AppendLine("EQ*39~");//Prosth seg++; strb.AppendLine("EQ*27~");//Maxillofacial Prosth seg++; strb.AppendLine("EQ*37~");//Accident seg++; strb.AppendLine("EQ*38~");//Ortho seg++; strb.AppendLine("EQ*28~");//Adjunctive // //2000D If we add a dependent loop it would go here. It would be about 20 lines. //2100D, etc //EQ series, etc. //Not allowed to send this unless subscriber and dependent are different //We would also have to add code to process the EBs which distinguishes between subscribers and dependents. // //Transaction Trailer seg++; strb.AppendLine("SE*" +seg.ToString()+"*"//SE01: Total segments, including ST & SE +transactionNum.ToString().PadLeft(4,'0')+"~"); //End of transaction-------------------------------------------------------------------------------------- //Functional Group Trailer strb.AppendLine("GE*"+transactionNum.ToString()+"*"//GE01: Number of transaction sets included +groupControlNumber+"~");//GE02: Group Control number. Must be identical to GS06 //Interchange Control Trailer strb.AppendLine("IEA*1*"//IEA01: number of functional groups +batchNum.ToString().PadLeft(9,'0')+"~");//IEA02: Interchange control number return strb.ToString(); /* return @" ISA*00* *00* *30*AA0989922 *30*330989922 *030519*1608*U*00401*000012145*1*T*:~ GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~ ST*270*0001~ BHT*0022*13*ASX012145WEB*20030519*1608~ HL*1**20*1~ NM1*PR*2*Metlife*****PI*65978~ HL*2*1*21*1~ NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~ REF*TJ*200384584~ N3*JUNIT ROAD~ N4*CHICAGO*IL*60602~ PRV*PE*ZZ*1223G0001X~ HL*3*2*22*0~ TRN*1*12145*1AA0989922~ NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~ DMG*D8*19750323~ DTP*307*D8*20030519~ EQ*30~ SE*17*0001~ GE*1*12145~ IEA*1*000012145~"; */ //return "ISA*00* *00* *30*AA0989922 *30*330989922 *030519*1608*U*00401*000012145*1*T*:~GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~ST*270*0001~BHT*0022*13*ASX012145WEB*20030519*1608~HL*1**20*1~NM1*PR*2*Metlife*****PI*65978~HL*2*1*21*1~NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~REF*TJ*200384584~N3*JUNIT ROAD~N4*CHICAGO*IL*60602~PRV*PE*ZZ*1223G0001X~HL*3*2*22*0~TRN*1*12145*1AA0989922~NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~DMG*D8*19750323~DTP*307*D8*20030519~EQ*30~SE*17*0001~GE*1*12145~IEA*1*000012145~"; }
///<summary>Used when creating a claim to create any missing claimProcs. Also used in FormProcEdit if click button to add Estimate. Inserts it into db. It will still be altered after this to fill in the fields that actually attach it to the claim.</summary> public static void CreateEst(ClaimProc cp, Procedure proc, InsPlan plan,InsSub sub) { //No need to check RemotingRole; no call to db. cp.ProcNum=proc.ProcNum; //claimnum cp.PatNum=proc.PatNum; cp.ProvNum=proc.ProvNum; if(plan.PlanType=="c") {//capitation if(proc.ProcStatus==ProcStat.C) {//complete cp.Status=ClaimProcStatus.CapComplete;//in this case, a copy will be made later. } else {//usually TP status cp.Status=ClaimProcStatus.CapEstimate; } } else { cp.Status=ClaimProcStatus.Estimate; } cp.PlanNum=plan.PlanNum; cp.InsSubNum=sub.InsSubNum; cp.DateCP=proc.ProcDate; //Writeoff=0 cp.AllowedOverride=-1; cp.Percentage=-1; cp.PercentOverride=-1; cp.CopayAmt=-1; cp.NoBillIns=false; cp.PaidOtherIns=-1; cp.BaseEst=0; cp.DedEst=-1; cp.DedEstOverride=-1; cp.InsEstTotal=0; cp.InsEstTotalOverride=-1; cp.CopayOverride=-1; cp.PaidOtherInsOverride=-1; cp.ProcDate=proc.ProcDate; cp.WriteOffEst=-1; cp.WriteOffEstOverride=-1; cp.ClinicNum=proc.ClinicNum; Insert(cp); }
///<summary></summary> private void butOK_Click(object sender, System.EventArgs e) { if(textMain.Text==""){ MsgBox.Show(this,"Please paste the text generated by the other program into the large box first."); return; } pat=new Patient(); pat.PriProv=PrefC.GetLong(PrefName.PracticeDefaultProv); pat.BillingType=PrefC.GetLong(PrefName.PracticeDefaultBillType); guar=new Patient(); guar.PriProv=PrefC.GetLong(PrefName.PracticeDefaultProv); guar.BillingType=PrefC.GetLong(PrefName.PracticeDefaultBillType); subsc=new Patient(); subsc.PriProv=PrefC.GetLong(PrefName.PracticeDefaultProv); subsc.BillingType=PrefC.GetLong(PrefName.PracticeDefaultBillType); sub=new InsSub(); sub.ReleaseInfo=true; sub.AssignBen=true; plan=new InsPlan(); carrier=new Carrier(); insRelat="self";//this is the default if not included guarRelat="self"; InsEmp=""; GuarEmp=""; NoteMedicalComp=""; insPresent=false; annualMax=-1; deductible=-1; XmlTextReader reader=new XmlTextReader(new StringReader(textMain.Text)); reader.WhitespaceHandling=WhitespaceHandling.None; string element=""; string textValue=""; string rootElement=""; string segment="";//eg PatientIdentification string field="";//eg NameLast string endelement=""; warnings=""; try{ while(reader.Read()){ switch(reader.NodeType){ case XmlNodeType.Element: element=reader.Name; if(rootElement==""){//should be the first node if(element=="Message"){ rootElement="Message"; } else{ throw new Exception(element+" should not be the first element."); } } else if(segment==""){//expecting a new segment segment=element; if(segment!="MessageHeader" && segment!="PatientIdentification" && segment!="Guarantor" && segment!="Insurance") { throw new Exception(segment+" is not a recognized segment."); } } else{//expecting a new field field=element; } if(segment=="Insurance"){ insPresent=true; } break; case XmlNodeType.Text: textValue=reader.Value; if(field==""){ throw new Exception("Unexpected text: "+textValue); } break; case XmlNodeType.EndElement: endelement=reader.Name; if(field==""){//we're not in a field, so we must be closing a segment or rootelement if(segment==""){//we're not in a segment, so we must be closing the rootelement if(rootElement=="Message"){ rootElement=""; } else{ throw new Exception("Message closing element expected."); } } else{//must be closing a segment segment=""; } } else{//closing a field field=""; textValue=""; } break; }//switch if(rootElement==""){ break;//this will ignore anything after the message endelement } if(field!="" && textValue!=""){ if(segment=="MessageHeader"){ ProcessMSH(field,textValue); } else if(segment=="PatientIdentification"){ ProcessPID(field,textValue); } else if(segment=="Guarantor"){ ProcessGT(field,textValue); } else if(segment=="Insurance"){ ProcessINS(field,textValue); } } }//while } catch(Exception ex){ MessageBox.Show(ex.Message); //MsgBox.Show(this,"Error in the XML format."); reader.Close(); return; } finally{ reader.Close(); } //Warnings and errors----------------------------------------------------------------------------- if(pat.LName=="" || pat.FName=="" || pat.Birthdate.Year<1880){ MsgBox.Show(this,"Patient first and last name and birthdate are required. Could not import."); return; } //if guarRelat is not self, and name and birthdate not supplied, no error. Just make guar self. if(guarRelat!="self"){ if(guar.LName=="" || guar.FName=="" || guar.Birthdate.Year<1880){ warnings+="Guarantor information incomplete. Guarantor will be self.\r\n"; guarRelat="self"; } } if(insPresent){ if(carrier.CarrierName==""){ warnings+="Insurance CompanyName is missing. No insurance info will be imported.\r\n"; insPresent=false; } else if(insRelat!="self"){ if(subsc.LName=="" || subsc.FName=="" || subsc.Birthdate.Year<1880){ warnings+="Subscriber name or birthdate is missing. No insurance info will be imported.\r\n"; insPresent=false; } } else if(sub.SubscriberID==""){ warnings+="PolicyNumber/SubscriberID missing.\r\n"; sub.SubscriberID=" "; } } if(warnings!=""){ if(MessageBox.Show("It's safe to import, but you should be aware of the following issues:\r\n"+warnings+"\r\nContinue with Import?","Warnings",MessageBoxButtons.OKCancel)!=DialogResult.OK){ return; } } //Patient------------------------------------------------------------------------------------- //DataTable table; long patNum=Patients.GetPatNumByNameAndBirthday(pat.LName,pat.FName,pat.Birthdate); Patient existingPat=null; existingPatOld=null;//we will need this to do an update. if(patNum != 0){//a patient already exists, so only add missing fields existingPat=Patients.GetPat(patNum); existingPatOld=existingPat.Copy(); if(existingPat.MiddleI==""){//only alter existing if blank existingPat.MiddleI=pat.MiddleI; } if(pat.Gender!=PatientGender.Unknown){ existingPat.Gender=pat.Gender; } if(existingPat.Preferred==""){ existingPat.Preferred=pat.Preferred; } if(existingPat.Address==""){ existingPat.Address=pat.Address; } if(existingPat.Address2==""){ existingPat.Address2=pat.Address2; } if(existingPat.City==""){ existingPat.City=pat.City; } if(existingPat.State==""){ existingPat.State=pat.State; } if(existingPat.Zip==""){ existingPat.Zip=pat.Zip; } if(existingPat.HmPhone==""){ existingPat.HmPhone=pat.HmPhone; } if(existingPat.Email==""){ existingPat.Email=pat.Email; } if(existingPat.WkPhone==""){ existingPat.WkPhone=pat.WkPhone; } if(existingPat.Position==PatientPosition.Single){ existingPat.Position=pat.Position; } if(existingPat.SSN==""){ existingPat.SSN=pat.SSN; } existingPat.AddrNote+=pat.AddrNote;//concat Patients.Update(existingPat,existingPatOld); PatientNote PatientNoteCur=PatientNotes.Refresh(existingPat.PatNum,existingPat.Guarantor); PatientNoteCur.MedicalComp+=NoteMedicalComp; PatientNotes.Update(PatientNoteCur,existingPat.Guarantor); //guarantor will not be altered in any way }//if patient already exists else{//patient is new, so insert Patients.Insert(pat,false); existingPatOld=pat.Copy(); pat.Guarantor=pat.PatNum;//this can be changed later. Patients.Update(pat,existingPatOld); PatientNote PatientNoteCur=PatientNotes.Refresh(pat.PatNum,pat.Guarantor); PatientNoteCur.MedicalComp+=NoteMedicalComp; PatientNotes.Update(PatientNoteCur,pat.Guarantor); } //guar----------------------------------------------------------------------------------------------------- if(existingPat==null){//only add or alter guarantor for new patients if(guarRelat=="self"){ //pat is already set with guar as self //ignore all guar fields except EmployerName existingPatOld=pat.Copy(); pat.EmployerNum=Employers.GetEmployerNum(GuarEmp); Patients.Update(pat,existingPatOld); } else{ //if guarRelat is not self, and name and birthdate not supplied, a warning was issued, and relat was changed to self. //add guarantor or attach to an existing guarantor long guarNum=Patients.GetPatNumByNameAndBirthday(guar.LName,guar.FName,guar.Birthdate); if(guarNum != 0){//a guar already exists, so simply attach. Make no other changes existingPatOld=pat.Copy(); pat.Guarantor=guarNum; if(guarRelat=="parent"){ pat.Position=PatientPosition.Child; } Patients.Update(pat,existingPatOld); } else{//we need to completely create guar, then attach Patients.Insert(guar,false); //set guar for guar existingPatOld=guar.Copy(); guar.Guarantor=guar.PatNum; guar.EmployerNum=Employers.GetEmployerNum(GuarEmp); Patients.Update(guar,existingPatOld); //set guar for pat existingPatOld=pat.Copy(); pat.Guarantor=guar.PatNum; if(guarRelat=="parent"){ pat.Position=PatientPosition.Child; } Patients.Update(pat,existingPatOld); } } } //subsc-------------------------------------------------------------------------------------------------- if(!insPresent){ //this takes care of missing carrier name or subscriber info. MsgBox.Show(this,"Done"); DialogResult=DialogResult.OK; } if(insRelat=="self"){ sub.Subscriber=pat.PatNum; } else{//we need to find or add the subscriber patNum=Patients.GetPatNumByNameAndBirthday(subsc.LName,subsc.FName,subsc.Birthdate); if(patNum != 0){//a subsc already exists, so simply attach. Make no other changes sub.Subscriber=patNum; } else{//need to create and attach a subscriber Patients.Insert(subsc,false); //set guar to same guar as patient existingPatOld=subsc.Copy(); subsc.Guarantor=pat.Guarantor; Patients.Update(subsc,existingPatOld); sub.Subscriber=subsc.PatNum; } } //carrier------------------------------------------------------------------------------------------------- //Carriers.Cur=carrier; carrier=Carriers.GetIndentical(carrier);//this automatically finds or creates a carrier //plan------------------------------------------------------------------------------------------------------ plan.EmployerNum=Employers.GetEmployerNum(InsEmp); plan.CarrierNum=carrier.CarrierNum; InsPlans.Insert(plan); //Attach plan to subscriber sub.PlanNum=plan.PlanNum; InsSubs.Insert(sub); //Then attach plan List <PatPlan> PatPlanList=PatPlans.Refresh(pat.PatNum); PatPlan patplan=new PatPlan(); patplan.Ordinal=(byte)(PatPlanList.Count+1);//so the ordinal of the first entry will be 1, NOT 0. patplan.PatNum=pat.PatNum; patplan.InsSubNum=sub.InsSubNum; switch(insRelat){ case "self": patplan.Relationship=Relat.Self; break; case "parent": patplan.Relationship=Relat.Child; break; case "spouse": patplan.Relationship=Relat.Spouse; break; case "guardian": patplan.Relationship=Relat.Dependent; break; } PatPlans.Insert(patplan); //benefits if(annualMax!=-1 && CovCatC.ListShort.Count>0){ Benefit ben=new Benefit(); ben.BenefitType=InsBenefitType.Limitations; ben.CovCatNum=CovCatC.ListShort[0].CovCatNum; ben.MonetaryAmt=annualMax; ben.PlanNum=plan.PlanNum; ben.TimePeriod=BenefitTimePeriod.CalendarYear; Benefits.Insert(ben); } if(deductible!=-1 && CovCatC.ListShort.Count>0) { Benefit ben=new Benefit(); ben.BenefitType=InsBenefitType.Deductible; ben.CovCatNum=CovCatC.ListShort[0].CovCatNum; ben.MonetaryAmt=deductible; ben.PlanNum=plan.PlanNum; ben.TimePeriod=BenefitTimePeriod.CalendarYear; Benefits.Insert(ben); } MsgBox.Show(this,"Done"); DialogResult=DialogResult.OK; }
///<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); } if(clearhouse.CommBridge==EclaimsCommBridge.EDS) { x12response=EDS.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 {//not a 997, 999, 277 or 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){ 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{ 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 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); MessageBox.Show(etrans.Note); //CodeBase.MsgBoxCopyPaste msgbox=new CodeBase.MsgBoxCopyPaste(etrans.Note); //msgbox.ShowDialog(); //don't show the 270 interface. return; } 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); MessageBox.Show(etrans.Note); //CodeBase.MsgBoxCopyPaste msgbox=new CodeBase.MsgBoxCopyPaste(etrans.Note); //msgbox.ShowDialog(); //don't show the 277 interface. return; } else if(etrans271.Etype==EtransType.ERA_835) { X835 x835=new X835(x12response,""); string error835=x835.GetHumanReadable(); etrans.Note="Error: "+error835;//"Malformed document sent. 835 error returned."; Etranss.Update(etrans); MessageBox.Show(etrans.Note); //CodeBase.MsgBoxCopyPaste msgbox=new CodeBase.MsgBoxCopyPaste(etrans.Note); //msgbox.ShowDialog(); //don't show the 835 interface. return; } else { //271 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>In progress. Probably needs a different name. Info must be validated first. ///Set dependent to the currently selected patient, compares dependent.PatNum to subscriber.PatNum to either contruct a subscriber based or dependent based benefit request.</summary> public static string GenerateMessageText(Clearinghouse clearinghouseClin, Carrier carrier, Provider billProv, Clinic clinic, InsPlan insPlan, Patient subscriber, InsSub insSub, Patient patForRequest) { bool isSubscriberRequest = (subscriber.PatNum == patForRequest.PatNum); int batchNum = Clearinghouses.GetNextBatchNumber(clearinghouseClin); string groupControlNumber = batchNum.ToString(); //Must be unique within file. We will use batchNum int transactionNum = 1; StringBuilder strb = new StringBuilder(); //Interchange Control Header strb.Append("ISA*00* *"); //ISA01,ISA02: 00 + 10 spaces if (IsEmdeonDental(clearinghouseClin)) { strb.Append("00*" + Sout(clearinghouseClin.Password, 10, 10) + "*" //ISA03,ISA04: 00 + emdeon password padded to 10 characters + clearinghouseClin.ISA05 + "*" //ISA05: Sender ID type: ZZ=mutually defined. 30=TIN. Validated + "316:" + Sout(clearinghouseClin.LoginID, 11, 11) + "*" //ISA06: Emdeon vendor number + username + clearinghouseClin.ISA07 + "*" //ISA07: Receiver ID type: ZZ=mutually defined. 30=TIN. Validated + Sout("EMDEONDENTAL", 15, 15) + "*"); //ISA08: Receiver ID. Validated to make sure length is at least 2. } else { strb.Append("00* *" //ISA03,ISA04: 00 + 10 spaces + clearinghouseClin.ISA05 + "*" //ISA05: Sender ID type: ZZ=mutually defined. 30=TIN. Validated + X12Generator.GetISA06(clearinghouseClin) + "*" //ISA06: Sender ID(TIN). Or might be TIN of Open Dental + clearinghouseClin.ISA07 + "*" //ISA07: Receiver ID type: ZZ=mutually defined. 30=TIN. Validated + Sout(clearinghouseClin.ISA08, 15, 15) + "*"); //ISA08: Receiver ID. Validated to make sure length is at least 2. } strb.AppendLine(DateTime.Today.ToString("yyMMdd") + "*" //ISA09: today's date + DateTime.Now.ToString("HHmm") + "*" //ISA10: current time + "U*00401*" //ISA11 and ISA12. //ISA13: interchange control number, right aligned: + batchNum.ToString().PadLeft(9, '0') + "*" + "0*" //ISA14: no acknowledgment requested + clearinghouseClin.ISA15 + "*" //ISA15: T=Test P=Production. Validated. + ":~"); //ISA16: use ':' //Functional Group Header if (IsEmdeonDental(clearinghouseClin)) { strb.Append("GS*HS*" //GS01: HS for 270 benefit inquiry + X12Generator.GetGS02(clearinghouseClin) + "*" //GS02: Senders Code. Sometimes Jordan Sparks. Sometimes the sending clinic. + Sout("EMDEONDENTAL", 15, 15) + "*"); //GS03: Application Receiver's Code } else { strb.Append("GS*HS*" //GS01: HS for 270 benefit inquiry + X12Generator.GetGS02(clearinghouseClin) + "*" //GS02: Senders Code. Sometimes Jordan Sparks. Sometimes the sending clinic. + Sout(clearinghouseClin.GS03, 15, 2) + "*"); //GS03: Application Receiver's Code } strb.AppendLine(DateTime.Today.ToString("yyyyMMdd") + "*" //GS04: today's date + DateTime.Now.ToString("HHmm") + "*" //GS05: current time + groupControlNumber + "*" //GS06: Group control number. Max length 9. No padding necessary. + "X*" //GS07: X + "004010X092~"); //GS08: Version //Beginning of transaction-------------------------------------------------------------------------------- int seg = 0; //count segments for the ST-SE transaction //Transaction Set Header //ST02 Transact. control #. Must be unique within ISA seg++; strb.AppendLine("ST*270*" //ST01 + transactionNum.ToString().PadLeft(4, '0') + "~"); //ST02 seg++; strb.AppendLine("BHT*0022*13*" //BHT02: 13=request + transactionNum.ToString().PadLeft(4, '0') + "*" //BHT03. Can be same as ST02 + DateTime.Now.ToString("yyyyMMdd") + "*" //BHT04: Date + DateTime.Now.ToString("HHmmss") + "~"); //BHT05: Time, BHT06: not used //HL Loops----------------------------------------------------------------------------------------------- int HLcount = 1; //2000A HL: Information Source-------------------------------------------------------------------------- seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. Here, it's always 1. + "*" //HL02: No parent. Not used + "20*" //HL03: Heirarchical level code. 20=Information source + "1~"); //HL04: Heirarchical child code. 1=child HL present //2100A NM1 seg++; strb.AppendLine("NM1*PR*" //NM101: PR=Payer + "2*" //NM102: 2=Non person + Sout(carrier.CarrierName, 35) + "*" //NM103: Name Last. + "****" //NM104-07 not used + "PI*" //NM108: PI=PayorID + Sout(carrier.ElectID, 80, 2) + "~"); //NM109: PayorID. Validated to be at least length of 2. HLcount++; //2000B HL: Information Receiver------------------------------------------------------------------------ seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. Here, it's always 2. + "1*" //HL02: Heirarchical parent id number. 1 in this simple message. + "21*" //HL03: Heirarchical level code. 21=Information receiver + "1~"); //HL04: Heirarchical child code. 1=child HL present seg++; //2100B NM1: Information Receiver Name strb.AppendLine("NM1*1P*" //NM101: 1P=Provider + (billProv.IsNotPerson?"2":"1") + "*" //NM102: 1=person,2=non-person + Sout(billProv.LName, 35) + "*" //NM103: Last name + Sout(billProv.FName, 25) + "*" //NM104: First name + Sout(billProv.MI, 25, 1) + "*" //NM105: Middle name + "*" //NM106: not used + "*" //NM107: Name suffix. not used + "XX*" //NM108: ID code qualifier. 24=EIN. 34=SSN, XX=NPI + Sout(billProv.NationalProvID, 80) + "~"); //NM109: ID code. NPI validated //2100B REF: Information Receiver ID if (IsEmdeonDental(clearinghouseClin) && IsDentiCalCarrier(carrier)) { string ref4aSegment = ""; Clearinghouse clearinghouseDentiCalHQ = Clearinghouses.GetFirstOrDefault(x => IsDentiCalClearinghouse(x), true); if (clearinghouseDentiCalHQ != null) { Clearinghouse clearinghouseDentiCalClin = Clearinghouses.OverrideFields(clearinghouseDentiCalHQ, clearinghouseClin.ClinicNum); if (clearinghouseDentiCalClin != null) { ref4aSegment = clearinghouseDentiCalClin.Password; } } seg++; strb.Append("REF*4A*" + ref4aSegment + "~"); } seg++; strb.Append("REF*"); if (billProv.UsingTIN) { strb.Append("TJ*"); //REF01: qualifier. TJ=Federal TIN } else //SSN { strb.Append("SY*"); //REF01: qualifier. SY=SSN } strb.AppendLine(Sout(billProv.SSN, 30) + "~"); //REF02: ID //2100B N3: Information Receiver Address seg++; if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { strb.Append("N3*" + Sout(PrefC.GetString(PrefName.PracticeBillingAddress), 55)); //N301: Address } else if (clinic == null) { strb.Append("N3*" + Sout(PrefC.GetString(PrefName.PracticeAddress), 55)); //N301: Address } else { strb.Append("N3*" + Sout(clinic.Address, 55)); //N301: Address } if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { if (PrefC.GetString(PrefName.PracticeBillingAddress2) == "") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*" + Sout(PrefC.GetString(PrefName.PracticeBillingAddress2), 55) + "~"); } } else if (clinic == null) { if (PrefC.GetString(PrefName.PracticeAddress2) == "") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*" + Sout(PrefC.GetString(PrefName.PracticeAddress2), 55) + "~"); } } else { if (clinic.Address2 == "") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*" + Sout(clinic.Address2, 55) + "~"); } } //2100B N4: Information Receiver City/State/Zip seg++; if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { strb.AppendLine("N4*" + Sout(PrefC.GetString(PrefName.PracticeBillingCity), 30) + "*" //N401: City + Sout(PrefC.GetString(PrefName.PracticeBillingST), 2) + "*" //N402: State + Sout(PrefC.GetString(PrefName.PracticeBillingZip).Replace("-", ""), 15) + "~"); //N403: Zip } else if (clinic == null) { strb.AppendLine("N4*" + Sout(PrefC.GetString(PrefName.PracticeCity), 30) + "*" //N401: City + Sout(PrefC.GetString(PrefName.PracticeST), 2) + "*" //N402: State + Sout(PrefC.GetString(PrefName.PracticeZip).Replace("-", ""), 15) + "~"); //N403: Zip } else { strb.AppendLine("N4*" + Sout(clinic.City, 30) + "*" //N401: City + Sout(clinic.State, 2) + "*" //N402: State + Sout(clinic.Zip.Replace("-", ""), 15) + "~"); //N403: Zip } //2100B PRV: Information Receiver Provider Info seg++; //PRV*PE*ZZ*1223G0001X~ strb.AppendLine("PRV*PE*" //PRV01: Provider Code. PE=Performing. There are many other choices. + "ZZ*" //PRV02: ZZ=Mutually defined = health care provider taxonomy code + X12Generator.GetTaxonomy(billProv) + "~"); //PRV03: Specialty code HLcount++; //2000C HL: Subscriber----------------------------------------------------------------------------------- seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. Here, it's always 3. + "2*" //HL02: Heirarchical parent id number. 2 in this simple message. + "22*" //HL03: Heirarchical level code. 22=Subscriber + (isSubscriberRequest?"0~":"1~")); //HL04: Heirarchical child code. 0=no child HL present (no dependent) else 1 //2000C TRN: Subscriber Trace Number seg++; strb.AppendLine("TRN*1*" //TRN01: Trace Type Code. 1=Current Transaction Trace Numbers + "1*" //TRN02: Trace Number. We don't really have a good primary key yet. Keep it simple. Use 1. + "1" + billProv.SSN + "~"); //TRN03: Entity Identifier. First digit is 1=EIN. Next 9 digits are EIN. Length validated. //2100C NM1: Subscriber Name seg++; strb.AppendLine("NM1*IL*" //NM101: IL=Insured or Subscriber + "1*" //NM102: 1=Person + Sout(subscriber.LName, 35) + "*" //NM103: LName + Sout(subscriber.FName, 25) + "*" //NM104: FName + Sout(subscriber.MiddleI, 25) + "*" //NM105: MiddleName + "*" //NM106: not used + "*" //NM107: suffix. Not present in Open Dental yet. + "MI*" //NM108: MI=MemberID + Sout(insSub.SubscriberID.Replace("-", ""), 80) + "~"); //NM109: Subscriber ID. Validated to be L>2. //2100C REF: Subscriber Additional Information. Without this, old plans seem to be frequently returned. seg++; strb.AppendLine("REF*6P*" //REF01: 6P=GroupNumber + Sout(insPlan.GroupNum, 30) + "~"); //REF02: Supplemental ID. Validated. //2100C DMG: Subscriber Demographic Information seg++; strb.AppendLine("DMG*D8*" //DMG01: Date Time Period Qualifier. D8=CCYYMMDD + subscriber.Birthdate.ToString("yyyyMMdd") + "~"); //DMG02: Subscriber birthdate. Validated //DMG03: Gender code. Situational. F or M. Since this was left out in the example, //and since we don't want to send the wrong gender, we will not send this element. //2100C DTP: Subscriber Date. Deduced through trial and error that this is required by EHG even though not by X12 specs. seg++; strb.AppendLine("DTP*307*" //DTP01: Qualifier. 307=Eligibility + "D8*" //DTP02: Format Qualifier. + DateTime.Today.ToString("yyyyMMdd") + "~"); //DTP03: Date //2000D HL: Dependent Level Hierarchical Level if (isSubscriberRequest) { //2110C EQ: Subscriber Eligibility or Benefit Enquiry Information //X12 documentation seems to say that we can loop this 99 times to request very specific benefits. //ClaimConnect wants to see either an EQ*30 for "an eligibility request", or an EQ*35 for "a general benefits request". //The director of vendor implementation at ClaimConnect has informed us that we should send an EQ*35 to get the full set of benefits. seg++; strb.AppendLine("EQ*35~"); //Dental Care } else //Dependent based request. { HLcount++; seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. + (HLcount - 1).ToString() + "*" //HL02: Heirarchical parent id number. + "23*" //HL03: Heirarchical level code. 23=Dependent + "0~"); //HL04: Heirarchical child code. 0=no child HL present (no dependent) //2000D TRN: Dependent Trace Number seg++; strb.AppendLine("TRN*1*" //TRN01: Trace Type Code. 1=Current Transaction Trace Numbers + "1*" //TRN02: Trace Number. We don't really have a good primary key yet. Keep it simple. Use 1. + "1" + billProv.SSN + "~"); //TRN03: Entity Identifier. First digit is 1=EIN. Next 9 digits are EIN. Length validated. //2100D NM1: Dependent Name seg++; strb.AppendLine("NM1*03*" //NM101: 03=Dependent + "1*" //NM102: 1=Person + Sout(patForRequest.LName, 35) + "*" //NM103: Name Last or Organization Name + Sout(patForRequest.FName, 25) + "*" //NM104: Name First + Sout(patForRequest.MiddleI, 25) + "~"); //NM105: Name Middle //2100D REF: Dependent Additional Identification seg++; strb.AppendLine("REF*6P*" //REF01: 6P=GroupNumber + Sout(insPlan.GroupNum, 30) + "~"); //REF02: Supplemental ID. Validated. //2100D DMG: Dependent Demographic Information seg++; strb.AppendLine("DMG*D8*" //DMG01: Date Time Period Qualifier. D8=CCYYMMDD + patForRequest.Birthdate.ToString("yyyyMMdd") + "~"); //DMG02: Dependent birthdate. Validated //DMG03: Gender code. Situational. F or M. Since this was left out in the example, //and since we don't want to send the wrong gender, we will not send this element. //2100D DTP: DEPENDENT Date. Deduced through trial and error that this is required by EHG even though not by X12 specs. seg++; strb.AppendLine("DTP*307*" //DTP01: Qualifier. 307=Eligibility + "D8*" //DTP02: Format Qualifier. + DateTime.Today.ToString("yyyyMMdd") + "~"); //DTP03: Date seg++; strb.AppendLine("EQ*35~"); //Dental Care } //Transaction Trailer seg++; strb.AppendLine("SE*" + seg.ToString() + "*" //SE01: Total segments, including ST & SE + transactionNum.ToString().PadLeft(4, '0') + "~"); //End of transaction-------------------------------------------------------------------------------------- //Functional Group Trailer strb.AppendLine("GE*" + transactionNum.ToString() + "*" //GE01: Number of transaction sets included + groupControlNumber + "~"); //GE02: Group Control number. Must be identical to GS06 //Interchange Control Trailer strb.AppendLine("IEA*1*" //IEA01: number of functional groups + batchNum.ToString().PadLeft(9, '0') + "~"); //IEA02: Interchange control number return(strb.ToString()); /* * return @" * ISA*00* *00* *30*AA0989922 *30*330989922 *030519*1608*U*00401*000012145*1*T*:~ * GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~ * ST*270*0001~ * BHT*0022*13*ASX012145WEB*20030519*1608~ * HL*1**20*1~ * NM1*PR*2*Metlife*****PI*65978~ * HL*2*1*21*1~ * NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~ * REF*TJ*200384584~ * N3*JUNIT ROAD~ * N4*CHICAGO*IL*60602~ * PRV*PE*ZZ*1223G0001X~ * HL*3*2*22*0~ * TRN*1*12145*1AA0989922~ * NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~ * DMG*D8*19750323~ * DTP*307*D8*20030519~ * EQ*30~ * SE*17*0001~ * GE*1*12145~ * IEA*1*000012145~"; */ //return "ISA*00* *00* *30*AA0989922 *30*330989922 *030519*1608*U*00401*000012145*1*T*:~GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~ST*270*0001~BHT*0022*13*ASX012145WEB*20030519*1608~HL*1**20*1~NM1*PR*2*Metlife*****PI*65978~HL*2*1*21*1~NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~REF*TJ*200384584~N3*JUNIT ROAD~N4*CHICAGO*IL*60602~PRV*PE*ZZ*1223G0001X~HL*3*2*22*0~TRN*1*12145*1AA0989922~NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~DMG*D8*19750323~DTP*307*D8*20030519~EQ*30~SE*17*0001~GE*1*12145~IEA*1*000012145~"; }
public static string ClaimWithInvalidInsSubNum(bool verbose,bool isCheck) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { return Meth.GetString(MethodBase.GetCurrentMethod(),verbose,isCheck); } string log=""; if(isCheck) { //check 2 situations: //1. claim.PlanNum=0 and inssub.PlanNum=0 command=@"SELECT COUNT(*) FROM claim,inssub WHERE claim.InsSubNum=inssub.InsSubNum AND claim.PlanNum=0 AND inssub.PlanNum=0 "; int planCount=PIn.Int(Db.GetCount(command)); //2. claim.PlanNum=0 and inssub does not exist command=@"SELECT COUNT(*) FROM claim WHERE PlanNum=0 AND InsSubNum NOT IN (SELECT InsSubNum FROM inssub WHERE inssub.InsSubNum=claim.InsSubNum)"; int existCount=PIn.Int(Db.GetCount(command)); int numFound=planCount+existCount; if(numFound!=0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Claims with invalid InsSubNum: ")+numFound+"\r\n"; } //situation where PlanNum and InsSubNum are both invalid and not zero is handled in InsSubNumMismatchPlanNum } else { command=@"SELECT claim.ClaimNum,claim.PatNum FROM claim,inssub WHERE claim.InsSubNum=inssub.InsSubNum AND claim.PlanNum=0 AND inssub.PlanNum=0 " +"UNION " +"SELECT ClaimNum,PatNum FROM claim WHERE PlanNum=0 AND InsSubNum NOT IN (SELECT InsSubNum FROM inssub WHERE inssub.InsSubNum=claim.InsSubNum)"; table=Db.GetTable(command); long numberFixed=table.Rows.Count; InsPlan plan=null; InsSub sub=null; if(numberFixed>0) { log+=Lans.g("FormDatabaseMaintenance","List of patients who will need insurance information reentered:")+"\r\n"; } for(int i=0;i<numberFixed;i++) { plan=new InsPlan();//Create a dummy plan and carrier to attach claims and claim procs to. plan.IsHidden=true; plan.CarrierNum=Carriers.GetByNameAndPhone("UNKNOWN CARRIER","").CarrierNum; InsPlans.Insert(plan); long claimNum=PIn.Long(table.Rows[i]["ClaimNum"].ToString()); long patNum=PIn.Long(table.Rows[i]["PatNum"].ToString()); sub=new InsSub();//Create inssubs and attach claim and procs to both plan and inssub. sub.PlanNum=plan.PlanNum; sub.Subscriber=PIn.Long(table.Rows[i]["PatNum"].ToString()); sub.SubscriberID="unknown"; InsSubs.Insert(sub); command="UPDATE claim SET PlanNum="+plan.PlanNum+",InsSubNum="+sub.InsSubNum+" WHERE ClaimNum="+claimNum; Db.NonQ(command); command="UPDATE claimproc SET PlanNum="+plan.PlanNum+",InsSubNum="+sub.InsSubNum+" WHERE ClaimNum="+claimNum; Db.NonQ(command); Patient pat=Patients.GetLim(patNum); log+="PatNum: "+pat.PatNum+" - "+Patients.GetNameFL(pat.LName,pat.FName,pat.Preferred,pat.MiddleI)+"\r\n"; } if(numberFixed>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Claims with invalid InsSubNum fixed: ")+numberFixed.ToString()+"\r\n"; } } return log; }
public static string Validate(Clearinghouse clearhouse, Carrier carrier, Provider billProv, Clinic clinic, InsPlan insPlan, Patient subscriber, InsSub insSub) { StringBuilder strb = new StringBuilder(); X12Validate.ISA(clearhouse, strb); X12Validate.Carrier(carrier, strb); if (carrier.ElectID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Electronic ID"); } if (billProv.SSN.Length != 9) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Prov TIN 9 digits"); } X12Validate.BillProv(billProv, strb); if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { X12Validate.BillingAddress(strb); } else if (clinic == null) { X12Validate.PracticeAddress(strb); } else { X12Validate.Clinic(clinic, strb); } if (insSub.SubscriberID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("SubscriberID"); } if (subscriber.Birthdate.Year < 1880) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Subscriber Birthdate"); } if (insPlan.GroupNum == "") { if (strb.Length != 0) { strb.Append(","); } strb.Append("Group Number"); } return(strb.ToString()); }
///<summary>Returns the number of subscribers moved. ///No need to pass in userNum, it's set before remoting role check and passed to the server if necessary.</summary> public static long MoveSubscribers(long insPlanNumFrom, long insPlanNumTo, long userNum = 0) { if (RemotingClient.RemotingRole != RemotingRole.ServerWeb) { userNum = Security.CurUser.UserNum; //must be before normal remoting role check to get user at workstation } if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetLong(MethodBase.GetCurrentMethod(), insPlanNumFrom, insPlanNumTo, userNum)); } List <InsSub> listInsSubsFrom = GetListForPlanNum(insPlanNumFrom); List <long> listBlockedPatNums = new List <long>(); //Perform the same validation as when the user manually drops insplans from FormInsPlan using the Drop button. for (int i = 0; i < listInsSubsFrom.Count; i++) { InsSub insSubFrom = listInsSubsFrom[i]; List <PatPlan> listPatPlanFrom = PatPlans.Refresh(insSubFrom.Subscriber); for (int j = 0; j < listPatPlanFrom.Count; j++) { PatPlan patPlanFrom = listPatPlanFrom[j]; //The following comments and logic are copied from the FormInsPlan Drop button... //If they have a claim for this ins with today's date, don't let them drop. //We already have code in place to delete claimprocs when we drop ins, but the claimprocs attached to claims are protected. //The claim clearly needs to be deleted if they are dropping. We need the user to delete the claim before they drop the plan. //We also have code in place to add new claimprocs when they add the correct insurance. List <Claim> listClaims = Claims.Refresh(patPlanFrom.PatNum); //Get all claims for patient. for (int k = 0; k < listClaims.Count; k++) { if (listClaims[k].PlanNum != insPlanNumFrom) //Make sure the claim is for the insurance plan we are about to change, not any other plans the patient might have. { continue; } if (listClaims[k].DateService != DateTime.Today) //not today { continue; } //Patient currently has a claim for the insplan they are trying to drop. if (!listBlockedPatNums.Contains(patPlanFrom.PatNum)) { listBlockedPatNums.Add(patPlanFrom.PatNum); } } } } if (listBlockedPatNums.Count > 0) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < listBlockedPatNums.Count; i++) { sb.Append("\r\n"); Patient pat = Patients.GetPat(listBlockedPatNums[i]); sb.Append("#" + listBlockedPatNums[i] + " " + pat.GetNameFLFormal()); } throw new ApplicationException(Lans.g("InsSubs", "Before changing the subscribers on the insurance plan being moved from, please delete all of today's claims related to the insurance plan being moved from for the following patients") + ":" + sb.ToString()); } //This loop mimics some of the logic in PatPlans.Delete(). int insSubMovedCount = 0; for (int i = 0; i < listInsSubsFrom.Count; i++) { InsSub inssub = listInsSubsFrom[i]; long oldInsSubNum = inssub.InsSubNum; inssub.InsSubNum = 0; //This will allow us to insert a new record. inssub.PlanNum = insPlanNumTo; inssub.DateEffective = DateTime.MinValue; inssub.BenefitNotes = ""; inssub.SubscNote = ""; inssub.SecUserNumEntry = userNum; long insSubNumNew = InsSubs.Insert(inssub); string command = "SELECT PatNum FROM patplan WHERE InsSubNum=" + POut.Long(oldInsSubNum); DataTable tablePatsForInsSub = Db.GetTable(command); if (tablePatsForInsSub.Rows.Count == 0) { continue; } insSubMovedCount++; for (int j = 0; j < tablePatsForInsSub.Rows.Count; j++) { long patNum = PIn.Long(tablePatsForInsSub.Rows[j]["PatNum"].ToString()); List <PatPlan> listPatPlans = PatPlans.Refresh(patNum); for (int k = 0; k < listPatPlans.Count; k++) { PatPlan patPlan = listPatPlans[k]; if (patPlan.InsSubNum == oldInsSubNum) { command = "DELETE FROM benefit WHERE PatPlanNum=" + POut.Long(patPlan.PatPlanNum); //Delete patient specific benefits (rare). Db.NonQ(command); patPlan.InsSubNum = insSubNumNew; PatPlans.Update(patPlan); } } //Now that the plan has changed for the current subscriber, recalculate estimates. bool prefChanged = false; //Forcefully set pref false to prevent creating new estimates for all procs (including completed, sent procs) if (Prefs.UpdateBool(PrefName.ClaimProcsAllowedToBackdate, false)) { prefChanged = true; //We will turn the preference back on for the user after we finish our computations. } Family fam = Patients.GetFamily(patNum); Patient pat = fam.GetPatient(patNum); List <ClaimProc> listClaimProcs = ClaimProcs.Refresh(patNum); List <Procedure> listProcs = Procedures.Refresh(patNum); listPatPlans = PatPlans.Refresh(patNum); List <InsSub> listInsSubs = InsSubs.RefreshForFam(fam); List <InsPlan> listInsPlans = InsPlans.RefreshForSubList(listInsSubs); List <Benefit> listBenefits = Benefits.Refresh(listPatPlans, listInsSubs); Procedures.ComputeEstimatesForAll(patNum, listClaimProcs, listProcs, listInsPlans, listPatPlans, listBenefits, pat.Age, listInsSubs); if (prefChanged) { Prefs.UpdateBool(PrefName.ClaimProcsAllowedToBackdate, true); //set back to original value if changed. } } } InsPlan insPlanFrom = InsPlans.RefreshOne(insPlanNumFrom); InsPlan planOld = insPlanFrom.Copy(); insPlanFrom.IsHidden = true; InsPlans.Update(insPlanFrom, planOld); return(insSubMovedCount); }
private void butOK_Click(object sender,EventArgs e) { if( textBirthdate1.errorProvider1.GetError(textBirthdate1)!="" || textBirthdate2.errorProvider1.GetError(textBirthdate2)!="" || textBirthdate3.errorProvider1.GetError(textBirthdate3)!="" || textBirthdate4.errorProvider1.GetError(textBirthdate4)!="" || textBirthdate5.errorProvider1.GetError(textBirthdate5)!="" ){ MsgBox.Show(this,"Please fix data entry errors first."); return; } //no validation on birthdate reasonableness. if(textLName1.Text=="" || textFName1.Text==""){ MsgBox.Show(this,"Guarantor name must be entered."); return; } // Validate Insurance subscribers-------------------------------------------------------------------------------------------------------- if((comboSubscriber1.SelectedIndex==2 || comboSubscriber2.SelectedIndex==2) && (textFName2.Text=="" || textLName2.Text=="")){ MsgBox.Show(this,"Subscriber must have name entered."); return; } if((comboSubscriber1.SelectedIndex==3 || comboSubscriber2.SelectedIndex==3) && (textFName3.Text=="" || textLName3.Text=="")){ MsgBox.Show(this,"Subscriber must have name entered."); return; } if((comboSubscriber1.SelectedIndex==4 || comboSubscriber2.SelectedIndex==4) && (textFName4.Text=="" || textLName4.Text=="")){ MsgBox.Show(this,"Subscriber must have name entered."); return; } if((comboSubscriber1.SelectedIndex==5 || comboSubscriber2.SelectedIndex==5) && (textFName5.Text=="" || textLName5.Text=="")){ MsgBox.Show(this,"Subscriber must have name entered."); return; } // Validate Insurance Plans-------------------------------------------------------------------------------------------------------------- bool insComplete1=false; bool insComplete2=false; if(comboSubscriber1.SelectedIndex>0 && textSubscriberID1.Text!="" && textCarrier1.Text!="") { insComplete1=true; } if(comboSubscriber2.SelectedIndex>0 && textSubscriberID2.Text!="" && textCarrier2.Text!="") { insComplete2=true; } //test for insurance having only some of the critical fields filled in if(comboSubscriber1.SelectedIndex>0 || textSubscriberID1.Text!="" || textCarrier1.Text!="") { if(!insComplete1){ MsgBox.Show(this,"Subscriber, Subscriber ID, and Carrier are all required fields if adding insurance."); return; } } if(comboSubscriber2.SelectedIndex>0 || textSubscriberID2.Text!="" || textCarrier2.Text!="") { if(!insComplete2){ MsgBox.Show(this,"Subscriber, Subscriber ID, and Carrier are all required fields if adding insurance."); return; } } if(checkInsOne1.Checked || checkInsOne2.Checked || checkInsOne3.Checked || checkInsOne4.Checked || checkInsOne5.Checked) { if(!insComplete1){ MsgBox.Show(this,"Subscriber, Subscriber ID, and Carrier are all required fields if adding insurance."); return; } } if(checkInsTwo1.Checked || checkInsTwo2.Checked || checkInsTwo3.Checked || checkInsTwo4.Checked || checkInsTwo5.Checked) { if(!insComplete2){ MsgBox.Show(this,"Subscriber, Subscriber ID, and Carrier are all required fields if adding insurance."); return; } } //Validate Insurance subscriptions--------------------------------------------------------------------------------------------------- if(insComplete1){ if(!checkInsOne1.Checked && !checkInsOne2.Checked && !checkInsOne3.Checked && !checkInsOne4.Checked && !checkInsOne5.Checked) { MsgBox.Show(this,"Insurance information has been filled in, but has not been assigned to any patients."); return; } if(checkInsOne1.Checked && (textLName1.Text=="" || textFName1.Text=="")//Insurance1 assigned to invalid patient1 || checkInsOne2.Checked && (textLName2.Text=="" || textFName2.Text=="")//Insurance1 assigned to invalid patient2 || checkInsOne3.Checked && (textLName3.Text=="" || textFName3.Text=="")//Insurance1 assigned to invalid patient3 || checkInsOne4.Checked && (textLName4.Text=="" || textFName4.Text=="")//Insurance1 assigned to invalid patient4 || checkInsOne5.Checked && (textLName5.Text=="" || textFName5.Text=="")) //Insurance1 assigned to invalid patient5 { MsgBox.Show(this,"Insurance information 1 has been filled in, but has been assigned to a patient with no name."); return; } } if(insComplete2){ if(!checkInsTwo1.Checked && !checkInsTwo2.Checked && !checkInsTwo3.Checked && !checkInsTwo4.Checked && !checkInsTwo5.Checked) { MsgBox.Show(this,"Insurance information 2 has been filled in, but has not been assigned to any patients."); return; } if(checkInsTwo1.Checked && (textLName1.Text=="" || textFName1.Text=="")//Insurance2 assigned to invalid patient1 || checkInsTwo2.Checked && (textLName2.Text=="" || textFName2.Text=="")//Insurance2 assigned to invalid patient2 || checkInsTwo3.Checked && (textLName3.Text=="" || textFName3.Text=="")//Insurance2 assigned to invalid patient3 || checkInsTwo4.Checked && (textLName4.Text=="" || textFName4.Text=="")//Insurance2 assigned to invalid patient4 || checkInsTwo5.Checked && (textLName5.Text=="" || textFName5.Text=="")) //Insurance2 assigned to invalid patient5 { MsgBox.Show(this,"Insurance information 2 has been filled in, but has been assigned to a patient with no name."); return; } } //End of validation------------------------------------------------------------------------------------------ //Create Guarantor------------------------------------------------------------------------------------------- Patient guar=new Patient(); guar.LName=textLName1.Text; guar.FName=textFName1.Text; if(listGender1.SelectedIndex==0){ guar.Gender=PatientGender.Male; } else{ guar.Gender=PatientGender.Female; } if(listPosition1.SelectedIndex==0){ guar.Position=PatientPosition.Single; } else{ guar.Position=PatientPosition.Married; } guar.Birthdate=PIn.Date(textBirthdate1.Text); guar.BillingType=PrefC.GetLong(PrefName.PracticeDefaultBillType); guar.PatStatus=PatientStatus.Patient; guar.PriProv=ProviderC.ListShort[comboPriProv1.SelectedIndex].ProvNum; if(comboSecProv1.SelectedIndex>0){ guar.SecProv=ProviderC.ListShort[comboSecProv1.SelectedIndex-1].ProvNum; } guar.HmPhone=textHmPhone.Text; guar.Address=textAddress.Text; guar.Address2=textAddress2.Text; guar.City=textCity.Text; guar.State=textState.Text; guar.Zip=textZip.Text; guar.AddrNote=textAddrNotes.Text; guar.ClinicNum=Security.CurUser.ClinicNum; Patients.Insert(guar,false); Patient guarOld=guar.Copy(); guar.Guarantor=guar.PatNum; Patients.Update(guar,guarOld); RefAttach refAttach; if(textReferral.Text!=""){ //selectedReferral will already be set if user picked from list. //but, if selectedReferral doesn't match data in boxes, then clear it. if(selectedReferral!=null && (selectedReferral.LName!=textReferral.Text || selectedReferral.FName!=textReferralFName.Text)) { selectedReferral=null; } if(selectedReferral==null){ selectedReferral=new Referral(); selectedReferral.LName=textReferral.Text; selectedReferral.FName=textReferralFName.Text; Referrals.Insert(selectedReferral); } //Now we will always have a valid referral to attach. We will use it again for the other family members. refAttach=new RefAttach(); refAttach.IsFrom=true; refAttach.RefDate=DateTime.Today; refAttach.ReferralNum=selectedReferral.ReferralNum; refAttach.PatNum=guar.PatNum; RefAttaches.Insert(refAttach); } //Patient #2----------------------------------------------------------------------------------------------------- Patient pat2=null; if(textFName2.Text!="" && textLName2.Text!=""){ pat2=new Patient(); pat2.LName=textLName2.Text; pat2.FName=textFName2.Text; if(listGender2.SelectedIndex==0){ pat2.Gender=PatientGender.Male; } else{ pat2.Gender=PatientGender.Female; } if(listPosition2.SelectedIndex==0){ pat2.Position=PatientPosition.Single; } else{ pat2.Position=PatientPosition.Married; } pat2.Birthdate=PIn.Date(textBirthdate2.Text); pat2.BillingType=PrefC.GetLong(PrefName.PracticeDefaultBillType); pat2.PatStatus=PatientStatus.Patient; pat2.PriProv=ProviderC.ListShort[comboPriProv2.SelectedIndex].ProvNum; if(comboSecProv2.SelectedIndex>0){ pat2.SecProv=ProviderC.ListShort[comboSecProv2.SelectedIndex-1].ProvNum; } pat2.HmPhone=textHmPhone.Text; pat2.Address=textAddress.Text; pat2.Address2=textAddress2.Text; pat2.City=textCity.Text; pat2.State=textState.Text; pat2.Zip=textZip.Text; pat2.AddrNote=textAddrNotes.Text; pat2.ClinicNum=Security.CurUser.ClinicNum; pat2.Guarantor=guar.Guarantor; Patients.Insert(pat2,false); if(textReferral.Text!=""){ //selectedReferral will already have been set in the guarantor loop refAttach=new RefAttach(); refAttach.IsFrom=true; refAttach.RefDate=DateTime.Today; refAttach.ReferralNum=selectedReferral.ReferralNum; refAttach.PatNum=pat2.PatNum; RefAttaches.Insert(refAttach); } } //Patient #3----------------------------------------------------------------------------------------------------- Patient pat3=null; if(textFName3.Text!="" && textLName3.Text!=""){ pat3=new Patient(); pat3.LName=textLName3.Text; pat3.FName=textFName3.Text; if(listGender3.SelectedIndex==0){ pat3.Gender=PatientGender.Male; } else{ pat3.Gender=PatientGender.Female; } pat3.Position=PatientPosition.Child; pat3.Birthdate=PIn.Date(textBirthdate3.Text); pat3.BillingType=PrefC.GetLong(PrefName.PracticeDefaultBillType); pat3.PatStatus=PatientStatus.Patient; pat3.PriProv=ProviderC.ListShort[comboPriProv3.SelectedIndex].ProvNum; if(comboSecProv3.SelectedIndex>0){ pat3.SecProv=ProviderC.ListShort[comboSecProv3.SelectedIndex-1].ProvNum; } pat3.HmPhone=textHmPhone.Text; pat3.Address=textAddress.Text; pat3.Address2=textAddress2.Text; pat3.City=textCity.Text; pat3.State=textState.Text; pat3.Zip=textZip.Text; pat3.AddrNote=textAddrNotes.Text; pat3.ClinicNum=Security.CurUser.ClinicNum; pat3.Guarantor=guar.Guarantor; Patients.Insert(pat3,false); if(textReferral.Text!=""){ //selectedReferral will already have been set in the guarantor loop refAttach=new RefAttach(); refAttach.IsFrom=true; refAttach.RefDate=DateTime.Today; refAttach.ReferralNum=selectedReferral.ReferralNum; refAttach.PatNum=pat3.PatNum; RefAttaches.Insert(refAttach); } } //Patient #4----------------------------------------------------------------------------------------------------- Patient pat4=null; if(textFName4.Text!="" && textLName4.Text!=""){ pat4=new Patient(); pat4.LName=textLName4.Text; pat4.FName=textFName4.Text; if(listGender4.SelectedIndex==0){ pat4.Gender=PatientGender.Male; } else{ pat4.Gender=PatientGender.Female; } pat4.Position=PatientPosition.Child; pat4.Birthdate=PIn.Date(textBirthdate4.Text); pat4.BillingType=PrefC.GetLong(PrefName.PracticeDefaultBillType); pat4.PatStatus=PatientStatus.Patient; pat4.PriProv=ProviderC.ListShort[comboPriProv4.SelectedIndex].ProvNum; if(comboSecProv4.SelectedIndex>0){ pat4.SecProv=ProviderC.ListShort[comboSecProv4.SelectedIndex-1].ProvNum; } pat4.HmPhone=textHmPhone.Text; pat4.Address=textAddress.Text; pat4.Address2=textAddress2.Text; pat4.City=textCity.Text; pat4.State=textState.Text; pat4.Zip=textZip.Text; pat4.AddrNote=textAddrNotes.Text; pat4.ClinicNum=Security.CurUser.ClinicNum; pat4.Guarantor=guar.Guarantor; Patients.Insert(pat4,false); if(textReferral.Text!=""){ //selectedReferral will already have been set in the guarantor loop refAttach=new RefAttach(); refAttach.IsFrom=true; refAttach.RefDate=DateTime.Today; refAttach.ReferralNum=selectedReferral.ReferralNum; refAttach.PatNum=pat4.PatNum; RefAttaches.Insert(refAttach); } } //Patient #5----------------------------------------------------------------------------------------------------- Patient pat5=null; if(textFName5.Text!="" && textLName5.Text!=""){ pat5=new Patient(); pat5.LName=textLName5.Text; pat5.FName=textFName5.Text; if(listGender5.SelectedIndex==0){ pat5.Gender=PatientGender.Male; } else{ pat5.Gender=PatientGender.Female; } pat5.Position=PatientPosition.Child; pat5.Birthdate=PIn.Date(textBirthdate5.Text); pat5.BillingType=PrefC.GetLong(PrefName.PracticeDefaultBillType); pat5.PatStatus=PatientStatus.Patient; pat5.PriProv=ProviderC.ListShort[comboPriProv5.SelectedIndex].ProvNum; if(comboSecProv5.SelectedIndex>0){ pat5.SecProv=ProviderC.ListShort[comboSecProv5.SelectedIndex-1].ProvNum; } pat5.HmPhone=textHmPhone.Text; pat5.Address=textAddress.Text; pat5.Address2=textAddress2.Text; pat5.City=textCity.Text; pat5.State=textState.Text; pat5.Zip=textZip.Text; pat5.AddrNote=textAddrNotes.Text; pat5.ClinicNum=Security.CurUser.ClinicNum; pat5.Guarantor=guar.Guarantor; Patients.Insert(pat5,false); if(textReferral.Text!=""){ //selectedReferral will already have been set in the guarantor loop refAttach=new RefAttach(); refAttach.IsFrom=true; refAttach.RefDate=DateTime.Today; refAttach.ReferralNum=selectedReferral.ReferralNum; refAttach.PatNum=pat5.PatNum; RefAttaches.Insert(refAttach); } } //Insurance------------------------------------------------------------------------------------------------------------ InsSub sub1=null; InsSub sub2=null; if(selectedPlan1!=null){ //validate the ins fields. If they don't match perfectly, then set it to null if(Employers.GetName(selectedPlan1.EmployerNum)!=textEmployer1.Text || Carriers.GetName(selectedPlan1.CarrierNum)!=textCarrier1.Text || selectedPlan1.GroupName!=textGroupName1.Text || selectedPlan1.GroupNum!=textGroupNum1.Text) { selectedPlan1=null; } } if(selectedPlan2!=null){ if(Employers.GetName(selectedPlan2.EmployerNum)!=textEmployer2.Text || Carriers.GetName(selectedPlan2.CarrierNum)!=textCarrier2.Text || selectedPlan2.GroupName!=textGroupName2.Text || selectedPlan2.GroupNum!=textGroupNum2.Text) { selectedPlan2=null; } } if(selectedCarrier1!=null){ //validate the carrier fields. If they don't match perfectly, then set it to null if(selectedCarrier1.CarrierName!=textCarrier1.Text || selectedCarrier1.Phone!=textPhone1.Text) { selectedCarrier1=null; } } if(selectedCarrier2!=null){ if(selectedCarrier2.CarrierName!=textCarrier2.Text || selectedCarrier2.Phone!=textPhone2.Text) { selectedCarrier2=null; } } if(insComplete1){ if(selectedCarrier1==null){ //get a carrier, possibly creating a new one if needed. selectedCarrier1=Carriers.GetByNameAndPhone(textCarrier1.Text,textPhone1.Text); } long empNum1=Employers.GetEmployerNum(textEmployer1.Text); if(selectedPlan1==null){ //don't try to get a copy of an existing plan. Instead, start from scratch. selectedPlan1=new InsPlan(); selectedPlan1.EmployerNum=empNum1; selectedPlan1.CarrierNum=selectedCarrier1.CarrierNum; selectedPlan1.GroupName=textGroupName1.Text; selectedPlan1.GroupNum=textGroupNum1.Text; selectedPlan1.PlanType=""; InsPlans.Insert(selectedPlan1); Benefit ben; for(int i=0;i<CovCatC.ListShort.Count;i++){ if(CovCatC.ListShort[i].DefaultPercent==-1){ continue; } ben=new Benefit(); ben.BenefitType=InsBenefitType.CoInsurance; ben.CovCatNum=CovCatC.ListShort[i].CovCatNum; ben.PlanNum=selectedPlan1.PlanNum; ben.Percent=CovCatC.ListShort[i].DefaultPercent; ben.TimePeriod=BenefitTimePeriod.CalendarYear; ben.CodeNum=0; Benefits.Insert(ben); } } sub1=new InsSub(); sub1.PlanNum=selectedPlan1.PlanNum; sub1.AssignBen=true; sub1.ReleaseInfo=true; sub1.DateEffective=DateTime.MinValue; sub1.DateTerm=DateTime.MinValue; if(comboSubscriber1.SelectedIndex==1){ sub1.Subscriber=guar.PatNum; } if(comboSubscriber1.SelectedIndex==2){ sub1.Subscriber=pat2.PatNum; } if(comboSubscriber1.SelectedIndex==3){ sub1.Subscriber=pat3.PatNum; } if(comboSubscriber1.SelectedIndex==4){ sub1.Subscriber=pat4.PatNum; } if(comboSubscriber1.SelectedIndex==5){ sub1.Subscriber=pat5.PatNum; } sub1.SubscriberID=textSubscriberID1.Text; InsSubs.Insert(sub1); } if(insComplete2){ if(selectedCarrier2==null){ selectedCarrier2=Carriers.GetByNameAndPhone(textCarrier2.Text,textPhone2.Text); } long empNum2=Employers.GetEmployerNum(textEmployer2.Text); if(selectedPlan2==null){ //don't try to get a copy of an existing plan. Instead, start from scratch. selectedPlan2=new InsPlan(); selectedPlan2.EmployerNum=empNum2; selectedPlan2.CarrierNum=selectedCarrier2.CarrierNum; selectedPlan2.GroupName=textGroupName2.Text; selectedPlan2.GroupNum=textGroupNum2.Text; selectedPlan2.PlanType=""; InsPlans.Insert(selectedPlan2); Benefit ben; for(int i=0;i<CovCatC.ListShort.Count;i++){ if(CovCatC.ListShort[i].DefaultPercent==-1){ continue; } ben=new Benefit(); ben.BenefitType=InsBenefitType.CoInsurance; ben.CovCatNum=CovCatC.ListShort[i].CovCatNum; ben.PlanNum=selectedPlan2.PlanNum; ben.Percent=CovCatC.ListShort[i].DefaultPercent; ben.TimePeriod=BenefitTimePeriod.CalendarYear; ben.CodeNum=0; Benefits.Insert(ben); } } sub2=new InsSub(); sub2.PlanNum=selectedPlan2.PlanNum; sub2.AssignBen=true; sub2.ReleaseInfo=true; sub2.DateEffective=DateTime.MinValue; sub2.DateTerm=DateTime.MinValue; if(comboSubscriber2.SelectedIndex==1){ sub2.Subscriber=guar.PatNum; } if(comboSubscriber2.SelectedIndex==2){ sub2.Subscriber=pat2.PatNum; } if(comboSubscriber2.SelectedIndex==3){ sub2.Subscriber=pat3.PatNum; } if(comboSubscriber2.SelectedIndex==4){ sub2.Subscriber=pat4.PatNum; } if(comboSubscriber2.SelectedIndex==5){ sub2.Subscriber=pat5.PatNum; } sub2.SubscriberID=textSubscriberID2.Text; InsSubs.Insert(sub2); } PatPlan patplan; //attach insurance to subscriber-------------------------------------------------------------------------------- if(checkInsOne1.Checked){ patplan=new PatPlan(); //the only situation where ordinal would be 2 is if ins2 has this patient as the subscriber. if(comboSubscriber2.SelectedIndex==1){ patplan.Ordinal=2; } else{ patplan.Ordinal=1; } patplan.PatNum=guar.PatNum; patplan.InsSubNum=sub1.InsSubNum; if(comboSubscriber1.SelectedIndex==1){ patplan.Relationship=Relat.Self; } else if(comboSubscriber1.SelectedIndex==2){ patplan.Relationship=Relat.Spouse; } else{ //the subscriber would never be a child } PatPlans.Insert(patplan); } if(checkInsTwo1.Checked){ patplan=new PatPlan(); //the only situations where ordinal would be 1 is if ins1 is not checked or if ins2 has this patient as subscriber. if(comboSubscriber2.SelectedIndex==1){ patplan.Ordinal=1; } else if(!checkInsOne1.Checked){ patplan.Ordinal=1; } else{ patplan.Ordinal=2; } patplan.PatNum=guar.PatNum; patplan.InsSubNum=sub2.InsSubNum; if(comboSubscriber2.SelectedIndex==1){ patplan.Relationship=Relat.Self; } else if(comboSubscriber2.SelectedIndex==2){ patplan.Relationship=Relat.Spouse; } else{ //the subscriber would never be a child } PatPlans.Insert(patplan); } //attach insurance to patient 2, the other parent---------------------------------------------------------------------- if(checkInsOne2.Checked){ patplan=new PatPlan(); //the only situation where ordinal would be 2 is if ins2 has this patient as the subscriber. if(comboSubscriber2.SelectedIndex==2){ patplan.Ordinal=2; } else{ patplan.Ordinal=1; } patplan.PatNum=pat2.PatNum; patplan.InsSubNum=sub1.InsSubNum; if(comboSubscriber1.SelectedIndex==2){ patplan.Relationship=Relat.Self; } else if(comboSubscriber1.SelectedIndex==1){ patplan.Relationship=Relat.Spouse; } else{ //the subscriber would never be a child } PatPlans.Insert(patplan); } if(checkInsTwo2.Checked){ patplan=new PatPlan(); //the only situations where ordinal would be 1 is if ins1 is not checked or if ins2 has this patient as subscriber. if(comboSubscriber2.SelectedIndex==2){ patplan.Ordinal=1; } else if(!checkInsOne2.Checked){ patplan.Ordinal=1; } else{ patplan.Ordinal=2; } patplan.PatNum=pat2.PatNum; patplan.InsSubNum=sub2.InsSubNum; if(comboSubscriber2.SelectedIndex==2){ patplan.Relationship=Relat.Self; } else if(comboSubscriber2.SelectedIndex==1){ patplan.Relationship=Relat.Spouse; } else{ //the subscriber would never be a child } PatPlans.Insert(patplan); } //attach insurance to patient 3, a child---------------------------------------------------------------------- if(checkInsOne3.Checked){ patplan=new PatPlan(); patplan.Ordinal=1; patplan.PatNum=pat3.PatNum; patplan.InsSubNum=sub1.InsSubNum; patplan.Relationship=Relat.Child; PatPlans.Insert(patplan); } if(checkInsTwo3.Checked){ patplan=new PatPlan(); //the only situation where ordinal would be 1 is if ins1 is not checked. if(!checkInsOne3.Checked){ patplan.Ordinal=1; } else{ patplan.Ordinal=2; } patplan.PatNum=pat3.PatNum; patplan.InsSubNum=sub2.InsSubNum; patplan.Relationship=Relat.Child; PatPlans.Insert(patplan); } //attach insurance to patient 4, a child---------------------------------------------------------------------- if(checkInsOne4.Checked){ patplan=new PatPlan(); patplan.Ordinal=1; patplan.PatNum=pat4.PatNum; patplan.InsSubNum=sub1.InsSubNum; patplan.Relationship=Relat.Child; PatPlans.Insert(patplan); } if(checkInsTwo4.Checked){ patplan=new PatPlan(); //the only situation where ordinal would be 1 is if ins1 is not checked. if(!checkInsOne4.Checked){ patplan.Ordinal=1; } else{ patplan.Ordinal=2; } patplan.PatNum=pat4.PatNum; patplan.InsSubNum=sub2.InsSubNum; patplan.Relationship=Relat.Child; PatPlans.Insert(patplan); } //attach insurance to patient 5, a child---------------------------------------------------------------------- if(checkInsOne5.Checked){ patplan=new PatPlan(); patplan.Ordinal=1; patplan.PatNum=pat5.PatNum; patplan.InsSubNum=sub1.InsSubNum; patplan.Relationship=Relat.Child; PatPlans.Insert(patplan); } if(checkInsTwo5.Checked){ patplan=new PatPlan(); //the only situation where ordinal would be 1 is if ins1 is not checked. if(!checkInsOne5.Checked){ patplan.Ordinal=1; } else{ patplan.Ordinal=2; } patplan.PatNum=pat5.PatNum; patplan.InsSubNum=sub2.InsSubNum; patplan.Relationship=Relat.Child; PatPlans.Insert(patplan); } SelectedPatNum=guar.PatNum; MessageBox.Show("Done"); DialogResult=DialogResult.OK; }
///<summary>Gets all necessary info from db based on ThisPatNum and ThisClaimNum. Then fills displayStrings with the actual text that will display on claim. The isRenaissance flag is very temporary.</summary> private void FillDisplayStrings(bool isRenaissance){ if(PrintBlank){ if(CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Canadian. en-CA or fr-CA ClaimFormCur=ClaimForms.GetClaimFormByUniqueId("OD6");//CDA claim form } else { //Assume USA ClaimFormCur=ClaimForms.GetClaimFormByUniqueId("OD8");//ADA claim form } //ClaimFormItems.GetListForForm(ClaimFormCur.ClaimFormNum); displayStrings=new string[ClaimFormCur.Items.Length]; ListClaimProcs=new List<ClaimProc>(); return; } Family FamCur=Patients.GetFamily(PatNumCur); Patient PatCur=FamCur.GetPatient(PatNumCur); List<Claim> ClaimList=Claims.Refresh(PatCur.PatNum); ClaimCur=Claims.GetFromList(ClaimList,ClaimNumCur); //((Claim)Claims.HList[ThisClaimNum]).Clone(); ListInsSub2=InsSubs.RefreshForFam(FamCur); ListInsPlan=InsPlans.RefreshForSubList(ListInsSub2); ListPatPlans=PatPlans.Refresh(ClaimCur.PatNum); InsPlan otherPlan=InsPlans.GetPlan(ClaimCur.PlanNum2,ListInsPlan); InsSub otherSub=InsSubs.GetSub(ClaimCur.InsSubNum2,ListInsSub2); if(otherPlan==null){ otherPlan=new InsPlan();//easier than leaving it null } Carrier otherCarrier=new Carrier(); if(otherPlan.PlanNum!=0){ otherCarrier=Carriers.GetCarrier(otherPlan.CarrierNum); } //Employers.GetEmployer(otherPlan.EmployerNum); //Employer otherEmployer=Employers.Cur;//not actually used //then get the main plan subCur=InsSubs.GetSub(ClaimCur.InsSubNum,ListInsSub2); planCur=InsPlans.GetPlan(ClaimCur.PlanNum,ListInsPlan); Clinic clinic=Clinics.GetClinic(ClaimCur.ClinicNum); carrier=Carriers.GetCarrier(planCur.CarrierNum); //Employers.GetEmployer(InsPlans.Cur.EmployerNum); Patient subsc; if(FamCur.GetIndex(subCur.Subscriber)==-1) {//from another family subsc=Patients.GetPat(subCur.Subscriber); //Patients.Cur; //Patients.GetFamily(ThisPatNum);//return to current family } else{ subsc=FamCur.ListPats[FamCur.GetIndex(subCur.Subscriber)]; } Patient otherSubsc=new Patient(); if(otherPlan.PlanNum!=0){//if secondary insurance exists if(FamCur.GetIndex(otherSub.Subscriber)==-1) {//from another family otherSubsc=Patients.GetPat(otherSub.Subscriber); //Patients.Cur; //Patients.GetFamily(ThisPatNum);//return to current family } else{ otherSubsc=FamCur.ListPats[FamCur.GetIndex(otherSub.Subscriber)]; } } if(ClaimCur.ReferringProv>0){ ClaimReferral=Referrals.GetReferral(ClaimCur.ReferringProv); } ListProc=Procedures.Refresh(PatCur.PatNum); List<ToothInitial> initialList=ToothInitials.Refresh(PatCur.PatNum); //List<ClaimProc> ClaimProcList=ClaimProcs.Refresh(PatCur.PatNum); ClaimProcsForPat=ClaimProcs.Refresh(ClaimCur.PatNum); ClaimProcsForClaim=ClaimProcs.RefreshForClaim(ClaimCur.ClaimNum); ListClaimProcs=new List<ClaimProc>(); bool includeThis; Procedure proc; for(int i=0;i<ClaimProcsForClaim.Count;i++){//fill the arraylist if(ClaimProcsForClaim[i].ProcNum==0){ continue;//skip payments } if(CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Canadian. en-CA or fr-CA proc=Procedures.GetProcFromList(ListProc,ClaimProcsForClaim[i].ProcNum); if(proc.ProcNumLab!=0) { //This is a lab fee procedure. continue;//skip lab fee procedures in Canada, because they will show up on the same line as the procedure that they are attached to. } } includeThis=true; for(int j=0;j<ListClaimProcs.Count;j++){//loop through existing claimprocs if(ListClaimProcs[j].ProcNum==ClaimProcsForClaim[i].ProcNum){ includeThis=false;//skip duplicate procedures } } if(includeThis){ ListClaimProcs.Add(ClaimProcsForClaim[i]); } } List<string> missingTeeth=ToothInitials.GetMissingOrHiddenTeeth(initialList); ProcedureCode procCode; for(int j=missingTeeth.Count-1;j>=0;j--) {//loop backwards to keep index accurate as items are removed //if the missing tooth is missing because of an extraction being billed here, then exclude it for(int p=0;p<ListClaimProcs.Count;p++) { proc=Procedures.GetProcFromList(ListProc,ListClaimProcs[p].ProcNum); procCode=ProcedureCodes.GetProcCode(proc.CodeNum); if(procCode.PaintType==ToothPaintingType.Extraction && proc.ToothNum==missingTeeth[j]) { missingTeeth.RemoveAt(j); break; } } } //diagnoses--------------------------------------------------------------------------------------- diagnoses=new string[4]; for(int i=0;i<4;i++){ diagnoses[i]=""; } for(int i=0;i<ListClaimProcs.Count;i++){ proc=Procedures.GetProcFromList(ListProc,ListClaimProcs[i].ProcNum); if(proc.DiagnosticCode==""){ continue; } for(int d=0;d<4;d++){ if(diagnoses[d]==proc.DiagnosticCode){ break;//if it's already been added } if(diagnoses[d]==""){//we're at the end of the list of existing diagnoses, and no match diagnoses[d]=proc.DiagnosticCode;//so add it. break; } } //There's still a chance that the diagnosis didn't get added, if there were more than 4. } Provider treatDent=ProviderC.ListLong[Providers.GetIndexLong(ClaimCur.ProvTreat)]; if(ClaimFormCur==null){ if(ClaimCur.ClaimForm>0){ ClaimFormCur=ClaimForms.GetClaimForm(ClaimCur.ClaimForm); } else { ClaimFormCur=ClaimForms.GetClaimForm(planCur.ClaimFormNum); } } List<PatPlan> patPlans=null; displayStrings=new string[ClaimFormCur.Items.Length]; //a value is set for every item, but not every case will have a matching claimform item. for(int i=0;i<ClaimFormCur.Items.Length;i++){ if(ClaimFormCur.Items[i]==null){//Renaissance does not use [0] displayStrings[i]=""; continue; } switch(ClaimFormCur.Items[i].FieldName){ default://image. or procedure which gets filled in FillProcStrings. displayStrings[i]=""; break; case "FixedText": displayStrings[i]=ClaimFormCur.Items[i].FormatString; break; case "IsPreAuth": if(ClaimCur.ClaimType=="PreAuth") { displayStrings[i]="X"; } break; case "IsStandardClaim": if(ClaimCur.ClaimType!="PreAuth") { displayStrings[i]="X"; } break; case "ShowPreauthorizationIfPreauth": if(ClaimCur.ClaimType=="PreAuth") { displayStrings[i]="Preauthorization"; } break; case "IsMedicaidClaim"://this should later be replaced with an insplan field. if(PatCur.MedicaidID!="") { displayStrings[i]="X"; } break; case "IsGroupHealthPlan": string eclaimcode=InsFilingCodes.GetEclaimCode(planCur.FilingCode); if(PatCur.MedicaidID=="" && eclaimcode != "MC"//medicaid && eclaimcode != "CH"//champus && eclaimcode != "VA")//veterans //&& eclaimcode != ""//medicare? { displayStrings[i]="X"; } break; case "PreAuthString": displayStrings[i]=ClaimCur.PreAuthString; break; case "PriorAuthString": displayStrings[i]=ClaimCur.PriorAuthorizationNumber; break; case "PriInsCarrierName": displayStrings[i]=carrier.CarrierName; break; case "PriInsAddress": displayStrings[i]=carrier.Address; break; case "PriInsAddress2": displayStrings[i]=carrier.Address2; break; case "PriInsAddressComplete": displayStrings[i]=carrier.Address+" "+carrier.Address2; break; case "PriInsCity": displayStrings[i]=carrier.City; break; case "PriInsST": displayStrings[i]=carrier.State; break; case "PriInsZip": displayStrings[i]=carrier.Zip; break; case "OtherInsExists": if(otherPlan.PlanNum!=0) { displayStrings[i]="X"; } break; case "OtherInsNotExists": if(otherPlan.PlanNum==0) { displayStrings[i]="X"; } break; case "OtherInsExistsDent": if(otherPlan.PlanNum!=0) { if(!otherPlan.IsMedical) { displayStrings[i]="X"; } } break; case "OtherInsExistsMed": if(otherPlan.PlanNum!=0) { if(otherPlan.IsMedical) { displayStrings[i]="X"; } } break; case "OtherInsSubscrLastFirst": if(otherPlan.PlanNum!=0) { displayStrings[i]=otherSubsc.LName+", "+otherSubsc.FName+" "+otherSubsc.MiddleI; } break; case "OtherInsSubscrDOB": if(otherPlan.PlanNum!=0) { if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=otherSubsc.Birthdate.ToShortDateString(); } else { displayStrings[i]=otherSubsc.Birthdate.ToString(ClaimFormCur.Items[i].FormatString); } } break; case "OtherInsSubscrIsMale": if(otherPlan.PlanNum!=0 && otherSubsc.Gender==PatientGender.Male) { displayStrings[i]="X"; } break; case "OtherInsSubscrIsFemale": if(otherPlan.PlanNum!=0 && otherSubsc.Gender==PatientGender.Female) { displayStrings[i]="X"; } break; case "OtherInsSubscrID": if(otherPlan.PlanNum!=0) { displayStrings[i]=otherSub.SubscriberID; } break; //if(otherPlan.PlanNum!=0 && otherSubsc.SSN.Length==9){ // displayStrings[i]=otherSubsc.SSN.Substring(0,3) // +"-"+otherSubsc.SSN.Substring(3,2) // +"-"+otherSubsc.SSN.Substring(5); //} //break; case "OtherInsGroupNum": if(otherPlan.PlanNum!=0) { displayStrings[i]=otherPlan.GroupNum; } break; case "OtherInsRelatIsSelf": if(otherPlan.PlanNum!=0 && ClaimCur.PatRelat2==Relat.Self) { displayStrings[i]="X"; } break; case "OtherInsRelatIsSpouse": if(otherPlan.PlanNum!=0 && ClaimCur.PatRelat2==Relat.Spouse) { displayStrings[i]="X"; } break; case "OtherInsRelatIsChild": if(otherPlan.PlanNum!=0 && ClaimCur.PatRelat2==Relat.Child) { displayStrings[i]="X"; } break; case "OtherInsRelatIsOther": if(otherPlan.PlanNum!=0 && ( ClaimCur.PatRelat2==Relat.Dependent || ClaimCur.PatRelat2==Relat.Employee || ClaimCur.PatRelat2==Relat.HandicapDep || ClaimCur.PatRelat2==Relat.InjuredPlaintiff || ClaimCur.PatRelat2==Relat.LifePartner || ClaimCur.PatRelat2==Relat.SignifOther )) displayStrings[i]="X"; break; case "OtherInsCarrierName": if(otherPlan.PlanNum!=0) { displayStrings[i]=otherCarrier.CarrierName; } break; case "OtherInsAddress": if(otherPlan.PlanNum!=0) { displayStrings[i]=otherCarrier.Address; } break; case "OtherInsCity": if(otherPlan.PlanNum!=0) { displayStrings[i]=otherCarrier.City; } break; case "OtherInsST": if(otherPlan.PlanNum!=0) { displayStrings[i]=otherCarrier.State; } break; case "OtherInsZip": if(otherPlan.PlanNum!=0) { displayStrings[i]=otherCarrier.Zip; } break; case "SubscrLastFirst": displayStrings[i]=subsc.LName+", "+subsc.FName+" "+subsc.MiddleI; break; case "SubscrAddress": displayStrings[i]=subsc.Address; break; case "SubscrAddress2": displayStrings[i]=subsc.Address2; break; case "SubscrAddressComplete": displayStrings[i]=subsc.Address+" "+subsc.Address2; break; case "SubscrCity": displayStrings[i]=subsc.City; break; case "SubscrST": displayStrings[i]=subsc.State; break; case "SubscrZip": displayStrings[i]=subsc.Zip; break; case "SubscrPhone"://needs work. Only used for 1500 if(isRenaissance) { //Expecting (XXX)XXX-XXXX displayStrings[i]=subsc.HmPhone; if(subsc.HmPhone.Length>14) {//Might have a note following the number. displayStrings[i]=subsc.HmPhone.Substring(0,14); } } else { string phone=subsc.HmPhone.Replace("(",""); phone=phone.Replace(")"," "); phone=phone.Replace("-"," "); displayStrings[i]=phone; } break; case "SubscrDOB": if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=subsc.Birthdate.ToShortDateString();//MM/dd/yyyy } else { displayStrings[i]=subsc.Birthdate.ToString(ClaimFormCur.Items[i].FormatString); } break; case "SubscrIsMale": if(subsc.Gender==PatientGender.Male) { displayStrings[i]="X"; } break; case "SubscrIsFemale": if(subsc.Gender==PatientGender.Female) { displayStrings[i]="X"; } break; case "SubscrGender": if(subsc.Gender==PatientGender.Male) { displayStrings[i]="M"; } else { displayStrings[i]="F"; } break; case "SubscrIsMarried": if(subsc.Position==PatientPosition.Married) { displayStrings[i]="X"; } break; case "SubscrIsSingle": if(subsc.Position==PatientPosition.Single || subsc.Position==PatientPosition.Child || subsc.Position==PatientPosition.Widowed) { displayStrings[i]="X"; } break; case "SubscrID": patPlans=PatPlans.Refresh(PatNumCur); string patID=PatPlans.GetPatID(subCur.InsSubNum,patPlans); if(patID=="") { displayStrings[i]=subCur.SubscriberID; } else { displayStrings[i]=patID; } break; case "SubscrIDStrict": displayStrings[i]=subCur.SubscriberID; break; case "SubscrIsFTStudent": if(subsc.StudentStatus=="F") { displayStrings[i]="X"; } break; case "SubscrIsPTStudent": if(subsc.StudentStatus=="P") { displayStrings[i]="X"; } break; case "GroupName": displayStrings[i]=planCur.GroupName; break; case "GroupNum": displayStrings[i]=planCur.GroupNum; break; case "DivisionNo": displayStrings[i]=planCur.DivisionNo; break; case "EmployerName": displayStrings[i]=Employers.GetEmployer(planCur.EmployerNum).EmpName;; break; case "RelatIsSelf": if(ClaimCur.PatRelat==Relat.Self) { displayStrings[i]="X"; } break; case "RelatIsSpouse": if(ClaimCur.PatRelat==Relat.Spouse) { displayStrings[i]="X"; } break; case "RelatIsChild": if(ClaimCur.PatRelat==Relat.Child) { displayStrings[i]="X"; } break; case "RelatIsOther": if(ClaimCur.PatRelat==Relat.Dependent || ClaimCur.PatRelat==Relat.Employee || ClaimCur.PatRelat==Relat.HandicapDep || ClaimCur.PatRelat==Relat.InjuredPlaintiff || ClaimCur.PatRelat==Relat.LifePartner || ClaimCur.PatRelat==Relat.SignifOther) { displayStrings[i]="X"; } break; case "Relationship": if(CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Canadian. en-CA or fr-CA if(ClaimCur.PatRelat==Relat.Self) { displayStrings[i]="Self"; } else if(ClaimCur.PatRelat==Relat.Spouse) { displayStrings[i]="Spouse"; } else if(ClaimCur.PatRelat==Relat.Child) { displayStrings[i]="Child"; } else if(ClaimCur.PatRelat==Relat.SignifOther || ClaimCur.PatRelat==Relat.LifePartner) { displayStrings[i]="Common Law Spouse"; } else { displayStrings[i]="Other"; } } else { displayStrings[i]=ClaimCur.PatRelat.ToString(); } break; case "IsFTStudent": if(PatCur.StudentStatus=="F") { displayStrings[i]="X"; } break; case "IsPTStudent": if(PatCur.StudentStatus=="P") { displayStrings[i]="X"; } break; case "IsStudent": if(PatCur.StudentStatus=="P" || PatCur.StudentStatus=="F") { displayStrings[i]="X"; } break; case "CollegeName": displayStrings[i]=PatCur.SchoolName; break; case "PatientLastFirst": displayStrings[i]=PatCur.LName+", "+PatCur.FName+" "+PatCur.MiddleI; break; case "PatientFirstMiddleLast": displayStrings[i]=PatCur.FName+" "+PatCur.MiddleI+" "+PatCur.LName; break; case "PatientFirstName": displayStrings[i] = PatCur.FName; break; case "PatientMiddleName": displayStrings[i] = PatCur.MiddleI; break; case "PatientLastName": displayStrings[i] = PatCur.LName; break; case "PatientAddress": displayStrings[i]=PatCur.Address; break; case "PatientAddress2": displayStrings[i]=PatCur.Address2; break; case "PatientAddressComplete": displayStrings[i]=PatCur.Address+" "+PatCur.Address2; break; case "PatientCity": displayStrings[i]=PatCur.City; break; case "PatientST": displayStrings[i]=PatCur.State; break; case "PatientZip": displayStrings[i]=PatCur.Zip; break; case "PatientPhone"://needs work. Only used for 1500 if(isRenaissance) { //Expecting (XXX)XXX-XXXX displayStrings[i]=PatCur.HmPhone; if(PatCur.HmPhone.Length>14) {//Might have a note following the number. displayStrings[i]=PatCur.HmPhone.Substring(0,14); } } else { string phonep=PatCur.HmPhone.Replace("(",""); phonep=phonep.Replace(")"," "); phonep=phonep.Replace("-"," "); displayStrings[i]=phonep; } break; case "PatientDOB": if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=PatCur.Birthdate.ToShortDateString();//MM/dd/yyyy } else { displayStrings[i]=PatCur.Birthdate.ToString (ClaimFormCur.Items[i].FormatString); } break; case "PatientIsMale": if(PatCur.Gender==PatientGender.Male) { displayStrings[i]="X"; } break; case "PatientIsFemale": if(PatCur.Gender==PatientGender.Female) { displayStrings[i]="X"; } break; case "PatientGender": if(PatCur.Gender==PatientGender.Male) { displayStrings[i]="Male"; } else if(PatCur.Gender==PatientGender.Female) { displayStrings[i]="Female"; } break; case "PatientGenderLetter": if(subsc.Gender==PatientGender.Male) { displayStrings[i]="M"; } else { displayStrings[i]="F"; } break; case "PatientIsMarried": if(PatCur.Position==PatientPosition.Married) { displayStrings[i]="X"; } break; case "PatientIsSingle": if(PatCur.Position==PatientPosition.Single || PatCur.Position==PatientPosition.Child || PatCur.Position==PatientPosition.Widowed) { displayStrings[i]="X"; } break; case "PatIDFromPatPlan": //Dependant Code for Canada patPlans=PatPlans.Refresh(PatNumCur); if(CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Canadian. en-CA or fr-CA if(carrier.ElectID=="000064") { //Pacific Blue Cross (PBC) displayStrings[i]=subCur.SubscriberID+"-"+PatPlans.GetPatID(subCur.InsSubNum,patPlans); } } else { displayStrings[i]=PatPlans.GetPatID(subCur.InsSubNum,patPlans); } break; case "PatientSSN": if(PatCur.SSN.Length==9) { displayStrings[i]=PatCur.SSN.Substring(0,3) +"-"+PatCur.SSN.Substring(3,2) +"-"+PatCur.SSN.Substring(5); } else { displayStrings[i]=PatCur.SSN; } break; case "PatientMedicaidID": displayStrings[i]=PatCur.MedicaidID; break; case "PatientID-MedicaidOrSSN": if(PatCur.MedicaidID!="") { displayStrings[i]=PatCur.MedicaidID; } else { displayStrings[i]=PatCur.SSN; } break; case "PatientChartNum": displayStrings[i]=PatCur.ChartNumber; break; case "PatientPatNum": displayStrings[i]=PatCur.PatNum.ToString(); break; case "Diagnosis1": if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=diagnoses[0]; } else if(ClaimFormCur.Items[i].FormatString=="NoDec") { displayStrings[i]=diagnoses[0].Replace(".",""); } break; case "Diagnosis2": if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=diagnoses[1]; } else if(ClaimFormCur.Items[i].FormatString=="NoDec") { displayStrings[i]=diagnoses[1].Replace(".",""); } break; case "Diagnosis3": if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=diagnoses[2]; } else if(ClaimFormCur.Items[i].FormatString=="NoDec") { displayStrings[i]=diagnoses[2].Replace(".",""); } break; case "Diagnosis4": if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=diagnoses[3]; } else if(ClaimFormCur.Items[i].FormatString=="NoDec") { displayStrings[i]=diagnoses[3].Replace(".",""); } break; //this is where the procedures used to be case "Miss1": if(missingTeeth.Contains("1")) { displayStrings[i]="X"; } break; case "Miss2": if(missingTeeth.Contains("2")) { displayStrings[i]="X"; } break; case "Miss3": if(missingTeeth.Contains("3")) { displayStrings[i]="X"; } break; case "Miss4": if(missingTeeth.Contains("4")) { displayStrings[i]="X"; } break; case "Miss5": if(missingTeeth.Contains("5")) { displayStrings[i]="X"; } break; case "Miss6": if(missingTeeth.Contains("6")) { displayStrings[i]="X"; } break; case "Miss7": if(missingTeeth.Contains("7")) { displayStrings[i]="X"; } break; case "Miss8": if(missingTeeth.Contains("8")) { displayStrings[i]="X"; } break; case "Miss9": if(missingTeeth.Contains("9")) { displayStrings[i]="X"; } break; case "Miss10": if(missingTeeth.Contains("10")) { displayStrings[i]="X"; } break; case "Miss11": if(missingTeeth.Contains("11")) { displayStrings[i]="X"; } break; case "Miss12": if(missingTeeth.Contains("12")) { displayStrings[i]="X"; } break; case "Miss13": if(missingTeeth.Contains("13")) { displayStrings[i]="X"; } break; case "Miss14": if(missingTeeth.Contains("14")) { displayStrings[i]="X"; } break; case "Miss15": if(missingTeeth.Contains("15")) { displayStrings[i]="X"; } break; case "Miss16": if(missingTeeth.Contains("16")) { displayStrings[i]="X"; } break; case "Miss17": if(missingTeeth.Contains("17")) { displayStrings[i]="X"; } break; case "Miss18": if(missingTeeth.Contains("18")) { displayStrings[i]="X"; } break; case "Miss19": if(missingTeeth.Contains("19")) { displayStrings[i]="X"; } break; case "Miss20": if(missingTeeth.Contains("20")) { displayStrings[i]="X"; } break; case "Miss21": if(missingTeeth.Contains("21")) { displayStrings[i]="X"; } break; case "Miss22": if(missingTeeth.Contains("22")) { displayStrings[i]="X"; } break; case "Miss23": if(missingTeeth.Contains("23")) { displayStrings[i]="X"; } break; case "Miss24": if(missingTeeth.Contains("24")) { displayStrings[i]="X"; } break; case "Miss25": if(missingTeeth.Contains("25")) { displayStrings[i]="X"; } break; case "Miss26": if(missingTeeth.Contains("26")) { displayStrings[i]="X"; } break; case "Miss27": if(missingTeeth.Contains("27")) { displayStrings[i]="X"; } break; case "Miss28": if(missingTeeth.Contains("28")) { displayStrings[i]="X"; } break; case "Miss29": if(missingTeeth.Contains("29")) { displayStrings[i]="X"; } break; case "Miss30": if(missingTeeth.Contains("30")) { displayStrings[i]="X"; } break; case "Miss31": if(missingTeeth.Contains("31")) { displayStrings[i]="X"; } break; case "Miss32": if(missingTeeth.Contains("32")) { displayStrings[i]="X"; } break; case "Remarks": displayStrings[i]=""; if(CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Canadian. en-CA or fr-CA if(carrier.ElectID=="000064") { //Pacific Blue Cross (PBC) if(ClaimCur.ClaimType=="PreAuth") { displayStrings[i]+="Predetermination only."+Environment.NewLine; } else { if(subCur.AssignBen) { displayStrings[i]+="Please pay provider."+Environment.NewLine; } else { displayStrings[i]+="Please pay patient."+Environment.NewLine; } } } } if(ClaimCur.AttachmentID!="" && !ClaimCur.ClaimNote.StartsWith(ClaimCur.AttachmentID)){ displayStrings[i]=ClaimCur.AttachmentID+" "; } displayStrings[i]+=ClaimCur.ClaimNote; break; case "PatientRelease": if(subCur.ReleaseInfo) { displayStrings[i]="Signature on File"; } break; case "PatientReleaseDate": if(subCur.ReleaseInfo && ClaimCur.DateSent.Year > 1860) { if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=ClaimCur.DateSent.ToShortDateString(); } else { displayStrings[i]=ClaimCur.DateSent.ToString(ClaimFormCur.Items[i].FormatString); } } break; case "PatientAssignment": if(subCur.AssignBen) { displayStrings[i]="Signature on File"; } break; case "PatientAssignmentDate": if(subCur.AssignBen && ClaimCur.DateSent.Year > 1860) { if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=ClaimCur.DateSent.ToShortDateString(); } else { displayStrings[i]=ClaimCur.DateSent.ToString(ClaimFormCur.Items[i].FormatString); } } break; case "PlaceIsOffice": if(ClaimCur.PlaceService==PlaceOfService.Office) { displayStrings[i]="X"; } break; case "PlaceIsHospADA2002": if(ClaimCur.PlaceService==PlaceOfService.InpatHospital || ClaimCur.PlaceService==PlaceOfService.OutpatHospital) { displayStrings[i]="X"; } break; case "PlaceIsExtCareFacilityADA2002": if(ClaimCur.PlaceService==PlaceOfService.CustodialCareFacility || ClaimCur.PlaceService==PlaceOfService.SkilledNursFac) { displayStrings[i]="X"; } break; case "PlaceIsOtherADA2002": if(ClaimCur.PlaceService==PlaceOfService.PatientsHome || ClaimCur.PlaceService==PlaceOfService.OtherLocation) { displayStrings[i]="X"; } break; case "PlaceIsInpatHosp": if(ClaimCur.PlaceService==PlaceOfService.InpatHospital) { displayStrings[i]="X"; } break; case "PlaceIsOutpatHosp": if(ClaimCur.PlaceService==PlaceOfService.OutpatHospital) { displayStrings[i]="X"; } break; case "PlaceIsAdultLivCareFac": if(ClaimCur.PlaceService==PlaceOfService.CustodialCareFacility) { displayStrings[i]="X"; } break; case "PlaceIsSkilledNursFac": if(ClaimCur.PlaceService==PlaceOfService.SkilledNursFac) { displayStrings[i]="X"; } break; case "PlaceIsPatientsHome": if(ClaimCur.PlaceService==PlaceOfService.PatientsHome) { displayStrings[i]="X"; } break; case "PlaceIsOtherLocation": if(ClaimCur.PlaceService==PlaceOfService.OtherLocation) { displayStrings[i]="X"; } break; case "PlaceNumericCode": displayStrings[i]=GetPlaceOfServiceNum(ClaimCur.PlaceService); break; case "IsRadiographsAttached": if(ClaimCur.Radiographs>0) { displayStrings[i]="X"; } break; case "RadiographsNumAttached": displayStrings[i]=ClaimCur.Radiographs.ToString(); break; case "RadiographsNotAttached": if(ClaimCur.Radiographs==0) { displayStrings[i]="X"; } break; case "IsEnclosuresAttached": if(ClaimCur.Radiographs>0 || ClaimCur.AttachedImages>0 || ClaimCur.AttachedModels>0) { displayStrings[i]="X"; } break; case "AttachedImagesNum": displayStrings[i]=ClaimCur.AttachedImages.ToString(); break; case "AttachedModelsNum": displayStrings[i]=ClaimCur.AttachedModels.ToString(); break; case "IsNotOrtho": if(!ClaimCur.IsOrtho) { displayStrings[i]="X"; } break; case "IsOrtho": if(ClaimCur.IsOrtho) { displayStrings[i]="X"; } break; case "DateOrthoPlaced": if(ClaimCur.OrthoDate.Year > 1880){ if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=ClaimCur.OrthoDate.ToShortDateString(); } else { displayStrings[i]=ClaimCur.OrthoDate.ToString(ClaimFormCur.Items[i].FormatString); } } break; case "MonthsOrthoRemaining": if(ClaimCur.OrthoRemainM > 0) { displayStrings[i]=ClaimCur.OrthoRemainM.ToString(); } break; case "IsNotProsth": if(ClaimCur.IsProsthesis=="N") { displayStrings[i]="X"; } break; case "IsInitialProsth": if(ClaimCur.IsProsthesis=="I") { displayStrings[i]="X"; } break; case "IsNotReplacementProsth": if(ClaimCur.IsProsthesis!="R") {//=='I'nitial or 'N'o displayStrings[i]="X"; } break; case "IsReplacementProsth": if(ClaimCur.IsProsthesis=="R") { displayStrings[i]="X"; } break; case "DatePriorProsthPlaced": if(ClaimCur.PriorDate.Year > 1860){ if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=ClaimCur.PriorDate.ToShortDateString(); } else { displayStrings[i]=ClaimCur.PriorDate.ToString(ClaimFormCur.Items[i].FormatString); } } break; case "IsOccupational": if(ClaimCur.AccidentRelated=="E") { displayStrings[i]="X"; } break; case "IsNotOccupational": if(ClaimCur.AccidentRelated!="E") { displayStrings[i]="X"; } break; case "IsAutoAccident": if(ClaimCur.AccidentRelated=="A") { displayStrings[i]="X"; } break; case "IsNotAutoAccident": if(ClaimCur.AccidentRelated!="A") { displayStrings[i]="X"; } break; case "IsOtherAccident": if(ClaimCur.AccidentRelated=="O") { displayStrings[i]="X"; } break; case "IsNotOtherAccident": if(ClaimCur.AccidentRelated!="O") { displayStrings[i]="X"; } break; case "IsNotAccident": if(ClaimCur.AccidentRelated!="O" && ClaimCur.AccidentRelated!="A") { displayStrings[i]="X"; } break; case "IsAccident": if(ClaimCur.AccidentRelated!="") { displayStrings[i]="X"; } break; case "AccidentDate": if(ClaimCur.AccidentDate.Year > 1860){ if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=ClaimCur.AccidentDate.ToShortDateString(); } else { displayStrings[i]=ClaimCur.AccidentDate.ToString(ClaimFormCur.Items[i].FormatString); } } break; case "AccidentST": displayStrings[i]=ClaimCur.AccidentST; break; case "BillingDentist": Provider P=ProviderC.ListLong[Providers.GetIndexLong(ClaimCur.ProvBill)]; displayStrings[i]=P.FName+" "+P.MI+" "+P.LName+" "+P.Suffix; break; //case "BillingDentistAddress": // if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)){ // displayStrings[i]=PrefC.GetString(PrefName.PracticeBillingAddress); // } // else if(clinic==null) { // displayStrings[i]=PrefC.GetString(PrefName.PracticeAddress); // } // else { // displayStrings[i]=clinic.Address; // } // break; //case "BillingDentistAddress2": // if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { // displayStrings[i]=PrefC.GetString(PrefName.PracticeBillingAddress2); // } // else if(clinic==null) { // displayStrings[i]=PrefC.GetString(PrefName.PracticeAddress2); // } // else { // displayStrings[i]=clinic.Address2; // } // break; //case "BillingDentistCity": // if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { // displayStrings[i]=PrefC.GetString(PrefName.PracticeBillingCity); // } // else if(clinic==null) { // displayStrings[i]=PrefC.GetString(PrefName.PracticeCity); // } // else { // displayStrings[i]=clinic.City; // } // break; //case "BillingDentistST": // if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { // displayStrings[i]=PrefC.GetString(PrefName.PracticeBillingST); // } // else if(clinic==null) { // displayStrings[i]=PrefC.GetString(PrefName.PracticeST); // } // else { // displayStrings[i]=clinic.State; // } // break; //case "BillingDentistZip": // if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { // displayStrings[i]=PrefC.GetString(PrefName.PracticeBillingZip); // } // else if(clinic==null) { // displayStrings[i]=PrefC.GetString(PrefName.PracticeZip); // } // else { // displayStrings[i]=clinic.Zip; // } // break; case "BillingDentistMedicaidID": displayStrings[i]=ProviderC.ListLong[Providers.GetIndexLong(ClaimCur.ProvBill)].MedicaidID; break; case "BillingDentistProviderID": ProviderIdent[] provIdents=ProviderIdents.GetForPayor(ClaimCur.ProvBill,carrier.ElectID); if(provIdents.Length>0){ displayStrings[i]=provIdents[0].IDNumber;//just use the first one we find } break; case "BillingDentistNPI": displayStrings[i]=ProviderC.ListLong[Providers.GetIndexLong(ClaimCur.ProvBill)].NationalProvID; if(CultureInfo.CurrentCulture.Name.EndsWith("CA") && //Canadian. en-CA or fr-CA carrier.ElectID=="000064" && //Pacific Blue Cross (PBC) ProviderC.ListLong[Providers.GetIndexLong(ClaimCur.ProvBill)].NationalProvID!= ProviderC.ListLong[Providers.GetIndexLong(ClaimCur.ProvTreat)].NationalProvID && //Billing and treating providers are different displayStrings[i].Length==9) { //Only for provider numbers which have been entered correctly (to prevent and indexing exception). displayStrings[i]="00"+displayStrings[i].Substring(2,5)+"00"; } break; case "BillingDentistLicenseNum": displayStrings[i]=ProviderC.ListLong[Providers.GetIndexLong(ClaimCur.ProvBill)].StateLicense; break; case "BillingDentistSSNorTIN": displayStrings[i]=ProviderC.ListLong[Providers.GetIndexLong(ClaimCur.ProvBill)].SSN; break; case "BillingDentistNumIsSSN": if(!ProviderC.ListLong[Providers.GetIndexLong(ClaimCur.ProvBill)].UsingTIN) { displayStrings[i]="X"; } break; case "BillingDentistNumIsTIN": if(ProviderC.ListLong[Providers.GetIndexLong(ClaimCur.ProvBill)].UsingTIN) { displayStrings[i]="X"; } break; case "BillingDentistPh123": if(clinic==null){ if(PrefC.GetString(PrefName.PracticePhone).Length==10){ displayStrings[i]=PrefC.GetString(PrefName.PracticePhone).Substring(0,3); } } else{ if(clinic.Phone.Length==10){ displayStrings[i]=clinic.Phone.Substring(0,3); } } break; case "BillingDentistPh456": if(clinic==null){ if(PrefC.GetString(PrefName.PracticePhone).Length==10){ displayStrings[i]=PrefC.GetString(PrefName.PracticePhone).Substring(3,3); } } else{ if(clinic.Phone.Length==10){ displayStrings[i]=clinic.Phone.Substring(3,3); } } break; case "BillingDentistPh78910": if(clinic==null){ if(PrefC.GetString(PrefName.PracticePhone).Length==10){ displayStrings[i]=PrefC.GetString(PrefName.PracticePhone).Substring(6); } } else{ if(clinic.Phone.Length==10){ displayStrings[i]=clinic.Phone.Substring(6); } } break; case "BillingDentistPhoneFormatted": if(clinic==null){ if(PrefC.GetString(PrefName.PracticePhone).Length==10){ displayStrings[i]="("+PrefC.GetString(PrefName.PracticePhone).Substring(0,3) +")"+PrefC.GetString(PrefName.PracticePhone).Substring(3,3) +"-"+PrefC.GetString(PrefName.PracticePhone).Substring(6); } } else{ if(clinic.Phone.Length==10){ displayStrings[i]="("+clinic.Phone.Substring(0,3) +")"+clinic.Phone.Substring(3,3) +"-"+clinic.Phone.Substring(6); } } break; case "BillingDentistPhoneRaw": if(clinic==null) { displayStrings[i]=PrefC.GetString(PrefName.PracticePhone); } else { displayStrings[i]=clinic.Phone; } break; case "PayToDentistAddress": //Behaves just like the old BillingDentistAddress field, but is overridden by the Pay-To address if the Pay-To address has been specified. if(PrefC.GetString(PrefName.PracticePayToAddress)!="") { //All Pay-To address fields are used in 5010 eclaims when Pay-To address line 1 is not blank. displayStrings[i]=PrefC.GetString(PrefName.PracticePayToAddress); } else if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)){ displayStrings[i]=PrefC.GetString(PrefName.PracticeBillingAddress); } else if(clinic==null) { displayStrings[i]=PrefC.GetString(PrefName.PracticeAddress); } else { displayStrings[i]=clinic.Address; } break; case "PayToDentistAddress2": //Behaves just like the old BillingDentistAddress2 field, but is overridden by the Pay-To address if the Pay-To address has been specified. if(PrefC.GetString(PrefName.PracticePayToAddress)!="") { //All Pay-To address fields are used in 5010 eclaims when Pay-To address line 1 is not blank. displayStrings[i]=PrefC.GetString(PrefName.PracticePayToAddress2); } else if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)){ displayStrings[i]=PrefC.GetString(PrefName.PracticeBillingAddress2); } else if(clinic==null) { displayStrings[i]=PrefC.GetString(PrefName.PracticeAddress2); } else { displayStrings[i]=clinic.Address2; } break; case "PayToDentistCity": //Behaves just like the old BillingDentistCity field, but is overridden by the Pay-To address if the Pay-To address has been specified. if(PrefC.GetString(PrefName.PracticePayToAddress)!="") { //All Pay-To address fields are used in 5010 eclaims when Pay-To address line 1 is not blank. displayStrings[i]=PrefC.GetString(PrefName.PracticePayToCity); } else if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { displayStrings[i]=PrefC.GetString(PrefName.PracticeBillingCity); } else if(clinic==null) { displayStrings[i]=PrefC.GetString(PrefName.PracticeCity); } else { displayStrings[i]=clinic.City; } break; case "PayToDentistST": //Behaves just like the old BillingDentistST field, but is overridden by the Pay-To address if the Pay-To address has been specified. if(PrefC.GetString(PrefName.PracticePayToAddress)!="") { //All Pay-To address fields are used in 5010 eclaims when Pay-To address line 1 is not blank. displayStrings[i]=PrefC.GetString(PrefName.PracticePayToST); } else if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { displayStrings[i]=PrefC.GetString(PrefName.PracticeBillingST); } else if(clinic==null) { displayStrings[i]=PrefC.GetString(PrefName.PracticeST); } else { displayStrings[i]=clinic.State; } break; case "PayToDentistZip": //Behaves just like the old BillingDentistZip field, but is overridden by the Pay-To address if the Pay-To address has been specified. if(PrefC.GetString(PrefName.PracticePayToAddress)!="") { //All Pay-To address fields are used in 5010 eclaims when Pay-To address line 1 is not blank. displayStrings[i]=PrefC.GetString(PrefName.PracticePayToZip); } else if(PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { displayStrings[i]=PrefC.GetString(PrefName.PracticeBillingZip); } else if(clinic==null) { displayStrings[i]=PrefC.GetString(PrefName.PracticeZip); } else { displayStrings[i]=clinic.Zip; } break; case "TreatingDentistFName": displayStrings[i]=treatDent.FName; break; case "TreatingDentistLName": displayStrings[i]=treatDent.LName; break; case "TreatingDentistSignature": if(treatDent.SigOnFile){ if(PrefC.GetBool(PrefName.ClaimFormTreatDentSaysSigOnFile)){ displayStrings[i]="Signature on File"; } else{ displayStrings[i]=treatDent.FName+" "+treatDent.MI+" "+treatDent.LName+" "+treatDent.Suffix; } } break; case "TreatingDentistSigDate": if(treatDent.SigOnFile && ClaimCur.DateSent.Year > 1860){ if(ClaimFormCur.Items[i].FormatString=="") { displayStrings[i]=ClaimCur.DateSent.ToShortDateString(); } else { displayStrings[i]=ClaimCur.DateSent.ToString(ClaimFormCur.Items[i].FormatString); } } break; case "TreatingDentistMedicaidID": displayStrings[i]=treatDent.MedicaidID; break; case "TreatingDentistProviderID": provIdents=ProviderIdents.GetForPayor(ClaimCur.ProvTreat,carrier.ElectID); if(provIdents.Length>0) { displayStrings[i]=provIdents[0].IDNumber;//just use the first one we find } break; case "TreatingDentistNPI": displayStrings[i]=treatDent.NationalProvID; break; case "TreatingDentistLicense": displayStrings[i]=treatDent.StateLicense; break; case "TreatingDentistAddress": if(clinic==null) { displayStrings[i]=PrefC.GetString(PrefName.PracticeAddress); } else { displayStrings[i]=clinic.Address; } break; case "TreatingDentistCity": if(clinic==null) { displayStrings[i]=PrefC.GetString(PrefName.PracticeCity); } else { displayStrings[i]=clinic.City; } break; case "TreatingDentistST": if(clinic==null) { displayStrings[i]=PrefC.GetString(PrefName.PracticeST); } else { displayStrings[i]=clinic.State; } break; case "TreatingDentistZip": if(clinic==null) { displayStrings[i]=PrefC.GetString(PrefName.PracticeZip); } else { displayStrings[i]=clinic.Zip; } break; case "TreatingDentistPh123": if(clinic==null){ if(PrefC.GetString(PrefName.PracticePhone).Length==10){ displayStrings[i]=PrefC.GetString(PrefName.PracticePhone).Substring(0,3); } } else{ if(clinic.Phone.Length==10){ displayStrings[i]=clinic.Phone.Substring(0,3); } } break; case "TreatingDentistPh456": if(clinic==null){ if(PrefC.GetString(PrefName.PracticePhone).Length==10){ displayStrings[i]=PrefC.GetString(PrefName.PracticePhone).Substring(3,3); } } else{ if(clinic.Phone.Length==10){ displayStrings[i]=clinic.Phone.Substring(3,3); } } break; case "TreatingDentistPh78910": if(clinic==null){ if(PrefC.GetString(PrefName.PracticePhone).Length==10){ displayStrings[i]=PrefC.GetString(PrefName.PracticePhone).Substring(6); } } else{ if(clinic.Phone.Length==10){ displayStrings[i]=clinic.Phone.Substring(6); } } break; case "TreatingProviderSpecialty": displayStrings[i]=X12Generator.GetTaxonomy (ProviderC.ListLong[Providers.GetIndexLong(ClaimCur.ProvTreat)]); break; case "TotalPages": displayStrings[i]="";//totalPages.ToString();//bugs with this field that we can't fix since we didn't write that code. break; case "ReferringProvNPI": if(ClaimReferral==null){ displayStrings[i]=""; } else{ displayStrings[i]=ClaimReferral.NationalProvID; } break; case "ReferringProvNameFL": if(ClaimReferral==null){ displayStrings[i]=""; } else{ displayStrings[i]=ClaimReferral.GetNameFL(); } break; case "MedUniformBillType": displayStrings[i]=ClaimCur.UniformBillType; break; case "MedAdmissionTypeCode": displayStrings[i]=ClaimCur.AdmissionTypeCode; break; case "MedAdmissionSourceCode": displayStrings[i]=ClaimCur.AdmissionSourceCode; break; case "MedPatientStatusCode": displayStrings[i]=ClaimCur.PatientStatusCode; break; case "MedAccidentCode": //For UB04. if(ClaimCur.AccidentRelated=="A") { //Auto accident displayStrings[i]="01"; } else if(ClaimCur.AccidentRelated=="E") { //Employment related accident displayStrings[i]="04"; } break; }//switch if(CultureInfo.CurrentCulture.Name=="nl-BE" && displayStrings[i]==""){//Dutch Belgium displayStrings[i]="* * *"; } //Renaissance eclaims only: Remove newlines from display strings to prevent formatting issues, because the .rss file format requires each field on a single line. if(isRenaissance && displayStrings[i]!=null) { displayStrings[i]=displayStrings[i].Replace("\r","").Replace("\n",""); } }//for }
private void butOK_Click(object sender, System.EventArgs e) { if(gridMain.GetSelectedIndex()==-1){ MessageBox.Show(Lan.g(this,"Please select a plan first.")); return; } if(ViewRelat && listRelat.SelectedIndex==-1){ MessageBox.Show(Lan.g(this,"Please select a relationship first.")); return; } if(ViewRelat){ PatRelat=(Relat)listRelat.SelectedIndex; } SelectedSub=SubList[gridMain.GetSelectedIndex()]; SelectedPlan=InsPlans.GetPlan(SubList[gridMain.GetSelectedIndex()].PlanNum,PlanList); DialogResult=DialogResult.OK; }
private void butOK_Click(object sender, System.EventArgs e) { if(gridMain.GetSelectedIndex()==-1){ MessageBox.Show(Lan.g(this,"Please select a plan first.")); return; } if(listRelat.SelectedIndex==-1){ MessageBox.Show(Lan.g(this,"Please select a relationship first.")); return; } //if(comboClaimForm.SelectedIndex==-1) { // MessageBox.Show(Lan.g(this,"Please select a claimform first.")); // return; //} PatRelat=(Relat)listRelat.SelectedIndex; SelectedSub=SubList[gridMain.GetSelectedIndex()]; SelectedPlan=InsPlans.GetPlan(SubList[gridMain.GetSelectedIndex()].PlanNum,PlanList); //ClaimFormNum=ClaimForms.ListShort[comboClaimForm.SelectedIndex].ClaimFormNum; DialogResult=DialogResult.OK; }
//<summary>This is a field that is accessed only by clicking on the button because there's not room for it otherwise. This variable should be treated just as if it was a visible textBox.</summary> //private string BenefitNotes; ///<summary>Called from ContrFamily and FormInsPlans. Must pass in the plan, patPlan, and sub, although patPlan and sub can be null.</summary> public FormInsPlan(InsPlan planCur,PatPlan patPlanCur,InsSub subCur){ Cursor=Cursors.WaitCursor; InitializeComponent(); PlanCur=planCur; PatPlanCur=patPlanCur; SubCur=subCur; listEmps=new ListBox(); listEmps.Location=new Point(panelPlan.Left+groupPlan.Left+textEmployer.Left, panelPlan.Top+groupPlan.Top+textEmployer.Bottom); listEmps.Size=new Size(231,100); listEmps.Visible=false; listEmps.Click += new System.EventHandler(listEmps_Click); listEmps.DoubleClick += new System.EventHandler(listEmps_DoubleClick); listEmps.MouseEnter += new System.EventHandler(listEmps_MouseEnter); listEmps.MouseLeave += new System.EventHandler(listEmps_MouseLeave); Controls.Add(listEmps); listEmps.BringToFront(); listCars=new ListBox(); listCars.Location=new Point(panelPlan.Left+groupPlan.Left+groupCarrier.Left+textCarrier.Left, panelPlan.Top+groupPlan.Top+groupCarrier.Top+textCarrier.Bottom); listCars.Size=new Size(700,100); listCars.HorizontalScrollbar=true; listCars.Visible=false; listCars.Click += new System.EventHandler(listCars_Click); listCars.DoubleClick += new System.EventHandler(listCars_DoubleClick); listCars.MouseEnter += new System.EventHandler(listCars_MouseEnter); listCars.MouseLeave += new System.EventHandler(listCars_MouseLeave); Controls.Add(listCars); listCars.BringToFront(); //tbPercentPlan.CellClicked += new OpenDental.ContrTable.CellEventHandler(tbPercentPlan_CellClicked); //tbPercentPat.CellClicked += new OpenDental.ContrTable.CellEventHandler(tbPercentPat_CellClicked); Lan.F(this); if(CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Canadian. en-CA or fr-CA labelPatID.Text=Lan.g(this,"Dependant Code"); labelCitySTZip.Text=Lan.g(this,"City,Prov,Post"); //Postal Code"; butSearch.Visible=false; labelElectronicID.Text="EDI Code"; comboElectIDdescript.Visible=false; labelGroupNum.Text=Lan.g(this,"Plan Number"); checkIsPMP.Checked=(planCur.CanadianPlanFlag!=null && planCur.CanadianPlanFlag!=""); } else{ labelDivisionDash.Visible=false; textDivisionNo.Visible=false; groupCanadian.Visible=false; } if(CultureInfo.CurrentCulture.Name.Length>=4 && CultureInfo.CurrentCulture.Name.Substring(3)=="GB"){//en-GB labelCitySTZip.Text=Lan.g(this,"City,Postcode"); } panelPat.BackColor=DefC.Long[(int)DefCat.MiscColors][0].ItemColor; //labelViewRequestDocument.Text=" "; //if(!PrefC.GetBool(PrefName.CustomizedForPracticeWeb")) { // butEligibility.Visible=false; // labelViewRequestDocument.Visible=false; //} Cursor=Cursors.Default; }
///<summary></summary> public static long SendClaimReversal(Claim claim,InsPlan plan,InsSub insSub) { StringBuilder strb=new StringBuilder(); Clearinghouse clearhouse=Canadian.GetClearinghouse(); if(clearhouse==null) { throw new ApplicationException(Lan.g("CanadianOutput","Canadian clearinghouse not found.")); } string saveFolder=clearhouse.ExportPath; if(!Directory.Exists(saveFolder)) { throw new ApplicationException(saveFolder+" not found."); } Carrier carrier=Carriers.GetCarrier(plan.CarrierNum); if((carrier.CanadianSupportedTypes&CanSupTransTypes.ClaimReversal_02)!=CanSupTransTypes.ClaimReversal_02) { throw new ApplicationException(Lan.g("CanadianOutput","The carrier does not support reversal transactions.")); } if(carrier.CanadianNetworkNum==0) { throw new ApplicationException("Carrier network not set."); } CanadianNetwork network=CanadianNetworks.GetNetwork(carrier.CanadianNetworkNum); Etrans etrans=Etranss.CreateCanadianOutput(claim.PatNum,carrier.CarrierNum,carrier.CanadianNetworkNum, clearhouse.ClearinghouseNum,EtransType.ClaimReversal_CA,plan.PlanNum,insSub.InsSubNum); etrans.ClaimNum=claim.ClaimNum;//We don't normally use a claim number with Etranss.CreateCanadianOutput(), but here we need the claim number so that we can show the claim reversal in the claim history. Etranss.Update(etrans); Patient patient=Patients.GetPat(claim.PatNum); Provider prov=Providers.GetProv(claim.ProvTreat); if(!prov.IsCDAnet) { throw new ApplicationException(Lan.g("CanadianOutput","Treating provider is not setup to use CDANet.")); } Provider billProv=ProviderC.ListLong[Providers.GetIndexLong(claim.ProvBill)]; if(!billProv.IsCDAnet) { throw new ApplicationException(Lan.g("CanadianOutput","Billing provider is not setup to use CDANet.")); } InsPlan insPlan=InsPlans.GetPlan(claim.PlanNum,new List<InsPlan>()); Patient subscriber=Patients.GetPat(insSub.Subscriber); //create message---------------------------------------------------------------------------------------------- //A01 transaction prefix 12 AN strb.Append(Canadian.TidyAN(network.CanadianTransactionPrefix,12)); //A02 office sequence number 6 N //We are required to use the same office sequence number as the original claim. etrans.OfficeSequenceNumber=0;//Clear the randomly generated office sequence number. List<Etrans> claimTransactions=Etranss.GetAllForOneClaim(claim.ClaimNum); DateTime originalEtransDateTime=DateTime.MinValue;//So we can get the latest matching transaction. for(int i=0;i<claimTransactions.Count;i++) { if(claimTransactions[i].Etype==EtransType.Claim_CA || claimTransactions[i].Etype==EtransType.ClaimCOB_CA) { Etrans ack=Etranss.GetEtrans(claimTransactions[i].AckEtransNum); if(ack==null) {//For those claims sent that didn't receive a response (i.e. when there is an exception while sending a claim). continue; } string messageText=EtransMessageTexts.GetMessageText(ack.EtransMessageTextNum); CCDFieldInputter messageData=new CCDFieldInputter(messageText); CCDField transRefNum=messageData.GetFieldById("G01"); if(transRefNum!=null && transRefNum.valuestr==claim.CanadaTransRefNum && claimTransactions[i].DateTimeTrans>originalEtransDateTime) { etrans.OfficeSequenceNumber=PIn.Int(messageData.GetFieldById("A02").valuestr); originalEtransDateTime=claimTransactions[i].DateTimeTrans; } } } DateTime serverDate=MiscData.GetNowDateTime().Date; if(originalEtransDateTime.Date!=serverDate) { throw new ApplicationException(Lan.g("CanadianOutput","Claims can only be reversed on the day that they were sent. The claim can only be manually reversed.")); } strb.Append(Canadian.TidyN(etrans.OfficeSequenceNumber,6)); //A03 format version number 2 N strb.Append(carrier.CDAnetVersion);//eg. "04", validated in UI //A04 transaction code 2 N strb.Append("02");//Same for both versions 02 and 04. //A05 carrier id number 6 N strb.Append(carrier.ElectID);//already validated as 6 digit number. //A06 software system id 3 AN strb.Append(Canadian.SoftwareSystemId()); if(carrier.CDAnetVersion!="02") { //version 04 //A10 encryption method 1 N strb.Append(carrier.CanadianEncryptionMethod);//validated in UI } if(carrier.CDAnetVersion=="02") { //A07 message length N4 strb.Append(Canadian.TidyN("133",4)); } else { //version 04 //A07 message length N 5 strb.Append(Canadian.TidyN("164",5)); } if(carrier.CDAnetVersion!="02") { //version 04 //A09 carrier transaction counter 5 N #if DEBUG strb.Append("11111"); #else strb.Append(Canadian.TidyN(etrans.CarrierTransCounter,5)); #endif } //B01 CDA provider number 9 AN strb.Append(Canadian.TidyAN(prov.NationalProvID,9));//already validated //B02 provider office number 4 AN strb.Append(Canadian.TidyAN(prov.CanadianOfficeNum,4));//already validated if(carrier.CDAnetVersion!="02") { //version 04 //B03 billing provider number 9 AN //might need to account for possible 5 digit prov id assigned by carrier strb.Append(Canadian.TidyAN(billProv.NationalProvID,9));//already validated //B04 billing provider office number 4 AN strb.Append(Canadian.TidyAN(billProv.CanadianOfficeNum,4));//already validated } if(carrier.CDAnetVersion=="02") { //C01 primary policy/plan number 8 AN //only validated to ensure that it's not blank and is less than 8. Also that no spaces. strb.Append(Canadian.TidyAN(insPlan.GroupNum,8)); } else { //version 04 //C01 primary policy/plan number 12 AN //only validated to ensure that it's not blank and is less than 12. Also that no spaces. strb.Append(Canadian.TidyAN(insPlan.GroupNum,12)); } //C11 primary division/section number 10 AN strb.Append(Canadian.TidyAN(insPlan.DivisionNo,10)); if(carrier.CDAnetVersion=="02") { //C02 subscriber id number 11 AN strb.Append(Canadian.TidyAN(insSub.SubscriberID.Replace("-",""),11));//validated } else { //version 04 //C02 subscriber id number 12 AN strb.Append(Canadian.TidyAN(insSub.SubscriberID.Replace("-",""),12));//validated } //C03 relationship code 1 N //User interface does not only show Canadian options, but all options are handled. strb.Append(Canadian.GetRelationshipCode(claim.PatRelat)); if(carrier.CDAnetVersion=="02") { //D02 subscriber last name 25 A strb.Append(Canadian.TidyA(subscriber.LName,25));//validated } else { //version 04 //D02 subscriber last name 25 AE strb.Append(Canadian.TidyAE(subscriber.LName,25,true));//validated } if(carrier.CDAnetVersion=="02") { //D03 subscriber first name 15 A strb.Append(Canadian.TidyA(subscriber.FName,15));//validated } else { //version 04 //D03 subscriber first name 15 AE strb.Append(Canadian.TidyAE(subscriber.FName,15,true));//validated } if(carrier.CDAnetVersion=="02") { //D04 subscriber middle initial 1 A strb.Append(Canadian.TidyA(subscriber.MiddleI,1)); } else { //version 04 //D04 subscriber middle initial 1 AE strb.Append(Canadian.TidyAE(subscriber.MiddleI,1)); } if(carrier.CDAnetVersion!="02") { //version 04 //For Future Use strb.Append("000000"); } //G01 transaction reference number of original claim AN 14 strb.Append(Canadian.TidyAN(claim.CanadaTransRefNum,14)); string result=""; bool resultIsError=false; try { result=Canadian.PassToIca(strb.ToString(),clearhouse); } catch(ApplicationException ex) { result=ex.Message; resultIsError=true; //Etranss.Delete(etrans.EtransNum);//we don't want to do this, because we want the incremented etrans.OfficeSequenceNumber to be saved //Attach an ack indicating failure. } //Attach an ack to the etrans Etrans etransAck=new Etrans(); etransAck.PatNum=etrans.PatNum; etransAck.PlanNum=etrans.PlanNum; etransAck.InsSubNum=etrans.InsSubNum; etransAck.CarrierNum=etrans.CarrierNum; etransAck.DateTimeTrans=DateTime.Now; if(resultIsError) { etransAck.AckCode="R";//To allow the user to try and reverse the claim again. etransAck.Etype=EtransType.AckError; etrans.Note="failed"; } else { try { CCDFieldInputter fieldInputter=new CCDFieldInputter(result); CCDField fieldG05=fieldInputter.GetFieldById("G05"); if(fieldG05!=null) { etransAck.AckCode=fieldG05.valuestr; } etransAck.Etype=fieldInputter.GetEtransType(); } catch { etransAck.AckCode="R";//To allow the user to try and reverse the claim again. etransAck.Etype=EtransType.AckError; etrans.Note="Could not parse response from ITRANS."; } } Etranss.Insert(etransAck); Etranss.SetMessage(etransAck.EtransNum,result); etrans.AckEtransNum=etransAck.EtransNum; Etranss.Update(etrans); Etranss.SetMessage(etrans.EtransNum,strb.ToString()); if(resultIsError) { throw new ApplicationException(result); } new FormCCDPrint(etrans,result,true);//Print the response. if(etrans.AckCode=="R") { throw new ApplicationException(Lan.g("CanadianOutput","Reversal was rejected by clearinghouse. The claim must be reversed manually.")); } return etransAck.EtransNum; }