Exemple #1
0
        private void FormPayPlanCredits_Load(object sender, EventArgs e)
        {
            _listPatNums = new List <long>();
            _listPatNums.Add(_patCur.PatNum);
            _listAdjustments = Adjustments.GetAdjustForPats(_listPatNums);
            _listProcs       = Procedures.GetCompAndTpForPats(_listPatNums);
            List <PayPlan> listPayPlans = PayPlans.GetForPats(_listPatNums, _patCur.PatNum);        //Used to figure out how much we need to pay off procs with, also contains insurance payplans.

            _listPayPlanCharges = new List <PayPlanCharge>();
            if (listPayPlans.Count > 0)
            {
                //get all current payplan charges for plans already on the patient, excluding the current one.
                _listPayPlanCharges = PayPlanCharges.GetDueForPayPlans(listPayPlans, _patCur.PatNum)                                               //Does not get charges for the future.
                                      .Where(x => !(x.PayPlanNum == _payPlanCur.PayPlanNum && x.ChargeType == PayPlanChargeType.Credit)).ToList(); //do not get credits for current payplan
            }
            List <PaySplit> tempListPaySplits = PaySplits.GetForPats(_listPatNums).Where(x => x.UnearnedType == 0).ToList();                       //Might contain payplan payments. Do not include unearned.

            _listPaySplits     = tempListPaySplits.FindAll(x => x.PayPlanNum == 0 || listPayPlans.Exists(y => y.PayPlanNum == x.PayPlanNum));
            _listPayments      = Payments.GetNonSplitForPats(_listPatNums);
            _listInsPayAsTotal = ClaimProcs.GetByTotForPats(_listPatNums);          //Claimprocs paid as total, might contain ins payplan payments.
            _listClaimProcs    = ClaimProcs.GetForProcs(_listProcs.Select(x => x.ProcNum).ToList());
            textCode.Text      = Lan.g(this, "None");
            FillGrid();
            if (!Security.IsAuthorized(Permissions.PayPlanEdit, true))
            {
                this.DisableForm(butCancel, checkHideUnattached, checkShowImplicit, butPrint, gridMain);
            }
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        ///<summary>Retrieves data and uses them to create new PayPlanExtended objects.
        ///Heavy lifting (db calls and double loops) done here once upon load.  This also gets called if the user clicks "Refresh Data".</summary>
        private bool LoadData()
        {
            List <PayPlan>       listPayPlans;
            List <PayPlanCharge> listPayPlanCharges;
            List <ClaimProc>     listPayPlanClaimProcs;
            List <Patient>       listPatients;
            List <InsPlan>       listInsPlans;

            listPayPlans = PayPlans.GetAllOpenInsPayPlans();
            if (listPayPlans.Count == 0)
            {
                MsgBox.Show(this, "There are no insurance payment plans past due.");
                return(false);
            }
            listPayPlanCharges    = PayPlanCharges.GetForPayPlans(listPayPlans.Select(x => x.PayPlanNum).ToList()).Where(x => x.ChargeType == PayPlanChargeType.Debit).ToList();
            listPayPlanClaimProcs = ClaimProcs.GetForPayPlans(listPayPlans.Select(x => x.PayPlanNum).ToList()
                                                              , new List <ClaimProcStatus>()
            {
                ClaimProcStatus.Received, ClaimProcStatus.Supplemental
            });
            listPatients         = Patients.GetLimForPats(listPayPlans.Select(x => x.PatNum).ToList());
            listInsPlans         = InsPlans.GetPlans(listPayPlans.Select(x => x.PlanNum).ToList());
            _listPayPlanExtended = new List <PayPlanExtended>();
            foreach (PayPlan plan in listPayPlans)
            {
                //for each payplan, create a PayPlanExtended object which contains all of the payment plan's information and it's charges.
                //pass in the plan, the list of associated charges, and the list of associated claimprocs (payments).
                _listPayPlanExtended.Add(new PayPlanExtended(plan,
                                                             listPatients.FirstOrDefault(x => x.PatNum == plan.PatNum),
                                                             listPayPlanCharges.Where(x => x.PayPlanNum == plan.PayPlanNum).ToList(),
                                                             listPayPlanClaimProcs.Where(x => x.PayPlanNum == plan.PayPlanNum).ToList(),
                                                             listInsPlans.FirstOrDefault(x => x.PlanNum == plan.PlanNum)));
            }
            return(true);
        }
Exemple #4
0
 private void FormProcSelect_Load(object sender, System.EventArgs e)
 {
     if (_isMultiSelect)
     {
         gridMain.SelectionMode = OpenDental.UI.GridSelectionMode.MultiExtended;
     }
     _listSelectedProcs = new List <Procedure>();
     _listProcedures    = Procedures.GetCompleteForPats(new List <long> {
         _patNumCur
     });
     _listAdjustments = Adjustments.GetAdjustForPats(new List <long> {
         _patNumCur
     });
     _listPayPlanCharges = PayPlanCharges.GetDueForPayPlans(PayPlans.GetForPats(null, _patNumCur), _patNumCur).ToList();        //Does not get charges for the future.
     _listPaySplits      = PaySplits.GetForPats(new List <long> {
         _patNumCur
     });                                                                            //Might contain payplan payments.
     _listInsPayAsTotal = ClaimProcs.GetByTotForPats(new List <long> {
         _patNumCur
     });
     _listClaimProcs          = ClaimProcs.GetForProcs(_listProcedures.Select(x => x.ProcNum).ToList());
     labelUnallocated.Visible = _doShowUnallocatedLabel;
     if (PrefC.GetInt(PrefName.RigorousAdjustments) == (int)RigorousAdjustments.DontEnforce)
     {
         radioIncludeAllCredits.Checked = true;
     }
     else
     {
         radioOnlyAllocatedCredits.Checked = true;
     }
     FillGrid();
 }
        /// <summary>Returns true if ClaimProcAllowCreditsGreaterThanProcFee preference allows the user to add credits greater than the proc fee. Otherwise returns false </summary>
        private bool isClaimProcGreaterThanProcFee()
        {
            ClaimProcCreditsGreaterThanProcFee creditsGreaterPref = (ClaimProcCreditsGreaterThanProcFee)PrefC.GetInt(PrefName.ClaimProcAllowCreditsGreaterThanProcFee);

            if (creditsGreaterPref == ClaimProcCreditsGreaterThanProcFee.Allow)
            {
                return(true);
            }
            List <Procedure>  listProcs                 = Procedures.GetManyProc(ClaimProcsToEdit.Select(x => x.ProcNum).ToList(), false);
            List <ClaimProc>  listClaimProcsForPat      = ClaimProcs.Refresh(PatCur.PatNum);
            List <PaySplit>   listPaySplitForSelectedCP = PaySplits.GetPaySplitsFromProcs(ClaimProcsToEdit.Select(x => x.ProcNum).ToList());
            List <Adjustment> listAdjForSelectedCP      = Adjustments.GetForProcs(ClaimProcsToEdit.Select(x => x.ProcNum).ToList());
            bool          isCreditGreater               = false;
            List <string> listProcDescripts             = new List <string>();

            for (int i = 0; i < ClaimProcsToEdit.Length; i++)
            {
                ClaimProc claimProcCur = ClaimProcsToEdit[i];
                int       insPayIdx    = gridMain.ListGridColumns.GetIndex(Lan.g("TableClaimProc", "Ins Pay"));
                int       writeoffIdx  = gridMain.ListGridColumns.GetIndex(Lan.g("TableClaimProc", "Writeoff"));
                int       feeAcctIdx   = gridMain.ListGridColumns.GetIndex(Lan.g("TableClaimProc", "Fee"));
                decimal   insPayAmt    = (decimal)ClaimProcs.ProcInsPay(listClaimProcsForPat.FindAll(x => x.ClaimProcNum != claimProcCur.ClaimProcNum), claimProcCur.ProcNum)
                                         + PIn.Decimal(gridMain.ListGridRows[i].Cells[insPayIdx].Text);
                decimal writeOff = (decimal)ClaimProcs.ProcWriteoff(listClaimProcsForPat.FindAll(x => x.ClaimProcNum != claimProcCur.ClaimProcNum), claimProcCur.ProcNum)
                                   + PIn.Decimal(gridMain.ListGridRows[i].Cells[writeoffIdx].Text);
                decimal feeAcct   = PIn.Decimal(gridMain.ListGridRows[i].Cells[feeAcctIdx].Text);
                decimal adj       = listAdjForSelectedCP.Where(x => x.ProcNum == claimProcCur.ProcNum).Select(x => (decimal)x.AdjAmt).Sum();
                decimal patPayAmt = listPaySplitForSelectedCP.Where(x => x.ProcNum == claimProcCur.ProcNum).Select(x => (decimal)x.SplitAmt).Sum();
                //Any changes to this calculation should also consider FormClaimProc.IsClaimProcGreaterThanProcFee().
                decimal creditRem = feeAcct - patPayAmt - insPayAmt - writeOff + adj;
                isCreditGreater |= (creditRem.IsLessThanZero());
                if (creditRem.IsLessThanZero())
                {
                    Procedure proc = listProcs.FirstOrDefault(x => x.ProcNum == claimProcCur.ProcNum);
                    listProcDescripts.Add((proc == null ? "" : ProcedureCodes.GetProcCode(proc.CodeNum).ProcCode)
                                          + "\t" + Lan.g(this, "Fee") + ": " + feeAcct.ToString("F")
                                          + "\t" + Lan.g(this, "Credits") + ": " + (Math.Abs(-patPayAmt - insPayAmt - writeOff + adj)).ToString("F")
                                          + "\t" + Lan.g(this, "Remaining") + ": (" + Math.Abs(creditRem).ToString("F") + ")");
                }
            }
            if (!isCreditGreater)
            {
                return(true);
            }
            if (creditsGreaterPref == ClaimProcCreditsGreaterThanProcFee.Block)
            {
                MsgBoxCopyPaste msgBox = new MsgBoxCopyPaste(Lan.g(this, "Remaining amount is negative for the following procedures") + ":\r\n"
                                                             + string.Join("\r\n", listProcDescripts) + "\r\n" + Lan.g(this, "Not allowed to continue."));
                msgBox.Text = Lan.g(this, "Overpaid Procedure Warning");
                msgBox.ShowDialog();
                return(false);
            }
            if (creditsGreaterPref == ClaimProcCreditsGreaterThanProcFee.Warn)
            {
                return(MessageBox.Show(Lan.g(this, "Remaining amount is negative for the following procedures") + ":\r\n"
                                       + string.Join("\r\n", listProcDescripts.Take(10)) + "\r\n" + (listProcDescripts.Count > 10?"...\r\n":"") + Lan.g(this, "Continue?")
                                       , Lan.g(this, "Overpaid Procedure Warning"), MessageBoxButtons.OKCancel) == DialogResult.OK);
            }
            return(true);           //should never get to this line, only possible if another enum value is added to allow, warn, and block
        }
Exemple #6
0
        private void butOK_Click(object sender, System.EventArgs e)
        {
            if (textDate.errorProvider1.GetError(textDate) != ""
                )
            {
                MessageBox.Show(Lan.g(this, "Please fix data entry errors first."));
                return;
            }
            if (tb2.SelectedIndices.Length == 0)
            {
                MessageBox.Show(Lan.g(this, "At least one item must be selected, or use the delete button."));
                return;
            }
            if (comboClinic.SelectedIndex == 0)
            {
                ClaimPaymentCur.ClinicNum = 0;
            }
            else
            {
                ClaimPaymentCur.ClinicNum = Clinics.List[comboClinic.SelectedIndex - 1].ClinicNum;
            }
            ClaimPaymentCur.CheckAmt    = PIn.PDouble(textAmount.Text);
            ClaimPaymentCur.CheckDate   = PIn.PDate(textDate.Text);
            ClaimPaymentCur.CheckNum    = textCheckNum.Text;
            ClaimPaymentCur.BankBranch  = textBankBranch.Text;
            ClaimPaymentCur.CarrierName = textCarrierName.Text;
            ClaimPaymentCur.Note        = textNote.Text;
            try{
                ClaimPayments.Update(ClaimPaymentCur);                //error thrown if trying to change amount and already attached to a deposit.
            }
            catch (ApplicationException ex) {
                MessageBox.Show(ex.Message);
                return;
            }
            //this could be optimized to only save changes.
            //Would require a starting AL to compare to.
            //But this isn't bad, since changes all saved at the very end
            ArrayList ALselected = new ArrayList();

            for (int i = 0; i < tb2.SelectedIndices.Length; i++)
            {
                ALselected.Add(tb2.SelectedIndices[i]);
            }
            for (int i = 0; i < splits.Length; i++)
            {
                if (ALselected.Contains(i))                //row is selected
                {
                    ClaimProcs.SetForClaim(splits[i].ClaimNum, ClaimPaymentCur.ClaimPaymentNum,
                                           ClaimPaymentCur.CheckDate, true);
                }
                else                 //row not selected
                {
                    ClaimProcs.SetForClaim(splits[i].ClaimNum, ClaimPaymentCur.ClaimPaymentNum,
                                           ClaimPaymentCur.CheckDate, false);
                }
            }
            DialogResult = DialogResult.OK;
        }
 private void ExtractData(PatientDashboardDataEventArgs data)
 {
     _listInsPlans = data.ListInsPlans;
     _listInsSubs  = data.ListInsSubs;
     _listPatPlans = data.ListPatPlans;
     _listBenefits = data.ListBenefits;
     _histList     = data.HistList ?? ClaimProcs.GetHistList(_pat.PatNum, _listBenefits, _listPatPlans, _listInsPlans, DateTime.Today, _listInsSubs);
     _pat          = data.Pat;
 }
Exemple #8
0
        private void RefreshFromDb()
        {
            List <long> listClaimNums = _x835.ListClaimsPaid.Select(x => x.ClaimNum).Where(x => x != 0).ToList();

            _listAttaches = Etrans835Attaches.GetForEtransNumOrClaimNums(false, EtransCur.EtransNum, listClaimNums.ToArray());        //Includes manually detached and split attaches.
            //We have to add additional claimNums from _listAttaches to account for claims split from their original ERA.
            listClaimNums.AddRange(_listAttaches.Where(x => x.ClaimNum != 0).Select(x => x.ClaimNum).Distinct());
            _listClaimProcs = ClaimProcs.RefreshForClaims(listClaimNums);
        }
Exemple #9
0
        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
        }
Exemple #10
0
        ///<summary>This method converts the AccountEntry objects we get back from AccountModules.GetListUnpaidAccountCharges() to MultiAdjEntry objects.
        ///These are used to fill the grid and do all relevant logic in this form. This method will return a fresh list of procedures and will not show
        ///any existing adjustments that may have been made in this form already. Called on load and when checkShowImplicit is clicked.
        ///When called from checkShowImplicit any existing adjustments made will not be shown.(Ask Andrew about this functionality)</summary>
        private List <MultiAdjEntry> FillListGridEntries(CreditCalcType calc)
        {
            List <MultiAdjEntry> retVal = new List <MultiAdjEntry>();

            #region Get required data
            List <Procedure> listProcedures = Procedures.GetCompleteForPats(new List <long> {
                _patCur.PatNum
            });
            //Does not get charges for the future.
            List <PaySplit> listPaySplits = PaySplits.GetForPats(new List <long> {
                _patCur.PatNum
            }).Where(x => x.UnearnedType == 0).ToList();
            List <Adjustment> listAdjustments = Adjustments.GetAdjustForPats(new List <long> {
                _patCur.PatNum
            });
            //Might contain payplan payments. Do not include unearned.
            List <PayPlanCharge> listPayPlanCharges = PayPlanCharges.GetDueForPayPlans(PayPlans.GetForPats(null, _patCur.PatNum), _patCur.PatNum).ToList();
            List <ClaimProc>     listInsPayAsTotal  = ClaimProcs.GetByTotForPats(new List <long> {
                _patCur.PatNum
            });
            List <ClaimProc> listClaimProcs = ClaimProcs.GetForProcs(listProcedures.Select(x => x.ProcNum).ToList());
            #endregion
            List <AccountEntry> listAccountCharges = AccountModules.GetListUnpaidAccountCharges(listProcedures, listAdjustments
                                                                                                , listPaySplits, listClaimProcs, listPayPlanCharges, listInsPayAsTotal, calc, new List <PaySplit>());
            List <AccountEntry> listAccountChargesIncludeAll = null;
            if (calc == CreditCalcType.ExcludeAll)
            {
                //We need to get all credits so that our AmtRemBefore can reflect what has truly been allocated to the procedure.
                listAccountChargesIncludeAll = AccountModules.GetListUnpaidAccountCharges(listProcedures, listAdjustments
                                                                                          , listPaySplits, listClaimProcs, listPayPlanCharges, listInsPayAsTotal, CreditCalcType.IncludeAll, new List <PaySplit>());
            }
            MultiAdjEntry multiEntry = null;
            foreach (AccountEntry entry in listAccountCharges)
            {
                //We only want AccountEntries that are completed procedures.
                if (entry.GetType() != typeof(ProcExtended))
                {
                    continue;
                }
                ProcExtended procEntry = (ProcExtended)entry.Tag;
                if ((_listSelectedProcs != null && _listSelectedProcs.Any(x => x.ProcNum == procEntry.Proc.ProcNum)) ||        //Allow selected procs to show if paid off
                    entry.AmountEnd != 0)                     //All unpaid procedures should always show up per Nathan
                {
                    double amtRemBefore = (double)(listAccountChargesIncludeAll?.FirstOrDefault(x => x.Tag.GetType() == typeof(ProcExtended) &&
                                                                                                ((ProcExtended)x.Tag).Proc.ProcNum == procEntry.Proc.ProcNum) ?? entry).AmountStart;
                    multiEntry = new MultiAdjEntry(procEntry.Proc, (double)entry.AmountStart, (double)entry.AmountEnd, amtRemBefore);
                    retVal.Add(multiEntry);
                }
            }
            OrderListGridEntries();
            return(retVal);
        }
 private void FormProcSelect_Load(object sender, System.EventArgs e)
 {
     if (_isMultiSelect)
     {
         gridMain.SelectionMode = OpenDental.UI.GridSelectionMode.MultiExtended;
     }
     _listSelectedProcs = new List <Procedure>();
     _listProcedures    = Procedures.GetCompleteForPats(new List <long> {
         _patNumCur
     });
     if (ShowTpProcs)
     {
         _listProcedures.AddRange(Procedures.GetTpForPats(new List <long> {
             _patNumCur
         }));
     }
     _listAdjustments = Adjustments.GetAdjustForPats(new List <long> {
         _patNumCur
     });
     _listPayPlanCharges = PayPlanCharges.GetDueForPayPlans(PayPlans.GetForPats(null, _patNumCur), _patNumCur).ToList();        //Does not get charges for the future.
     _listPaySplits      = PaySplits.GetForPats(new List <long> {
         _patNumCur
     });                                                                            //Might contain payplan payments.
     foreach (PaySplit split in ListSplitsCur)
     {
         //If this is a new payment, its paysplits will not be in the database yet, so we need to add them manually. We might also need to set the
         //ProcNum on the pay split if it has changed and has not been saved to the database.
         PaySplit splitDb = _listPaySplits.FirstOrDefault(x => x.IsSame(split));
         if (splitDb == null)
         {
             _listPaySplits.Add(split);
         }
         else
         {
             splitDb.ProcNum = split.ProcNum;
         }
     }
     _listInsPayAsTotal = ClaimProcs.GetByTotForPats(new List <long> {
         _patNumCur
     });
     _listClaimProcs          = ClaimProcs.GetForProcs(_listProcedures.Select(x => x.ProcNum).ToList());
     labelUnallocated.Visible = _doShowUnallocatedLabel;
     if (PrefC.GetInt(PrefName.RigorousAdjustments) == (int)RigorousAdjustments.DontEnforce)
     {
         radioIncludeAllCredits.Checked = true;
     }
     else
     {
         radioOnlyAllocatedCredits.Checked = true;
     }
     FillGrid();
 }
Exemple #12
0
        private void FormProcEditAll_Load(object sender, EventArgs e)
        {
            ProcOldList = new List <Procedure>();
            for (int i = 0; i < ProcList.Count; i++)
            {
                ProcOldList.Add(ProcList[i].Copy());
            }
            AnyAreC = false;
            DateTime oldestDateEntryC = DateTime.Today;
            bool     datesAreSame     = true;

            for (int i = 0; i < ProcList.Count; i++)
            {
                if (ProcList[i].ProcStatus == ProcStat.C)
                {
                    AnyAreC = true;
                    if (ProcList[i].ProcDate < oldestDateEntryC)
                    {
                        oldestDateEntryC = ProcList[i].ProcDate;
                    }
                }
                if (ProcList[0].ProcDate != ProcList[i].ProcDate)
                {
                    datesAreSame = false;
                }
            }
            if (AnyAreC)
            {
                if (!Security.IsAuthorized(Permissions.ProcComplEdit, oldestDateEntryC))
                {
                    butOK.Enabled         = false;
                    butEditAnyway.Enabled = false;
                }
            }
            List <ClaimProc> ClaimProcList = ClaimProcs.Refresh(ProcList[0].PatNum);

            if (Procedures.IsAttachedToClaim(ProcList, ClaimProcList))
            {
                //StartedAttachedToClaim=true;
                //however, this doesn't stop someone from creating a claim while this window is open,
                //so this is checked at the end, too.
                textDate.Enabled      = false;
                butToday.Enabled      = false;
                butEditAnyway.Visible = true;
                labelClaim.Visible    = true;
            }
            if (datesAreSame)
            {
                textDate.Text = ProcList[0].ProcDate.ToShortDateString();
            }
        }
        /// <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();
        }
Exemple #14
0
 private void butDelete_Click(object sender, EventArgs e)
 {
     if (IsNew)
     {
         DialogResult = DialogResult.Cancel;
         return;
     }
     if (!MsgBox.Show("All", MsgBoxButtons.OKCancel, "Delete?"))
     {
         return;
     }
     ClaimProcs.Delete(ClaimProcCur);
     DialogResult = DialogResult.OK;
 }
Exemple #15
0
        private void butOK_Click(object sender, System.EventArgs e)
        {
            if (textProcDate.errorProvider1.GetError(textProcDate) != "" ||
                textAmount.errorProvider1.GetError(textAmount) != "")
            {
                MsgBox.Show(this, "Please fix data entry errors first.");
                return;
            }
            if (textProcDate.Text == "")
            {
                MsgBox.Show(this, "Please enter a date first.");
                return;
            }
            if (_procCur.ProcStatus == ProcStat.C && PIn.Date(textProcDate.Text).Date > DateTime.Today.Date && !PrefC.GetBool(PrefName.FutureTransDatesAllowed))
            {
                MsgBox.Show(this, "Completed procedures cannot be set for future dates.");
                return;
            }
            if (textAmount.Text == "")
            {
                MsgBox.Show(this, "Please enter an amount.");
                return;
            }
            if (comboProv.GetSelectedProvNum() != _procOld.ProvNum && PrefC.GetBool(PrefName.ProcProvChangesClaimProcWithClaim))
            {
                List <ClaimProc> listClaimProc = ClaimProcs.GetForProc(ClaimProcs.Refresh(_procOld.PatNum), _procOld.ProcNum);
                if (listClaimProc.Any(x => x.Status == ClaimProcStatus.Received ||
                                      x.Status == ClaimProcStatus.Supplemental ||
                                      x.Status == ClaimProcStatus.CapClaim))
                {
                    MsgBox.Show(this, "The provider cannot be changed when this procedure is attached to a claim.");
                    return;
                }
            }
            _procCur.ProcDate    = PIn.Date(textProcDate.Text);
            _procCur.ProcFee     = PIn.Double(textAmount.Text);
            _procCur.Note        = textChartNotes.Text;
            _procCur.BillingNote = textAccountNotes.Text;
            _procCur.ProvNum     = comboProv.GetSelectedProvNum();
            _procCur.ClinicNum   = comboClinic.SelectedClinicNum;
            Procedures.Update(_procCur, _procOld);
            ProcedureCode procedureCode = ProcedureCodes.GetProcCode(_procCur.CodeNum);
            string        logText       = procedureCode.ProcCode + " (" + _procCur.ProcStatus + "), " + Lan.g(this, "Fee") + ": " + _procCur.ProcFee.ToString("c") + ", " + procedureCode.Descript;

            SecurityLogs.MakeLogEntry(IsNew ? Permissions.ProcComplCreate : Permissions.ProcComplEdit, _procCur.PatNum, logText);
            DialogResult = DialogResult.OK;
        }
        ///<summary>Returns true if InsPayNoWriteoffMoreThanProc preference is turned on and the sum of write off amount is greater than the proc fee.
        ///Otherwise returns false </summary>
        private bool IsWriteOffGreaterThanProcFee()
        {
            if (!PrefC.GetBool(PrefName.InsPayNoWriteoffMoreThanProc))
            {
                return(false);               //InsPayNoWriteoffMoreThanProc preference is off. No need to check.
            }
            List <ClaimProc>  listClaimProcsForPat  = ClaimProcs.Refresh(PatCur.PatNum);
            List <Adjustment> listAdjustmentsForPat = Adjustments.GetForProcs(ClaimProcsToEdit.Select(x => x.ProcNum).Where(x => x != 0).ToList());
            bool          isWriteoffGreater         = false;
            List <string> listProcDescripts         = new List <string>();

            for (int i = 0; i < ClaimProcsToEdit.Length; i++)
            {
                ClaimProc claimProcCur = ClaimProcsToEdit[i];
                //Fetch all adjustments for the given procedure.
                List <Adjustment> listClaimProcAdjustments = listAdjustmentsForPat.Where(x => x.ProcNum == claimProcCur.ProcNum).ToList();
                int     writeoffIdx = gridMain.ListGridColumns.GetIndex(Lan.g("TableClaimProc", "Writeoff"));
                int     feeAcctIdx  = gridMain.ListGridColumns.GetIndex(Lan.g("TableClaimProc", "Fee"));
                decimal writeOff    = (decimal)ClaimProcs.ProcWriteoff(listClaimProcsForPat.FindAll(x => x.ClaimProcNum != claimProcCur.ClaimProcNum), claimProcCur.ProcNum)
                                      + PIn.Decimal(gridMain.ListGridRows[i].Cells[writeoffIdx].Text);
                decimal feeAcct = PIn.Decimal(gridMain.ListGridRows[i].Cells[feeAcctIdx].Text);
                decimal adjAcct = listClaimProcAdjustments.Sum(x => (decimal)x.AdjAmt);
                //Any changes to this calculation should also consider FormClaimProc.IsWriteOffGreaterThanProc().
                decimal writeoffRem = feeAcct - writeOff + adjAcct;
                isWriteoffGreater |= (writeoffRem.IsLessThanZero() && writeOff.IsGreaterThanZero());
                if (writeoffRem.IsLessThanZero() && writeOff.IsGreaterThanZero())
                {
                    Procedure proc = Procedures.GetProcFromList(ProcList, claimProcCur.ProcNum);                 //will return a new procedure if none found.
                    listProcDescripts.Add((proc == null ? "" : ProcedureCodes.GetProcCode(proc.CodeNum).ProcCode)
                                          + "\t" + Lan.g(this, "Fee") + ": " + feeAcct.ToString("F")
                                          + "\t" + Lan.g(this, "Adjustments") + ": " + adjAcct.ToString("F")
                                          + "\t" + Lan.g(this, "Write-off") + ": " + (Math.Abs(-writeOff)).ToString("F")
                                          + "\t" + Lan.g(this, "Remaining") + ": (" + Math.Abs(writeoffRem).ToString("F") + ")");
                }
            }
            if (isWriteoffGreater)
            {
                MsgBoxCopyPaste msgBox = new MsgBoxCopyPaste(Lan.g(this, "Write-off amount is greater than the adjusted procedure fee for the following "
                                                                   + "procedure(s)") + ":\r\n" + string.Join("\r\n", listProcDescripts) + "\r\n" + Lan.g(this, "Not allowed to continue."));
                msgBox.Text = Lan.g(this, "Excessive Write-off");
                msgBox.ShowDialog();
                return(true);
            }
            return(false);
        }
 public void RefreshData(Patient pat, SheetField sheetField)
 {
     _listInsPlans = new List <InsPlan>();
     _listInsSubs  = new List <InsSub>();
     _listPatPlans = new List <PatPlan>();
     _listBenefits = new List <Benefit>();
     _histList     = new List <ClaimProcHist>();
     _pat          = pat;
     if (_pat == null)
     {
         return;
     }
     _listPatPlans = PatPlans.Refresh(_pat.PatNum);
     _listInsSubs  = InsSubs.RefreshForFam(Patients.GetFamily(_pat.PatNum));
     _listInsPlans = InsPlans.RefreshForSubList(_listInsSubs);
     _listBenefits = Benefits.Refresh(_listPatPlans, _listInsSubs);
     _histList     = ClaimProcs.GetHistList(_pat.PatNum, _listBenefits, _listPatPlans, _listInsPlans, DateTime.Today, _listInsSubs);
 }
 private void TransferClaimsPayAsTotal()
 {
     ClaimProcs.FixClaimsNoProcedures(_listFamilyPatNums);
     if (!ProcedureCodes.GetContainsKey("ZZZFIX"))
     {
         Cache.Refresh(InvalidType.ProcCodes);                //Refresh local cache only because middle tier has already inserted the signal.
     }
     try {
         _claimTransferResult = ClaimProcs.TransferClaimsAsTotalToProcedures(_listFamilyPatNums);
     }
     catch (ApplicationException ex) {
         FriendlyException.Show(ex.Message, ex);
         return;
     }
     if (_claimTransferResult != null && _claimTransferResult.ListInsertedClaimProcs.Count > 0)           //valid and items were created
     {
         SecurityLogs.MakeLogEntry(Permissions.ClaimProcReceivedEdit, _patCur.PatNum, "Automatic transfer of claims pay as total from income transfer.");
     }
 }
Exemple #19
0
        ///<summary>Computes balance for a single patient without making any calls to the database. If the balance doesn't match the stored patient balance, then it makes one update to the database and returns true to trigger calculation of aging.</summary>
        public static bool ComputeBalances(Procedure[] procList, ClaimProc[] claimProcList, Patient PatCur, PaySplit[] paySplitList, Adjustment[] AdjustmentList, PayPlan[] payPlanList, PayPlanCharge[] payPlanChargeList)
        {
            //must have refreshed all 5 first
            double calcBal
                = Procedures.ComputeBal(procList)
                  + ClaimProcs.ComputeBal(claimProcList)
                  + Adjustments.ComputeBal(AdjustmentList)
                  - PaySplits.ComputeBal(paySplitList)
                  + PayPlans.ComputeBal(PatCur.PatNum, payPlanList, payPlanChargeList);

            if (calcBal != PatCur.EstBalance)
            {
                Patient PatOld = PatCur.Copy();
                PatCur.EstBalance = calcBal;
                Patients.Update(PatCur, PatOld);
                return(true);
            }
            return(false);
        }
Exemple #20
0
        ///<summary>Deletes the patplan with the specified patPlanNum.  Rearranges the other patplans for the patient to keep the ordinal sequence contiguous.  Then, recomputes all estimates for this patient because their coverage is now different.  Also sets patient.HasIns to the correct value.</summary>
        public static void Delete(int patPlanNum)
        {
            string    command = "SELECT PatNum FROM patplan WHERE PatPlanNum=" + POut.PInt(patPlanNum);
            DataTable table   = General.GetTable(command);

            if (table.Rows.Count == 0)
            {
                return;
            }
            int patNum = PIn.PInt(table.Rows[0][0].ToString());

            PatPlan[] patPlans    = Refresh(patNum);
            bool      doDecrement = false;

            for (int i = 0; i < patPlans.Length; i++)
            {
                if (doDecrement)                //patPlan has already been deleted, so decrement the rest.
                {
                    command = "UPDATE patplan SET Ordinal=" + POut.PInt(patPlans[i].Ordinal - 1)
                              + " WHERE PatPlanNum=" + POut.PInt(patPlans[i].PatPlanNum);
                    General.NonQ(command);
                    continue;
                }
                if (patPlans[i].PatPlanNum == patPlanNum)
                {
                    command = "DELETE FROM patplan WHERE PatPlanNum=" + POut.PInt(patPlanNum);
                    General.NonQ(command);
                    command = "DELETE FROM benefit WHERE PatPlanNum=" + POut.PInt(patPlanNum);
                    General.NonQ(command);
                    doDecrement = true;
                }
            }
            Family  fam = Patients.GetFamily(patNum);
            Patient pat = fam.GetPatient(patNum);

            ClaimProc[] claimProcs = ClaimProcs.Refresh(patNum);
            Procedure[] procs      = Procedures.Refresh(patNum);
            patPlans = PatPlans.Refresh(patNum);
            InsPlan[] planList = InsPlans.Refresh(fam);
            Benefit[] benList  = Benefits.Refresh(patPlans);
            Procedures.ComputeEstimatesForAll(patNum, claimProcs, procs, planList, patPlans, benList);
            Patients.SetHasIns(patNum);
        }
Exemple #21
0
        ///<summary>Used when closing the edit plan window to find all patients using this plan and to update all claimProcs for each patient.  This keeps estimates correct.</summary>
        public static void ComputeEstimatesForPlan(int planNum)
        {
            string    command = "SELECT PatNum FROM patplan WHERE PlanNum=" + POut.PInt(planNum);
            DataTable table   = General.GetTable(command);
            int       patNum  = 0;

            for (int i = 0; i < table.Rows.Count; i++)
            {
                patNum = PIn.PInt(table.Rows[i][0].ToString());
                Family      fam         = Patients.GetFamily(patNum);
                Patient     pat         = fam.GetPatient(patNum);
                ClaimProc[] claimProcs  = ClaimProcs.Refresh(patNum);
                Procedure[] procs       = Procedures.Refresh(patNum);
                InsPlan[]   plans       = InsPlans.Refresh(fam);
                PatPlan[]   patPlans    = PatPlans.Refresh(patNum);
                Benefit[]   benefitList = Benefits.Refresh(patPlans);
                Procedures.ComputeEstimatesForAll(patNum, claimProcs, procs, plans, patPlans, benefitList);
                Patients.SetHasIns(patNum);
            }
        }
Exemple #22
0
        ///<summary>Runs Procedures.ComputeEstimates for given proc and listClaimProcs.
        ///Does not update existing ClaimProcs or insert new ClaimProcs in the database.
        ///Outs new ClaimProcs added by Procedures.ComputeEstimates, listClaimProcs will contain any added claimProcs.</summary>
        private void RecomputeEstimates(Procedure proc, List <ClaimProc> listClaimProcs, out List <ClaimProc> listNewClaimProcs,
                                        OrthoProcLink orthoProcLink, OrthoCase orthoCase, OrthoSchedule orthoSchedule, List <OrthoProcLink> listOrthoProcLinksForOrthoCase)
        {
            List <ClaimProc> listOrigClaimProcs = new List <ClaimProc>(listClaimProcs);
            Patient          pat          = Patients.GetPat(proc.PatNum);
            List <PatPlan>   listPatPlans = PatPlans.GetPatPlansForPat(pat.PatNum);
            List <InsSub>    listInsSubs  = InsSubs.GetMany(listPatPlans.Select(x => x.InsSubNum).ToList());
            List <InsPlan>   listInsPlans = InsPlans.GetByInsSubs(listInsSubs.Select(x => x.InsSubNum).ToList());
            List <Benefit>   listBenefits = Benefits.Refresh(listPatPlans, listInsSubs);      //Same method used in FormProcEdit.Load()->GetLoadData()
            //FormProcEdit uses GetHistList(....,procDate:DateTimeOD.Today,...)
            List <ClaimProcHist> listHist = ClaimProcs.GetHistList(pat.PatNum, listBenefits, listPatPlans, listInsPlans, DateTimeOD.Today, listInsSubs);
            bool isSaveToDb = false;

            //When isSaveToDb is true any estimates that are missing will be inserted into DB and it refreshes listClaimProcs from the Db.
            //Refreshing the list results in losing the changes to ProvNum and ProcDate.
            Procedures.ComputeEstimates(proc, pat.PatNum, ref listClaimProcs, false, listInsPlans, listPatPlans, listBenefits, listHist,
                                        new List <ClaimProcHist> {
            }, isSaveToDb, pat.Age, listInsSubs
                                        , useProcDateOnProc: true,
                                        orthoProcLink: orthoProcLink, orthoCase: orthoCase, orthoSchedule: orthoSchedule, listOrthoProcLinksForOrthoCase: listOrthoProcLinksForOrthoCase);
            listNewClaimProcs = listClaimProcs.Except(listOrigClaimProcs).ToList();
        }
 private void FormIncomeTransferManage_FormClosing(object sender, FormClosingEventArgs e)
 {
     if (DialogResult == DialogResult.OK)
     {
         return;
     }
     //Clean up any potential entities that were inserted during window interactions.
     if (_unallocatedPayNum != 0)
     {
         //user is canceling out of the window and an unallocated transfer was made.
         ODException.SwallowAnyException(() => {
             Payments.Delete(_unallocatedPayNum);
             SecurityLogs.MakeLogEntry(Permissions.PaymentEdit, _patCur.PatNum, $"Automatic transfer deleted for payNum: {_unallocatedPayNum}.");
         });
     }
     if (_claimTransferResult != null)
     {
         //user is canceling out of the window and an claim transfer was made.
         if (_claimTransferResult.ListInsertedClaimProcs.Count > 0)
         {
             ODException.SwallowAnyException(() => {
                 ClaimProcs.DeleteMany(_claimTransferResult.ListInsertedClaimProcs);
                 SecurityLogs.MakeLogEntry(Permissions.PaymentEdit, _patCur.PatNum, $"Automatically transferred claimprocs deleted.");
             });
         }
         if (_claimTransferResult.ListInsertedPaySplits.Count > 0)
         {
             ODException.SwallowAnyException(() => {
                 List <long> listDistinctPayNums = _claimTransferResult.ListInsertedPaySplits.Select(x => x.PayNum).Distinct().ToList();
                 foreach (long payNum in listDistinctPayNums)
                 {
                     Payments.Delete(payNum);
                 }
                 SecurityLogs.MakeLogEntry(Permissions.PaymentEdit, _patCur.PatNum, $"Automatically transferred unearned from claimprocs deleted.");
             });
         }
     }
 }
Exemple #24
0
 private void butOK_Click(object sender, System.EventArgs e)
 {
     if (textDate.errorProvider1.GetError(textDate) != "" ||
         textInsUsed.errorProvider1.GetError(textInsUsed) != "" ||
         textDedUsed.errorProvider1.GetError(textDedUsed) != ""
         )
     {
         MessageBox.Show(Lan.g("All", "Please fix data entry errors first."));
         return;
     }
     ClaimProcCur.ProcDate   = PIn.Date(textDate.Text);
     ClaimProcCur.InsPayAmt  = PIn.Double(textInsUsed.Text);
     ClaimProcCur.DedApplied = PIn.Double(textDedUsed.Text);
     if (IsNew)
     {
         ClaimProcs.Insert(ClaimProcCur);
     }
     else
     {
         ClaimProcs.Update(ClaimProcCur);
     }
     DialogResult = DialogResult.OK;
 }
        ///<summary>Fills the main grid.  If reload Data is true, account data will be (re)fetched from the database.
        ///If false then data already in memory is used.</summary>
        private void FillGridMain()
        {
            gridMain.BeginUpdate();
            gridMain.ListGridColumns.Clear();
            GridColumn col;

            col = new GridColumn(Lan.g(this, "Name"), 240);
            gridMain.ListGridColumns.Add(col);
            col = new GridColumn(Lan.g(this, "Balance"), 100, GridSortingStrategy.AmountParse);
            gridMain.ListGridColumns.Add(col);
            gridMain.ListGridRows.Clear();
            GridRow row;

            PaymentEdit.ConstructResults results;
            //Make a row for every guarantor that has family members with positive and negative balances.
            List <long> listPatNumsForBatch = _dictCurrentFamilyBatch.Values.Select(x => x.ListFamilyMembers)
                                              .SelectMany(y => y.Select(z => z.PatNum)).ToList();
            List <PaySplit>  listSplitsForBatch           = PaySplits.GetForPats(listPatNumsForBatch);
            List <ClaimProc> listClaimsPayAsTotalForBatch = ClaimProcs.GetByTotForPats(listPatNumsForBatch);

            foreach (KeyValuePair <long, FamilyAccount> kvp in _dictCurrentFamilyBatch)
            {
                //Get all family members now so we cut down on memory used.
                FamilyAccount   famAccount                = kvp.Value;
                List <Patient>  listPatients              = famAccount.ListFamilyMembers;
                List <long>     listFamilyPatNums         = listPatients.Select(x => x.PatNum).ToList();
                long            guarantorNum              = kvp.Key;
                List <PaySplit> listSplitsForPats         = listSplitsForBatch.FindAll(x => x.PatNum.In(listFamilyPatNums));
                long            unallocatedTransferPayNum = PaymentEdit.CreateAndInsertUnallocatedPayment(listPatients.First(x => x.PatNum == guarantorNum));
                if (!listSplitsForPats.IsNullOrEmpty())
                {
                    PaymentEdit.IncomeTransferData txfrResults = PaymentEdit.TransferUnallocatedSplitToUnearned(listSplitsForPats, unallocatedTransferPayNum);
                    foreach (PaySplit split in txfrResults.ListSplitsCur)
                    {
                        split.PayNum = unallocatedTransferPayNum;       //Set the PayNum because it was purposefully set to 0 above to save queries.
                        PaySplits.Insert(split);                        //Need to insert in a loop to get the PrimaryKey
                    }
                    foreach (PaySplits.PaySplitAssociated splitAssociated in txfrResults.ListSplitsAssociated)
                    {
                        if (splitAssociated.PaySplitLinked != null && splitAssociated.PaySplitOrig != null)
                        {
                            PaySplits.UpdateFSplitNum(splitAssociated.PaySplitOrig.SplitNum, splitAssociated.PaySplitLinked.SplitNum);
                        }
                    }
                }
                List <ClaimProc> listClaimsAsTotalForPats = listClaimsPayAsTotalForBatch.FindAll(x => x.PatNum.In(listFamilyPatNums));
                ClaimProcs.TransferClaimsAsTotalToProcedures(listPatients.Select(x => x.PatNum).ToList(), listClaimsAsTotalForPats);
                results = PaymentEdit.ConstructAndLinkChargeCredits(listPatients.Select(x => x.PatNum).ToList(), guarantorNum, new List <PaySplit>(),
                                                                    new Payment(), new List <AccountEntry>(), true);
                famAccount.Account = results;
                List <AccountEntry> listAccountEntries = results.ListAccountCharges;
                //Get guarantor info and fill the row/grid
                Patient guarantor = listPatients.FirstOrDefault(x => x.PatNum == guarantorNum);
                row = new GridRow();
                row.Cells.Add(guarantor.GetNameLFnoPref());
                row.Cells.Add((listAccountEntries.Sum(x => x.AmountEnd)).ToString("f"));
                row.Tag = famAccount;         //Store relevant family info in the guarantor row.
                row.DropDownInitiallyDown = false;
                row.Bold = true;              //Bold parent rows to show it is giving the family balance.
                gridMain.ListGridRows.Add(row);
                //Make child rows
                foreach (Patient p in listPatients)
                {
                    GridRow rowChild = new GridRow();
                    rowChild.Cells.Add(p.GetNameLFnoPref());
                    rowChild.Cells.Add(listAccountEntries.Where(x => x.PatNum == p.PatNum).Sum(x => x.AmountEnd).ToString("f"));
                    rowChild.DropDownParent = row;
                    gridMain.ListGridRows.Add(rowChild);
                }
            }
            gridMain.EndUpdate();
            gridMain.Update();
            labelBatchCount.Text = $"Current batch: {_batchNum} Total batches: {_listBatches.Count()}";
            //Invalidate and update the label to force it to be in sync with the progress bar that is on a separate thread.
            labelBatchCount.Invalidate();
            labelBatchCount.Update();
        }
        ///<summary>raised for each page to be printed.  One page per appointment.</summary>
        private void pd_PrintPage(object sender, PrintPageEventArgs ev)
        {
            if (ApptNum != 0)           //just for one appointment
            {
                date = Appointments.DateSelected;
            }
            Graphics   g = ev.Graphics;
            float      y = 50;
            float      x = 0;
            string     str;
            float      sizeW;       //used when measuring text for placement
            Font       fontTitle   = new Font(FontFamily.GenericSansSerif, 11, FontStyle.Bold);
            Font       fontHeading = new Font(FontFamily.GenericSansSerif, 9, FontStyle.Bold);
            Font       font        = new Font(FontFamily.GenericSansSerif, 8);
            SolidBrush brush       = new SolidBrush(Color.Black);

            //Title----------------------------------------------------------------------------------------------------------
            str   = Lan.g(this, "Routing Slip");
            sizeW = g.MeasureString(str, fontTitle).Width;
            x     = 425 - sizeW / 2;
            g.DrawString(str, fontTitle, brush, x, y);
            y += 35;
            x  = 75;
            //Today's appointment, including procedures-----------------------------------------------------------------------
            Family  fam = Patients.GetFamily(Appts[pagesPrinted].PatNum);
            Patient pat = fam.GetPatient(Appts[pagesPrinted].PatNum);

            str = pat.GetNameFL();
            g.DrawString(str, fontHeading, brush, x, y);
            y  += 18;
            str = Appts[pagesPrinted].AptDateTime.ToShortTimeString() + "  " + Appts[pagesPrinted].AptDateTime.ToShortDateString();
            g.DrawString(str, fontHeading, brush, x, y);
            y  += 18;
            str = (Appts[pagesPrinted].Pattern.Length * 5).ToString() + " " + Lan.g(this, "minutes");
            g.DrawString(str, font, brush, x, y);
            y  += 15;
            str = Providers.GetAbbr(Appts[pagesPrinted].ProvNum);
            g.DrawString(str, font, brush, x, y);
            y += 15;
            if (Appts[pagesPrinted].ProvHyg != 0)
            {
                str = Providers.GetAbbr(Appts[pagesPrinted].ProvHyg);
                g.DrawString(str, font, brush, x, y);
                y += 15;
            }
            str = Lan.g(this, "Procedures:");
            g.DrawString(str, font, brush, x, y);
            y += 15;
            Procedure[] procsAll = Procedures.Refresh(pat.PatNum);
            Procedure[] procsApt = Procedures.GetProcsOneApt(Appts[pagesPrinted].AptNum, procsAll);
            for (int i = 0; i < procsApt.Length; i++)
            {
                str = "   " + Procedures.GetDescription(procsApt[i]);
                g.DrawString(str, font, brush, x, y);
                y += 15;
            }
            str = Lan.g(this, "Note:") + " " + Appts[pagesPrinted].Note;
            g.DrawString(str, font, brush, x, y);
            y += 25;
            //Patient/Family Info---------------------------------------------------------------------------------------------
            g.DrawLine(Pens.Black, 75, y, 775, y);
            str = Lan.g(this, "Patient Info");
            g.DrawString(str, fontHeading, brush, x, y);
            y  += 18;
            str = Lan.g(this, "PatNum:") + " " + pat.PatNum.ToString();
            g.DrawString(str, font, brush, x, y);
            y  += 15;
            str = Lan.g(this, "Age:") + " ";
            if (pat.Age > 0)
            {
                str += pat.Age.ToString();
            }
            g.DrawString(str, font, brush, x, y);
            y  += 15;
            str = Lan.g(this, "Date of First Visit:") + " ";
            if (pat.DateFirstVisit.Year < 1880)
            {
                str += "?";
            }
            else if (pat.DateFirstVisit == Appts[pagesPrinted].AptDateTime.Date)
            {
                str += Lan.g(this, "New Patient");
            }
            else
            {
                str += pat.DateFirstVisit.ToShortDateString();
            }
            g.DrawString(str, font, brush, x, y);
            y  += 15;
            str = Lan.g(this, "Billing Type:") + " " + DefB.GetName(DefCat.BillingTypes, pat.BillingType);
            g.DrawString(str, font, brush, x, y);
            y += 15;
            Recall[] recallList = Recalls.GetList(new int[] { pat.PatNum });
            str = Lan.g(this, "Recall Due Date:") + " ";
            if (recallList.Length > 0)
            {
                str += recallList[0].DateDue.ToShortDateString();
            }
            g.DrawString(str, font, brush, x, y);
            y  += 15;
            str = Lan.g(this, "Medical notes:") + " " + pat.MedUrgNote;
            g.DrawString(str, font, brush, x, y);
            y += 25;
            //Other Family Members
            str = Lan.g(this, "Other Family Members");
            g.DrawString(str, fontHeading, brush, x, y);
            y += 18;
            for (int i = 0; i < fam.List.Length; i++)
            {
                if (fam.List[i].PatNum == pat.PatNum)
                {
                    continue;
                }
                str = fam.List[i].GetNameFL();
                if (fam.List[i].Age > 0)
                {
                    str += ",   " + fam.List[i].Age.ToString();
                }
                g.DrawString(str, font, brush, x, y);
                y += 15;
            }
            y += 10;
            //Insurance Info--------------------------------------------------------------------------------------------------
            g.DrawLine(Pens.Black, 75, y, 775, y);
            str = Lan.g(this, "Insurance");
            g.DrawString(str, fontHeading, brush, x, y);
            y += 18;
            PatPlan[]   patPlanList   = PatPlans.Refresh(pat.PatNum);
            InsPlan[]   plans         = InsPlans.Refresh(fam);
            ClaimProc[] claimProcList = ClaimProcs.Refresh(pat.PatNum);
            Benefit[]   benefits      = Benefits.Refresh(patPlanList);
            InsPlan     plan;
            Carrier     carrier;
            string      subscriber;
            double      max;
            double      deduct;

            if (patPlanList.Length == 0)
            {
                str = Lan.g(this, "none");
                g.DrawString(str, font, brush, x, y);
                y += 15;
            }
            for (int i = 0; i < patPlanList.Length; i++)
            {
                plan    = InsPlans.GetPlan(patPlanList[i].PlanNum, plans);
                carrier = Carriers.GetCarrier(plan.CarrierNum);
                str     = carrier.CarrierName;
                g.DrawString(str, fontHeading, brush, x, y);
                y         += 18;
                subscriber = fam.GetNameInFamFL(plan.Subscriber);
                if (subscriber == "")               //subscriber from another family
                {
                    subscriber = Patients.GetLim(plan.Subscriber).GetNameLF();
                }
                str = Lan.g(this, "Subscriber:") + " " + subscriber;
                g.DrawString(str, font, brush, x, y);
                y += 15;
                bool isFamMax = Benefits.GetIsFamMax(benefits, plan.PlanNum);
                str = "";
                if (isFamMax)
                {
                    str += Lan.g(this, "Family ");
                }
                str += Lan.g(this, "Annual Max:") + " ";
                max  = Benefits.GetAnnualMax(benefits, plan.PlanNum, patPlanList[i].PatPlanNum);
                if (max != -1)
                {
                    str += max.ToString("n0") + " ";
                }
                str += "   ";
                bool isFamDed = Benefits.GetIsFamDed(benefits, plan.PlanNum);
                if (isFamDed)
                {
                    str += Lan.g(this, "Family ");
                }
                str   += Lan.g(this, "Deductible:") + " ";
                deduct = Benefits.GetDeductible(benefits, plan.PlanNum, patPlanList[i].PatPlanNum);
                if (deduct != -1)
                {
                    str += deduct.ToString("n0");
                }
                g.DrawString(str, font, brush, x, y);
                y  += 15;
                str = "";
                for (int j = 0; j < benefits.Length; j++)
                {
                    if (benefits[j].PlanNum != plan.PlanNum)
                    {
                        continue;
                    }
                    if (benefits[j].BenefitType != InsBenefitType.Percentage)
                    {
                        continue;
                    }
                    if (str != "")
                    {
                        str += ",  ";
                    }
                    str += CovCats.GetDesc(benefits[j].CovCatNum) + " " + benefits[j].Percent.ToString() + "%";
                }
                if (str != "")
                {
                    g.DrawString(str, font, brush, x, y);
                    y += 15;
                }
                double pend = 0;
                double used = 0;
                if (isFamMax || isFamDed)
                {
                    ClaimProc[] claimProcsFam = ClaimProcs.RefreshFam(plan.PlanNum);
                    used = InsPlans.GetInsUsed(claimProcsFam, date, plan.PlanNum, patPlanList[i].PatPlanNum, -1, plans, benefits);
                    pend = InsPlans.GetPending(claimProcsFam, date, plan, patPlanList[i].PatPlanNum, -1, benefits);
                }
                else
                {
                    used = InsPlans.GetInsUsed(claimProcList, date, plan.PlanNum, patPlanList[i].PatPlanNum, -1, plans, benefits);
                    pend = InsPlans.GetPending(claimProcList, date, plan, patPlanList[i].PatPlanNum, -1, benefits);
                }
                str = Lan.g(this, "Ins Used:") + " " + used.ToString("n");
                g.DrawString(str, font, brush, x, y);
                y  += 15;
                str = Lan.g(this, "Ins Pending:") + " " + pend.ToString("n");
                g.DrawString(str, font, brush, x, y);
                y += 15;
            }
            y += 10;
            //Account Info---------------------------------------------------------------------------------------------------
            g.DrawLine(Pens.Black, 75, y, 775, y);
            str = Lan.g(this, "Account Info");
            g.DrawString(str, fontHeading, brush, x, y);
            y  += 18;
            str = Lan.g(this, "Guarantor:") + " " + fam.List[0].GetNameFL();
            g.DrawString(str, font, brush, x, y);
            y  += 15;
            str = Lan.g(this, "Balance:") + (fam.List[0].BalTotal - fam.List[0].InsEst).ToString("c");
            if (fam.List[0].InsEst > .01)
            {
                str += "  (" + fam.List[0].BalTotal.ToString("c") + " - "
                       + fam.List[0].InsEst.ToString("c") + " " + Lan.g(this, "InsEst") + ")";
            }
            g.DrawString(str, font, brush, x, y);
            y  += 15;
            str = Lan.g(this, "Aging:")
                  + "  0-30:" + fam.List[0].Bal_0_30.ToString("c")
                  + "  31-60:" + fam.List[0].Bal_31_60.ToString("c")
                  + "  61-90:" + fam.List[0].Bal_61_90.ToString("c")
                  + "  90+:" + fam.List[0].BalOver90.ToString("c");
            g.DrawString(str, font, brush, x, y);
            y  += 15;
            str = Lan.g(this, "Fam Urgent Fin Note:")
                  + fam.List[0].FamFinUrgNote;
            g.DrawString(str, font, brush, x, y);
            y += 15;
            y += 10;
            //Treatment Plan--------------------------------------------------------------------------------------------------
            g.DrawLine(Pens.Black, 75, y, 775, y);
            str = Lan.g(this, "Treatment Plan");
            g.DrawString(str, fontHeading, brush, x, y);
            y += 18;
            for (int i = 0; i < procsAll.Length; i++)
            {
                if (procsAll[i].ProcStatus != ProcStat.TP)
                {
                    continue;
                }
                str = Procedures.GetDescription(procsAll[i]);
                g.DrawString(str, font, brush, x, y);
                y += 15;
            }
            pagesPrinted++;
            if (pagesPrinted == Appts.Length)
            {
                ev.HasMorePages = false;
                pagesPrinted    = 0;
            }
            else
            {
                ev.HasMorePages = true;
            }
        }
        private void butNewClaims_Click(object sender, EventArgs e)
        {
            if (gridMain.SelectedIndices.Length == 0)           //No selections made.
            {
                MsgBox.Show(this, "Please select at least one procedure.");
                return;
            }
            if (!ContrAccount.CheckClearinghouseDefaults())
            {
                return;
            }
            //Generate List and Table----------------------------------------------------------------------------------------------------------------------
            //List of all procedures being shown.
            //Pulls procedures based off of the PatNum, if the row was selected in gridMain and if it has been attached to a claim.
            List <ProcNotBilled> listNotBilledProcs = new List <ProcNotBilled>();
            List <long>          listPatNums        = new List <long>();
            Patient          patOld            = new Patient();
            List <Claim>     listPatClaims     = new List <Claim>();
            List <ClaimProc> listPatClaimProcs = new List <ClaimProc>();
            List <ClaimProc> listCurClaimProcs = new List <ClaimProc>();
            //Table rows need to be 1:1 with gridMain rows due to logic in ContrAccount.toolBarButIns_Click(...).
            DataTable table = new DataTable();

            //Required columns as mentioned by ContrAccount.toolBarButIns_Click().
            table.Columns.Add("ProcNum");
            table.Columns.Add("chargesDouble");
            table.Columns.Add("ProcNumLab");
            for (int i = 0; i < gridMain.Rows.Count; i++)                         //Loop through gridMain to construct listNotBilledProcs.
            {
                long      procNumCur = PIn.Long(gridMain.Rows[i].Tag.ToString()); //Tag is set to procNum in fillGrid().
                Procedure procCur    = Procedures.GetOneProc(procNumCur, false);
                long      patNumCur  = procCur.PatNum;
                if (patOld.PatNum != patNumCur)               //Procedures in gridMain are ordered by patient, so when the patient changes, we know previous patient is complete.
                {
                    listPatClaims     = Claims.Refresh(patNumCur);
                    listPatClaimProcs = ClaimProcs.Refresh(patNumCur);
                    patOld            = Patients.GetPat(procCur.PatNum);
                }
                listCurClaimProcs = ClaimProcs.GetForProc(listPatClaimProcs, procNumCur);
                bool hasPriClaim = false;
                bool hasSecClaim = false;
                for (int j = 0; j < listCurClaimProcs.Count; j++)
                {
                    ClaimProc claimProcCur = listCurClaimProcs[j];
                    if (claimProcCur.ClaimNum > 0 && claimProcCur.Status != ClaimProcStatus.Preauth && claimProcCur.Status != ClaimProcStatus.Estimate)
                    {
                        Claim claimCur = Claims.GetFromList(listPatClaims, claimProcCur.ClaimNum);
                        switch (claimCur.ClaimType)
                        {
                        case "P":
                            hasPriClaim = true;
                            break;

                        case "S":
                            hasSecClaim = true;
                            break;
                        }
                    }
                }
                bool isSelected = gridMain.SelectedIndices.Contains(i);
                listNotBilledProcs.Add(new ProcNotBilled(patOld, procNumCur, i, isSelected, hasPriClaim, hasSecClaim, procCur.ClinicNum, procCur.PlaceService));
                DataRow row = table.NewRow();
                row["ProcNum"] = procNumCur;
                #region Calculate chargesDouble
                //Logic copied from AccountModules.GetAccount(...) line 857.
                double qty = (procCur.UnitQty + procCur.BaseUnits);
                if (qty == 0)
                {
                    qty = 1;
                }
                double writeOffCapSum = listPatClaimProcs.Where(x => x.Status == ClaimProcStatus.CapComplete).Select(y => y.WriteOff).ToList().Sum();
                row["chargesDouble"] = (procCur.ProcFee * qty) - writeOffCapSum;
                row["ProcNumLab"]    = procCur.ProcNumLab;
                #endregion Calculate chargesDouble
                table.Rows.Add(row);
                if (listPatNums.Contains(patNumCur))
                {
                    continue;
                }
                listPatNums.Add(patNumCur);
            }
            List <List <ProcNotBilled> > listGroupedProcs = new List <List <ProcNotBilled> >();
            Patient          patCur           = null;
            List <PatPlan>   listPatPlans     = null;
            List <InsSub>    listInsSubs      = null;
            List <InsPlan>   listInsPlans     = null;
            List <Procedure> listPatientProcs = null;
            ProcNotBilled    procNotBilled    = new ProcNotBilled();    //When automatically grouping,  this is used as the procedure to group by.
            long             patNumOld        = 0;
            int claimCreatedCount             = 0;
            int patIndex = 0;
            //The procedures show in the grid ordered by patient.  Also listPatNums contains unique patnums which are in the same order as the grid.
            while (patIndex < listPatNums.Count)
            {
                List <ProcNotBilled> listProcs = listNotBilledProcs.Where(x => x.Patient.PatNum == listPatNums[patIndex] && x.IsRowSelected && !x.IsAttached).ToList();
                if (listProcs.Count == 0)
                {
                    patNumOld = listPatNums[patIndex];
                    patIndex++;                    //No procedures were selected for this patient.
                    continue;
                }
                else
                {
                    //Maintain the same patient, in order to create one or more additional claims for the remaining procedures.
                    //Currently will only happen for specific instances;
                    //--Canadian customers who are attempting to create a claim with over 7 procedures.
                    //--When checkAutoGroupProcs is checked and when there are multiple procedure groupings by GroupKey status, ClinicNum, and placeService.
                }
                if (patNumOld != listPatNums[patIndex])               //The patient could repeat if we had to group the procedures for the patinet into multiple claims.
                {
                    patCur           = Patients.GetPat(listPatNums[patIndex]);
                    listPatPlans     = PatPlans.Refresh(patCur.PatNum);
                    listInsSubs      = InsSubs.RefreshForFam(Patients.GetFamily(patCur.PatNum));
                    listInsPlans     = InsPlans.RefreshForSubList(listInsSubs);
                    listPatientProcs = Procedures.Refresh(patCur.PatNum);
                }
                if (checkAutoGroupProcs.Checked)                 //Automatically Group Procedures.
                {
                    procNotBilled = listProcs[0];
                    //Update listProcs to reflect those that match the procNotBilled values.
                    listProcs = listProcs.FindAll(x => x.HasPriClaim == procNotBilled.HasPriClaim && x.HasSecClaim == procNotBilled.HasSecClaim);
                    if (PrefC.HasClinicsEnabled)                     //Group by clinic only if clinics enabled.
                    {
                        listProcs = listProcs.FindAll(x => x.ClinicNum == procNotBilled.ClinicNum);
                    }
                    else if (!PrefC.GetBool(PrefName.EasyHidePublicHealth))                     //Group by Place of Service only if Public Health feature is enabled.
                    {
                        listProcs = listProcs.FindAll(x => x.PlaceService == procNotBilled.PlaceService);
                    }
                }
                GetUniqueDiagnosticCodes(listProcs, listPatientProcs, listPatPlans, listInsSubs, listInsPlans);
                if (listProcs.Count > 7 && CultureInfo.CurrentCulture.Name.EndsWith("CA")) //Canadian. en-CA or fr-CA
                {
                    listProcs = listProcs.Take(7).ToList();                                //Returns first 7 items of the list.
                }
                listProcs.ForEach(x => x.IsAttached = true);                               //This way we can not attach procedures to multiple claims thanks to the logic above.
                if (listProcs.Any(x => listProcs[0].PlaceService != x.PlaceService) || listProcs.Any(x => listProcs[0].ClinicNum != x.ClinicNum))
                {
                    //Regardless if we are automatically grouping or not,
                    //if all procs in our list at this point do not share the same PlaceService or ClinicNum then claims will not be made.
                }
                else                  //Basic validation passed.
                {
                    if (!listProcs[0].HasPriClaim &&                 //Medical claim.
                        PatPlans.GetOrdinal(PriSecMed.Medical, listPatPlans, listInsPlans, listInsSubs) > 0 &&                    //Has medical ins.
                        PatPlans.GetOrdinal(PriSecMed.Primary, listPatPlans, listInsPlans, listInsSubs) == 0 &&                    //Does not have primary dental ins.
                        PatPlans.GetOrdinal(PriSecMed.Secondary, listPatPlans, listInsPlans, listInsSubs) == 0)                       //Does not have secondary dental ins.
                    {
                        claimCreatedCount++;
                    }
                    else                                                                                                                      //Not a medical claim.
                    {
                        if (!listProcs[0].HasPriClaim && PatPlans.GetOrdinal(PriSecMed.Primary, listPatPlans, listInsPlans, listInsSubs) > 0) //Primary claim.
                        {
                            claimCreatedCount++;
                        }
                        if (!listProcs[0].HasSecClaim && PatPlans.GetOrdinal(PriSecMed.Secondary, listPatPlans, listInsPlans, listInsSubs) > 0)                  //Secondary claim.
                        {
                            claimCreatedCount++;
                        }
                    }
                }
                listGroupedProcs.Add(listProcs);
            }
            if (!MsgBox.Show(this, true, "Clicking continue will create up to " + POut.Int(claimCreatedCount) + " claims and cannot be undone, except by manually going to each account.  "
                             + "Some claims may not be created if there are validation issues.  Would you like to proceed?"))
            {
                return;
            }
            //Create Claims--------------------------------------------------------------------------------------------------------------------------------
            claimCreatedCount = 0;
            string claimErrors = "";
            foreach (List <ProcNotBilled> listProcs in listGroupedProcs)
            {
                patCur = listProcs[0].Patient;
                gridMain.SetSelected(false);                //Need to deslect all rows each time so that ContrAccount.toolBarButIns_Click(...) only uses pertinent rows.
                for (int j = 0; j < listProcs.Count; j++)
                {
                    gridMain.SetSelected(listProcs[j].RowIndex, true);                   //Select the pertinent rows so that they will be attached to the claim below.
                }
                ContrAccount.toolBarButIns_Click(false, patCur, Patients.GetFamily(patCur.PatNum), gridMain, table,
                                                 procNotBilled.HasPriClaim, procNotBilled.HasSecClaim);
                string errorTitle = patCur.PatNum + " " + patCur.GetNameLFnoPref() + " - ";
                if (patNumOld == patCur.PatNum && !string.IsNullOrEmpty(ContrAccount.ClaimErrorsCur))
                {
                    claimErrors += "\t\t" + ContrAccount.ClaimErrorsCur + "\r\n";
                }
                else if (!string.IsNullOrEmpty(ContrAccount.ClaimErrorsCur))
                {
                    claimErrors += errorTitle + ContrAccount.ClaimErrorsCur + "\r\n";
                }
                claimCreatedCount += ContrAccount.ClaimCreatedCount;
                patNumOld          = patCur.PatNum;
            }
            FillGrid();
            if (!string.IsNullOrEmpty(claimErrors))
            {
                MsgBoxCopyPaste form = new MsgBoxCopyPaste(claimErrors);
                form.ShowDialog();
            }
            MessageBox.Show(Lan.g(this, "Number of claims created") + ": " + claimCreatedCount);
        }
Exemple #28
0
 private void butOK_Click(object sender, System.EventArgs e)
 {
     if (textDate.Text == "")
     {
         MsgBox.Show(this, "Please enter a date.");
         return;
     }
     if (textCarrierName.Text == "")
     {
         MsgBox.Show(this, "Please enter a carrier.");
         return;
     }
     if (textDate.errorProvider1.GetError(textDate) != "" ||
         textAmount.errorProvider1.GetError(textAmount) != "" ||
         textDateIssued.errorProvider1.GetError(textDateIssued) != "")
     {
         MsgBox.Show(this, "Please fix data entry errors first.");
         return;
     }
     if (PIn.Double(textAmount.Text) == 0)
     {
         MsgBox.Show(this, "Please enter an amount.");
         return;
     }
     if (IsNew)
     {
         //prevents backdating of initial check
         if (!Security.IsAuthorized(Permissions.InsPayCreate, PIn.Date(textDate.Text)))
         {
             return;
         }
         //prevents attaching claimprocs with a date that is older than allowed by security.
     }
     else
     {
         //Editing an old entry will already be blocked if the date was too old, and user will not be able to click OK button.
         //This catches it if user changed the date to be older.
         if (!Security.IsAuthorized(Permissions.InsPayEdit, PIn.Date(textDate.Text)))
         {
             return;
         }
     }
     if (!PrefC.GetBool(PrefName.EasyNoClinics))
     {
         if (comboClinic.SelectedIndex == 0)
         {
             ClaimPaymentCur.ClinicNum = 0;
         }
         else
         {
             ClaimPaymentCur.ClinicNum = Clinics.List[comboClinic.SelectedIndex - 1].ClinicNum;
         }
     }
     ClaimPaymentCur.CheckDate   = PIn.Date(textDate.Text);
     ClaimPaymentCur.DateIssued  = PIn.Date(textDateIssued.Text);
     ClaimPaymentCur.CheckAmt    = PIn.Double(textAmount.Text);
     ClaimPaymentCur.CheckNum    = textCheckNum.Text;
     ClaimPaymentCur.BankBranch  = textBankBranch.Text;
     ClaimPaymentCur.CarrierName = textCarrierName.Text;
     ClaimPaymentCur.Note        = textNote.Text;
     try{
         if (IsNew)
         {
             ClaimPayments.Insert(ClaimPaymentCur);                    //error thrown if trying to change amount and already attached to a deposit.
         }
         else
         {
             ClaimPayments.Update(ClaimPaymentCur);                    //error thrown if trying to change amount and already attached to a deposit.
         }
     }
     catch (ApplicationException ex) {
         MessageBox.Show(ex.Message);
         return;
     }
     ClaimProcs.SynchDateCP(ClaimPaymentCur.ClaimPaymentNum, ClaimPaymentCur.CheckDate);
     DialogResult = DialogResult.OK;
 }
Exemple #29
0
        private void butOK_Click(object sender, System.EventArgs e)
        {
            if (textDate.Text == "")
            {
                MsgBox.Show(this, "Please enter a date first.");
                return;
            }
            if (PIn.Date(textDate.Text).Date > DateTime.Today.Date && !PrefC.GetBool(PrefName.FutureTransDatesAllowed) &&
                !PrefC.GetBool(PrefName.AllowFutureInsPayments))
            {
                MsgBox.Show(this, "Payments cannot be for a date in the future.");
                return;                 //probably not necesasary since this is an old form, but just in case we use it again
            }
            if (textDate.errorProvider1.GetError(textDate) != "")
            {
                MsgBox.Show(this, "Please fix data entry errors first.");
                return;
            }
            if (gridMain.SelectedIndices.Length == 0)
            {
                MessageBox.Show(Lan.g(this, "At least one item must be selected, or use the delete button."));
                return;
            }
            if (IsNew)
            {
                //prevents backdating of initial check
                if (!Security.IsAuthorized(Permissions.InsPayCreate, PIn.Date(textDate.Text)))
                {
                    return;
                }
                //prevents attaching claimprocs with a date that is older than allowed by security.
            }
            else
            {
                //Editing an old entry will already be blocked if the date was too old, and user will not be able to click OK button.
                //This catches it if user changed the date to be older.
                if (!Security.IsAuthorized(Permissions.InsPayEdit, PIn.Date(textDate.Text)))
                {
                    return;
                }
            }
            if (comboClinic.SelectedIndex == 0)
            {
                ClaimPaymentCur.ClinicNum = 0;
            }
            else
            {
                ClaimPaymentCur.ClinicNum = _listClinics[comboClinic.SelectedIndex - 1].ClinicNum;
            }
            ClaimPaymentCur.CheckAmt    = PIn.Double(textAmount.Text);
            ClaimPaymentCur.CheckDate   = PIn.Date(textDate.Text);
            ClaimPaymentCur.CheckNum    = textCheckNum.Text;
            ClaimPaymentCur.BankBranch  = textBankBranch.Text;
            ClaimPaymentCur.CarrierName = textCarrierName.Text;
            ClaimPaymentCur.Note        = textNote.Text;
            try{
                ClaimPayments.Update(ClaimPaymentCur);                //error thrown if trying to change amount and already attached to a deposit.
            }
            catch (ApplicationException ex) {
                MessageBox.Show(ex.Message);
                return;
            }
            //this could be optimized to only save changes.
            //Would require a starting list to compare to.
            //But this isn't bad, since changes all saved at the very end
            List <int> selectedRows = new List <int>();

            for (int i = 0; i < gridMain.SelectedIndices.Length; i++)
            {
                selectedRows.Add(gridMain.SelectedIndices[i]);
            }
            for (int i = 0; i < splits.Count; i++)
            {
                if (selectedRows.Contains(i))                //row is selected
                {
                    ClaimProcs.SetForClaimOld(splits[i].ClaimNum, ClaimPaymentCur.ClaimPaymentNum, ClaimPaymentCur.CheckDate, true);
                    //Audit trail isn't perfect, since it doesn't make an entry if you remove a claim from a payment.
                    //And it always makes more audit trail entries when you click OK, even if you didn't actually attach new claims.
                    //But since this will cover the vast majority if situations.
                    if (IsNew)
                    {
                        SecurityLogs.MakeLogEntry(Permissions.InsPayCreate, splits[i].PatNum,
                                                  Patients.GetLim(splits[i].PatNum).GetNameLF() + ", "
                                                  + Lan.g(this, "Total Amt: ") + ClaimPaymentCur.CheckAmt.ToString("c") + ", "
                                                  + Lan.g(this, "Claim Split: ") + splits[i].InsPayAmt.ToString("c"));
                    }
                    else
                    {
                        SecurityLogs.MakeLogEntry(Permissions.InsPayEdit, splits[i].PatNum,
                                                  Patients.GetLim(splits[i].PatNum).GetNameLF() + ", "
                                                  + Lan.g(this, "Total Amt: ") + ClaimPaymentCur.CheckAmt.ToString("c") + ", "
                                                  + Lan.g(this, "Claim Split: ") + splits[i].InsPayAmt.ToString("c"));
                    }
                }
                else                 //row not selected
                                     //If user had not been attaching their inspayments to checks, then this will cause such payments to annoyingly have their
                                     //date changed to the current date.  This prompts them to call us.  Then, we tell them to attach to checks.
                {
                    ClaimProcs.SetForClaimOld(splits[i].ClaimNum, ClaimPaymentCur.ClaimPaymentNum, ClaimPaymentCur.CheckDate, false);
                }
            }
            DialogResult = DialogResult.OK;
        }
Exemple #30
0
        ///<summary>Fills grid based on values in _listEtrans.
        ///Set isRefreshNeeded to true when we need to reinitialize local dictionarys after in memory list is also updated. Required true for first time running.
        ///Also allows you to passed in predetermined filter options.</summary>
        private void FillGrid(bool isRefreshNeeded, List <string> listSelectedStatuses, List <long> listSelectedClinicNums,
                              string carrierName, string checkTraceNum, string amountMin, string amountMax, string controlId)
        {
            Cursor = Cursors.WaitCursor;
            labelControlId.Visible = PrefC.GetBool(PrefName.EraShowControlIdFilter);
            textControlId.Visible  = PrefC.GetBool(PrefName.EraShowControlIdFilter);
            Action actionCloseProgress = null;

            if (isRefreshNeeded)
            {
                actionCloseProgress = ODProgress.Show(ODEventType.Etrans, typeof(EtransEvent), Lan.g(this, "Gathering data") + "...");
                _dictEtrans835s.Clear();
                _dictEtransClaims.Clear();
                List <Etrans835Attach>    listAttached        = Etrans835Attaches.GetForEtrans(_listAllEtrans.Select(x => x.EtransNum).ToArray());
                Dictionary <long, string> dictEtransMessages  = new Dictionary <long, string>();
                List <X12ClaimMatch>      list835ClaimMatches = new List <X12ClaimMatch>();
                Dictionary <long, int>    dictClaimMatchCount = new Dictionary <long, int>(); //1:1 with _listEtranss. Stores how many claim matches each 835 has.
                int batchQueryInterval = 500;                                                 //Every 500 rows we get the next 500 message texts to save memory.
                int rowCur             = 0;
                foreach (Etrans etrans in _listAllEtrans)
                {
                    if (rowCur % batchQueryInterval == 0)
                    {
                        int range = Math.Min(batchQueryInterval, _listAllEtrans.Count - rowCur);                   //Either the full batchQueryInterval amount or the remaining amount of etrans.
                        dictEtransMessages = EtransMessageTexts.GetMessageTexts(_listAllEtrans.GetRange(rowCur, range).Select(x => x.EtransMessageTextNum).ToList(), false);
                    }
                    rowCur++;
                    EtransEvent.Fire(ODEventType.Etrans, Lan.g(this, "Processing 835: ") + ": " + rowCur + " out of " + _listAllEtrans.Count);
                    List <Etrans835Attach> listAttachedTo835 = listAttached.FindAll(x => x.EtransNum == etrans.EtransNum);
                    X835 x835 = new X835(etrans, dictEtransMessages[etrans.EtransMessageTextNum], etrans.TranSetId835, listAttachedTo835, true);
                    _dictEtrans835s.Add(etrans.EtransNum, x835);
                    List <X12ClaimMatch> listClaimMatches = x835.GetClaimMatches();
                    dictClaimMatchCount.Add(etrans.EtransNum, listClaimMatches.Count);
                    list835ClaimMatches.AddRange(listClaimMatches);
                }
                #region Set 835 unattached in batch and build _dictEtransClaims and _dictClaimPayCheckNums.
                EtransEvent.Fire(ODEventType.Etrans, Lan.g(this, "Gathering internal claim matches."));
                List <long> listClaimNums = Claims.GetClaimFromX12(list835ClaimMatches);             //Can return null.
                EtransEvent.Fire(ODEventType.Etrans, Lan.g(this, "Building data sets."));
                int         claimIndexCur        = 0;
                List <long> listMatchedClaimNums = new List <long>();
                foreach (Etrans etrans in _listAllEtrans)
                {
                    X835 x835 = _dictEtrans835s[etrans.EtransNum];
                    if (listClaimNums != null)
                    {
                        x835.SetClaimNumsForUnattached(listClaimNums.GetRange(claimIndexCur, dictClaimMatchCount[etrans.EtransNum]));
                    }
                    claimIndexCur += dictClaimMatchCount[etrans.EtransNum];
                    listMatchedClaimNums.AddRange(x835.ListClaimsPaid.FindAll(x => x.ClaimNum != 0).Select(x => x.ClaimNum).ToList());
                }
                List <Claim> listClaims = Claims.GetClaimsFromClaimNums(listMatchedClaimNums.Distinct().ToList());
                //The following line includes manually detached and split attaches.
                _listAllAttaches   = Etrans835Attaches.GetForEtransNumOrClaimNums(false, _listAllEtrans.Select(x => x.EtransNum).ToList(), listMatchedClaimNums.ToArray());
                _listAllClaimProcs = ClaimProcs.RefreshForClaims(listMatchedClaimNums);
                foreach (Etrans etrans in _listAllEtrans)
                {
                    X835 x835 = _dictEtrans835s[etrans.EtransNum];
                    #region _dictEtransClaims, _dictClaimPayCheckNums
                    _dictEtransClaims.Add(etrans.EtransNum, new List <Claim>());
                    List <long>  listSubClaimNums = x835.ListClaimsPaid.FindAll(x => x.ClaimNum != 0).Select(y => y.ClaimNum).ToList();
                    List <Claim> listClaimsFor835 = listClaims.FindAll(x => listSubClaimNums.Contains(x.ClaimNum));
                    foreach (Hx835_Claim claim in x835.ListClaimsPaid)
                    {
                        Claim claimCur = listClaimsFor835.FirstOrDefault(x => x.ClaimNum == claim.ClaimNum);                    //Can be null.
                        _dictEtransClaims[etrans.EtransNum].Add(claimCur);
                    }
                    #endregion
                }
                EtransEvent.Fire(ODEventType.Etrans, Lan.g(this, "Filling Grid."));
                #endregion
            }
            gridMain.BeginUpdate();
            #region Initilize columns
            gridMain.ListGridColumns.Clear();
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Patient Name"), 250));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Carrier Name"), 190));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Status"), 80));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Date"), 80, GridSortingStrategy.DateParse));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Amount"), 80, GridSortingStrategy.AmountParse));
            if (PrefC.HasClinicsEnabled)
            {
                gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Clinic"), 70));
            }
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Code"), 37, HorizontalAlignment.Center));
            if (PrefC.GetBool(PrefName.EraShowControlIdFilter))
            {
                gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "ControlID"), -1));
            }
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Note"), -2));
            #endregion
            gridMain.ListGridRows.Clear();
            foreach (Etrans etrans in _listAllEtrans)
            {
                X835 x835 = _dictEtrans835s[etrans.EtransNum];
                #region Filter: Carrier Name
                if (carrierName != "" && !x835.PayerName.ToLower().Contains(carrierName.ToLower().Trim()))
                {
                    continue;
                }
                #endregion
                string status = GetStringStatus(etrans.EtransNum);
                #region Filter: Status
                if (!listSelectedStatuses.Contains(status.Replace("*", "")))                //The filter will ignore finalized with detached claims.
                {
                    continue;
                }
                #endregion
                //List of ClinicNums for the current etrans.ListClaimsPaid from the DB.
                List <long> listClinicNums = _dictEtransClaims[etrans.EtransNum].Select(x => x == null? 0 :x.ClinicNum).Distinct().ToList();
                #region Filter: Clinics
                if (PrefC.HasClinicsEnabled && !listClinicNums.Exists(x => listSelectedClinicNums.Contains(x)))
                {
                    continue;                    //The ClinicNums associated to the 835 do not match any of the selected ClinicNums, so nothing to show in this 835.
                }
                #endregion
                #region Filter: Check and Trace Value
                if (checkTraceNum != "" && !x835.TransRefNum.ToLower().Contains(checkTraceNum.ToLower().Trim()))               //Trace Number does not match
                {
                    continue;
                }
                #endregion
                #region Filter: Insurance Check Range Min and Max
                if (amountMin != "" && x835.InsPaid < PIn.Decimal(amountMin) || amountMax != "" && x835.InsPaid > PIn.Decimal(amountMax))
                {
                    continue;                    //Either the InsPaid is below or above our range.
                }
                #endregion
                #region Filter: ControlID
                if (controlId != "" && !x835.ControlId.ToLower().Contains(controlId.ToLower()))
                {
                    continue;
                }
                #endregion
                GridRow row = new GridRow();
                #region Column: Patient Name
                List <string> listPatNames = x835.ListClaimsPaid.Select(x => x.PatientName.ToString()).Distinct().ToList();
                string        patName      = (listPatNames.Count > 0 ? listPatNames[0] : "");
                if (listPatNames.Count > 1)
                {
                    patName = "(" + POut.Long(listPatNames.Count) + ")";
                }
                row.Cells.Add(patName);
                #endregion
                row.Cells.Add(x835.PayerName);
                row.Cells.Add(status);                //See GetStringStatus(...) for possible values.
                row.Cells.Add(POut.Date(etrans.DateTimeTrans));
                row.Cells.Add(POut.Decimal(x835.InsPaid));
                #region Column: Clinic
                if (PrefC.HasClinicsEnabled)
                {
                    string clinicAbbr = "";
                    if (listClinicNums.Count == 1)
                    {
                        if (listClinicNums[0] == 0)
                        {
                            clinicAbbr = Lan.g(this, "Unassigned");
                        }
                        else
                        {
                            clinicAbbr = Clinics.GetAbbr(listClinicNums[0]);
                        }
                    }
                    else if (listClinicNums.Count > 1)
                    {
                        clinicAbbr = "(" + Lan.g(this, "Multiple") + ")";
                    }
                    row.Cells.Add(clinicAbbr);
                }
                #endregion
                row.Cells.Add(x835._paymentMethodCode);
                if (PrefC.GetBool(PrefName.EraShowControlIdFilter))
                {
                    row.Cells.Add(x835.ControlId);
                }
                row.Cells.Add(etrans.Note);
                row.Tag = etrans;
                gridMain.ListGridRows.Add(row);
            }
            gridMain.EndUpdate();
            actionCloseProgress?.Invoke();            //When this function executes quickly this can fail rarely, fail silently because of WaitCursor.
            Cursor = Cursors.Default;
        }