private void butRun_Click(object sender, EventArgs e) { List <ClaimPaySplit> splits = Claims.GetInsPayNotAttachedForFixTool(); if (splits.Count == 0) { MsgBox.Show(this, "There are currently no insurance payments that are not attached to an insurance check."); return; } Cursor = Cursors.WaitCursor; for (int i = 0; i < splits.Count; i++) { Claim claim = Claims.GetClaim(splits[i].ClaimNum); ClaimPayment cp = new ClaimPayment(); cp.CheckDate = claim.DateService; cp.CheckAmt = splits[i].InsPayAmt; cp.ClinicNum = claim.ClinicNum; cp.CarrierName = splits[i].Carrier; ClaimPayments.Insert(cp); List <ClaimProc> claimP = ClaimProcs.RefreshForClaim(splits[i].ClaimNum); for (int j = 0; j < claimP.Count; j++) { claimP[j].DateCP = claim.DateService; claimP[j].ClaimPaymentNum = cp.ClaimPaymentNum; ClaimProcs.Update(claimP[j]); } } Cursor = Cursors.Default; MessageBox.Show(Lan.g(this, "Insurance checks created: ") + splits.Count); }
private void butRun_Click(object sender, EventArgs e) { List <ClaimPaySplit> splits = Claims.GetInsPayNotAttachedForFixTool(); if (splits.Count == 0) { MsgBox.Show(this, "There are currently no insurance payments that are not attached to an insurance check."); DialogResult = DialogResult.OK; //Close the window because there is nothing else to do return; } Cursor = Cursors.WaitCursor; string invalidClaimDate = ""; DateTime curDate = MiscData.GetNowDateTime().Date; for (int i = 0; i < splits.Count; i++) { Claim claim = Claims.GetClaim(splits[i].ClaimNum); if (claim == null) { continue; } if (claim.DateReceived.Date > curDate && !PrefC.GetBool(PrefName.AllowFutureInsPayments) && !PrefC.GetBool(PrefName.FutureTransDatesAllowed)) { invalidClaimDate += "\r\n" + Lan.g(this, "PatNum") + " " + claim.PatNum + ", " + claim.DateService.ToShortDateString(); continue; } ClaimPayment cp = new ClaimPayment(); cp.CheckDate = claim.DateReceived; cp.CheckAmt = splits[i].InsPayAmt; cp.ClinicNum = claim.ClinicNum; cp.CarrierName = splits[i].Carrier; cp.PayType = Defs.GetFirstForCategory(DefCat.InsurancePaymentType, true).DefNum; ClaimPayments.Insert(cp); List <ClaimProc> claimP = ClaimProcs.RefreshForClaim(splits[i].ClaimNum); for (int j = 0; j < claimP.Count; j++) { if (claimP[j].ClaimPaymentNum != 0 || claimP[j].InsPayAmt == 0) //If claimpayment already attached to claimproc or ins didn't pay. { continue; //Do not change } claimP[j].DateCP = claim.DateReceived; claimP[j].ClaimPaymentNum = cp.ClaimPaymentNum; ClaimProcs.Update(claimP[j]); } } Cursor = Cursors.Default; if (invalidClaimDate != "") { invalidClaimDate = "\r\n" + Lan.g(this, "Cannot make future-dated insurance payments for these claims:") + invalidClaimDate; } MsgBoxCopyPaste messageBox = new MsgBoxCopyPaste(Lan.g(this, "Insurance checks created:") + " " + splits.Count + invalidClaimDate); messageBox.Show(); DialogResult = DialogResult.OK; //Close the window because there is nothing else to do }
/// <summary>Creates a check for the claim selected. Copied logic from FormClaimEdit.cs</summary> private void createCheckToolStripMenuItem_Click(object sender, EventArgs e) { if (!Security.IsAuthorized(Permissions.InsPayCreate)) //date not checked here, but it will be checked when saving the check to prevent backdating { return; } if (PrefC.GetBool(PrefName.ClaimPaymentBatchOnly)) { //Is there a permission in the manage module that would block this behavior? Are we sending the user into a TRAP?! MsgBox.Show(this, "Please use Batch Insurance in Manage Module to Finalize Payments."); return; } RpUnfinalizedInsPay.UnfinalizedInsPay unfinalPay = (RpUnfinalizedInsPay.UnfinalizedInsPay)gridMain.ListGridRows[gridMain.SelectedIndices[0]].Tag; if (unfinalPay.ClaimCur == null) { MsgBox.Show(this, "Unable to find claim for this partial payment."); return; } List <ClaimProc> listClaimProcForClaim = ClaimProcs.RefreshForClaim(unfinalPay.ClaimCur.ClaimNum); if (!listClaimProcForClaim.Any(x => x.Status.In(ClaimProcs.GetInsPaidStatuses()))) { MessageBox.Show(Lan.g(this, "There are no valid received payments for this claim.")); return; } ClaimPayment claimPayment = new ClaimPayment(); claimPayment.CheckDate = MiscData.GetNowDateTime().Date; //Today's date for easier tracking by the office and to avoid backdating before accounting lock dates. claimPayment.IsPartial = true; claimPayment.ClinicNum = unfinalPay.ClinicCur.ClinicNum; Family famCur = Patients.GetFamily(unfinalPay.PatientCur.PatNum); List <InsSub> listInsSub = InsSubs.RefreshForFam(famCur); List <InsPlan> listInsPlan = InsPlans.RefreshForSubList(listInsSub); claimPayment.CarrierName = Carriers.GetName(InsPlans.GetPlan(unfinalPay.ClaimCur.PlanNum, listInsPlan).CarrierNum); ClaimPayments.Insert(claimPayment); double amt = ClaimProcs.AttachAllOutstandingToPayment(claimPayment.ClaimPaymentNum, PrefC.DateClaimReceivedAfter); claimPayment.CheckAmt = amt; try { ClaimPayments.Update(claimPayment); } catch (ApplicationException ex) { MessageBox.Show(ex.Message); return; } FormClaimEdit.FormFinalizePaymentHelper(claimPayment, unfinalPay.ClaimCur, unfinalPay.PatientCur, famCur); LoadData(); FillGrid(); }
///<summary>Updates all claimproc estimates and also updates claim totals to db. Must supply procList which includes all procedures that this claim is linked to. Will also need to refresh afterwards to see the results</summary> public static void CalculateAndUpdate(List <Procedure> procList, List <InsPlan> planList, Claim claimCur, List <PatPlan> patPlans, List <Benefit> benefitList, int patientAge, List <InsSub> subList) { //we need more than just the claimprocs for this claim. //in order to run Procedures.ComputeEstimates, we need all claimprocs for all procedures attached to this claim List <ClaimProc> ClaimProcsAll = ClaimProcs.Refresh(claimCur.PatNum); List <ClaimProc> ClaimProcsForClaim = ClaimProcs.RefreshForClaim(claimCur.ClaimNum); //will be ordered by line number. double claimFee = 0; double dedApplied = 0; double insPayEst = 0; double insPayAmt = 0; double writeoff = 0; InsPlan plan = InsPlans.GetPlan(claimCur.PlanNum, planList); if (plan == null) { return; } long patPlanNum = PatPlans.GetPatPlanNum(claimCur.InsSubNum, patPlans); //first loop handles totals for received items. for (int i = 0; i < ClaimProcsForClaim.Count; i++) { if (ClaimProcsForClaim[i].Status != ClaimProcStatus.Received) { continue; //disregard any status except Receieved. } claimFee += ClaimProcsForClaim[i].FeeBilled; dedApplied += ClaimProcsForClaim[i].DedApplied; insPayEst += ClaimProcsForClaim[i].InsPayEst; insPayAmt += ClaimProcsForClaim[i].InsPayAmt; writeoff += ClaimProcsForClaim[i].WriteOff; } //loop again only for procs not received. //And for preauth. Procedure ProcCur; //InsPlan plan=InsPlans.GetPlan(claimCur.PlanNum,planList); List <ClaimProcHist> histList = ClaimProcs.GetHistList(claimCur.PatNum, benefitList, patPlans, planList, claimCur.ClaimNum, claimCur.DateService, subList); List <ClaimProc> claimProcListOld = new List <ClaimProc>(); //make a copy for (int i = 0; i < ClaimProcsAll.Count; i++) { claimProcListOld.Add(ClaimProcsAll[i].Copy()); } List <ClaimProcHist> loopList = new List <ClaimProcHist>(); for (int i = 0; i < ClaimProcsForClaim.Count; i++) //loop through each proc { ProcCur = Procedures.GetProcFromList(procList, ClaimProcsForClaim[i].ProcNum); //in order for ComputeEstimates to give accurate Writeoff when creating a claim, InsPayEst must be filled for the claimproc with status of NotReceived. //So, we must set it here. We need to set it in the claimProcsAll list. Find the matching one. for (int j = 0; j < ClaimProcsAll.Count; j++) { if (ClaimProcsAll[j].ClaimProcNum == ClaimProcsForClaim[i].ClaimProcNum) //same claimproc in a different list { if (ClaimProcsForClaim[i].Status == ClaimProcStatus.NotReceived && ProcCur != null) //ignores payments, etc { ClaimProcsAll[j].InsPayEst = ClaimProcs.GetInsEstTotal(ClaimProcsAll[j]); } } } //When this is the secondary claim, HistList includes the primary estimates, which is something we don't want because the primary calculations gets confused. //So, we must remove those bad entries from histList. for (int h = histList.Count - 1; h >= 0; h--) //loop through the histList backwards { if (histList[h].ProcNum != ProcCur.ProcNum) { continue; //Makes sure we will only be excluding histList entries for procs on this claim. } //we already excluded this claimNum when getting the histList. if (histList[h].Status != ClaimProcStatus.NotReceived) { continue; //The only ones that are a problem are the ones on the primary claim not received yet. } histList.RemoveAt(h); } Procedures.ComputeEstimates(ProcCur, claimCur.PatNum, ref ClaimProcsAll, false, planList, patPlans, benefitList, histList, loopList, false, patientAge, subList); //then, add this information to loopList so that the next procedure is aware of it. loopList.AddRange(ClaimProcs.GetHistForProc(ClaimProcsAll, ProcCur.ProcNum, ProcCur.CodeNum)); } //save changes in the list to the database ClaimProcs.Synch(ref ClaimProcsAll, claimProcListOld); ClaimProcsForClaim = ClaimProcs.RefreshForClaim(claimCur.ClaimNum); //But ClaimProcsAll has not been refreshed. for (int i = 0; i < ClaimProcsForClaim.Count; i++) { if (ClaimProcsForClaim[i].Status != ClaimProcStatus.NotReceived && ClaimProcsForClaim[i].Status != ClaimProcStatus.Preauth && ClaimProcsForClaim[i].Status != ClaimProcStatus.CapClaim) { continue; } ProcCur = Procedures.GetProcFromList(procList, ClaimProcsForClaim[i].ProcNum); if (ProcCur.ProcNum == 0) { continue; //ignores payments, etc } //fee: int qty = ProcCur.UnitQty + ProcCur.BaseUnits; if (qty == 0) { qty = 1; } if (plan.ClaimsUseUCR) //use UCR for the provider of the procedure { long provNum = ProcCur.ProvNum; if (provNum == 0) //if no prov set, then use practice default. { provNum = PrefC.GetLong(PrefName.PracticeDefaultProv); } //get the fee based on code and prov fee sched double feebilled = Fees.GetAmount0(ProcCur.CodeNum, ProviderC.ListLong[Providers.GetIndexLong(provNum)].FeeSched); if (feebilled > ProcCur.ProcFee) { ClaimProcsForClaim[i].FeeBilled = qty * feebilled; } else { ClaimProcsForClaim[i].FeeBilled = qty * ProcCur.ProcFee; } } //else if(claimCur.ClaimType=="Cap") {//Even for capitation, use the proc fee. // ClaimProcsForClaim[i].FeeBilled=0; //} else //don't use ucr. Use the procedure fee instead. { ClaimProcsForClaim[i].FeeBilled = qty * ProcCur.ProcFee; } claimFee += ClaimProcsForClaim[i].FeeBilled; if (claimCur.ClaimType == "PreAuth" || claimCur.ClaimType == "Other" || claimCur.ClaimType == "Cap") { //only the fee gets calculated, the rest does not ClaimProcs.Update(ClaimProcsForClaim[i]); continue; } //ClaimProcs.ComputeBaseEst(ClaimProcsForClaim[i],ProcCur.ProcFee,ProcCur.ToothNum,ProcCur.CodeNum,plan,patPlanNum,benefitList,histList,loopList); ClaimProcsForClaim[i].InsPayEst = ClaimProcs.GetInsEstTotal(ClaimProcsForClaim[i]); //Yes, this is duplicated from further up. ClaimProcsForClaim[i].DedApplied = ClaimProcs.GetDedEst(ClaimProcsForClaim[i]); if (ClaimProcsForClaim[i].Status == ClaimProcStatus.NotReceived) //(vs preauth) { ClaimProcsForClaim[i].WriteOff = ClaimProcs.GetWriteOffEstimate(ClaimProcsForClaim[i]); writeoff += ClaimProcsForClaim[i].WriteOff; /* * ClaimProcsForClaim[i].WriteOff=0; * if(claimCur.ClaimType=="P" && plan.PlanType=="p") {//Primary && PPO * double insplanAllowed=Fees.GetAmount(ProcCur.CodeNum,plan.FeeSched); * if(insplanAllowed!=-1) { * ClaimProcsForClaim[i].WriteOff=ProcCur.ProcFee-insplanAllowed; * } * //else, if -1 fee not found, then do not show a writeoff. User can change writeoff if they disagree. * } * writeoff+=ClaimProcsForClaim[i].WriteOff;*/ } dedApplied += ClaimProcsForClaim[i].DedApplied; insPayEst += ClaimProcsForClaim[i].InsPayEst; ClaimProcsForClaim[i].ProcDate = ProcCur.ProcDate.Date; //this solves a rare bug. Keeps dates synched. //It's rare enough that I'm not goint to add it to the db maint tool. ClaimProcs.Update(ClaimProcsForClaim[i]); //but notice that the ClaimProcs lists are not refreshed until the loop is finished. } //for claimprocs.forclaim claimCur.ClaimFee = claimFee; claimCur.DedApplied = dedApplied; claimCur.InsPayEst = insPayEst; claimCur.InsPayAmt = insPayAmt; claimCur.WriteOff = writeoff; //Cur=ClaimCur; Claims.Update(claimCur); }
private void FillClaimDetails(int rowIndex) { Claim claimSelected = (Claim)gridClaims.Rows[rowIndex].Tag; bool isSupplemental = (claimSelected.ClaimStatus == "R"); _listClaimProcsForClaim = ClaimProcs.RefreshForClaim(claimSelected.ClaimNum) .Where(x => x.ProcNum != 0 && x.Status.In(ClaimProcStatus.Received, ClaimProcStatus.NotReceived, ClaimProcStatus.Preauth)) .ToList(); gridClaimDetails.BeginUpdate(); if (gridClaimDetails.Columns.Count == 0) { #region grid columns gridClaimDetails.Columns.Add(new UI.ODGridColumn("ProcCode", 100)); gridClaimDetails.Columns.Add(new UI.ODGridColumn("ProcFee", 100)); gridClaimDetails.Columns.Add(new UI.ODGridColumn("ProcStatus", 0)); gridClaimDetails.Columns.Add(new UI.ODGridColumn("IsMatch", 0)); gridClaimDetails.Columns.Add(new UI.ODGridColumn("EraCode", 100)); gridClaimDetails.Columns.Add(new UI.ODGridColumn("EraFee", 100)); #endregion } gridClaimDetails.Rows.Clear(); List <Hx835_Proc> listUnMatchedEraProcs = new List <Hx835_Proc>(); List <Tuple <Hx835_Proc, ClaimProc> > listMatchedEraProcs = new List <Tuple <Hx835_Proc, ClaimProc> >(); foreach (Hx835_Proc proc in _x835Claim.ListProcs) { ClaimProc claimProc = _listClaimProcsForClaim.FirstOrDefault(x => //Mimics proc matching in claimPaid.GetPaymentsForClaimProcs(...) x.ProcNum != 0 && ((x.ProcNum == proc.ProcNum) || (x.CodeSent == proc.ProcCodeBilled && (decimal)x.FeeBilled == proc.ProcFee && (isSupplemental && x.Status == ClaimProcStatus.Received || !isSupplemental && x.Status == ClaimProcStatus.NotReceived) && x.TagOD == null)) ); if (claimProc == null) //Not found { listUnMatchedEraProcs.Add(proc); } else { claimProc.TagOD = true; //Flag set to indicate that claimProc has been handled listMatchedEraProcs.Add(new Tuple <Hx835_Proc, ClaimProc>(proc, claimProc)); } } #region ERA procs that could not be matched foreach (Hx835_Proc proc in listUnMatchedEraProcs) { UI.ODGridRow row = new UI.ODGridRow(); row.Cells.Add(""); row.Cells.Add(""); row.Cells.Add(""); row.Cells.Add("N"); row.Cells.Add(proc.ProcCodeBilled); row.Cells.Add(POut.Decimal(proc.ProcFee)); row.ColorText = Color.Red; row.Bold = true; gridClaimDetails.Rows.Add(row); } #endregion #region ERA procs that we can match. foreach (Tuple <Hx835_Proc, ClaimProc> match in listMatchedEraProcs) { Hx835_Proc proc = match.Item1; ClaimProc claimProc = match.Item2; UI.ODGridRow row = new UI.ODGridRow(); row.Cells.Add(claimProc.CodeSent); row.Cells.Add(POut.Double(claimProc.FeeBilled)); #region Status column switch (claimProc.Status) { case ClaimProcStatus.Received: row.Cells.Add("Recd"); break; case ClaimProcStatus.NotReceived: row.Cells.Add(""); break; } #endregion row.Cells.Add("Y"); row.Cells.Add(proc.ProcCodeBilled); row.Cells.Add(POut.Decimal(proc.ProcFee)); row.ColorText = Color.Green; row.Bold = true; gridClaimDetails.Rows.Add(row); } #endregion #region Claim claimProcs that could not be matched. foreach (ClaimProc claimProc in _listClaimProcsForClaim) { if (claimProc.TagOD != null) { continue; } UI.ODGridRow row = new UI.ODGridRow(); row.Cells.Add(claimProc.CodeSent); row.Cells.Add(POut.Double(claimProc.FeeBilled)); switch (claimProc.Status) { #region Status column case ClaimProcStatus.Received: row.Cells.Add("Recd"); break; case ClaimProcStatus.NotReceived: row.Cells.Add(""); break; } #endregion row.Cells.Add("N"); row.Cells.Add(""); row.Cells.Add(""); gridClaimDetails.Rows.Add(row); } #endregion gridClaimDetails.EndUpdate(); }