Пример #1
0
        /// <summary>Returns true if a finance charge is added, false if one is not added</summary>
        private bool AddFinanceCharge(long PatNum, DateTime date, string APR, string atLeast, string ifOver, double OverallBalance, long PriProv, long adjType)
        {
            if (date > DateTime.Today && !PrefC.GetBool(PrefName.FutureTransDatesAllowed))
            {
                MsgBox.Show(this, "Adjustments cannot be made for future dates. Finance charge was not added.");
                return(false);
            }
            InstallmentPlan installPlan = InstallmentPlans.GetOneForFam(PatNum);

            if (installPlan != null)           //Patient has an installment plan so use that APR instead.
            {
                APR = installPlan.APR.ToString();
            }
            Adjustment AdjustmentCur = new Adjustment();

            AdjustmentCur.PatNum = PatNum;
            //AdjustmentCur.DateEntry=PIn.PDate(textDate.Text);//automatically handled
            AdjustmentCur.AdjDate  = date;
            AdjustmentCur.ProcDate = date;
            AdjustmentCur.AdjType  = adjType;
            AdjustmentCur.AdjNote  = "";           //"Finance Charge";
            AdjustmentCur.AdjAmt   = Math.Round(((PIn.Double(APR) * .01d / 12d) * OverallBalance), 2);
            if (AdjustmentCur.AdjAmt.IsZero() || AdjustmentCur.AdjAmt < PIn.Double(ifOver))
            {
                //Don't add the charge if it is less than FinanceChargeOnlyIfOver; if the charge is exactly equal to FinanceChargeOnlyIfOver,
                //the charge will be added. Ex., AdjAmt=2.00 and FinanceChargeOnlyIfOver=2.00, the charge will be added.
                //Unless AdjAmt=0.00, in which case don't add a $0.00 finance charge
                return(false);
            }
            //Add an amount that is at least the amount of FinanceChargeAtLeast
            AdjustmentCur.AdjAmt  = Math.Max(AdjustmentCur.AdjAmt, PIn.Double(atLeast));
            AdjustmentCur.ProvNum = PriProv;
            Adjustments.Insert(AdjustmentCur);
            return(true);
        }
Пример #2
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();
 }
Пример #3
0
        private void butOK_Click(object sender, EventArgs e)
        {
            bool hasNegAmt = false;

            foreach (MultiAdjEntry mae in _listGridEntries)
            {
                if (mae.Adj == null)
                {
                    continue;                    //Procedures
                }
                decimal remAfter = (decimal)mae.AmtRemBefore + (decimal)mae.Adj.AdjAmt;
                if (remAfter.IsLessThanZero())
                {
                    hasNegAmt = true;
                    break;
                }
            }
            if (hasNegAmt && !MsgBox.Show(this, MsgBoxButtons.OKCancel, "Remaining amount on a procedure is negative.  Continue?", "Overpaid Procedure Warning"))
            {
                return;
            }
            foreach (MultiAdjEntry row in _listGridEntries)
            {
                if (row.Adj == null)               //skip over Procedure rows
                {
                    continue;
                }
                Adjustments.Insert(row.Adj);
            }
            DialogResult = DialogResult.OK;
        }
Пример #4
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);
            }
        }
Пример #5
0
        /// <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
        }
Пример #6
0
        private void butOK_Click(object sender, System.EventArgs e)
        {
            if (textDate.errorProvider1.GetError(textDate) != "" ||
                textAPR.errorProvider1.GetError(textAPR) != "")
            {
                MessageBox.Show(Lan.g(this, "Please fix data entry errors first."));
                return;
            }

            if (PIn.PInt(textAPR.Text) < 2)
            {
                if (MessageBox.Show(Lan.g(this, "The APR is much lower than normal. Do you wish to proceed?"), "", MessageBoxButtons.OKCancel) != DialogResult.OK)
                {
                    return;
                }
            }
            //Patients.ResetAging();
            //Ledgers.UpdateFinanceCharges(PIn.PDate(textDate.Text));
            PatAging[] AgingList = Patients.GetAgingList();
            double     OverallBalance;

            for (int i = 0; i < AgingList.Length; i++)
            {
                OverallBalance = 0;              //this WILL NOT be the same as the patient's total balance
                if (radio30.Checked)
                {
                    OverallBalance = AgingList[i].Bal_31_60 + AgingList[i].Bal_61_90 + AgingList[i].BalOver90;
                }
                if (radio60.Checked)
                {
                    OverallBalance = AgingList[i].Bal_61_90 + AgingList[i].BalOver90;
                }
                if (radio90.Checked)
                {
                    OverallBalance = AgingList[i].BalOver90;
                }
                if (OverallBalance > 0)
                {
                    Adjustment AdjustmentCur = new Adjustment();
                    AdjustmentCur.PatNum = AgingList[i].PatNum;
                    //AdjustmentCur.DateEntry=PIn.PDate(textDate.Text);//automatically handled
                    AdjustmentCur.AdjDate  = PIn.PDate(textDate.Text);
                    AdjustmentCur.ProcDate = PIn.PDate(textDate.Text);
                    AdjustmentCur.AdjType  = DefB.Short[(int)DefCat.AdjTypes]
                                             [(int)ALPosIndices[listAdjType.SelectedIndex]].DefNum;
                    AdjustmentCur.AdjNote = "Finance Charge";
                    AdjustmentCur.AdjAmt  = Math.Round(((PIn.PDouble(textAPR.Text) * .01 / 12) * OverallBalance), 2);
                    AdjustmentCur.ProvNum = AgingList[i].PriProv;
                    Adjustments.InsertOrUpdate(AdjustmentCur, true);
                }
            }
            Prefs.UpdateString("FinanceChargeAPR", textAPR.Text);
            Prefs.UpdateInt("FinanceChargeAdjustmentType",
                            DefB.Short[(int)DefCat.AdjTypes][(int)ALPosIndices[listAdjType.SelectedIndex]].DefNum);
            Prefs.UpdateString("FinanceChargeLastRun", POut.PDate(DateTime.Today, false));
            DataValid.SetInvalid(InvalidTypes.Prefs);
            MessageBox.Show(Lan.g(this, "Finance Charges Added."));
            DialogResult = DialogResult.OK;
        }
Пример #7
0
 private void butCancel_Click(object sender, System.EventArgs e)
 {
     if (IsNew)
     {
         if (Patients.GetPat(_procCur.PatNum).DiscountPlanNum != 0)
         {
             Adjustments.DeleteForProcedure(_procCur.ProcNum);                    //Delete discount plan adjustment
         }
         Procedures.Delete(_procCur.ProcNum);
     }
     DialogResult = DialogResult.Cancel;
 }
Пример #8
0
 private void FormProcBroken_FormClosing(object sender, FormClosingEventArgs e)
 {
     if (DialogResult == DialogResult.Cancel && IsNew)
     {
         if (Patients.GetPat(_procCur.PatNum).DiscountPlanNum != 0)
         {
             Adjustments.DeleteForProcedure(_procCur.ProcNum);                    //Delete discount plan adjustment
         }
         Procedures.Delete(_procCur.ProcNum);
         IsProcDeleted = true;
     }
 }
Пример #9
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);
        }
Пример #10
0
 private void FormAdjustmentPicker_Load(object sender, EventArgs e)
 {
     if (_isUnattachedMode)
     {
         checkUnattached.Checked = true;
         checkUnattached.Enabled = false;
     }
     if (_listAdjustments == null)
     {
         _listAdjustments = Adjustments.Refresh(_patNum).ToList();
     }
     FillGrid();
 }
Пример #11
0
        private void AddFinanceCharge(long PatNum, DateTime date, string APR, double OverallBalance, long PriProv)
        {
            Adjustment AdjustmentCur = new Adjustment();

            AdjustmentCur.PatNum = PatNum;
            //AdjustmentCur.DateEntry=PIn.PDate(textDate.Text);//automatically handled
            AdjustmentCur.AdjDate  = date;
            AdjustmentCur.ProcDate = date;
            AdjustmentCur.AdjType  = PrefC.GetLong(PrefName.FinanceChargeAdjustmentType);
            AdjustmentCur.AdjNote  = "";           //"Finance Charge";
            AdjustmentCur.AdjAmt   = Math.Round(((PIn.Double(APR) * .01d / 12d) * OverallBalance), 2);
            AdjustmentCur.ProvNum  = PriProv;
            Adjustments.Insert(AdjustmentCur);
        }
Пример #12
0
 private void butOK_Click(object sender, EventArgs e)
 {
     if (_listGridEntries.Any(x => x.RemAfter.IsLessThan(0)) &&
         !MsgBox.Show(this, MsgBoxButtons.OKCancel, "Remaining amount on a procedure is negative.  Continue?", "Overpaid Procedure Warning"))
     {
         return;
     }
     foreach (MultiAdjEntry row in _listGridEntries)
     {
         if (row.Adj == null)               //skip over Procedure rows
         {
             continue;
         }
         Adjustments.Insert(row.Adj);
     }
     DialogResult = DialogResult.OK;
 }
Пример #13
0
        ///<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);
        }
Пример #14
0
        private void AddBillingCharge(long PatNum, DateTime date, string BillingChargeAmount, long PriProv)
        {
            if (date > DateTime.Today && !PrefC.GetBool(PrefName.FutureTransDatesAllowed))
            {
                MsgBox.Show(this, "Adjustments cannot be made for future dates");
                return;
            }
            Adjustment AdjustmentCur = new Adjustment();

            AdjustmentCur.PatNum = PatNum;
            //AdjustmentCur.DateEntry=PIn.PDate(textDate.Text);//automatically handled
            AdjustmentCur.AdjDate  = date;
            AdjustmentCur.ProcDate = date;
            AdjustmentCur.AdjType  = PrefC.GetLong(PrefName.BillingChargeAdjustmentType);
            AdjustmentCur.AdjNote  = "";           //"Billing Charge";
            AdjustmentCur.AdjAmt   = PIn.Double(BillingChargeAmount);
            AdjustmentCur.ProvNum  = PriProv;
            Adjustments.Insert(AdjustmentCur);
        }
Пример #15
0
        private void FormAdjustSelect_Load(object sender, EventArgs e)
        {
            List <Adjustment> listAdjusts = Adjustments.GetAdjustForPats(new List <long>()
            {
                PatNumCur
            }).FindAll(x => x.ProcNum == 0);                                                                                                 //Get all unallocated adjustments for current pat.

            foreach (Adjustment adjust in listAdjusts)
            {
                _listAdjusts.Add(new AccountEntry(adjust));
            }
            _listSplitsForAdjusts = PaySplits.GetForAdjustments(listAdjusts.Select(x => x.AdjNum).ToList());
            foreach (AccountEntry entry in _listAdjusts)
            {
                //Figure out how much each adjustment has left, not counting this payment.
                entry.AmountStart -= (decimal)Adjustments.GetAmtAllocated(entry.PriKey, PayNumCur, _listSplitsForAdjusts.FindAll(x => x.AdjNum == entry.PriKey));
                //Reduce adjustments based on current payment's splits as well (this is in-memory list, could be new, could be modified) but not the current split
                entry.AmountStart -= (decimal)Adjustments.GetAmtAllocated(entry.PriKey, 0, ListSplitsForPayment.FindAll(x => x.AdjNum == entry.PriKey && x != PaySplitCur));
            }
            FillGrid();
        }
Пример #16
0
        private void butPreviousProc_Click(object sender, EventArgs e)
        {
            FormProcSelect FormPS = new FormProcSelect(_patCur.PatNum, false);

            if (FormPS.ShowDialog() != DialogResult.OK)
            {
                return;
            }
            //isMultiSelect is set to false so should only ever be one procedure, constructing in a way to handle multiple in case we ever want to change
            //isMultiSelect to be true.
            foreach (Procedure proc in FormPS.ListSelectedProcs)
            {
                //Use our list of ProcedureCodes so irrelevant codes result in a new ProcedureCode with blank values.
                ProcedureCode procCode = ProcedureCodes.GetProcCode(proc.CodeNum, _listPrePaySupportCodes);
                //Didn't exist in our list of ProcedureCodes, tell user it won't be added.
                if (procCode.CodeNum == 0)
                {
                    //Did not translate because HQ only.
                    MsgBox.Show(this, "Selected procedure cannot be used with the Prepayment Tool.");
                    continue;
                }
                ProcedureCharge procCharge    = new ProcedureCharge(procCode, proc.ProcFee);
                Adjustment      taxAdjustment = Adjustments.GetSalesTaxForProc(proc.ProcNum);
                if (taxAdjustment != null)
                {
                    procCharge.EstTax           = taxAdjustment.AdjAmt;
                    procCharge.HasTaxAdjustment = true;
                }
                else
                {
                    procCharge.EstTax = 0;
                }
                procCharge.Calc();
                _listPreviouslyCompProcedureCharges.Add(procCharge);
                _listCompletedProcs.Add(proc);
            }
            //This calls FillGridCompletedProcs()
            FillGridPrepayment();
        }
Пример #17
0
        private void butOK_Click(object sender, System.EventArgs e)
        {
            bool isDiscountPlanAdj = (Defs.GetValue(DefCat.AdjTypes, _adjustmentCur.AdjType) == "dp");

            if (textAdjDate.errorProvider1.GetError(textAdjDate) != "" ||
                textProcDate.errorProvider1.GetError(textProcDate) != "" ||
                textAmount.errorProvider1.GetError(textAmount) != "")
            {
                MsgBox.Show(this, "Please fix data entry errors first.");
                return;
            }
            if (PIn.Date(textAdjDate.Text).Date > DateTime.Today.Date && !PrefC.GetBool(PrefName.FutureTransDatesAllowed))
            {
                MsgBox.Show(this, "Adjustment date can not be in the future.");
                return;
            }
            if (textAmount.Text == "")
            {
                MessageBox.Show(Lan.g(this, "Please enter an amount."));
                return;
            }
            if (!isDiscountPlanAdj && listTypeNeg.SelectedIndex == -1 && listTypePos.SelectedIndex == -1)
            {
                MsgBox.Show(this, "Please select a type first.");
                return;
            }
            if (IsNew && AvaTax.IsEnabled() && listTypePos.SelectedIndex > -1 &&
                (_listAdjPosCats[listTypePos.SelectedIndex].DefNum == AvaTax.SalesTaxAdjType || _listAdjPosCats[listTypePos.SelectedIndex].DefNum == AvaTax.SalesTaxReturnAdjType) &&
                !Security.IsAuthorized(Permissions.SalesTaxAdjEdit))
            {
                return;
            }
            if (PrefC.GetInt(PrefName.RigorousAdjustments) == 0 && _adjustmentCur.ProcNum == 0)
            {
                MsgBox.Show(this, "You must attach a procedure to the adjustment.");
                return;
            }
            if (_adjRemAmt < 0)
            {
                if (!MsgBox.Show(this, MsgBoxButtons.OKCancel, "Remaining amount is negative.  Continue?", "Overpaid Procedure Warning"))
                {
                    return;
                }
            }
            bool            changeAdjSplit         = false;
            List <PaySplit> listPaySplitsForAdjust = new List <PaySplit>();

            if (IsNew)
            {
                //prevents backdating of initial adjustment
                if (!Security.IsAuthorized(Permissions.AdjustmentCreate, PIn.Date(textAdjDate.Text), true)) //Give message later.
                {
                    if (!_checkZeroAmount)                                                                  //Let user create as long as Amount is zero and has edit zero permissions.  This was checked on load.
                    {
                        MessageBox.Show(Lans.g("Security", "Not authorized for") + "\r\n" + GroupPermissions.GetDesc(Permissions.AdjustmentCreate));
                        return;
                    }
                }
            }
            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.AdjustmentEdit, PIn.Date(textAdjDate.Text)))
                {
                    return;
                }
                if (_adjustmentCur.ProvNum != comboProv.GetSelectedProvNum())
                {
                    listPaySplitsForAdjust = PaySplits.GetForAdjustments(new List <long>()
                    {
                        _adjustmentCur.AdjNum
                    });
                    foreach (PaySplit paySplit in listPaySplitsForAdjust)
                    {
                        if (!Security.IsAuthorized(Permissions.PaymentEdit, Payments.GetPayment(paySplit.PayNum).PayDate))
                        {
                            return;
                        }
                        if (comboProv.GetSelectedProvNum() != paySplit.ProvNum && PrefC.GetInt(PrefName.RigorousAccounting) == (int)RigorousAdjustments.EnforceFully)
                        {
                            changeAdjSplit = true;
                            break;
                        }
                    }
                    if (changeAdjSplit &&
                        !MsgBox.Show(this, MsgBoxButtons.OKCancel, "The provider for the associated payment splits will be changed to match the provider on the "
                                     + "adjustment."))
                    {
                        return;
                    }
                }
            }
            //DateEntry not allowed to change
            DateTime datePreviousChange = _adjustmentCur.SecDateTEdit;

            _adjustmentCur.AdjDate   = PIn.Date(textAdjDate.Text);
            _adjustmentCur.ProcDate  = PIn.Date(textProcDate.Text);
            _adjustmentCur.ProvNum   = comboProv.GetSelectedProvNum();
            _adjustmentCur.ClinicNum = comboClinic.SelectedClinicNum;
            if (listTypePos.SelectedIndex != -1)
            {
                _adjustmentCur.AdjType = _listAdjPosCats[listTypePos.SelectedIndex].DefNum;
                _adjustmentCur.AdjAmt  = PIn.Double(textAmount.Text);
            }
            if (listTypeNeg.SelectedIndex != -1)
            {
                _adjustmentCur.AdjType = _listAdjNegCats[listTypeNeg.SelectedIndex].DefNum;
                _adjustmentCur.AdjAmt  = -PIn.Double(textAmount.Text);
            }
            if (isDiscountPlanAdj)
            {
                //AdjustmentCur.AdjType is already set to a "discount plan" adj type.
                _adjustmentCur.AdjAmt = -PIn.Double(textAmount.Text);
            }
            if (_checkZeroAmount && _adjustmentCur.AdjAmt != 0)
            {
                MsgBox.Show(this, "Amount has to be 0.00 due to security permission.");
                return;
            }
            _adjustmentCur.AdjNote = textNote.Text;
            try{
                if (IsNew)
                {
                    Adjustments.Insert(_adjustmentCur);
                    SecurityLogs.MakeLogEntry(Permissions.AdjustmentCreate, _adjustmentCur.PatNum,
                                              _patCur.GetNameLF() + ", "
                                              + _adjustmentCur.AdjAmt.ToString("c"));
                    TsiTransLogs.CheckAndInsertLogsIfAdjTypeExcluded(_adjustmentCur, _isTsiAdj);
                }
                else
                {
                    Adjustments.Update(_adjustmentCur);
                    SecurityLogs.MakeLogEntry(Permissions.AdjustmentEdit, _adjustmentCur.PatNum, _patCur.GetNameLF() + ", " + _adjustmentCur.AdjAmt.ToString("c"), 0
                                              , datePreviousChange);
                }
            }
            catch (Exception ex) {          //even though it doesn't currently throw any exceptions
                MessageBox.Show(ex.Message);
                return;
            }
            if (changeAdjSplit)
            {
                PaySplits.UpdateProvForAdjust(_adjustmentCur, listPaySplitsForAdjust);
            }
            DialogResult = DialogResult.OK;
        }
Пример #18
0
        private void FillProcedure()
        {
            if (_adjustmentCur.ProcNum == 0)
            {
                textProcDate2.Text       = "";
                textProcProv.Text        = "";
                textProcTooth.Text       = "";
                textProcDescription.Text = "";
                textProcFee.Text         = "";
                textProcWriteoff.Text    = "";
                textProcInsPaid.Text     = "";
                textProcInsEst.Text      = "";
                textProcAdj.Text         = "";
                textProcPatPaid.Text     = "";
                textProcAdjCur.Text      = "";
                labelProcRemain.Text     = "";
                _adjRemAmt = 0;
                return;
            }
            Procedure         procCur         = Procedures.GetOneProc(_adjustmentCur.ProcNum, false);
            List <ClaimProc>  listClaimProcs  = ClaimProcs.Refresh(procCur.PatNum);
            List <Adjustment> listAdjustments = Adjustments.Refresh(procCur.PatNum)
                                                .Where(x => x.ProcNum == procCur.ProcNum && x.AdjNum != _adjustmentCur.AdjNum).ToList();

            textProcDate.Text        = procCur.ProcDate.ToShortDateString();
            textProcDate2.Text       = procCur.ProcDate.ToShortDateString();
            textProcProv.Text        = Providers.GetAbbr(procCur.ProvNum);
            textProcTooth.Text       = Tooth.ToInternat(procCur.ToothNum);
            textProcDescription.Text = ProcedureCodes.GetProcCode(procCur.CodeNum).Descript;
            double procWO      = -ClaimProcs.ProcWriteoff(listClaimProcs, procCur.ProcNum);
            double procInsPaid = -ClaimProcs.ProcInsPay(listClaimProcs, procCur.ProcNum);
            double procInsEst  = -ClaimProcs.ProcEstNotReceived(listClaimProcs, procCur.ProcNum);
            double procAdj     = listAdjustments.Sum(x => x.AdjAmt);
            double procPatPaid = -PaySplits.GetTotForProc(procCur);

            textProcFee.Text      = procCur.ProcFeeTotal.ToString("F");
            textProcWriteoff.Text = procWO == 0?"":procWO.ToString("F");
            textProcInsPaid.Text  = procInsPaid == 0?"":procInsPaid.ToString("F");
            textProcInsEst.Text   = procInsEst == 0?"":procInsEst.ToString("F");
            textProcAdj.Text      = procAdj == 0?"":procAdj.ToString("F");
            textProcPatPaid.Text  = procPatPaid == 0?"":procPatPaid.ToString("F");
            //Intelligently sum the values above based on statuses instead of blindly adding all of the values together.
            //The remaining amount is typically called the "patient portion" so utilze the centralized method that gets the patient portion.
            decimal patPort    = ClaimProcs.GetPatPortion(procCur, listClaimProcs, listAdjustments);
            double  procAdjCur = 0;

            if (textAmount.errorProvider1.GetError(textAmount) == "")
            {
                if (listTypePos.SelectedIndex > -1)              //pos
                {
                    procAdjCur = PIn.Double(textAmount.Text);
                }
                else if (listTypeNeg.SelectedIndex > -1 || Defs.GetValue(DefCat.AdjTypes, _adjustmentCur.AdjType) == "dp")           //neg or discount plan
                {
                    procAdjCur = -PIn.Double(textAmount.Text);
                }
            }
            textProcAdjCur.Text = procAdjCur == 0?"":procAdjCur.ToString("F");
            //Add the current adjustment amount to the patient portion which will give the newly calculated remaining amount.
            _adjRemAmt           = (decimal)procAdjCur + (decimal)procPatPaid + patPort;
            labelProcRemain.Text = _adjRemAmt.ToString("c");
        }
Пример #19
0
 private void butOK_Click(object sender, System.EventArgs e)
 {
     if (textAdjDate.errorProvider1.GetError(textAdjDate) != "" ||
         textProcDate.errorProvider1.GetError(textProcDate) != "" ||
         textAmount.errorProvider1.GetError(textAmount) != ""
         )
     {
         MsgBox.Show(this, "Please fix data entry errors first.");
         return;
     }
     if (textAmount.Text == "")
     {
         MessageBox.Show(Lan.g(this, "Please enter an amount."));
         return;
     }
     if (listTypeNeg.SelectedIndex == -1 && listTypePos.SelectedIndex == -1)
     {
         MsgBox.Show(this, "Please select a type first.");
         return;
     }
     //DateEntry not allowed to change
     AdjustmentCur.AdjDate  = PIn.PDate(textAdjDate.Text);
     AdjustmentCur.ProcDate = PIn.PDate(textProcDate.Text);
     if (listProvider.SelectedIndex == -1)
     {
         AdjustmentCur.ProvNum = PatCur.PriProv;
     }
     else
     {
         AdjustmentCur.ProvNum = Providers.List[this.listProvider.SelectedIndex].ProvNum;
     }
     if (listTypePos.SelectedIndex != -1)
     {
         AdjustmentCur.AdjType
             = DefB.Short[(int)DefCat.AdjTypes][(int)PosIndex[listTypePos.SelectedIndex]].DefNum;
     }
     if (listTypeNeg.SelectedIndex != -1)
     {
         AdjustmentCur.AdjType
             = DefB.Short[(int)DefCat.AdjTypes][(int)NegIndex[listTypeNeg.SelectedIndex]].DefNum;
     }
     if (DefB.GetValue(DefCat.AdjTypes, AdjustmentCur.AdjType) == "+")         //pos
     {
         AdjustmentCur.AdjAmt = PIn.PDouble(textAmount.Text);
     }
     else             //neg
     {
         AdjustmentCur.AdjAmt = -PIn.PDouble(textAmount.Text);
     }
     AdjustmentCur.AdjNote = textNote.Text;
     try{
         Adjustments.InsertOrUpdate(AdjustmentCur, IsNew);
     }
     catch (Exception ex) {          //even though it doesn't currently throw any exceptions
         MessageBox.Show(ex.Message);
         return;
     }
     if (IsNew)
     {
         SecurityLogs.MakeLogEntry(Permissions.AdjustmentCreate, AdjustmentCur.PatNum,
                                   Patients.GetLim(AdjustmentCur.PatNum).GetNameLF() + ", "
                                   + AdjustmentCur.AdjAmt.ToString("c"));
     }
     else
     {
         SecurityLogs.MakeLogEntry(Permissions.AdjustmentEdit, AdjustmentCur.PatNum,
                                   Patients.GetLim(AdjustmentCur.PatNum).GetNameLF() + ", "
                                   + AdjustmentCur.AdjAmt.ToString("c"));
     }
     DialogResult = DialogResult.OK;
 }
Пример #20
0
        private void butUndo_Click(object sender, EventArgs e)
        {
            string chargeType = (radioFinanceCharge.Checked?"Finance":"Billing");

            if (MessageBox.Show(Lan.g(this, "Undo all " + chargeType.ToLower() + " charges for") + " " + textDateUndo.Text + "?", "", MessageBoxButtons.OKCancel)
                != DialogResult.OK)
            {
                return;
            }
            Action actionCloseProgress = null;
            int    rowsAffected        = 0;

            try {
                actionCloseProgress = ODProgressOld.ShowProgressStatus(chargeType + "Charge", this,
                                                                       Lan.g(this, "Deleting " + chargeType.ToLower() + " charge adjustments") + "...");
                Cursor       = Cursors.WaitCursor;
                rowsAffected = (int)Adjustments.UndoFinanceOrBillingCharges(PIn.Date(textDateUndo.Text), radioBillingCharge.Checked);
            }
            finally {
                actionCloseProgress?.Invoke();                //effectively terminates progress bar
                Cursor = Cursors.Default;
            }
            MessageBox.Show(Lan.g(this, chargeType + " charge adjustments deleted") + ": " + rowsAffected);
            if (rowsAffected == 0)
            {
                DialogResult = DialogResult.OK;
                return;
            }
            actionCloseProgress = null;
            if (PrefC.GetBool(PrefName.AgingIsEnterprise))
            {
                if (!RunAgingEnterprise())
                {
                    MsgBox.Show(this, "There was an error calculating aging after the " + chargeType.ToLower() + " charge adjustments were deleted.\r\n"
                                + "You should run aging later to update affected accounts.");
                }
            }
            else
            {
                try {
                    DateTime asOfDate = (PrefC.GetBool(PrefName.AgingCalculatedMonthlyInsteadOfDaily)?PrefC.GetDate(PrefName.DateLastAging):DateTime.Today);
                    actionCloseProgress = ODProgressOld.ShowProgressStatus("FinanceCharge", this, Lan.g(this, "Calculating aging for all patients as of") + " "
                                                                           + asOfDate.ToShortDateString() + "...");
                    Cursor = Cursors.WaitCursor;
                    Ledgers.RunAging();
                }
                catch (MySqlException ex) {
                    actionCloseProgress?.Invoke();                    //effectively terminates progress bar
                    Cursor = Cursors.Default;
                    if (ex == null || ex.Number != 1213)              //not a deadlock error, just throw
                    {
                        throw;
                    }
                    MsgBox.Show(this, "There was a deadlock error calculating aging after the " + chargeType.ToLower() + " charge adjustments were deleted.\r\n"
                                + "You should run aging later to update affected accounts.");
                }
                finally {
                    actionCloseProgress?.Invoke();                    //effectively terminates progress bar
                    Cursor = Cursors.Default;
                }
            }
            SecurityLogs.MakeLogEntry(Permissions.Setup, 0, chargeType + " Charges undo. Date " + textDateUndo.Text);
            DialogResult = DialogResult.OK;
        }
Пример #21
0
        private void butOK_Click(object sender, System.EventArgs e)
        {
            if (textDate.errorProvider1.GetError(textDate) != "" ||
                textAPR.errorProvider1.GetError(textAPR) != "" ||
                textAtLeast.errorProvider1.GetError(textAtLeast) != "" ||
                textOver.errorProvider1.GetError(textOver) != "")
            {
                MsgBox.Show(this, "Please fix data entry errors first.");
                return;
            }
            DateTime date = PIn.Date(textDate.Text);

            if (PrefC.GetDate(PrefName.FinanceChargeLastRun).AddDays(25) > date)
            {
                if (!MsgBox.Show(this, true, "Warning.  Finance charges should not be run more than once per month.  Continue?"))
                {
                    return;
                }
            }
            else if (PrefC.GetDate(PrefName.BillingChargeLastRun).AddDays(25) > date)
            {
                if (!MsgBox.Show(this, true, "Warning.  Billing charges should not be run more than once per month.  Continue?"))
                {
                    return;
                }
            }
            if (listBillType.SelectedIndices.Count == 0)
            {
                MsgBox.Show(this, "Please select at least one billing type first.");
                return;
            }
            if (PIn.Long(textAPR.Text) < 2)
            {
                if (!MsgBox.Show(this, true, "The APR is much lower than normal. Do you wish to proceed?"))
                {
                    return;
                }
            }
            if (PrefC.GetBool(PrefName.AgingCalculatedMonthlyInsteadOfDaily) && PrefC.GetDate(PrefName.DateLastAging).AddMonths(1) <= DateTime.Today)
            {
                if (!MsgBox.Show(this, MsgBoxButtons.OKCancel, "It has been more than a month since aging has been run.  It is recommended that you update the "
                                 + "aging date and run aging before continuing."))
                {
                    return;
                }
                //we might also consider a warning if textDate.Text does not match DateLastAging.  Probably not needed for daily aging, though.
            }
            string      chargeType            = (radioFinanceCharge.Checked?"Finance":"Billing");//For display only
            List <long> listSelectedBillTypes = listBillType.SelectedIndices.OfType <int>().Select(x => _listBillingTypeDefs[x].DefNum).ToList();
            Action      actionCloseProgress   = null;
            int         chargesAdded          = 0;

            try {
                actionCloseProgress = ODProgressOld.ShowProgressStatus("FinanceCharge", this, Lan.g(this, "Gathering patients with aged balances") + "...");
                List <PatAging> listPatAgings = Patients.GetAgingListSimple(listSelectedBillTypes, new List <long> {
                });                                                                                                                //Ordered by PatNum, for thread concurrency
                long adjType = PrefC.GetLong(PrefName.FinanceChargeAdjustmentType);
                Dictionary <long, List <Adjustment> > dictPatAdjustments = new Dictionary <long, List <Adjustment> >();
                if (!checkCompound.Checked)
                {
                    int daysOver = (radio30.Checked ? 30
                                                : radio60.Checked ? 60
                                                : 90);
                    DateTime maxAdjDate = MiscData.GetNowDateTime().Date.AddDays(-daysOver);
                    dictPatAdjustments = Adjustments.GetAdjustForPatsByType(listPatAgings.Select(x => x.PatNum).ToList(), adjType, maxAdjDate);
                }
                int           chargesProcessed = 0;
                List <Action> listActions      = new List <Action>();
                foreach (PatAging patAgingCur in listPatAgings)
                {
                    listActions.Add(new Action(() => {
                        if (++chargesProcessed % 5 == 0)
                        {
                            ODEvent.Fire(new ODEventArgs("FinanceCharge", Lan.g(this, "Processing " + chargeType + " charges") + ": " + chargesProcessed + " out of "
                                                         + listPatAgings.Count));
                        }
                        //This WILL NOT be the same as the patient's total balance. Start with BalOver90 since all options include that bucket. Add others if needed.
                        double overallBalance = patAgingCur.BalOver90 + (radio60.Checked?patAgingCur.Bal_61_90:radio30.Checked?(patAgingCur.Bal_31_60 + patAgingCur.Bal_61_90):0);
                        if (overallBalance <= .01d)
                        {
                            return;
                        }
                        if (radioBillingCharge.Checked)
                        {
                            AddBillingCharge(patAgingCur.PatNum, date, textBillingCharge.Text, patAgingCur.PriProv);
                        }
                        else                                                                                 //Finance charge
                        {
                            if (dictPatAdjustments.ContainsKey(patAgingCur.PatNum))                          //Only contains key if checkCompound is not checked.
                            {
                                overallBalance -= dictPatAdjustments[patAgingCur.PatNum].Sum(x => x.AdjAmt); //Dict always contains patNum as key, but list can be empty.
                            }
                            if (!AddFinanceCharge(patAgingCur.PatNum, date, textAPR.Text, textAtLeast.Text, textOver.Text, overallBalance, patAgingCur.PriProv, adjType))
                            {
                                return;
                            }
                        }
                        chargesAdded++;
                    }));
                }
                ODThread.RunParallel(listActions, TimeSpan.FromMinutes(2));               //each group of actions gets X minutes.
                if (radioFinanceCharge.Checked)
                {
                    if (Prefs.UpdateString(PrefName.FinanceChargeAPR, textAPR.Text)
                        | Prefs.UpdateString(PrefName.FinanceChargeLastRun, POut.Date(date, false))
                        | Prefs.UpdateString(PrefName.FinanceChargeAtLeast, textAtLeast.Text)
                        | Prefs.UpdateString(PrefName.FinanceChargeOnlyIfOver, textOver.Text)
                        | Prefs.UpdateString(PrefName.BillingChargeOrFinanceIsDefault, "Finance"))
                    {
                        DataValid.SetInvalid(InvalidType.Prefs);
                    }
                }
                else if (radioBillingCharge.Checked)
                {
                    if (Prefs.UpdateString(PrefName.BillingChargeAmount, textBillingCharge.Text)
                        | Prefs.UpdateString(PrefName.BillingChargeLastRun, POut.Date(date, false))
                        | Prefs.UpdateString(PrefName.BillingChargeOrFinanceIsDefault, "Billing"))
                    {
                        DataValid.SetInvalid(InvalidType.Prefs);
                    }
                }
            }
            finally {
                actionCloseProgress?.Invoke();                //terminates progress bar
            }
            MessageBox.Show(Lan.g(this, chargeType + " charges added") + ": " + chargesAdded);
            if (PrefC.GetBool(PrefName.AgingIsEnterprise))
            {
                if (!RunAgingEnterprise())
                {
                    MsgBox.Show(this, "There was an error calculating aging after the " + chargeType.ToLower() + " charge adjustments were added.\r\n"
                                + "You should run aging later to update affected accounts.");
                }
            }
            else
            {
                DateTime asOfDate = (PrefC.GetBool(PrefName.AgingCalculatedMonthlyInsteadOfDaily)?PrefC.GetDate(PrefName.DateLastAging):DateTime.Today);
                actionCloseProgress = ODProgressOld.ShowProgressStatus("FinanceCharge", this, Lan.g(this, "Calculating aging for all patients as of") + " "
                                                                       + asOfDate.ToShortDateString() + "...");
                Cursor = Cursors.WaitCursor;
                try {
                    Ledgers.RunAging();
                }
                catch (MySqlException ex) {
                    actionCloseProgress?.Invoke();                    //terminates progress bar
                    Cursor = Cursors.Default;
                    if (ex == null || ex.Number != 1213)              //not a deadlock error, just throw
                    {
                        throw;
                    }
                    MsgBox.Show(this, "There was a deadlock error calculating aging after the " + chargeType.ToLower() + " charge adjustments were added.\r\n"
                                + "You should run aging later to update affected accounts.");
                }
                finally {
                    actionCloseProgress?.Invoke();                    //terminates progress bar
                    Cursor = Cursors.Default;
                }
            }
            DialogResult = DialogResult.OK;
        }
Пример #22
0
        private int ReallocateAll()
        {
            string    command = "SELECT DefNum FROM definition WHERE Category=1 AND ItemName='Reallocation'";
            DataTable table   = General.GetTable(command);
            int       defnum;

            if (table.Rows.Count == 0)
            {
                Def def = new Def();
                def.Category  = DefCat.AdjTypes;
                def.ItemName  = "Reallocation";
                def.ItemValue = "+";
                def.ItemOrder = DefB.Long[(int)DefCat.AdjTypes].Length;
                Defs.Insert(def);
                defnum = def.DefNum;
                DataValid.SetInvalid(InvalidTypes.Defs);
            }
            else
            {
                defnum = PIn.PInt(table.Rows[0][0].ToString());
            }
            //find all families where someone has a negative balance.
            command = "SELECT DISTINCT Guarantor FROM patient WHERE EstBalance < 0";
            DataTable tableGuarantors = General.GetTable(command);
            int       changed         = 0;

            //bool result;
            double[]   familyBals;
            DataTable  tablePatients;
            Adjustment adj;
            Double     delta;

            for (int i = 0; i < tableGuarantors.Rows.Count; i++)
            {
                command       = "SELECT PatNum,EstBalance FROM patient WHERE Guarantor=" + tableGuarantors.Rows[i][0].ToString();
                tablePatients = General.GetTable(command);
                if (tablePatients.Rows.Count == 1)              //impossible to allocate
                {
                    continue;
                }
                familyBals = new double[tablePatients.Rows.Count];
                for (int p = 0; p < tablePatients.Rows.Count; p++)
                {
                    familyBals[p] = PIn.PDouble(tablePatients.Rows[p]["EstBalance"].ToString());
                }
                for (int p = 0; p < familyBals.Length; p++)
                {
                    if (familyBals[p] < 0)                          //if a negative bal found
                    {
                        for (int j = 0; j < familyBals.Length; j++) //look for a positive bal to adjust
                        {
                            if (j == p)
                            {
                                continue;                                //skip same patient
                            }
                            if (familyBals[j] <= 0)
                            {
                                continue;                        //no neg bal
                            }
                            if (familyBals[j] >= -familyBals[p]) //if sufficient bal to zero out the neg
                            {
                                familyBals[j] += familyBals[p];  //because p is neg
                                familyBals[p]  = 0;
                                break;                           //quit looking for a pos bal to adj.
                            }
                            else                                 //only enough bal to reduce the negative, not eliminate it
                            {
                                familyBals[p] += familyBals[j];  //because p is neg
                                familyBals[j]  = 0;
                            }
                        }
                    }
                }
                //now, save any changes to db:
                for (int p = 0; p < familyBals.Length; p++)
                {
                    if (familyBals[p] == PIn.PDouble(tablePatients.Rows[p]["EstBalance"].ToString()))
                    {
                        continue;                        //same, so no change to db
                    }
                    adj          = new Adjustment();
                    adj.PatNum   = PIn.PInt(tablePatients.Rows[p]["PatNum"].ToString());
                    adj.AdjDate  = DateTime.Today;
                    adj.AdjNote  = "Automatic";
                    adj.AdjType  = defnum;
                    adj.ProcDate = DateTime.Today;
                    adj.ProvNum  = PrefB.GetInt("PracticeDefaultProv");
                    delta        = familyBals[p] - PIn.PDouble(tablePatients.Rows[p]["EstBalance"].ToString());         //works whether pos or neg
                    adj.AdjAmt   = delta;
                    Adjustments.InsertOrUpdate(adj, true);
                    command = "UPDATE patient SET EstBalance=EstBalance+'" + POut.PDouble(delta) + "' WHERE PatNum=" + tablePatients.Rows[p]["PatNum"].ToString();
                    General.NonQ(command);
                    changed++;
                }
            }
            return(changed);
        }