///<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></summary> public static void Update(InsPlan plan) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),plan); return; } Crud.InsPlanCrud.Update(plan); }
///<summary>It's fastest if you supply a plan list that contains the plan, but it also works just fine if it can't initally locate the plan in the list. You can supply an list of length 0 or null. If still not found, returns null.</summary> public static InsPlan GetPlan(long planNum,List<InsPlan> planList) { //No need to check RemotingRole; no call to db. InsPlan retPlan=new InsPlan(); if(planNum==0) { return null; } if(planList==null) { planList=new List<InsPlan>(); } bool found=false; for(int i=0;i<planList.Count;i++) { if(planList[i].PlanNum==planNum) { found=true; retPlan=planList[i]; } } if(!found) { retPlan=RefreshOne(planNum);//retPlan will now be null if not found } if(retPlan==null) { //MessageBox.Show(Lans.g("InsPlans","Database is inconsistent. Please run the database maintenance tool.")); return new InsPlan(); } if(retPlan==null) { return null; } return retPlan; }
///<summary>Tests all fields for equality.</summary> public static bool AreEqualValue(InsPlan plan1,InsPlan plan2) { if(plan1.PlanNum==plan2.PlanNum && plan1.GroupName==plan2.GroupName && plan1.GroupNum==plan2.GroupNum && plan1.PlanNote==plan2.PlanNote && plan1.FeeSched==plan2.FeeSched && plan1.PlanType==plan2.PlanType && plan1.ClaimFormNum==plan2.ClaimFormNum && plan1.UseAltCode==plan2.UseAltCode && plan1.ClaimsUseUCR==plan2.ClaimsUseUCR && plan1.CopayFeeSched==plan2.CopayFeeSched && plan1.EmployerNum==plan2.EmployerNum && plan1.CarrierNum==plan2.CarrierNum && plan1.AllowedFeeSched==plan2.AllowedFeeSched && plan1.TrojanID==plan2.TrojanID && plan1.DivisionNo==plan2.DivisionNo && plan1.IsMedical==plan2.IsMedical && plan1.FilingCode==plan2.FilingCode && plan1.DentaideCardSequence==plan2.DentaideCardSequence && plan1.ShowBaseUnits==plan2.ShowBaseUnits && plan1.CodeSubstNone==plan2.CodeSubstNone && plan1.IsHidden==plan2.IsHidden && plan1.MonthRenew==plan2.MonthRenew && plan1.FilingCodeSubtype==plan2.FilingCodeSubtype && plan1.CanadianPlanFlag==plan2.CanadianPlanFlag && plan1.CobRule==plan2.CobRule) { return true; } return false; }
///<summary>Looks for logs that show that the insplan or carrier changed and retrieves the previous insplan/carrier's information. ///Called from GetLinkedLogs and, between the two methods, recursively retrieves logs linked to the logs that are returned from this method.</summary> private static List <InsEditLog> GetChangedLogs(List <InsEditLog> listLogs) { //No need to check RemotingRole; no call to db. List <InsEditLog> listInsPlanChangedLogs = listLogs.FindAll(x => ((x.LogType == InsEditLogType.InsPlan && x.FieldName == "PlanNum") || (x.LogType == InsEditLogType.Carrier && x.FieldName == "CarrierNum")) && x.OldValue != "NEW" && x.NewValue != "DELETED").ToList(); foreach (InsEditLog editLogCur in listInsPlanChangedLogs) { if (editLogCur.FieldName == "PlanNum") { InsPlan oldPlan = InsPlans.GetPlan(PIn.Long(editLogCur.OldValue), null); if (oldPlan != null) { listLogs.AddRange(GetLinkedLogs(oldPlan.CarrierNum, InsEditLogType.Carrier, editLogCur, listLogs)); } listLogs.AddRange(GetLinkedLogs(PIn.Long(editLogCur.OldValue), InsEditLogType.InsPlan, editLogCur, listLogs)); } if (editLogCur.FieldName == "CarrierNum") { listLogs.AddRange(GetLinkedLogs(PIn.Long(editLogCur.OldValue), InsEditLogType.Carrier, editLogCur, listLogs)); } } return(listLogs); }
///<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>Also fills PlanNum from db.</summary> public static long Insert(InsPlan plan,bool useExistingPK) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { plan.PlanNum=Meth.GetLong(MethodBase.GetCurrentMethod(),plan,useExistingPK); return plan.PlanNum; } return Crud.InsPlanCrud.Insert(plan,useExistingPK); }
/* * ///<summary>IComparable.CompareTo implementation. This is used to determine if plans are identical. The criteria is that they have 6 fields in common: Employer, Carrier, GroupName, GroupNum, DivisionNo, and IsMedical. There is no less than or greater than; just not equal.</summary> * public int CompareTo(object obj) { * if(!(obj is InsPlan)) { * throw new ArgumentException("object is not an InsPlan"); * } * InsPlan plan=(InsPlan)obj; * if(plan.EmployerNum==EmployerNum * && plan.CarrierNum==CarrierNum * && plan.GroupName==GroupName * && plan.GroupNum==GroupNum * && plan.DivisionNo==DivisionNo * && plan.IsMedical==IsMedical) * { * return 0;//they are the same * } * return -1; * }*/ ///<summary>Returns a copy of this InsPlan.</summary> public InsPlan Copy() { InsPlan p = new InsPlan(); p.PlanNum = PlanNum; p.Subscriber = Subscriber; p.DateEffective = DateEffective; p.DateTerm = DateTerm; p.GroupName = GroupName; p.GroupNum = GroupNum; p.PlanNote = PlanNote; p.FeeSched = FeeSched; p.ReleaseInfo = ReleaseInfo; p.AssignBen = AssignBen; p.PlanType = PlanType; p.ClaimFormNum = ClaimFormNum; p.UseAltCode = UseAltCode; p.ClaimsUseUCR = ClaimsUseUCR; p.CopayFeeSched = CopayFeeSched; p.SubscriberID = SubscriberID; p.EmployerNum = EmployerNum; p.CarrierNum = CarrierNum; p.AllowedFeeSched = AllowedFeeSched; p.TrojanID = TrojanID; p.DivisionNo = DivisionNo; p.BenefitNotes = BenefitNotes; p.IsMedical = IsMedical; p.SubscNote = SubscNote; p.FilingCode = FilingCode; p.DentaideCardSequence = DentaideCardSequence; p.NumberPlans = NumberPlans; return(p); }
///<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>Gets the fee schedule from the primary MEDICAL insurance plan, ///the first insurance plan, the patient, or the provider in that order.</summary> public static long GetMedFeeSched(Patient pat, List <InsPlan> planList, List <PatPlan> patPlans, List <InsSub> subList, long procProvNum) { //No need to check RemotingRole; no call to db. long retVal = 0; if (PatPlans.GetInsSubNum(patPlans, 1) != 0) { //Pick the medinsplan with the ordinal closest to zero int planOrdinal = 10; //This is a hack, but I doubt anyone would have more than 10 plans bool hasMedIns = false; //Keep track of whether we found a medical insurance plan, if not use dental insurance fee schedule. InsSub subCur; foreach (PatPlan patplan in patPlans) { subCur = InsSubs.GetSub(patplan.InsSubNum, subList); if (patplan.Ordinal < planOrdinal && InsPlans.GetPlan(subCur.PlanNum, planList).IsMedical) { planOrdinal = patplan.Ordinal; hasMedIns = true; } } if (!hasMedIns) //If this patient doesn't have medical insurance (under ordinal 10) { return(GetFeeSched(pat, planList, patPlans, subList, procProvNum)); //Use dental insurance fee schedule } subCur = InsSubs.GetSub(PatPlans.GetInsSubNum(patPlans, planOrdinal), 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 = Providers.GetFirst(true).FeeSched; } else { Provider providerFirst = Providers.GetFirst(); //Used in order to preserve old behavior... If this fails, then old code would have failed. Provider provider = Providers.GetFirstOrDefault(x => x.ProvNum == pat.PriProv) ?? providerFirst; retVal = provider.FeeSched; } } } return(retVal); }
public static bool HasSubstCodeForPlan(InsPlan insPlan, long codeNum, List <SubstitutionLink> listSubLinks) { //No need to check RemotingRole; no call to db. if (insPlan.CodeSubstNone) { return(false); } return(!listSubLinks.Exists(x => x.PlanNum == insPlan.PlanNum && x.CodeNum == codeNum)); }
///<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>Creats an insurance plan with the default fee schedule of 53.</summary> public static InsPlan CreateInsPlanPPO(long carrierNum,long feeSchedNum, EnumCobRule cobRule){ InsPlan plan=new InsPlan(); plan.CarrierNum=carrierNum; plan.PlanType="p"; plan.FeeSched=feeSchedNum; plan.CobRule=cobRule; InsPlans.Insert(plan); return plan; }
///<summary>Also fills PlanNum from db.</summary> public static long Insert(InsPlan plan,bool useExistingPK) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { plan.PlanNum=Meth.GetLong(MethodBase.GetCurrentMethod(),plan,useExistingPK); return plan.PlanNum; } if(DataConnection.DBtype==DatabaseType.Oracle) { return Crud.InsPlanCrud.Insert(plan);//Oracle ALWAYS uses existing PKs because they do not support auto-incrementing. } return Crud.InsPlanCrud.Insert(plan,useExistingPK); }
///<summary>Gets the fee schedule from the primary MEDICAL insurance plan, the patient, or the provider in that order.</summary> public static long GetMedFeeSched(Patient pat, List <InsPlan> planList, List <PatPlan> patPlans, List <InsSub> subList) { //No need to check RemotingRole; no call to db. ?? long retVal = 0; if (PatPlans.GetInsSubNum(patPlans, 1) != 0) { //Pick the medinsplan with the ordinal closest to zero int planOrdinal = 10; //This is a hack, but I doubt anyone would have more than 10 plans InsSub subCur; foreach (PatPlan patplan in patPlans) { subCur = InsSubs.GetSub(patplan.InsSubNum, subList); if (patplan.Ordinal < planOrdinal && InsPlans.GetPlan(subCur.PlanNum, planList).IsMedical) { planOrdinal = patplan.Ordinal; } } subCur = InsSubs.GetSub(PatPlans.GetInsSubNum(patPlans, planOrdinal), 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>Gets the fee sched from the first insplan, the patient, or the provider in that order. Uses procProvNum if>0, otherwise pat.PriProv. ///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, long procProvNum) { //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 priPlanFeeSched = 0; PatPlan patPlanPri = patPlans.FirstOrDefault(x => x.Ordinal == 1); if (patPlanPri != null) { InsPlan planCur = InsPlans.GetPlan(InsSubs.GetSub(patPlanPri.InsSubNum, subList).PlanNum, planList); if (planCur != null) { priPlanFeeSched = planCur.FeeSched; } } return(GetFeeSched(priPlanFeeSched, pat.FeeSched, procProvNum != 0?procProvNum:pat.PriProv)); //use procProvNum, but if 0 then default to pat.PriProv }
///<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); }
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(); }
private void butNone_Click(object sender,EventArgs e) { SelectedPlan=null; 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); } }
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(); }
private void butPick2_Click(object sender,EventArgs e) { FormInsPlans FormIP=new FormInsPlans(); FormIP.empText=textEmployer2.Text; FormIP.carrierText=textCarrier2.Text; FormIP.IsSelectMode=true; FormIP.ShowDialog(); if(FormIP.DialogResult==DialogResult.Cancel) { return; } selectedPlan2=FormIP.SelectedPlan.Copy(); //Non-synched fields: //selectedPlan2.SubscriberID=textSubscriberID.Text;//later //selectedPlan2.DateEffective=DateTime.MinValue; //selectedPlan2.DateTerm=DateTime.MinValue; //PlanCur.ReleaseInfo=checkRelease.Checked; //PlanCur.AssignBen=checkAssign.Checked; //PlanCur.SubscNote=textSubscNote.Text; //Benefits will be created when click OK. textEmployer2.Text=Employers.GetName(selectedPlan2.EmployerNum); FillCarrier2(selectedPlan2.CarrierNum); textGroupName2.Text=selectedPlan2.GroupName; textGroupNum2.Text=selectedPlan2.GroupNum; }
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()); }
private void FormClaimProcEdit_Load(object sender, System.EventArgs e) { if(NoPermissionProc){//blocks users with no permission to edit procedure butOK.Enabled=false; butDelete.Enabled=false; } else if(ClaimProcCur.ClaimNum>0){ Claim claim=Claims.GetClaim(ClaimProcCur.ClaimNum); if(!Security.IsAuthorized(Permissions.ClaimSentEdit,claim.DateSent,true)) {//attached to claim, no permission for claims. butOK.Enabled=false; butDelete.Enabled=false; } } InsSub sub=InsSubs.GetSub(ClaimProcCur.InsSubNum,SubList); Plan=InsPlans.GetPlan(sub.PlanNum,PlanList); PatPlanNum=PatPlans.GetPatPlanNum(sub.InsSubNum,PatPlanList); BenefitList=null;//only fill it if proc PaidOtherInsTotal=ClaimProcs.GetPaidOtherInsTotal(ClaimProcCur,PatPlanList); PaidOtherInsBaseEst=ClaimProcs.GetPaidOtherInsBaseEst(ClaimProcCur,PatPlanList); WriteOffOtherIns=ClaimProcs.GetWriteOffOtherIns(ClaimProcCur,PatPlanList); List<InsSub> subList=InsSubs.RefreshForFam(FamCur); textInsPlan.Text=InsPlans.GetDescript(ClaimProcCur.PlanNum,FamCur,PlanList,ClaimProcCur.InsSubNum,subList); checkNoBillIns.Checked=ClaimProcCur.NoBillIns; if(ClaimProcCur.ClaimPaymentNum>0){//attached to ins check textDateCP.ReadOnly=true;//DateCP always the same as the payment date and can't be changed here if(!Security.IsAuthorized(Permissions.InsPayEdit,ClaimProcCur.DateCP)){ butOK.Enabled=false; } textInsPayAmt.ReadOnly=true; labelAttachedToCheck.Visible=true; butDelete.Enabled=false; } //This new expanded security prevents editing completed claimprocs, even if not attached to an ins check. //For example, a zero payment with a writeoff amount. Must prevent changing that date. else if((ClaimProcCur.Status==ClaimProcStatus.CapComplete || ClaimProcCur.Status==ClaimProcStatus.Received || ClaimProcCur.Status==ClaimProcStatus.Supplemental) && !Security.IsAuthorized(Permissions.InsPayEdit,ClaimProcCur.DateCP))// { textDateCP.ReadOnly=true; butOK.Enabled=false; textInsPayAmt.ReadOnly=true; labelAttachedToCheck.Visible=false; //listStatus.Enabled=false;//this is handled in the mousedown event butDelete.Enabled=false; } else{ labelAttachedToCheck.Visible=false; } if(ClaimProcCur.ProcNum==0){//total payment for a claim IsProc=false; textDescription.Text="Total Payment"; textProcDate.ReadOnly=false; } else{ IsProc=true; BenefitList=Benefits.RefreshForPlan(ClaimProcCur.PlanNum,PatPlanNum); if(proc==null){ proc=Procedures.GetOneProc(ClaimProcCur.ProcNum,false); } textDescription.Text=ProcedureCodes.GetProcCode(proc.CodeNum).Descript; textProcDate.ReadOnly=true;//user not allowed to edit ProcDate unless it's for a total payment } if(ClaimProcCur.ClaimNum>0){//attached to claim radioClaim.Checked=true; checkNoBillIns.Enabled=false; if(IsInClaim){//(not from the procedure window) labelNotInClaim.Visible=false; } else{//must be accessing it from the Procedure window textCodeSent.ReadOnly=true; textFeeBilled.ReadOnly=true; labelNotInClaim.Visible=true; textDedApplied.ReadOnly=true; textInsPayEst.ReadOnly=true; textInsPayAmt.ReadOnly=true; textWriteOff.ReadOnly=true; } groupClaimInfo.Visible=true; if(ClaimProcCur.ProcNum==0){//if a total entry rather than by proc panelEstimateInfo.Visible=false; //labelPatTotal.Visible=false; labelInsPayAmt.Font=new Font(labelInsPayAmt.Font,FontStyle.Bold); labelProcDate.Visible=false; textProcDate.Visible=false; labelCodeSent.Visible=false; textCodeSent.Visible=false; labelFeeBilled.Visible=false; textFeeBilled.Visible=false; } else if(ClaimProcCur.Status==ClaimProcStatus.Received){ labelInsPayAmt.Font=new Font(labelInsPayAmt.Font,FontStyle.Bold); } //butOK.Enabled=false; //butDelete.Enabled=false; //MessageBox.Show(panelEstimateInfo.Visible.ToString()); } else //not attached to a claim if(ClaimProcCur.PlanNum>0 && (ClaimProcCur.Status==ClaimProcStatus.CapEstimate || ClaimProcCur.Status==ClaimProcStatus.CapComplete)) { //InsPlans.Cur.PlanType=="c"){//capitation proc,whether Estimate or CapComplete,never billed to ins foreach(System.Windows.Forms.Control control in panelEstimateInfo.Controls){ control.Visible=false; } foreach(System.Windows.Forms.Control control in groupClaimInfo.Controls){ control.Visible=false; } groupClaimInfo.Text=""; labelFee.Visible=true; textFee.Visible=true; labelCopayAmt.Visible=true; textCopayAmt.Visible=true; textCopayOverride.Visible=true; if(ClaimProcCur.Status==ClaimProcStatus.CapEstimate) { labelWriteOffEst.Visible=true; textWriteOffEst.Visible=true; } else {//capcomplete labelWriteOff.Visible=true; textWriteOff.Visible=true; } //labelPatTotal.Visible=true; groupClaim.Visible=false; labelNotInClaim.Visible=false; } else{//estimate groupClaimInfo.Visible=false; radioEstimate.Checked=true; labelNotInClaim.Visible=false; panelClaimExtras.Visible=false; } comboStatus.Items.Clear(); comboStatus.Items.Add(Lan.g(this,"Estimate")); comboStatus.Items.Add(Lan.g(this,"Not Received")); comboStatus.Items.Add(Lan.g(this,"Received")); comboStatus.Items.Add(Lan.g(this,"PreAuthorization")); comboStatus.Items.Add(Lan.g(this,"Supplemental")); comboStatus.Items.Add(Lan.g(this,"CapClaim")); comboStatus.Items.Add(Lan.g(this,"CapEstimate")); comboStatus.Items.Add(Lan.g(this,"CapComplete")); SetComboStatus(ClaimProcCur.Status); if(ClaimProcCur.Status==ClaimProcStatus.Received || ClaimProcCur.Status==ClaimProcStatus.Supplemental){ labelDateEntry.Visible=true; textDateEntry.Visible=true; } else{ labelDateEntry.Visible=false; textDateEntry.Visible=false; } comboProvider.Items.Clear(); for(int i=0;i<ProviderC.ListShort.Count;i++){ comboProvider.Items.Add(ProviderC.ListShort[i].Abbr); if(ClaimProcCur.ProvNum==ProviderC.ListShort[i].ProvNum){ comboProvider.SelectedIndex=i; } } //this is not used, because the provider might simply be hidden. See bottom of page. //if(listProv.SelectedIndex==-1){ // listProv.SelectedIndex=0;//there should always be a provider //} if(PrefC.GetBool(PrefName.EasyNoClinics)) { labelClinic.Visible=false; textClinic.Visible=false; } else { textClinic.Text=Clinics.GetDesc(ClaimProcCur.ClinicNum); } textDateEntry.Text=ClaimProcCur.DateEntry.ToShortDateString(); if(ClaimProcCur.ProcDate.Year<1880){ textProcDate.Text=""; } else{ textProcDate.Text=ClaimProcCur.ProcDate.ToShortDateString(); } if(ClaimProcCur.DateCP.Year<1880){ textDateCP.Text=""; } else{ textDateCP.Text=ClaimProcCur.DateCP.ToShortDateString(); } textCodeSent.Text=ClaimProcCur.CodeSent; textFeeBilled.Text=ClaimProcCur.FeeBilled.ToString("n"); textRemarks.Text=ClaimProcCur.Remarks; FillInitialAmounts(); ComputeAmounts(); //MessageBox.Show(panelEstimateInfo.Visible.ToString()); }
///<summary>Calculates the Base estimate, InsEstTotal, and all the other insurance numbers for a single claimproc. This is is not done on the fly. Use Procedure.GetEst to later retrieve the estimate. This function replaces all of the upper estimating logic that was within FormClaimProc. BaseEst=((fee or allowedOverride)-Copay) x (percentage or percentOverride). The calling class must have already created the claimProc, and this function simply updates the BaseEst field of that claimproc. pst.Tot not used. For Estimate and CapEstimate, all the estimate fields will be recalculated except the overrides. histList and loopList can be null. If so, then deductible and annual max will not be recalculated. histList and loopList may only make sense in TP module and claimEdit. loopList contains all claimprocs in the current list (TP or claim) that come before this procedure. PaidOtherInsTot should only contain sum of InsEstTotal/Override, or paid, depending on the status. PaidOtherInsBase also includes actual payments.</summary> public static void ComputeBaseEst(ClaimProc cp,double procFee,string toothNum,long codeNum,InsPlan plan,long patPlanNum,List<Benefit> benList,List<ClaimProcHist> histList,List<ClaimProcHist> loopList,List<PatPlan> patPlanList,double paidOtherInsTot,double paidOtherInsBase,int patientAge,double writeOffOtherIns) { //No need to check RemotingRole; no call to db. if(cp.Status==ClaimProcStatus.CapClaim || cp.Status==ClaimProcStatus.CapComplete || cp.Status==ClaimProcStatus.Preauth || cp.Status==ClaimProcStatus.Supplemental) { return;//never compute estimates for those types listed above. } if(plan.PlanType=="c"//if capitation plan && cp.Status==ClaimProcStatus.Estimate)//and ordinary estimate { cp.Status=ClaimProcStatus.CapEstimate; } if(plan.PlanType!="c"//if not capitation plan && cp.Status==ClaimProcStatus.CapEstimate)//and estimate is a capitation estimate { cp.Status=ClaimProcStatus.Estimate; } //NoBillIns is only calculated when creating the claimproc, even if resetAll is true. //If user then changes a procCode, it does not cause an update of all procedures with that code. if(cp.NoBillIns) { cp.AllowedOverride=-1; cp.CopayAmt=0; cp.CopayOverride=-1; cp.Percentage=-1; cp.PercentOverride=-1; cp.DedEst=-1; cp.DedEstOverride=-1; cp.PaidOtherIns=-1; cp.BaseEst=0; cp.InsEstTotal=0; cp.InsEstTotalOverride=-1; cp.WriteOff=0; cp.PaidOtherInsOverride=-1; cp.WriteOffEst=-1; cp.WriteOffEstOverride=-1; return; } cp.EstimateNote=""; //This function is called every time a ProcFee is changed, //so the BaseEst does reflect the new ProcFee. //ProcFee---------------------------------------------------------------------------------------------- cp.BaseEst=procFee; cp.InsEstTotal=procFee; //Allowed---------------------------------------------------------------------------------------------- double allowed=procFee;//could be fee, or could be a little less. Used further down in paidOtherIns. if(cp.AllowedOverride!=-1) { if(cp.AllowedOverride > procFee){ cp.AllowedOverride=procFee; } allowed=cp.AllowedOverride; cp.BaseEst=cp.AllowedOverride; cp.InsEstTotal=cp.AllowedOverride; } else if(plan.PlanType=="c"){//capitation estimate. No allowed fee sched. No substitute codes. allowed=procFee; cp.BaseEst=procFee; cp.InsEstTotal=procFee; } else { //no point in wasting time calculating this unless it's needed. double carrierAllowed=InsPlans.GetAllowed(ProcedureCodes.GetProcCode(codeNum).ProcCode,plan.FeeSched,plan.AllowedFeeSched, plan.CodeSubstNone,plan.PlanType,toothNum,cp.ProvNum); if(carrierAllowed != -1) { if(carrierAllowed > procFee) { allowed=procFee; cp.BaseEst=procFee; cp.InsEstTotal=procFee; } else { allowed=carrierAllowed; cp.BaseEst=carrierAllowed; cp.InsEstTotal=carrierAllowed; } } } //Copay---------------------------------------------------------------------------------------------- cp.CopayAmt=InsPlans.GetCopay(codeNum,plan.FeeSched,plan.CopayFeeSched); if(cp.CopayAmt > allowed) {//if the copay is greater than the allowed fee calculated above cp.CopayAmt=allowed;//reduce the copay } if(cp.CopayOverride > allowed) {//or if the copay override is greater than the allowed fee calculated above cp.CopayOverride=allowed;//reduce the override } if(cp.Status==ClaimProcStatus.CapEstimate) { //this does automate the Writeoff. If user does not want writeoff automated, //then they will have to complete the procedure first. (very rare) if(cp.CopayAmt==-1) { cp.CopayAmt=0; } if(cp.CopayOverride != -1) {//override the copay cp.WriteOffEst=cp.BaseEst-cp.CopayOverride; } else if(cp.CopayAmt!=-1) {//use the calculated copay cp.WriteOffEst=cp.BaseEst-cp.CopayAmt; } if(cp.WriteOffEst<0) { cp.WriteOffEst=0; } cp.WriteOff=cp.WriteOffEst; cp.DedApplied=0; cp.DedEst=0; cp.Percentage=-1; cp.PercentOverride=-1; cp.BaseEst=0; cp.InsEstTotal=0; return; } if(cp.CopayOverride != -1) {//subtract copay if override cp.BaseEst-=cp.CopayOverride; cp.InsEstTotal-=cp.CopayOverride; } else if(cp.CopayAmt != -1) {//otherwise subtract calculated copay cp.BaseEst-=cp.CopayAmt; cp.InsEstTotal-=cp.CopayAmt; } //Deductible---------------------------------------------------------------------------------------- //The code below handles partial usage of available deductible. DateTime procDate; if(cp.Status==ClaimProcStatus.Estimate) { procDate=DateTime.Today; } else { procDate=cp.ProcDate; } if(loopList!=null && histList!=null) { cp.DedEst=Benefits.GetDeductibleByCode(benList,plan.PlanNum,patPlanNum,procDate,ProcedureCodes.GetStringProcCode(codeNum),histList,loopList,plan,cp.PatNum); } if(cp.DedEst > cp.InsEstTotal){//if the deductible is more than the fee cp.DedEst=cp.InsEstTotal;//reduce the deductible } if(cp.DedEstOverride > cp.InsEstTotal) {//if the deductible override is more than the fee cp.DedEstOverride=cp.InsEstTotal;//reduce the override. } if(cp.DedEstOverride != -1) {//use the override cp.InsEstTotal-=cp.DedEstOverride;//subtract } else if(cp.DedEst != -1){//use the calculated deductible cp.InsEstTotal-=cp.DedEst; } //Percentage---------------------------------------------------------------------------------------- cp.Percentage=Benefits.GetPercent(ProcedureCodes.GetProcCode(codeNum).ProcCode,plan.PlanType,plan.PlanNum,patPlanNum,benList);//will never =-1 if(cp.PercentOverride != -1) {//override, so use PercentOverride cp.BaseEst=cp.BaseEst*(double)cp.PercentOverride/100d; cp.InsEstTotal=cp.InsEstTotal*(double)cp.PercentOverride/100d; } else if(cp.Percentage != -1) {//use calculated Percentage cp.BaseEst=cp.BaseEst*(double)cp.Percentage/100d; cp.InsEstTotal=cp.InsEstTotal*(double)cp.Percentage/100d; } //PaidOtherIns---------------------------------------------------------------------------------------- //double paidOtherInsActual=GetPaidOtherIns(cp,patPlanList,patPlanNum,histList);//can return -1 for primary PatPlan pp=PatPlans.GetFromList(patPlanList.ToArray(),patPlanNum); //if -1, that indicates primary ins, not a proc, or no histlist. We should not alter it in this case. //if(paidOtherInsActual!=-1) { //An older restriction was that histList must not be null. But since this is now straight from db, that's not restriction. if(pp==null) { //corruption. Do nothing. } else if(pp.Ordinal==1 || cp.ProcNum==0){ cp.PaidOtherIns=0; } else{//if secondary or greater //The normal calculation uses the InsEstTotal from the primary ins. //But in TP module, if not using max and deduct, then the amount estimated to be paid by primary will be different. //It will use the primary BaseEst instead of the primary InsEstTotal. //Since the only use of BaseEst here is to handle this alternate viewing in the TP, //the secondary BaseEst should use the primary BaseEst when calculating paidOtherIns. //The BaseEst will, however, use PaidOtherInsOverride, if user has entered one. //This calculation doesn't need to be accurate unless viewing TP, //so it's ok to pass in a dummy value, like paidOtherInsTotal. //We do InsEstTotal first //cp.PaidOtherIns=paidOtherInsActual+paidOtherInsEstTotal; cp.PaidOtherIns=paidOtherInsTot; double paidOtherInsTotTemp=cp.PaidOtherIns; if(cp.PaidOtherInsOverride != -1) {//use the override paidOtherInsTotTemp=cp.PaidOtherInsOverride; } //example: Fee:200, InsEstT:80, BaseEst:100, PaidOI:110. //So... MaxPtP:90. //Since InsEstT is not greater than MaxPtoP, no change. //Since BaseEst is greater than MaxPtoP, BaseEst changed to 90. if(paidOtherInsTotTemp != -1) { double maxPossibleToPay=0; if(plan.CobRule==EnumCobRule.Basic) { maxPossibleToPay=allowed-paidOtherInsTotTemp; } else if(plan.CobRule==EnumCobRule.Standard) { double patPortionTot=procFee - paidOtherInsTotTemp - writeOffOtherIns;//patPortion for InsEstTotal maxPossibleToPay=Math.Min(cp.BaseEst,patPortionTot);//The lesser of what insurance would pay if they were primary, and the patient portion. } else{//plan.CobRule==EnumCobRule.CarveOut maxPossibleToPay=cp.BaseEst - paidOtherInsTotTemp; } if(maxPossibleToPay<0) { maxPossibleToPay=0; } if(cp.InsEstTotal > maxPossibleToPay) { cp.InsEstTotal=maxPossibleToPay;//reduce the estimate } } //Then, we do BaseEst double paidOtherInsBaseTemp=paidOtherInsBase;//paidOtherInsActual+paidOtherInsBaseEst; if(cp.PaidOtherInsOverride != -1) {//use the override paidOtherInsBaseTemp=cp.PaidOtherInsOverride; } if(paidOtherInsBaseTemp != -1) { double maxPossibleToPay=0; if(plan.CobRule==EnumCobRule.Basic) { maxPossibleToPay=allowed-paidOtherInsBaseTemp; } else if(plan.CobRule==EnumCobRule.Standard) { double patPortionBase=procFee - paidOtherInsBaseTemp - writeOffOtherIns;//patPortion for BaseEst maxPossibleToPay=Math.Min(cp.BaseEst,patPortionBase); } else {//plan.CobRule==EnumCobRule.CarveOut maxPossibleToPay=cp.BaseEst - paidOtherInsBaseTemp; } if(maxPossibleToPay<0) { maxPossibleToPay=0; } if(cp.BaseEst > maxPossibleToPay) { cp.BaseEst=maxPossibleToPay;//reduce the base est } } } //Exclusions--------------------------------------------------------------------------------------- //We are not going to consider date of proc. Just simple exclusions if(Benefits.IsExcluded(ProcedureCodes.GetStringProcCode(codeNum),benList,plan.PlanNum,patPlanNum)) { cp.BaseEst=0; cp.InsEstTotal=0; if(cp.EstimateNote!="") { cp.EstimateNote+=", "; } cp.EstimateNote+=Lans.g("ClaimProcs","Exclusion"); } //base estimate is now done and will not be altered further. From here out, we are only altering insEstTotal //annual max and other limitations-------------------------------------------------------------------------------- if(loopList!=null && histList!=null) { string note=""; cp.InsEstTotal=Benefits.GetLimitationByCode(benList,plan.PlanNum,patPlanNum,procDate,ProcedureCodes.GetStringProcCode(codeNum),histList,loopList,plan,cp.PatNum,out note,cp.InsEstTotal,patientAge,cp.InsSubNum); if(note != "") { if(cp.EstimateNote != "") { cp.EstimateNote+=", "; } cp.EstimateNote+=note; } } //procDate;//was already calculated in the deductible section. //Writeoff Estimate------------------------------------------------------------------------------------------ if(plan.PlanType=="p") {//PPO //we can't use the allowed previously calculated, because it might be the allowed of a substituted code. //so we will calculate the allowed all over again, but this time, without using a substitution code. //AllowedFeeSched and toothNum do not need to be passed in. codeSubstNone is set to true to not subst. double carrierAllowedNoSubst=InsPlans.GetAllowed(ProcedureCodes.GetProcCode(codeNum).ProcCode,plan.FeeSched,0, true,"p","",cp.ProvNum); double allowedNoSubst=procFee; if(carrierAllowedNoSubst != -1) { if(carrierAllowedNoSubst > procFee) { allowedNoSubst=procFee; } else { allowedNoSubst=carrierAllowedNoSubst; } } double normalWriteOff=procFee-allowedNoSubst;//This is what the normal writeoff would be if no other insurance was involved. if(normalWriteOff<0) { normalWriteOff=0; } double remainingWriteOff=procFee-paidOtherInsTot-writeOffOtherIns;//This is the fee minus whatever other ins has already paid or written off. if(remainingWriteOff<0) { remainingWriteOff=0; } if(writeOffOtherIns>0) {//no secondary writeoff estimates allowed cp.WriteOffEst=0;//The reasoning for this is covered in the manual under Unit Test #1 and COB. } //We can't go over either number. We must use the smaller of the two. If one of them is zero, then the writeoff is zero. else if(remainingWriteOff==0 || normalWriteOff==0) { cp.WriteOffEst=0; } else if(remainingWriteOff<=normalWriteOff) { cp.WriteOffEst=remainingWriteOff; } else { cp.WriteOffEst=normalWriteOff; } } //capitation calculation never makes it this far: //else if(plan.PlanType=="c") {//capitation // cp.WriteOffEst=cp.WriteOff;//this probably needs to change //} else { cp.WriteOffEst=-1; } }
///<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>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~"; }
///<summary>Only call this function for a patPlan such that the carrier has an electid of 000064, which signified that it is for Pacific Blue Cross (PBC).</summary> private static string GetMissingDataForPatPlanPacificBlueCross(PatPlan patPlan,InsPlan insPlan) { string retVal=""; string dependantCode=patPlan.PatID;//C17 int dependantNum=-1; if(dependantCode!="") { try { dependantNum=PIn.Int(dependantCode); } catch { } } string relationshipCode=GetRelationshipCode(patPlan.Relationship);//C03 if(relationshipCode=="1") {//self if(dependantCode!="00") { if(retVal!="") retVal+=", "; retVal+="Dependant code must be 00 for Self with Pacific Blue Cross"; } } else if(relationshipCode=="2") {//spouse if(dependantCode!="01" && !(dependantNum>=90 && dependantNum<=99)) { if(retVal!="") retVal+=", "; retVal+="Dependant code must be 01, or between 90 and 99 for Spouse with Pacific Blue Cross"; } } else if(relationshipCode=="3") {//child if(dependantNum<2 || dependantNum>89 || dependantCode.Length!=2) { retVal+="Dependant code must be between 02 and 89 for Child with Pacific Blue Cross"; } } else if(relationshipCode=="4") {//common law spouse if(dependantCode!="01" && !(dependantNum>=90 && dependantNum<=99)) { if(retVal!="") retVal+=", "; retVal+="Dependant code must be 01, or between 90 and 99 for Common-law with Pacific Blue Cross"; } } else { retVal+="Relationship code must be Self, Spouse, Child, LifePartner, or SignifOther with Pacific Blue Cross"; } return retVal; }
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()); }
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; }
///<summary>This used to be an enumeration.</summary> private static string GetFilingCode(InsPlan plan) { string filingcode=InsFilingCodes.GetEclaimCode(plan.FilingCode); //must be one or two char in length. if(filingcode=="" || filingcode.Length>2) { return "CI"; } return Sout(filingcode,2,1); /* switch(plan.FilingCode){ case InsFilingCodeOld.SelfPay: return "09"; case InsFilingCodeOld.OtherNonFed: return "11"; case InsFilingCodeOld.PPO: return "12"; case InsFilingCodeOld.POS: return "13"; case InsFilingCodeOld.EPO: return "14"; case InsFilingCodeOld.Indemnity: return "15"; case InsFilingCodeOld.HMO_MedicareRisk: return "16"; case InsFilingCodeOld.DMO: return "17"; case InsFilingCodeOld.BCBS: return "BL"; case InsFilingCodeOld.Champus: return "CH"; case InsFilingCodeOld.Commercial_Insurance: return "CI"; case InsFilingCodeOld.Disability: return "DS"; case InsFilingCodeOld.FEP: return "FI"; case InsFilingCodeOld.HMO: return "HM"; case InsFilingCodeOld.LiabilityMedical: return "LM"; case InsFilingCodeOld.MedicarePartB: return "MB"; case InsFilingCodeOld.Medicaid: return "MC"; case InsFilingCodeOld.ManagedCare_NonHMO: return "MH"; case InsFilingCodeOld.OtherFederalProgram: return "OF"; case InsFilingCodeOld.SelfAdministered: return "SA"; case InsFilingCodeOld.Veterans: return "VA"; case InsFilingCodeOld.WorkersComp: return "WC"; case InsFilingCodeOld.MutuallyDefined: return "ZZ"; default: return "CI"; } */ }
///<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); }
///<summary>Used only in ClaimProcs.ComputeBaseEst. Gets a deductible amount from the supplied list of benefits. Ignores benefits that do not match either the planNum or the patPlanNum. It figures out how much was already used and reduces the returned value by that amount. Both individual and family deductibles will reduce the returned value independently. Works for individual procs, categories, and general.</summary> public static double GetDeductibleByCode(List<Benefit> benList,long planNum,long patPlanNum,DateTime procDate,string procCode,List<ClaimProcHist> histList,List<ClaimProcHist> loopList,InsPlan plan,long patNum) { //No need to check RemotingRole; no call to db. #region filter benList for deductibles //first, create a much shorter list with only relevant benefits in it. List<Benefit> listShort=new List<Benefit>(); for(int i=0;i<benList.Count;i++) { if(benList[i].PlanNum==0 && benList[i].PatPlanNum!=patPlanNum) { continue; } if(benList[i].PatPlanNum==0 && benList[i].PlanNum!=planNum) { continue; } if(benList[i].BenefitType!=InsBenefitType.Deductible) { continue; } //if(benList[i].QuantityQualifier!=BenefitQuantity.None) { // continue; //} if(benList[i].TimePeriod!=BenefitTimePeriod.CalendarYear && benList[i].TimePeriod!=BenefitTimePeriod.ServiceYear && benList[i].TimePeriod!=BenefitTimePeriod.Lifetime)//this is probably only going to be used in annual max, though { continue; } listShort.Add(benList[i]); } #endregion #region get individual deductibles //look for the best matching individual deduct---------------------------------------------------------------- Benefit benIndGeneral=null; Benefit benInd=null; #region no category for(int i=0;i<listShort.Count;i++){ if(listShort[i].CoverageLevel == BenefitCoverageLevel.Family){ continue; } if(listShort[i].CodeNum>0){ continue; } if(listShort[i].CovCatNum==0){ benInd=listShort[i]; //This deductible must be a general deductible since it has no associated category benIndGeneral=listShort[i];//sum of deductibles should not exceed this amount, even if benInd is less. } } #endregion #region specific category. CovSpan[] spansForCat; for(int i=0;i<listShort.Count;i++){ if(listShort[i].CoverageLevel == BenefitCoverageLevel.Family){ continue; } if(listShort[i].CodeNum>0){ continue; } if(listShort[i].CovCatNum!=0){ //see if the span matches spansForCat=CovSpans.GetForCat(listShort[i].CovCatNum); bool isMatch=false; for(int j=0;j<spansForCat.Length;j++){ if(String.Compare(procCode,spansForCat[j].FromCode)>=0 && String.Compare(procCode,spansForCat[j].ToCode)<=0){ isMatch=true; break; } } if(!isMatch) { continue;//no match } if(benInd != null && benInd.CovCatNum!=0){//must compare //only use the new one if the item order is larger if(CovCats.GetOrderShort(listShort[i].CovCatNum) > CovCats.GetOrderShort(benInd.CovCatNum)){ benInd=listShort[i]; } } else{//first one encountered for a category benInd=listShort[i]; } } } #endregion #region specific code for(int i=0;i<listShort.Count;i++){ if(listShort[i].CoverageLevel == BenefitCoverageLevel.Family){ continue; } if(listShort[i].CodeNum==0){ continue; } if(procCode==ProcedureCodes.GetStringProcCode(listShort[i].CodeNum)){ benInd=listShort[i]; } } #endregion #endregion #region get family deductibles //look for the best matching family deduct---------------------------------------------------------------- Benefit benFam=null; #region no category for(int i=0;i<listShort.Count;i++) { if(listShort[i].CoverageLevel != BenefitCoverageLevel.Family) { continue; } if(listShort[i].CodeNum>0) { continue; } if(listShort[i].CovCatNum==0) { benFam=listShort[i]; } } #endregion #region specific category. for(int i=0;i<listShort.Count;i++) { if(listShort[i].CoverageLevel != BenefitCoverageLevel.Family) { continue; } if(listShort[i].CodeNum>0) { continue; } if(listShort[i].CovCatNum!=0) { //see if the span matches spansForCat=CovSpans.GetForCat(listShort[i].CovCatNum); bool isMatch=false; for(int j=0;j<spansForCat.Length;j++) { if(String.Compare(procCode,spansForCat[j].FromCode)>=0 && String.Compare(procCode,spansForCat[j].ToCode)<=0) { isMatch=true; break; } } if(!isMatch) { continue;//no match } if(benFam != null && benFam.CovCatNum!=0) {//must compare //only use the new one if the item order is larger if(CovCats.GetOrderShort(listShort[i].CovCatNum) > CovCats.GetOrderShort(benFam.CovCatNum)) { benFam=listShort[i]; } } else {//first one encountered for a category benFam=listShort[i]; } } } #endregion #region specific code for(int i=0;i<listShort.Count;i++) { if(listShort[i].CoverageLevel != BenefitCoverageLevel.Family) { continue; } if(listShort[i].CodeNum==0) { continue; } if(procCode==ProcedureCodes.GetStringProcCode(listShort[i].CodeNum)) { benFam=listShort[i]; } } #endregion #endregion //example. $50 individual deduct, $150 family deduct. //Only individual deductibles make sense as the starting point. //Family deductible just limits the sum of individual deductibles. //If there is no individual deductible that matches, then return 0. if(benInd==null || benInd.MonetaryAmt==-1 || benInd.MonetaryAmt==0) { return 0; } double retVal=benInd.MonetaryAmt; #region reduce by amount individual already paid this year //reduce by amount individual already paid this year-------------------------------------------------------------------- //establish date range for procedures to consider DateTime dateStart=BenefitLogic.ComputeRenewDate(procDate,plan.MonthRenew); DateTime dateEnd=procDate;//I guess we don't want to consider anything after the date of this procedure. if(benInd.TimePeriod==BenefitTimePeriod.Lifetime) { dateStart=DateTime.MinValue; } for(int i=0;i<histList.Count;i++) { if(histList[i].PlanNum != planNum) { continue;//different plan } if(histList[i].ProcDate<dateStart || histList[i].ProcDate>dateEnd) { continue; } if(histList[i].PatNum != patNum) { continue;//this is for someone else in the family } //Procedure specific deductibles need to take all deductibles into consideration, not just deductibles that have been applied towards the specific procedure. //if(benInd.CodeNum!=0) {//specific code // if(ProcedureCodes.GetStringProcCode(benInd.CodeNum)!=histList[i].StrProcCode) { // continue; // } //} else if(histList[i].Status==ClaimProcStatus.Adjustment) { //We always want to apply the deductible for any adjustment to insurance benefits. //This code must be directly above the following "else if(benInd.CovCatNum!=0) {" because adjustments do not have procedure codes to compare. //Therefore, the following else if block will not find a match and will continue looping through histList instead of correctly applying deductible. if(benInd.CovCatNum!=0 && CovCats.GetEbenCat(benInd.CovCatNum)!=EbenefitCategory.General) {//This ensures that the deductible adjustment will only apply to General and None categories. continue; } } else if(benInd.CovCatNum!=0) {//specific category spansForCat=CovSpans.GetForCat(benInd.CovCatNum); bool isMatch=false; for(int j=0;j<spansForCat.Length;j++) { if(String.Compare(histList[i].StrProcCode,spansForCat[j].FromCode)>=0 && String.Compare(histList[i].StrProcCode,spansForCat[j].ToCode)<=0) { isMatch=true; break; } } if(!isMatch) { continue; } } //if no category, then benefits are not restricted by proc code. if(histList[i].Deduct==-1) { continue; } retVal-=histList[i].Deduct; } #endregion #region reduce by amount individual already paid in loopList //now, do a similar thing with loopList, individ----------------------------------------------------------------------- #region diagnostic/preventive workaround //There is a kludgey workaround in the loop below. //It handles the very specific problem of a single diagnostic/preventive deductible even though we have two separate benefits for it. //The better solution will be benefits with multiple categories or spans. //This workaround is only applied if there are both a diagnostic and a preventive deductible for the same amount. //If the benefit is diagnostic, then also check the spans of the preventive category CovSpan[] otherSpans=null; if(CovCats.GetEbenCat(benInd.CovCatNum)==EbenefitCategory.Diagnostic){ for(int i=0;i<listShort.Count;i++){//look through the benefits again if(listShort[i].CoverageLevel!=BenefitCoverageLevel.Individual){ continue; } if(CovCats.GetEbenCat(listShort[i].CovCatNum)!=EbenefitCategory.RoutinePreventive){ continue; } otherSpans=CovSpans.GetForCat(listShort[i].CovCatNum); } } //if the benefit is preventive, then also check the spans of the diagnostic category if(CovCats.GetEbenCat(benInd.CovCatNum)==EbenefitCategory.RoutinePreventive){ for(int i=0;i<listShort.Count;i++){//look through the benefits again if(listShort[i].CoverageLevel!=BenefitCoverageLevel.Individual){ continue; } if(CovCats.GetEbenCat(listShort[i].CovCatNum)!=EbenefitCategory.Diagnostic){ continue; } otherSpans=CovSpans.GetForCat(listShort[i].CovCatNum); } } #endregion for(int i=0;i<loopList.Count;i++) { #region filter loopList //no date restriction, since all TP or part of current claim //if(histList[i].ProcDate<dateStart || histList[i].ProcDate>dateEnd) { // continue; //} if(loopList[i].PlanNum != planNum) { continue;//different plan. Even the loop list can contain info for multiple plans. } if(loopList[i].PatNum != patNum) { continue;//this is for someone else in the family } //Loop list needs to consider procedure specific codes so that deductibles apply to other procedures within a TP if necessary. E.g. Unit Test 16 if(benInd.CodeNum!=0) {//specific code if(ProcedureCodes.GetStringProcCode(benInd.CodeNum)!=loopList[i].StrProcCode) { continue; } } else if(benInd.CovCatNum!=0) {//specific category spansForCat=CovSpans.GetForCat(benInd.CovCatNum); bool isMatch=false; for(int j=0;j<spansForCat.Length;j++) { if(String.Compare(loopList[i].StrProcCode,spansForCat[j].FromCode)>=0 && String.Compare(loopList[i].StrProcCode,spansForCat[j].ToCode)<=0) { isMatch=true; break; } } if(otherSpans!=null){ for(int j=0;j<otherSpans.Length;j++) { if(String.Compare(loopList[i].StrProcCode,otherSpans[j].FromCode)>=0 && String.Compare(loopList[i].StrProcCode,otherSpans[j].ToCode)<=0) { isMatch=true; break; } } } if(!isMatch) { continue; } } //if no category, then benefits are not restricted by proc code. if(loopList[i].Deduct==-1) { continue; } #endregion retVal-=loopList[i].Deduct; } #endregion if(retVal<=0) { return 0; } double deductUsedInLoopList=0;//sum of deductibles in looplist for(int i=0;i<loopList.Count;i++) { deductUsedInLoopList+=loopList[i].Deduct; } if(benIndGeneral!=null) {//if there exists a general deductible if((retVal + deductUsedInLoopList) > benIndGeneral.MonetaryAmt) {//if this would put us over the general deductible, instead make that amount //examples: if (25+45) > 50, then return 50-45=5. retVal=benIndGeneral.MonetaryAmt - deductUsedInLoopList;// (fix for Unit Test 16) } } //if there is still a deductible, we might still reduce it based on family ded used. if(benFam==null || benFam.MonetaryAmt==-1) { return retVal; } double famded=benFam.MonetaryAmt; #region reduce by amount family already paid this year //reduce the family deductible by amounts already used---------------------------------------------------------- for(int i=0;i<histList.Count;i++) { if(histList[i].ProcDate<dateStart || histList[i].ProcDate>dateEnd) { continue; } if(histList[i].PlanNum != planNum) { continue;//different plan } //now, we do want to see all family members. //if(histList[i].PatNum != patNum) { // continue;//this is for someone else in the family //} //Procedure specific deductibles need to take all deductibles into consideration, not just deductibles that have been applied towards the specific procedure. //if(benFam.CodeNum!=0) {//specific code // if(ProcedureCodes.GetStringProcCode(benFam.CodeNum)!=histList[i].StrProcCode) { // continue; // } //} else if(benFam.CovCatNum!=0) {//specific category spansForCat=CovSpans.GetForCat(benFam.CovCatNum); bool isMatch=false; for(int j=0;j<spansForCat.Length;j++) { if(String.Compare(histList[i].StrProcCode,spansForCat[j].FromCode)>=0 && String.Compare(histList[i].StrProcCode,spansForCat[j].ToCode)<=0) { isMatch=true; break; } } if(!isMatch) { continue; } } //if no category, then benefits are not restricted by proc code. if(histList[i].Deduct==-1) { continue; } famded-=histList[i].Deduct; } #endregion #region reduce by amount family already paid in loopList //reduce family ded by amounts already used in loop--------------------------------------------------------------- for(int i=0;i<loopList.Count;i++) { if(loopList[i].PlanNum != planNum) { continue;//different plan } //Loop list needs to consider procedure specific codes so that deductibles apply to other procedures within a TP if necessary. if(benFam.CodeNum!=0) {//specific code if(ProcedureCodes.GetStringProcCode(benFam.CodeNum)!=loopList[i].StrProcCode) { continue; } } else if(benFam.CovCatNum!=0) {//specific category spansForCat=CovSpans.GetForCat(benFam.CovCatNum); bool isMatch=false; for(int j=0;j<spansForCat.Length;j++) { if(String.Compare(loopList[i].StrProcCode,spansForCat[j].FromCode)>=0 && String.Compare(loopList[i].StrProcCode,spansForCat[j].ToCode)<=0) { isMatch=true; break; } } if(!isMatch) { continue; } } //if no category, then benefits are not restricted by proc code. if(loopList[i].Deduct==-1) { continue; } famded-=loopList[i].Deduct; } #endregion //if the family deductible has all been used up on other procs if(famded<=0) { return 0;//then no deductible, regardless of what we computed for individual } if(retVal > famded) {//example; retInd=$50, but 120 of 150 family ded has been used. famded=30. We need to return 30. return famded; } return retVal; }
public static void IncrementOrthoNextClaimDates(PatPlan patPlan, InsPlan insPlan, int monthsTreat, PatientNote patNoteCur) { patPlan.OrthoAutoNextClaimDate = GetOrthoNextClaimDate(patPlan.OrthoAutoNextClaimDate, patNoteCur, insPlan.OrthoAutoProcFreq, monthsTreat); Update(patPlan); }
///<summary>Used only in ClaimProcs.ComputeBaseEst. Calculates the most specific limitation for the specified code. This is usually an annual max, ortho max, or fluoride limitation (only if age match). Ignores benefits that do not match either the planNum or the patPlanNum. It figures out how much was already used and reduces the returned value by that amount. Both individual and family limitations will reduce the returned value independently. Works for individual procs, categories, and general. Also outputs a string description of the limitation. There don't seem to be any situations where multiple limitations would each partially reduce coverage for a single code, other than ind/fam. The returned value will be the original insEstTotal passed in unless there was some limitation that reduced it.</summary> public static double GetLimitationByCode(List<Benefit> benList,long planNum,long patPlanNum,DateTime procDate,string procCodeStr,List<ClaimProcHist> histList,List<ClaimProcHist> loopList,InsPlan plan,long patNum,out string note,double insEstTotal,int patientAge,long insSubNum) { //No need to check RemotingRole;no call to db. note =""; //first, create a much shorter list with only relevant benefits in it. List<Benefit> listShort=new List<Benefit>(); for(int i=0;i<benList.Count;i++) { if(benList[i].PlanNum==0 && benList[i].PatPlanNum!=patPlanNum) { continue; } if(benList[i].PatPlanNum==0 && benList[i].PlanNum!=planNum) { continue; } if(benList[i].BenefitType!=InsBenefitType.Limitations) { continue; } //if(benList[i].TimePeriod!=BenefitTimePeriod.CalendarYear // && benList[i].TimePeriod!=BenefitTimePeriod.ServiceYear // && benList[i].TimePeriod!=BenefitTimePeriod.Lifetime) //{ // continue; //} listShort.Add(benList[i]); } //look for the best matching individual limitation---------------------------------------------------------------- Benefit benInd=null; //start with no category for(int i=0;i<listShort.Count;i++) { if(listShort[i].CoverageLevel == BenefitCoverageLevel.Family) { continue; } if(listShort[i].CodeNum>0) { continue; } if(listShort[i].CovCatNum==0) { benInd=listShort[i]; } } //then, specific category. CovSpan[] spansForCat; for(int i=0;i<listShort.Count;i++) { if(listShort[i].CoverageLevel == BenefitCoverageLevel.Family) { continue; } if(listShort[i].CodeNum>0) { continue; } if(listShort[i].CovCatNum!=0) { //see if the span matches spansForCat=CovSpans.GetForCat(listShort[i].CovCatNum); bool isMatch=false; for(int j=0;j<spansForCat.Length;j++) { if(String.Compare(procCodeStr,spansForCat[j].FromCode)>=0 && String.Compare(procCodeStr,spansForCat[j].ToCode)<=0) { isMatch=true; break; } } if(!isMatch) { continue;//no match } if(listShort[i].QuantityQualifier==BenefitQuantity.NumberOfServices || listShort[i].QuantityQualifier==BenefitQuantity.Months || listShort[i].QuantityQualifier==BenefitQuantity.Years) { continue;//exclude frequencies } //If it's an age based limitation, then make sure the patient age matches. //If we have an age match, then we exit the method right here. if(listShort[i].QuantityQualifier==BenefitQuantity.AgeLimit && listShort[i].Quantity > 0) { if(patientAge > listShort[i].Quantity) { note=Lans.g("Benefits","Age limitation:")+" "+listShort[i].Quantity.ToString(); return 0;//not covered if too old. } } if(benInd != null && benInd.CovCatNum!=0) {//must compare //only use the new one if the item order is larger if(CovCats.GetOrderShort(listShort[i].CovCatNum) > CovCats.GetOrderShort(benInd.CovCatNum)) { benInd=listShort[i]; } } else {//first one encountered for a category benInd=listShort[i]; } } } //then, specific code for(int i=0;i<listShort.Count;i++) { if(listShort[i].CoverageLevel == BenefitCoverageLevel.Family) { continue; } if(listShort[i].CodeNum==0) { continue; } if(procCodeStr!=ProcedureCodes.GetStringProcCode(listShort[i].CodeNum)) { continue; } if(listShort[i].QuantityQualifier==BenefitQuantity.NumberOfServices || listShort[i].QuantityQualifier==BenefitQuantity.Months || listShort[i].QuantityQualifier==BenefitQuantity.Years) { continue;//exclude frequencies } //if it's an age based limitation, then make sure the patient age matches. //If we have an age match, then we exit the method right here. if(listShort[i].QuantityQualifier==BenefitQuantity.AgeLimit && listShort[i].Quantity > 0){ if(patientAge > listShort[i].Quantity){ note=Lans.g("Benefits","Age limitation:")+" "+listShort[i].Quantity.ToString(); return 0;//not covered if too old. } } else{//anything but an age limit benInd=listShort[i]; } } //look for the best matching family limitation---------------------------------------------------------------- Benefit benFam=null; //start with no category for(int i=0;i<listShort.Count;i++) { if(listShort[i].CoverageLevel != BenefitCoverageLevel.Family) { continue; } if(listShort[i].CodeNum>0) { continue; } if(listShort[i].CovCatNum==0) { benFam=listShort[i]; } } //then, specific category. for(int i=0;i<listShort.Count;i++) { if(listShort[i].CoverageLevel != BenefitCoverageLevel.Family) { continue; } if(listShort[i].CodeNum>0) { continue; } if(listShort[i].CovCatNum!=0) { //see if the span matches spansForCat=CovSpans.GetForCat(listShort[i].CovCatNum); bool isMatch=false; for(int j=0;j<spansForCat.Length;j++) { if(String.Compare(procCodeStr,spansForCat[j].FromCode)>=0 && String.Compare(procCodeStr,spansForCat[j].ToCode)<=0) { isMatch=true; break; } } if(!isMatch) { continue;//no match } if(benFam != null && benFam.CovCatNum!=0) {//must compare //only use the new one if the item order is larger if(CovCats.GetOrderShort(listShort[i].CovCatNum) > CovCats.GetOrderShort(benFam.CovCatNum)) { benFam=listShort[i]; } } else {//first one encountered for a category benFam=listShort[i]; } } } //then, specific code for(int i=0;i<listShort.Count;i++) { if(listShort[i].CoverageLevel != BenefitCoverageLevel.Family) { continue; } if(listShort[i].CodeNum==0) { continue; } if(procCodeStr==ProcedureCodes.GetStringProcCode(listShort[i].CodeNum)) { benFam=listShort[i]; } } //example. $1000 individual max, $3000 family max. //Only individual max makes sense as the starting point. Only family max is now being considered as well. //Family max just limits the sum of individual maxes. Family max may be the only cap being used. //If there is no individual limitation that matches, then return 0. No longer valid. Return amount covered by ins, whether individual or family max. //fluoride age limit already handled, so all that's left is maximums. ... if((benInd==null || benInd.MonetaryAmt==-1 || benInd.MonetaryAmt==0) && (benFam==null || benFam.MonetaryAmt==-1 || benFam.MonetaryAmt==0)){ //if(benInd==null || benInd.MonetaryAmt==-1 || benInd.MonetaryAmt==0) { return insEstTotal;//no max found for this code. } double maxInd=0; if(benInd!=null) { maxInd=benInd.MonetaryAmt; } //reduce individual max by amount already paid this year/lifetime--------------------------------------------------- //establish date range for procedures to consider DateTime dateStart=BenefitLogic.ComputeRenewDate(procDate,plan.MonthRenew); DateTime dateEnd=procDate;//don't consider anything after the date of this procedure. if(benInd!=null) { if(benInd.TimePeriod==BenefitTimePeriod.Lifetime) { dateStart=DateTime.MinValue; } for(int i=0;i<histList.Count;i++) { if(histList[i].InsSubNum != insSubNum) { continue;//different plan } if(histList[i].ProcDate<dateStart || histList[i].ProcDate>dateEnd) { continue; } if(histList[i].PatNum != patNum) { continue;//this is for someone else in the family //SHOULD PROBABLY NOT SKIP THIS IN THE CASE OF FAM BUT NO IND MAX. :( } if(benInd.CodeNum!=0) {//specific code //Enhance this later when code spans are supported. if(ProcedureCodes.GetStringProcCode(benInd.CodeNum)!=histList[i].StrProcCode) { continue; } } else if(benInd.CovCatNum!=0) {//specific category spansForCat=CovSpans.GetForCat(benInd.CovCatNum); bool isMatch=false; if(histList[i].StrProcCode=="") {//If this was a 'total' payment that was not attached to a procedure if(CovCats.GetEbenCat(benInd.CovCatNum)==EbenefitCategory.General) {//And if this is the general category //Then it should affect this max. isMatch=true; } } else {//If the payment was attached to a proc, then the proc must be in the coderange of this annual max benefit for(int j=0;j<spansForCat.Length;j++) { if(String.Compare(histList[i].StrProcCode,spansForCat[j].FromCode)>=0 && String.Compare(histList[i].StrProcCode,spansForCat[j].ToCode)<=0) { isMatch=true; break; } } } if(!isMatch) { continue; } } //if no category, then benefits are not restricted by proc code. //In other words, the benefit applies to all codes. //At this point, we know that the proc in the loopList falls within this max benefit. //But it may also fall within a more restrictive benefit which would take precedence over this one. if(TighterLimitExists(listShort,benInd,histList[i])) { continue; } maxInd-=histList[i].Amount; } } //reduce individual max by amount in loop ------------------------------------------------------------------ if(benInd!=null) { for(int i=0;i<loopList.Count;i++) { //no date restriction, since all TP or part of current claim //if(histList[i].ProcDate<dateStart || histList[i].ProcDate>dateEnd) { // continue; //} if(loopList[i].InsSubNum != insSubNum) { continue;//different plan. Even the loop list can contain info for multiple plans. } if(loopList[i].PatNum != patNum) { continue;//this is for someone else in the family } if(benInd.CodeNum!=0) {//specific code //Enhance this later when code spans are supported. if(ProcedureCodes.GetStringProcCode(benInd.CodeNum)!=loopList[i].StrProcCode) { continue; } } else if(benInd.CovCatNum!=0) {//specific category spansForCat=CovSpans.GetForCat(benInd.CovCatNum); bool isMatch=false; if(loopList[i].StrProcCode=="") {//If this was a 'total' payment that was not attached to a procedure if(CovCats.GetEbenCat(benInd.CovCatNum)==EbenefitCategory.General) {//And if this is the general category //Then it should affect this max. isMatch=true; } } else {//If the payment was attached to a proc, then the proc must be in the coderange of this annual max benefit for(int j=0;j<spansForCat.Length;j++) { if(String.Compare(loopList[i].StrProcCode,spansForCat[j].FromCode)>=0 && String.Compare(loopList[i].StrProcCode,spansForCat[j].ToCode)<=0) { isMatch=true; break; } } } if(!isMatch) { continue; } } else {//if no category, then benefits are not normally restricted by proc code. //The problem is that if the amount in the loop is from an ortho proc, then the general category will exclude ortho. //But sometimes, the annual max is in the system as no category instead of general category. CovCat generalCat=CovCats.GetForEbenCat(EbenefitCategory.General); if(generalCat!=null) {//If there is a general category, then we only consider codes within it. This is how we exclude ortho. CovSpan[] covSpanArray=CovSpans.GetForCat(generalCat.CovCatNum); if(loopList[i].StrProcCode!="" && !CovSpans.IsCodeInSpans(loopList[i].StrProcCode,covSpanArray)) {//for example, ortho continue; } } } //At this point, we know that the proc in the loopList falls within this max benefit. //But it may also fall within a more restrictive benefit which would take precedence over this one. if(TighterLimitExists(listShort,benInd,loopList[i])) { continue; } maxInd-=loopList[i].Amount; } } if(benInd!=null) { if(maxInd <= 0) {//then patient has used up all of their annual max, so no coverage. if(benInd.TimePeriod==BenefitTimePeriod.Lifetime) { note+=Lans.g("Benefits","Over lifetime max"); } else if(benInd.TimePeriod==BenefitTimePeriod.CalendarYear || benInd.TimePeriod==BenefitTimePeriod.ServiceYear) { note+=Lans.g("Benefits","Over annual max"); } return 0; } } double retVal=insEstTotal; if(benInd!=null){ if(maxInd < insEstTotal) {//if there's not enough left in the individual annual max to cover this proc. retVal=maxInd;//insurance will only cover up to the remaining annual max } } //Three situations: //1. Ind only. //Handled in the next 10 lines, then return. // //2. Ind and Fam max present. //There seems to be enough to cover at least part of this procedure. //There may also be a family max that has been met which may partially or completely reduce coverage of this proc. // //3. Fam only. We don't know how much is left. //maxInd=-1 //benInd=null if(benFam==null || benFam.MonetaryAmt==-1) {//if no family max. Ind only. if(retVal != insEstTotal){//and procedure is not fully covered by ind max if(benInd!=null) {//redundant if(benInd.TimePeriod==BenefitTimePeriod.Lifetime) { note+=Lans.g("Benefits","Over lifetime max"); } else if(benInd.TimePeriod==BenefitTimePeriod.CalendarYear || benInd.TimePeriod==BenefitTimePeriod.ServiceYear) { note+=Lans.g("Benefits","Over annual max"); } } } return retVal;//no family max anyway, so no need to go further. } double maxFam=benFam.MonetaryAmt; //reduce the family max by amounts already used---------------------------------------------------------- for(int i=0;i<histList.Count;i++) { if(histList[i].ProcDate<dateStart || histList[i].ProcDate>dateEnd) { continue; } if(histList[i].PlanNum != planNum) { continue;//different plan } //now, we do want to see all family members. //if(histList[i].PatNum != patNum) { // continue;//this is for someone else in the family //} if(benFam.CodeNum!=0) {//specific code if(ProcedureCodes.GetStringProcCode(benFam.CodeNum)!=histList[i].StrProcCode) { continue; } } else if(benFam.CovCatNum!=0) {//specific category spansForCat=CovSpans.GetForCat(benFam.CovCatNum); bool isMatch=false; if(histList[i].StrProcCode=="") {//If this was a 'total' payment that was not attached to a procedure if(CovCats.GetEbenCat(benFam.CovCatNum)==EbenefitCategory.General) {//And if this is the general category //Then it should affect this max. isMatch=true; } } else { for(int j=0;j<spansForCat.Length;j++) { if(String.Compare(histList[i].StrProcCode,spansForCat[j].FromCode)>=0 && String.Compare(histList[i].StrProcCode,spansForCat[j].ToCode)<=0) { isMatch=true; break; } } } if(!isMatch) { continue; } } //if no category, then benefits are not restricted by proc code. maxFam-=histList[i].Amount; } //reduce family max by amounts already used in loop--------------------------------------------------------------- for(int i=0;i<loopList.Count;i++) { if(loopList[i].PlanNum != planNum) { continue;//different plan } if(benFam.CodeNum!=0) {//specific code if(ProcedureCodes.GetStringProcCode(benFam.CodeNum)!=loopList[i].StrProcCode) { continue; } } else if(benFam.CovCatNum!=0) {//specific category spansForCat=CovSpans.GetForCat(benFam.CovCatNum); bool isMatch=false; if(loopList[i].StrProcCode=="") {//If this was a 'total' payment that was not attached to a procedure if(CovCats.GetEbenCat(benFam.CovCatNum)==EbenefitCategory.General) {//And if this is the general category //Then it should affect this max. isMatch=true; } } else { for(int j=0;j<spansForCat.Length;j++) { if(String.Compare(loopList[i].StrProcCode,spansForCat[j].FromCode)>=0 && String.Compare(loopList[i].StrProcCode,spansForCat[j].ToCode)<=0) { isMatch=true; break; } } } if(!isMatch) { continue; } } //if no category, then benefits are not restricted by proc code. maxFam-=loopList[i].Amount; } //if the family max has all been used up on other procs if(maxFam<=0) { if(benInd==null) { note+=Lans.g("Benefits","Over family max"); } else{//and there is an individual max. if(benInd.TimePeriod==BenefitTimePeriod.Lifetime) { note+=Lans.g("Benefits","Over family lifetime max"); } else if(benInd.TimePeriod==BenefitTimePeriod.CalendarYear || benInd.TimePeriod==BenefitTimePeriod.ServiceYear) { note+=Lans.g("Benefits","Over family annual max"); } } return 0;//then no coverage, regardless of what we computed for individual } //This section was causing a bug. I'm really not even sure what it was attempting to do, since it's common for family max to be greater than indiv max /*if(maxFam > maxInd) {//restrict by maxInd //which we already calculated if(benInd.TimePeriod==BenefitTimePeriod.Lifetime) { note+=Lans.g("Benefits","Over lifetime max"); } else if(benInd.TimePeriod==BenefitTimePeriod.CalendarYear || benInd.TimePeriod==BenefitTimePeriod.ServiceYear) { note+=Lans.g("Benefits","Over annual max"); } return retVal; }*/ if((benInd==null) || (maxFam < maxInd)) {//restrict by maxFam if(maxFam < retVal) {//if there's not enough left in the annual max to cover this proc. //example. retVal=$70. But 2970 of 3000 family max has been used. maxFam=30. We need to return 30. if(benInd==null) { note+=Lans.g("Benefits","Over family max"); } else{//both ind and fam if(benInd.TimePeriod==BenefitTimePeriod.Lifetime) { note+=Lans.g("Benefits","Over family lifetime max"); } else if(benInd.TimePeriod==BenefitTimePeriod.CalendarYear || benInd.TimePeriod==BenefitTimePeriod.ServiceYear) { note+=Lans.g("Benefits","Over family annual max"); } } return maxFam;//insurance will only cover up to the remaining annual max } } if(retVal < insEstTotal) {//must have been an individual restriction if(benInd==null) {//js I don't understand this situation. It will probably not happen, but this is safe. note+=Lans.g("Benefits","Over annual max"); } else { if(benInd.TimePeriod==BenefitTimePeriod.Lifetime) { note+=Lans.g("Benefits","Over lifetime max"); } else if(benInd.TimePeriod==BenefitTimePeriod.CalendarYear || benInd.TimePeriod==BenefitTimePeriod.ServiceYear) { note+=Lans.g("Benefits","Over annual max"); } } } return retVal; }
/// <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; }
private void gridMain_CellDoubleClick(object sender,ODGridClickEventArgs e){ InsPlan plan=InsPlans.GetPlan(PIn.Long(table.Rows[e.Row]["PlanNum"].ToString()),null); if(IsSelectMode) { SelectedPlan=plan.Copy(); DialogResult=DialogResult.OK; return; } FormInsPlan FormIP=new FormInsPlan(plan,null,null); FormIP.ShowDialog(); if(FormIP.DialogResult!=DialogResult.OK) { return; } FillGrid(); }
///<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~"; }
private void butMerge_Click(object sender,EventArgs e) { if(gridMain.SelectedIndices.Length<2) { MessageBox.Show(Lan.g(this,"Please select at least two items first.")); return; } InsPlan[] listSelected=new InsPlan[gridMain.SelectedIndices.Length]; for(int i=0;i<listSelected.Length;i++){ listSelected[i]=InsPlans.GetPlan(PIn.Long(table.Rows[gridMain.SelectedIndices[i]]["PlanNum"].ToString()),null); listSelected[i].NumberSubscribers=PIn.Int(table.Rows[gridMain.SelectedIndices[i]]["subscribers"].ToString()); } FormInsPlansMerge FormI=new FormInsPlansMerge(); FormI.ListAll=listSelected; FormI.ShowDialog(); if(FormI.DialogResult!=DialogResult.OK){ return; } //Do the merge. InsPlan planToMergeTo=FormI.PlanToMergeTo.Copy(); //List<Benefit> benList=Benefits.RefreshForPlan(planToMergeTo,0); Cursor=Cursors.WaitCursor; for(int i=0;i<listSelected.Length;i++){//loop through each selected plan //skip the planToMergeTo, because it's already correct if(planToMergeTo.PlanNum==listSelected[i].PlanNum){ continue; } //==Michael - We are changing plans here, but not carriers, so this is not needed: //SecurityLogs.MakeLogEntry(Permissions.InsPlanChangeCarrierName InsPlans.ChangeReferences(listSelected[i].PlanNum,planToMergeTo.PlanNum); Benefits.DeleteForPlan(listSelected[i].PlanNum); InsPlans.Delete(listSelected[i].PlanNum); //for(int j=0;j<planNums.Count;j++) { //InsPlans.ComputeEstimatesForPlan(planNums[j]); //Eliminated in 5.0 for speed. //} } FillGrid(); //highlight the merged plan for(int i=0;i<table.Rows.Count;i++){ for(int j=0;j<listSelected.Length;j++){ if(table.Rows[i]["PlanNum"].ToString()==listSelected[j].PlanNum.ToString()){ gridMain.SetSelected(i,true); } } } Cursor=Cursors.Default; }
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; }
private void butBlank_Click(object sender, System.EventArgs e) { //this button is normally not visible. It's only set visible when IsSelectMode. SelectedPlan=new InsPlan(); DialogResult=DialogResult.OK; }
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 butOK_Click(object sender, System.EventArgs e) { //only visible if IsSelectMode if(gridMain.SelectedIndices.Length==0){ MessageBox.Show(Lan.g(this,"Please select an item first.")); return; } if(gridMain.SelectedIndices.Length>1) { MessageBox.Show(Lan.g(this,"Please select only one item first.")); return; } SelectedPlan=InsPlans.GetPlan(PIn.Long(table.Rows[gridMain.SelectedIndices[0]]["PlanNum"].ToString()),null).Copy(); 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(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; }
///<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>Calculates the time available to verify based on a variety of patient and appointment factors. ///Looks at Appointment date, appointment creation date, last verification date, next scheduled verification, insurance renewal ///</summary> public static InsVerify SetTimeAvailableForVerify(InsVerify insVer, PlanToVerify planType, int appointmentScheduledDays, int insBenefitEligibilityDays, int patientEnrollmentDays) { //DateAppointmentScheduled-DateAppointmentCreated DateTime dateTimeLatestApptScheduling; //DateAppointmentScheduled-appointmentScheduledDays (default is 7) DateTime dateTimeUntilAppt; //DateTime the appointment takes place. DateTime dateTimeAppointment; //DateTime the patient was scheduled to be re-verified DateTime dateTimeScheduledReVerify; //DateTime verification last took place. Will be 01/01/0001 if verification has never happened. DateTime dateTimeLastVerified; //DateTime the insurance renewal month rolls over. //The month the renewal takes place is stored in the database. If the month is 0, then it is actually january. //It is the first day of the given month at midnight, or (Month#)/01/(year) @ 00:00AM. //Set to max val by default in case the PrefName.InsVerifyFutureDateBenefitYear=false. //Since max val is later in time than the appointment time, it will be ignored. DateTime dateBenifitRenewalNeeded = DateTime.MaxValue; #region Appointment Dates dateTimeAppointment = insVer.AppointmentDateTime; dateTimeUntilAppt = insVer.AppointmentDateTime.AddDays(-appointmentScheduledDays); //Calculate when the appointment was put into it's current time slot. //This will be the earliest datetime where the scheduled appointment time is what it is now List <HistAppointment> listHistAppt = HistAppointments.GetForApt(insVer.AptNum); listHistAppt.RemoveAll(x => x.AptDateTime.Date != insVer.AppointmentDateTime.Date); listHistAppt = listHistAppt.Where(x => x.AptStatus == ApptStatus.Scheduled).OrderBy(x => x.AptDateTime).ToList(); if (listHistAppt.Count > 0) { //If the appointment was moved to the current date after the (Apt.DateTime-appointmentScheduledDays), //we only had (Apt.DateTime-listHistAppt.First().HistDateTstamp) days instead of (appointmentScheduledDays) dateTimeLatestApptScheduling = listHistAppt.First().HistDateTStamp; } else { //Just in case there's no history for an appointment for some reason. //Shouldn't happen because a log entry is created when the appointment is created. //Use the date the appointment was created. This is better than nothing and should never happen anyways. dateTimeLatestApptScheduling = Appointments.GetOneApt(insVer.AptNum).SecDateEntry; } #endregion Appointment Dates #region Insurance Verification dateTimeLastVerified = insVer.DateLastVerified; //Add defined number of days to date last verified to calculate when the next verification date should have started. if (planType == PlanToVerify.InsuranceBenefits) { if (insVer.DateLastVerified == DateTime.MinValue) //If it's the min value, the insurance has never been verified. { dateTimeScheduledReVerify = insVer.DateTimeEntry; } else { dateTimeScheduledReVerify = insVer.DateLastVerified.AddDays(insBenefitEligibilityDays); } } else //PlanToVerify.PatientEligibility { if (insVer.DateLastVerified == DateTime.MinValue) { dateTimeScheduledReVerify = insVer.DateTimeEntry; } else { dateTimeScheduledReVerify = insVer.DateLastVerified.AddDays(patientEnrollmentDays); } } #endregion insurance verification #region Benifit Renewal if (PrefC.GetBool(PrefName.InsVerifyFutureDateBenefitYear)) { InsPlan insPlan = InsPlans.GetPlan(insVer.PlanNum, null); //Setup the month renew dates. Need all 3 years in case the appointment verify window crosses over a year //e.g. Appt verify date: 12/30/2016 and Appt Date: 1/6/2017 DateTime dateTimeOldestRenewal = new DateTime(DateTime.Now.Year - 1, Math.Max((byte)1, insPlan.MonthRenew), 1); DateTime dateTimeMiddleRenewal = new DateTime(DateTime.Now.Year, Math.Max((byte)1, insPlan.MonthRenew), 1); DateTime dateTimeNewestRenewal = new DateTime(DateTime.Now.Year + 1, Math.Max((byte)1, insPlan.MonthRenew), 1); //We want to find the date closest to the appointment date without going past it. if (dateTimeMiddleRenewal > dateTimeAppointment) { dateBenifitRenewalNeeded = dateTimeOldestRenewal; } else { if (dateTimeNewestRenewal > dateTimeAppointment) { dateBenifitRenewalNeeded = dateTimeMiddleRenewal; } else { dateBenifitRenewalNeeded = dateTimeNewestRenewal; } } } #endregion Benifit Renewal DateTime dateTimeAbleToVerify = VerifyDateCalulation(dateTimeUntilAppt, dateTimeLatestApptScheduling, dateTimeScheduledReVerify, dateBenifitRenewalNeeded); insVer.HoursAvailableForVerification = insVer.AppointmentDateTime.Subtract(dateTimeAbleToVerify).TotalHours; return(insVer); }
private void butOK_Click(object sender, System.EventArgs e) { PlanToMergeTo=ListAll[gridMain.GetSelectedIndex()].Copy(); DialogResult=DialogResult.OK; }