예제 #1
0
 private void butOK_Click(object sender, System.EventArgs e)
 {
     if (textDateCalc.errorProvider1.GetError(textDateCalc) != ""
         )
     {
         MsgBox.Show(this, "Please fix data entry errors first.");
         return;
     }
     if (!MsgBox.Show(this, true, "Click OK to update aging."))
     {
         return;
     }
     Cursor = Cursors.WaitCursor;
     Patients.ResetAging();
     int[] allGuarantors = Ledgers.GetAllGuarantors();
     for (int i = 0; i < allGuarantors.Length; i++)
     {
         Ledgers.ComputeAging(allGuarantors[i], PIn.PDate(textDateCalc.Text));
         Patients.UpdateAging(allGuarantors[i], Ledgers.Bal[0], Ledgers.Bal[1], Ledgers.Bal[2]
                              , Ledgers.Bal[3], Ledgers.InsEst, Ledgers.BalTotal);
     }
     if (Prefs.UpdateString("DateLastAging", POut.PDate(DateTime.Today, false)))
     {
         DataValid.SetInvalid(InvalidTypes.Prefs);
     }
     Cursor = Cursors.Default;
     MsgBox.Show(this, "Aging Complete");
     DialogResult = DialogResult.OK;
 }
예제 #2
0
 private void butUndo_Click(object sender, EventArgs e)
 {
     if (radioFinanceCharge.Checked)
     {
         if (MessageBox.Show(Lan.g(this, "Undo all finance charges for ") + textDateUndo.Text + "?", "", MessageBoxButtons.OKCancel)
             != DialogResult.OK)
         {
             return;
         }
         long rowsAffected = Adjustments.UndoFinanceCharges(PIn.Date(textDateUndo.Text));
         MessageBox.Show(Lan.g(this, "Finance charge adjustments deleted: ") + rowsAffected.ToString());
         Ledgers.RunAging();
         SecurityLogs.MakeLogEntry(Permissions.Setup, 0, "Finance Charges undo. Date " + textDateUndo.Text);
         DialogResult = DialogResult.OK;
     }
     else if (radioBillingCharge.Checked)
     {
         if (MessageBox.Show(Lan.g(this, "Undo all billing charges for ") + textDateUndo.Text + "?", "", MessageBoxButtons.OKCancel)
             != DialogResult.OK)
         {
             return;
         }
         long rowsAffected = Adjustments.UndoBillingCharges(PIn.Date(textDateUndo.Text));
         MessageBox.Show(Lan.g(this, "Billing charge adjustments deleted: ") + rowsAffected.ToString());
         Ledgers.RunAging();
         SecurityLogs.MakeLogEntry(Permissions.Setup, 0, "Billing Charges undo. Date " + textDateUndo.Text);
         DialogResult = DialogResult.OK;
     }
 }
예제 #3
0
        ///<summary>If !isPreCharges, a message box will display for any errors instructing users to try again.  If the failed aging attempt is after
        ///charges have been added/deleted, we don't want to inform the user that the transaction failed so run again since the charges were successfully
        ///inserted/deleted and it was only updating the aged balances that failed.  If isPreCharges, this won't run aging again if the last aging run was
        ///today.  If !isPreCharges, we will run aging even if it was run today to update aged bals to include the charges added/deleted.</summary>
        private bool RunAgingEnterprise(bool isOnLoad = false)
        {
            DateTime dtNow         = MiscData.GetNowDateTime();
            DateTime dtToday       = dtNow.Date;
            DateTime dateLastAging = PrefC.GetDate(PrefName.DateLastAging);

            if (isOnLoad && dateLastAging.Date == dtToday)
            {
                return(true);               //this is prior to inserting/deleting charges and aging has already been run for this date
            }
            Prefs.RefreshCache();
            DateTime dateTAgingBeganPref = PrefC.GetDateT(PrefName.AgingBeginDateTime);

            if (dateTAgingBeganPref > DateTime.MinValue)
            {
                if (isOnLoad)
                {
                    MessageBox.Show(this, Lan.g(this, "In order to add finance charges, aging must be calculated, but you cannot run aging until it has finished "
                                                + "the current calculations which began on") + " " + dateTAgingBeganPref.ToString() + ".\r\n" + Lans.g(this, "If you believe the current aging "
                                                                                                                                                       + "process has finished, a user with SecurityAdmin permission can manually clear the date and time by going to Setup | Miscellaneous and "
                                                                                                                                                       + "pressing the 'Clear' button."));
                }
                return(false);
            }
            Prefs.UpdateString(PrefName.AgingBeginDateTime, POut.DateT(dtNow, false)); //get lock on pref to block others
            Signalods.SetInvalid(InvalidType.Prefs);                                   //signal a cache refresh so other computers will have the updated pref as quickly as possible
            Action actionCloseProgress = null;

            try {
                actionCloseProgress = ODProgressOld.ShowProgressStatus("FinanceCharge", this, Lan.g(this, "Calculating enterprise aging for all patients as of") + " "
                                                                       + dtToday.ToShortDateString() + "...");
                Cursor = Cursors.WaitCursor;
                Ledgers.ComputeAging(0, dtToday);
                Prefs.UpdateString(PrefName.DateLastAging, POut.Date(dtToday, false));
            }
            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;
                }
                if (isOnLoad)
                {
                    MsgBox.Show(this, "Deadlock error detected in enterprise aging transaction and rolled back. Try again later.");
                }
                return(false);
            }
            finally {
                actionCloseProgress?.Invoke();                       //effectively terminates progress bar
                Cursor = Cursors.Default;
                Prefs.UpdateString(PrefName.AgingBeginDateTime, ""); //clear lock on pref whether aging was successful or not
                Signalods.SetInvalid(InvalidType.Prefs);
            }
            return(true);
        }
예제 #4
0
        private bool RunAgingEnterprise(DateTime dateCalc)
        {
            DateTime dateLastAging = PrefC.GetDate(PrefName.DateLastAging);

            if (dateLastAging.Date == dateCalc.Date)
            {
                if (MessageBox.Show(this, Lan.g(this, "Aging has already been calculated for") + " " + dateCalc.ToShortDateString() + " "
                                    + Lan.g(this, "and does not normally need to run more than once per day.\r\n\r\nRun anway?"), "", MessageBoxButtons.YesNo) != DialogResult.Yes)
                {
                    return(false);
                }
            }
            //Refresh prefs because AgingBeginDateTime is very time sensitive
            Prefs.RefreshCache();
            DateTime dateTAgingBeganPref = PrefC.GetDateT(PrefName.AgingBeginDateTime);

            if (dateTAgingBeganPref > DateTime.MinValue)
            {
                MessageBox.Show(this, Lan.g(this, "You cannot run aging until it has finished the current calculations which began on") + " "
                                + dateTAgingBeganPref.ToString() + ".\r\n" + Lans.g(this, "If you believe the current aging process has finished, a user with SecurityAdmin permission "
                                                                                    + "can manually clear the date and time by going to Setup | Miscellaneous and pressing the 'Clear' button."));
                return(false);
            }
            Prefs.UpdateString(PrefName.AgingBeginDateTime, POut.DateT(MiscData.GetNowDateTime(), false)); //get lock on pref to block others
            Signalods.SetInvalid(InvalidType.Prefs);                                                       //signal a cache refresh so other computers will have the updated pref as quickly as possible
            Action actionCloseAgingProgress = null;

            try {
                actionCloseAgingProgress = ODProgressOld.ShowProgressStatus("ComputeAging", this,
                                                                            Lan.g(this, "Calculating enterprise aging for all patients as of") + " " + dateCalc.ToShortDateString() + "...");
                Cursor = Cursors.WaitCursor;
                Ledgers.ComputeAging(0, dateCalc);
                Prefs.UpdateString(PrefName.DateLastAging, POut.Date(dateCalc, false));
            }
            catch (MySqlException ex) {
                actionCloseAgingProgress?.Invoke();
                Cursor = Cursors.Default;
                if (ex == null || ex.Number != 1213)             //not a deadlock error, just throw
                {
                    throw;
                }
                MsgBox.Show(this, "Deadlock error detected in aging transaction and rolled back. Try again later.");
                return(false);
            }
            finally {
                actionCloseAgingProgress?.Invoke();
                Cursor = Cursors.Default;
                Prefs.UpdateString(PrefName.AgingBeginDateTime, "");               //clear lock on pref whether aging was successful or not
                Signalods.SetInvalid(InvalidType.Prefs);
            }
            return(true);
        }
예제 #5
0
        private void butOK_Click(object sender, System.EventArgs e)
        {
            if (textDateCalc.errorProvider1.GetError(textDateCalc) != "")
            {
                MsgBox.Show(this, "Please fix data entry errors first.");
                return;
            }
            DateTime dateCalc = PIn.Date(textDateCalc.Text);
            Action   actionCloseAgingProgress = null;

            if (PrefC.GetBool(PrefName.AgingIsEnterprise))
            {
                //if this is true, dateCalc has to be DateTime.Today and aging calculated daily not monthly.
                if (!RunAgingEnterprise(dateCalc))
                {
                    //Errors displayed from RunAgingEnterprise
                    return;
                }
            }
            else
            {
                try {
                    actionCloseAgingProgress = ODProgressOld.ShowProgressStatus("ComputeAging", this, Lan.g(this, "Calculating aging for all patients as of") + " "
                                                                                + dateCalc.ToShortDateString() + "...");
                    Cursor = Cursors.WaitCursor;
                    Ledgers.ComputeAging(0, dateCalc);
                }
                catch (MySqlException ex) {
                    actionCloseAgingProgress?.Invoke();
                    Cursor = Cursors.Default;
                    if (ex == null || ex.Number != 1213)                 //not a deadlock error, just throw
                    {
                        throw;
                    }
                    MsgBox.Show(this, "Deadlock error detected in aging transaction and rolled back. Try again later.");
                    DialogResult = DialogResult.Cancel;
                    return;
                }
                finally {
                    actionCloseAgingProgress?.Invoke();
                    Cursor = Cursors.Default;
                }
                if (Prefs.UpdateString(PrefName.DateLastAging, POut.Date(dateCalc, false)))
                {
                    DataValid.SetInvalid(InvalidType.Prefs);
                }
            }
            MsgBox.Show(this, "Aging Complete");
            DialogResult = DialogResult.OK;
        }
예제 #6
0
        private void FormFinanceCharges_Load(object sender, System.EventArgs e)
        {
            if (PrefC.GetLong(PrefName.FinanceChargeAdjustmentType) == 0)
            {
                MsgBox.Show(this, "No finance charge adjustment type has been set.  Please go to Setup | Modules to fix this.");
                DialogResult = DialogResult.Cancel;
                return;
            }
            if (PrefC.GetLong(PrefName.BillingChargeAdjustmentType) == 0)
            {
                MsgBox.Show(this, "No billing charge adjustment type has been set.  Please go to Setup | Modules to fix this.");
                DialogResult = DialogResult.Cancel;
                return;
            }
            Ledgers.RunAging();
            if (DefC.Short[(int)DefCat.BillingTypes].Length == 0)          //highly unlikely that this would happen
            {
                MsgBox.Show(this, "No billing types have been set up or are visible.");
                DialogResult = DialogResult.Cancel;
                return;
            }
            textDate.Text          = DateTime.Today.ToShortDateString();
            textAPR.MaxVal         = 100;
            textAPR.MinVal         = 0;
            textAPR.Text           = PrefC.GetString(PrefName.FinanceChargeAPR);
            textBillingCharge.Text = PrefC.GetString(PrefName.BillingChargeAmount);
            for (int i = 0; i < DefC.Short[(int)DefCat.BillingTypes].Length; i++)
            {
                listBillType.Items.Add(DefC.Short[(int)DefCat.BillingTypes][i].ItemName);
                listBillType.SetSelected(i, true);
            }
            string defaultChargeMethod = PrefC.GetString(PrefName.BillingChargeOrFinanceIsDefault);

            if (defaultChargeMethod == "Finance")
            {
                radioFinanceCharge.Checked = true;
                textDateLastRun.Text       = PrefC.GetDate(PrefName.FinanceChargeLastRun).ToShortDateString();
                textDateUndo.Text          = PrefC.GetDate(PrefName.FinanceChargeLastRun).ToShortDateString();
            }
            else if (defaultChargeMethod == "Billing")
            {
                radioBillingCharge.Checked = true;
                textDateLastRun.Text       = PrefC.GetDate(PrefName.BillingChargeLastRun).ToShortDateString();
                textDateUndo.Text          = PrefC.GetDate(PrefName.BillingChargeLastRun).ToShortDateString();
            }
        }
예제 #7
0
        private bool RunAgingEnterprise(DateTime dateCalc)
        {
            DateTime dateLastAging = PrefC.GetDate(PrefName.DateLastAging);

            if (dateLastAging.Date == dateCalc.Date)
            {
                if (MessageBox.Show(this, Lan.g(this, "Aging has already been calculated for") + " " + dateCalc.ToShortDateString() + " "
                                    + Lan.g(this, "and does not normally need to run more than once per day.\r\n\r\nRun anyway?"), "", MessageBoxButtons.YesNo) != DialogResult.Yes)
                {
                    return(false);
                }
            }
            //Refresh prefs because AgingBeginDateTime is very time sensitive
            Prefs.RefreshCache();
            DateTime dateTAgingBeganPref = PrefC.GetDateT(PrefName.AgingBeginDateTime);

            if (dateTAgingBeganPref > DateTime.MinValue)
            {
                MessageBox.Show(this, Lan.g(this, "You cannot run aging until it has finished the current calculations which began on") + " "
                                + dateTAgingBeganPref.ToString() + ".\r\n" + Lans.g(this, "If you believe the current aging process has finished, a user with SecurityAdmin permission "
                                                                                    + "can manually clear the date and time by going to Setup | Miscellaneous and pressing the 'Clear' button."));
                return(false);
            }
            SecurityLogs.MakeLogEntry(Permissions.AgingRan, 0, "Aging Ran - Aging Form");
            Prefs.UpdateString(PrefName.AgingBeginDateTime, POut.DateT(MiscData.GetNowDateTime(), false)); //get lock on pref to block others
            Signalods.SetInvalid(InvalidType.Prefs);                                                       //signal a cache refresh so other computers will have the updated pref as quickly as possible
            Cursor = Cursors.WaitCursor;
            bool result = true;

            ODProgress.ShowAction(
                () => {
                Ledgers.ComputeAging(0, dateCalc);
                Prefs.UpdateString(PrefName.DateLastAging, POut.Date(dateCalc, false));
            },
                startingMessage: Lan.g(this, "Calculating enterprise aging for all patients as of") + " " + dateCalc.ToShortDateString() + "...",
                actionException: ex => {
                Ledgers.AgingExceptionHandler(ex, this);
                result = false;
            }
                );
            Cursor = Cursors.Default;
            Prefs.UpdateString(PrefName.AgingBeginDateTime, "");           //clear lock on pref whether aging was successful or not
            Signalods.SetInvalid(InvalidType.Prefs);
            return(result);
        }
        private void butOK_Click(object sender, EventArgs e)
        {
            if (!Security.IsAuthorized(Permissions.PaymentCreate))
            {
                return;
            }
            double splitTotal = _listSplitsCur.Select(x => x.SplitAmt).Sum();

            if (!splitTotal.IsZero())              //income transfer
            {
                MsgBox.Show(this, "Income transfers must have a split total of 0.");
                return;
            }
            _listSplitsCur.RemoveAll(x => x.SplitAmt.IsZero());            //We don't want any zero splits.  They were there just for display purposes.
            if (_listSplitsCur.Count == 0)
            {
                Payments.Delete(_paymentCur);
            }
            else
            {
                foreach (PaySplit split in _listSplitsCur)
                {
                    PaySplits.Insert(split);
                }
                foreach (PaySplits.PaySplitAssociated split in _listSplitsAssociated)
                {
                    //Update the FSplitNum after inserts are made.
                    if (split.PaySplitLinked != null && split.PaySplitOrig != null)
                    {
                        PaySplits.UpdateFSplitNum(split.PaySplitOrig.SplitNum, split.PaySplitLinked.SplitNum);
                    }
                }
                if (_listSplitsCur.Count > 0)               //only make log when a payment with splits was made.
                {
                    string logText = Payments.GetSecuritylogEntryText(_paymentCur, _paymentCur, isNew: true) + ", " + Lans.g(this, "from Income Transfer Manager.");
                    SecurityLogs.MakeLogEntry(Permissions.PaymentCreate, _paymentCur.PatNum, logText);
                }
                string strErrorMsg = Ledgers.ComputeAgingForPaysplitsAllocatedToDiffPats(_patCur.PatNum, _listSplitsCur);
                if (!string.IsNullOrEmpty(strErrorMsg))
                {
                    MessageBox.Show(strErrorMsg);
                }
            }
            DialogResult = DialogResult.OK;
        }
예제 #9
0
 private void butOK_Click(object sender, System.EventArgs e)
 {
     if (textDateCalc.errorProvider1.GetError(textDateCalc) != ""
         )
     {
         MsgBox.Show(this, "Please fix data entry errors first.");
         return;
     }
     Cursor = Cursors.WaitCursor;
     Ledgers.ComputeAging(0, PIn.Date(textDateCalc.Text), false);
     if (Prefs.UpdateString(PrefName.DateLastAging, POut.Date(PIn.Date(textDateCalc.Text), false)))
     {
         DataValid.SetInvalid(InvalidType.Prefs);
     }
     Cursor = Cursors.Default;
     MsgBox.Show(this, "Aging Complete");
     DialogResult = DialogResult.OK;
 }
예제 #10
0
        private void butOK_Click(object sender, System.EventArgs e)
        {
            if (textDateCalc.errorProvider1.GetError(textDateCalc) != "")
            {
                MsgBox.Show(this, "Please fix data entry errors first.");
                return;
            }
            DateTime dateCalc = PIn.Date(textDateCalc.Text);

            if (PrefC.GetBool(PrefName.AgingIsEnterprise))
            {
                //if this is true, dateCalc has to be DateTime.Today and aging calculated daily not monthly.
                if (!RunAgingEnterprise(dateCalc))
                {
                    //Errors displayed from RunAgingEnterprise
                    return;
                }
            }
            else
            {
                SecurityLogs.MakeLogEntry(Permissions.AgingRan, 0, "Aging Ran - Aging Form");
                Cursor = Cursors.WaitCursor;
                bool result = true;
                ODProgress.ShowAction(() => Ledgers.ComputeAging(0, dateCalc),
                                      startingMessage: Lan.g(this, "Calculating aging for all patients as of") + " " + dateCalc.ToShortDateString() + "...",
                                      actionException: ex => {
                    Ledgers.AgingExceptionHandler(ex, this);
                    result = false;
                }
                                      );
                Cursor = Cursors.Default;
                if (!result)
                {
                    DialogResult = DialogResult.Cancel;
                    return;
                }
                if (Prefs.UpdateString(PrefName.DateLastAging, POut.Date(dateCalc, false)))
                {
                    DataValid.SetInvalid(InvalidType.Prefs);
                }
            }
            MsgBox.Show(this, "Aging Complete");
            DialogResult = DialogResult.OK;
        }
예제 #11
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;
            }
            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.
            }
            PatAging[] AgingList = Patients.GetAgingListArray();
            double     OverallBalance;
            int        rowsAffected = 0;
            bool       billingMatch;

            for (int i = 0; i < AgingList.Length; i++) //loop through each guarantor that owes money.
            {
                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;
                }
                else if (radio60.Checked)
                {
                    OverallBalance = AgingList[i].Bal_61_90 + AgingList[i].BalOver90;
                }
                else if (radio90.Checked)
                {
                    OverallBalance = AgingList[i].BalOver90;
                }
                if (OverallBalance <= .01d)
                {
                    continue;
                }
                billingMatch = false;
                for (int b = 0; b < listBillType.SelectedIndices.Count; b++)
                {
                    if (DefC.Short[(int)DefCat.BillingTypes][listBillType.SelectedIndices[b]].DefNum == AgingList[i].BillingType)
                    {
                        billingMatch = true;
                        break;
                    }
                }
                if (!billingMatch)
                {
                    continue;
                }
                if (radioFinanceCharge.Checked)
                {
                    AddFinanceCharge(AgingList[i].PatNum, date, textAPR.Text, OverallBalance, AgingList[i].PriProv);
                }
                else if (radioBillingCharge.Checked)
                {
                    AddBillingCharge(AgingList[i].PatNum, date, textBillingCharge.Text, AgingList[i].PriProv);
                }
                rowsAffected++;
            }
            if (radioFinanceCharge.Checked)
            {
                if (Prefs.UpdateString(PrefName.FinanceChargeAPR, textAPR.Text)
                    | Prefs.UpdateString(PrefName.FinanceChargeLastRun, POut.Date(date, false)))
                {
                    DataValid.SetInvalid(InvalidType.Prefs);
                }
                if (Prefs.UpdateString(PrefName.BillingChargeOrFinanceIsDefault, "Finance"))
                {
                    DataValid.SetInvalid(InvalidType.Prefs);
                }
                MessageBox.Show(Lan.g(this, "Finance Charges Added: ") + rowsAffected.ToString());
                Ledgers.RunAging();
                DialogResult = DialogResult.OK;
            }
            else if (radioBillingCharge.Checked)
            {
                if (Prefs.UpdateString(PrefName.BillingChargeAmount, textBillingCharge.Text)
                    | Prefs.UpdateString(PrefName.BillingChargeLastRun, POut.Date(date, false)))
                {
                    DataValid.SetInvalid(InvalidType.Prefs);
                }
                if (Prefs.UpdateString(PrefName.BillingChargeOrFinanceIsDefault, "Billing"))
                {
                    DataValid.SetInvalid(InvalidType.Prefs);
                }
                MessageBox.Show(Lan.g(this, "Billing Charges Added: ") + rowsAffected.ToString());
                Ledgers.RunAging();
                DialogResult = DialogResult.OK;
            }
        }
예제 #12
0
        private void butOK_Click(object sender, System.EventArgs e)
        {
            if (!checkBillTypesAll.Checked && listBillType.SelectedIndices.Count == 0)
            {
                MsgBox.Show(this, "At least one billing type must be selected.");
                return;
            }
            if (!checkProvAll.Checked && listProv.SelectedIndices.Count == 0)
            {
                MsgBox.Show(this, "At least one provider must be selected.");
                return;
            }
            if (textDate.errorProvider1.GetError(textDate) != "")
            {
                MsgBox.Show(this, "Invalid date.");
                return;
            }
            DateTime asOfDate = PIn.Date(textDate.Text);

            //The aging report always show historical numbers based on the date entered.
            Ledgers.ComputeAging(0, asOfDate, true);
            ReportSimpleGrid report = new ReportSimpleGrid();
            string           cmd    = "SELECT ";

            if (PrefC.GetBool(PrefName.ReportsShowPatNum))
            {
                cmd += DbHelper.Concat("Cast(PatNum AS CHAR)", "'-'", "LName", "', '", "FName", "' '", "MiddleI");
            }
            else
            {
                cmd += DbHelper.Concat("LName", "', '", "FName", "' '", "MiddleI");
            }
            cmd += ",Bal_0_30,Bal_31_60,Bal_61_90,BalOver90"
                   + ",BalTotal "
                   + ",InsEst"
                   + ",BalTotal-InsEst AS ";            //\"$pat\" ";
            if (DataConnection.DBtype == DatabaseType.MySql)
            {
                cmd += "$pat ";
            }
            else               //Oracle needs quotes.
            {
                cmd += "\"$pat\" ";
            }
            cmd += "FROM patient "
                   + "WHERE ";
            if (checkExcludeInactive.Checked)
            {
                cmd += "(patstatus != 2) AND ";
            }
            if (checkBadAddress.Checked)
            {
                cmd += "(zip !='') AND ";
            }
            if (checkOnlyNeg.Checked)
            {
                cmd += "BalTotal < '-.005' ";
            }
            else
            {
                if (radioAny.Checked)
                {
                    cmd +=
                        "(Bal_0_30 > '.005' OR Bal_31_60 > '.005' OR Bal_61_90 > '.005' OR BalOver90 > '.005'";
                }
                else if (radio30.Checked)
                {
                    cmd +=
                        "(Bal_31_60 > '.005' OR Bal_61_90 > '.005' OR BalOver90 > '.005'";
                }
                else if (radio60.Checked)
                {
                    cmd +=
                        "(Bal_61_90 > '.005' OR BalOver90 > '.005'";
                }
                else if (radio90.Checked)
                {
                    cmd +=
                        "(BalOver90 > '.005'";
                }
                if (checkIncludeNeg.Checked)
                {
                    cmd += " OR BalTotal < '-.005'";
                }
                cmd += ") ";
            }
            if (!checkBillTypesAll.Checked)
            {
                for (int i = 0; i < listBillType.SelectedIndices.Count; i++)
                {
                    if (i == 0)
                    {
                        cmd += " AND (billingtype = ";
                    }
                    else
                    {
                        cmd += " OR billingtype = ";
                    }
                    cmd += POut.Long(DefC.Short[(int)DefCat.BillingTypes][listBillType.SelectedIndices[i]].DefNum);
                }
                cmd += ") ";
            }
            if (!checkProvAll.Checked)
            {
                for (int i = 0; i < listProv.SelectedIndices.Count; i++)
                {
                    if (i == 0)
                    {
                        cmd += " AND (PriProv = ";
                    }
                    else
                    {
                        cmd += " OR PriProv = ";
                    }
                    cmd += POut.Long(ProviderC.ListShort[listProv.SelectedIndices[i]].ProvNum);
                }
                cmd += ") ";
            }
            cmd                += "ORDER BY LName,FName";
            report.Query        = cmd;
            FormQuery2          = new FormQuery(report);
            FormQuery2.IsReport = true;
            FormQuery2.SubmitReportQuery();
            //Recompute aging in a non-historical way, so that the numbers are returned to the way they
            //are normally used in other parts of the program.
            Ledgers.RunAging();
            //if(Prefs.UpdateString(PrefName.DateLastAging",POut.PDate(asOfDate,false))) {
            //	DataValid.SetInvalid(InvalidType.Prefs);
            //}
            report.Title = "AGING REPORT";
            report.SubTitle.Add(PrefC.GetString(PrefName.PracticeTitle));
            report.SubTitle.Add("As of " + textDate.Text);
            if (radioAny.Checked)
            {
                report.SubTitle.Add("Any Balance");
            }
            if (radio30.Checked)
            {
                report.SubTitle.Add("Over 30 Days");
            }
            if (radio60.Checked)
            {
                report.SubTitle.Add("Over 60 Days");
            }
            if (radio90.Checked)
            {
                report.SubTitle.Add("Over 90 Days");
            }
            if (checkBillTypesAll.Checked)
            {
                report.SubTitle.Add("All Billing Types");
            }
            else
            {
                string subt = DefC.Short[(int)DefCat.BillingTypes][listBillType.SelectedIndices[0]].ItemName;
                for (int i = 1; i < listBillType.SelectedIndices.Count; i++)
                {
                    subt += ", " + DefC.Short[(int)DefCat.BillingTypes][listBillType.SelectedIndices[i]].ItemName;
                }
                report.SubTitle.Add(subt);
            }
            //report.InitializeColumns(8);
            report.SetColumn(this, 0, "GUARANTOR", 160);
            report.SetColumn(this, 1, "0-30 DAYS", 80, HorizontalAlignment.Right);
            report.SetColumn(this, 2, "30-60 DAYS", 80, HorizontalAlignment.Right);
            report.SetColumn(this, 3, "60-90 DAYS", 80, HorizontalAlignment.Right);
            report.SetColumn(this, 4, "> 90 DAYS", 80, HorizontalAlignment.Right);
            report.SetColumn(this, 5, "TOTAL", 85, HorizontalAlignment.Right);
            report.SetColumn(this, 6, "-INS EST", 85, HorizontalAlignment.Right);
            report.SetColumn(this, 7, "=PATIENT", 85, HorizontalAlignment.Right);
            FormQuery2.ShowDialog();
            DialogResult = DialogResult.OK;
        }
예제 #13
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;
        }
예제 #14
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;
        }
예제 #15
0
        private void FormFinanceCharges_Load(object sender, System.EventArgs e)
        {
            if (PrefC.GetLong(PrefName.FinanceChargeAdjustmentType) == 0)
            {
                MsgBox.Show(this, "No finance charge adjustment type has been set.  Please go to Setup | Account to fix this.");
                DialogResult = DialogResult.Cancel;
                return;
            }
            if (PrefC.GetLong(PrefName.BillingChargeAdjustmentType) == 0)
            {
                MsgBox.Show(this, "No billing charge adjustment type has been set.  Please go to Setup | Account to fix this.");
                DialogResult = DialogResult.Cancel;
                return;
            }
            _listBillingTypeDefs = Defs.GetDefsForCategory(DefCat.BillingTypes, true);
            if (_listBillingTypeDefs.Count == 0)          //highly unlikely that this would happen
            {
                MsgBox.Show(this, "No billing types have been set up or are visible.");
                DialogResult = DialogResult.Cancel;
                return;
            }
            Action actionCloseAgingProgress = null;

            if (PrefC.GetBool(PrefName.AgingIsEnterprise))
            {
                if (!RunAgingEnterprise(true))
                {
                    DialogResult = DialogResult.Cancel;
                    return;
                }
            }
            else
            {
                try {
                    DateTime asOfDate = (PrefC.GetBool(PrefName.AgingCalculatedMonthlyInsteadOfDaily)?PrefC.GetDate(PrefName.DateLastAging):DateTime.Today);
                    actionCloseAgingProgress = ODProgressOld.ShowProgressStatus("ComputeAging", this, Lan.g(this, "Calculating aging for all patients as of") + " "
                                                                                + asOfDate.ToShortDateString() + "...");
                    Cursor = Cursors.WaitCursor;
                    Ledgers.RunAging();
                }
                catch (MySqlException ex) {
                    actionCloseAgingProgress?.Invoke();                  //effectively terminates progress bar
                    Cursor = Cursors.Default;
                    if (ex == null || ex.Number != 1213)                 //not a deadlock error, just throw
                    {
                        throw;
                    }
                    MsgBox.Show(this, "Deadlock error detected in aging transaction and rolled back. Try again later.");
                    DialogResult = DialogResult.Cancel;
                    return;
                }
                finally {
                    actionCloseAgingProgress?.Invoke();                    //effectively terminates progress bar
                    Cursor = Cursors.Default;
                }
            }
            textDate.Text          = DateTime.Today.ToShortDateString();
            textAPR.MaxVal         = 100;
            textAPR.MinVal         = 0;
            textAPR.Text           = PrefC.GetString(PrefName.FinanceChargeAPR);
            textBillingCharge.Text = PrefC.GetString(PrefName.BillingChargeAmount);
            for (int i = 0; i < _listBillingTypeDefs.Count; i++)
            {
                listBillType.Items.Add(_listBillingTypeDefs[i].ItemName);
                listBillType.SetSelected(i, true);
            }
            string defaultChargeMethod = PrefC.GetString(PrefName.BillingChargeOrFinanceIsDefault);

            if (defaultChargeMethod == "Finance")
            {
                radioFinanceCharge.Checked  = true;
                textDateLastRun.Text        = PrefC.GetDate(PrefName.FinanceChargeLastRun).ToShortDateString();
                textDateUndo.Text           = PrefC.GetDate(PrefName.FinanceChargeLastRun).ToShortDateString();
                textBillingCharge.ReadOnly  = true;
                textBillingCharge.BackColor = System.Drawing.SystemColors.Control;
            }
            else if (defaultChargeMethod == "Billing")
            {
                radioBillingCharge.Checked = true;
                textDateLastRun.Text       = PrefC.GetDate(PrefName.BillingChargeLastRun).ToShortDateString();
                textDateUndo.Text          = PrefC.GetDate(PrefName.BillingChargeLastRun).ToShortDateString();
            }
            textAtLeast.Text = PrefC.GetString(PrefName.FinanceChargeAtLeast);
            textOver.Text    = PrefC.GetString(PrefName.FinanceChargeOnlyIfOver);
        }
        private void butSend_Click(object sender, EventArgs e)
        {
            //Assuming the use of XCharge.  If adding another vendor (PayConnect for example)
            //make sure to move XCharge validation in FillGrid() to here.
            if (prog == null)           //Gets filled in FillGrid()
            {
                return;
            }
            if (gridMain.SelectedIndices.Length < 1)
            {
                MsgBox.Show(this, "Must select at least one recurring charge.");
                return;
            }
            if (!PaymentsWithinLockDate())
            {
                return;
            }
            string recurringResultFile = "Recurring charge results for " + DateTime.Now.ToShortDateString() + " ran at " + DateTime.Now.ToShortTimeString() + "\r\n\r\n";
            int    failed   = 0;
            int    success  = 0;
            string user     = ProgramProperties.GetPropVal(prog.ProgramNum, "Username");
            string password = ProgramProperties.GetPropVal(prog.ProgramNum, "Password");

            #region Card Charge Loop
            for (int i = 0; i < gridMain.SelectedIndices.Length; i++)
            {
                #region X-Charge
                if (table.Rows[gridMain.SelectedIndices[i]]["XChargeToken"].ToString() != "" &&
                    CreditCards.IsDuplicateXChargeToken(table.Rows[gridMain.SelectedIndices[i]]["XChargeToken"].ToString()))
                {
                    MessageBox.Show(Lan.g(this, "A duplicate token was found, the card cannot be charged for customer: ") + table.Rows[i]["PatName"].ToString());
                    continue;
                }
                insertPayment = false;
                ProcessStartInfo info       = new ProcessStartInfo(xPath);
                long             patNum     = PIn.Long(table.Rows[gridMain.SelectedIndices[i]]["PatNum"].ToString());
                string           resultfile = Path.Combine(Path.GetDirectoryName(xPath), "XResult.txt");
                File.Delete(resultfile);                //delete the old result file.
                info.Arguments = "";
                double   amt        = PIn.Double(table.Rows[gridMain.SelectedIndices[i]]["ChargeAmt"].ToString());
                DateTime exp        = PIn.Date(table.Rows[gridMain.SelectedIndices[i]]["CCExpiration"].ToString());
                string   address    = PIn.String(table.Rows[gridMain.SelectedIndices[i]]["Address"].ToString());
                string   addressPat = PIn.String(table.Rows[gridMain.SelectedIndices[i]]["AddressPat"].ToString());
                string   zip        = PIn.String(table.Rows[gridMain.SelectedIndices[i]]["Zip"].ToString());
                string   zipPat     = PIn.String(table.Rows[gridMain.SelectedIndices[i]]["ZipPat"].ToString());
                info.Arguments += "/AMOUNT:" + amt.ToString("F2") + " /LOCKAMOUNT ";
                info.Arguments += "/TRANSACTIONTYPE:PURCHASE /LOCKTRANTYPE ";
                if (table.Rows[gridMain.SelectedIndices[i]]["XChargeToken"].ToString() != "")
                {
                    info.Arguments += "/XCACCOUNTID:" + table.Rows[gridMain.SelectedIndices[i]]["XChargeToken"].ToString() + " ";
                    info.Arguments += "/RECURRING ";
                }
                else
                {
                    info.Arguments += "/ACCOUNT:" + table.Rows[gridMain.SelectedIndices[i]]["CCNumberMasked"].ToString() + " ";
                }
                if (exp.Year > 1880)
                {
                    info.Arguments += "/EXP:" + exp.ToString("MMyy") + " ";
                }
                if (address != "")
                {
                    info.Arguments += "\"/ADDRESS:" + address + "\" ";
                }
                else if (addressPat != "")
                {
                    info.Arguments += "\"/ADDRESS:" + addressPat + "\" ";
                }
                if (zip != "")
                {
                    info.Arguments += "\"/ZIP:" + zip + "\" ";
                }
                else if (zipPat != "")
                {
                    info.Arguments += "\"/ZIP:" + zipPat + "\" ";
                }
                info.Arguments += "/RECEIPT:Pat" + patNum + " ";          //aka invoice#
                info.Arguments += "\"/CLERK:" + Security.CurUser.UserName + " R\" /LOCKCLERK ";
                info.Arguments += "/RESULTFILE:\"" + resultfile + "\" ";
                info.Arguments += "/USERID:" + user + " ";
                info.Arguments += "/PASSWORD:"******" ";
                info.Arguments += "/HIDEMAINWINDOW ";
                info.Arguments += "/AUTOPROCESS ";
                info.Arguments += "/SMALLWINDOW ";
                info.Arguments += "/AUTOCLOSE ";
                info.Arguments += "/NORESULTDIALOG ";
                Cursor          = Cursors.WaitCursor;
                Process process = new Process();
                process.StartInfo           = info;
                process.EnableRaisingEvents = true;
                process.Start();
                while (!process.HasExited)
                {
                    Application.DoEvents();
                }
                Thread.Sleep(200);                //Wait 2/10 second to give time for file to be created.
                Cursor = Cursors.Default;
                string line       = "";
                string resultText = "";
                recurringResultFile += "PatNum: " + patNum + " Name: " + table.Rows[i]["PatName"].ToString() + "\r\n";
                using (TextReader reader = new StreamReader(resultfile)) {
                    line = reader.ReadLine();
                    while (line != null)
                    {
                        if (resultText != "")
                        {
                            resultText += "\r\n";
                        }
                        resultText += line;
                        if (line.StartsWith("RESULT="))
                        {
                            if (line == "RESULT=SUCCESS")
                            {
                                success++;
                                labelCharged.Text = Lan.g(this, "Charged=") + success;
                                insertPayment     = true;
                            }
                            else
                            {
                                failed++;
                                labelFailed.Text = Lan.g(this, "Failed=") + failed;
                            }
                        }
                        line = reader.ReadLine();
                    }
                    recurringResultFile += resultText + "\r\n\r\n";
                }
                #endregion
                if (insertPayment)
                {
                    Patient patCur     = Patients.GetPat(patNum);
                    Payment paymentCur = new Payment();
                    paymentCur.DateEntry = nowDateTime.Date;
                    paymentCur.PayDate   = GetPayDate(PIn.Date(table.Rows[gridMain.SelectedIndices[i]]["LatestPayment"].ToString()),
                                                      PIn.Date(table.Rows[gridMain.SelectedIndices[i]]["DateStart"].ToString()));
                    paymentCur.PatNum        = patCur.PatNum;
                    paymentCur.ClinicNum     = PIn.Long(table.Rows[gridMain.SelectedIndices[i]]["ClinicNum"].ToString());
                    paymentCur.PayType       = PIn.Int(ProgramProperties.GetPropVal(prog.ProgramNum, "PaymentType"));
                    paymentCur.PayAmt        = amt;
                    paymentCur.PayNote       = resultText;
                    paymentCur.IsRecurringCC = true;
                    Payments.Insert(paymentCur);
                    long provNum = PIn.Long(table.Rows[gridMain.SelectedIndices[i]]["ProvNum"].ToString()); //for payment plans only
                    if (provNum == 0)                                                                       //Regular payments need to apply to the provider that the family owes the most money to.
                    {
                        DataTable dt         = Patients.GetPaymentStartingBalances(patCur.Guarantor, paymentCur.PayNum);
                        double    highestAmt = 0;
                        for (int j = 0; j < dt.Rows.Count; j++)
                        {
                            double afterIns = PIn.Double(dt.Rows[j]["AfterIns"].ToString());
                            if (highestAmt >= afterIns)
                            {
                                continue;
                            }
                            highestAmt = afterIns;
                            provNum    = PIn.Long(dt.Rows[j]["ProvNum"].ToString());
                        }
                    }
                    PaySplit split = new PaySplit();
                    split.PatNum     = paymentCur.PatNum;
                    split.ClinicNum  = paymentCur.ClinicNum;
                    split.PayNum     = paymentCur.PayNum;
                    split.ProcDate   = paymentCur.PayDate;
                    split.DatePay    = paymentCur.PayDate;
                    split.ProvNum    = provNum;
                    split.SplitAmt   = paymentCur.PayAmt;
                    split.PayPlanNum = PIn.Long(table.Rows[gridMain.SelectedIndices[i]]["PayPlanNum"].ToString());
                    PaySplits.Insert(split);
                    if (PrefC.GetBool(PrefName.AgingCalculatedMonthlyInsteadOfDaily))
                    {
                        Ledgers.ComputeAging(patCur.Guarantor, PrefC.GetDate(PrefName.DateLastAging), false);
                    }
                    else
                    {
                        Ledgers.ComputeAging(patCur.Guarantor, DateTimeOD.Today, false);
                        if (PrefC.GetDate(PrefName.DateLastAging) != DateTime.Today)
                        {
                            Prefs.UpdateString(PrefName.DateLastAging, POut.Date(DateTime.Today, false));
                            //Since this is always called from UI, the above line works fine to keep the prefs cache current.
                        }
                    }
                }
            }
            #endregion
            try {
                File.WriteAllText(Path.Combine(Path.GetDirectoryName(xPath), "RecurringChargeResult.txt"), recurringResultFile);
            }
            catch { }             //Do nothing cause this is just for internal use.
            FillGrid();
            labelCharged.Text = Lan.g(this, "Charged=") + success;
            labelFailed.Text  = Lan.g(this, "Failed=") + failed;
            MsgBox.Show(this, "Done charging cards.\r\nIf there are any patients remaining in list, print the list and handle each one manually.");
        }