Exemplo n.º 1
0
 public static PaymentEdit.IncomeTransferData IncomeTransfer(long patNum, Family fam, Payment payCur, List <PayPlanCharge> listPayPlanCredits,
                                                             bool doIncludeHidden = false)
 {
     #region generate charges and credits for account
     //go through the logic that constructs the charges for the income transfer manager
     PaymentEdit.ConstructResults results = PaymentEdit.ConstructAndLinkChargeCredits(fam.ListPats.Select(x => x.PatNum).ToList(),
                                                                                      patNum, new List <PaySplit>(), payCur, new List <AccountEntry>(), true, false, doShowHiddenSplits: doIncludeHidden);
     PaymentEdit.IncomeTransferData transfers      = new PaymentEdit.IncomeTransferData();
     List <AccountEntry>            listPosCharges = results.ListAccountCharges.FindAll(x => x.AmountEnd > 0).OrderBy(x => x.Date).ToList();
     List <AccountEntry>            listNegCharges = results.ListAccountCharges.FindAll(x => x.AmountEnd < 0).OrderBy(x => x.Date).ToList();
     List <long>         listPatsWithPosCharges    = listPosCharges.Select(y => y.PatNum).Distinct().ToList();
     List <AccountEntry> listAccountEntries        = results.ListAccountCharges.FindAll(x => x.PatNum.In(listPatsWithPosCharges));
     #endregion
     //begin transfer loops
     #region transfer within payplans first
     PaymentEdit.IncomeTransferData payPlanResults = PaymentEdit.CreatePayplanLoop(listPosCharges, listNegCharges, listAccountEntries
                                                                                   , payCur.PayNum, listPayPlanCredits, DateTimeOD.Today);
     transfers.MergeIncomeTransferData(payPlanResults);
     #endregion
     #region regular transfers
     PaymentEdit.IncomeTransferData txfrResults = PaymentEdit.CreateTransferLoop(listPosCharges, listNegCharges, listAccountEntries
                                                                                 , payCur.PayNum, listPayPlanCredits, DateTimeOD.Today);
     transfers.MergeIncomeTransferData(txfrResults);
     #endregion
     return(transfers);
 }
Exemplo n.º 2
0
        ///<summary>Transfers unallocated to unearned (if present) and inserts those results into the database. Then performs transfer.
        ///This is the best representation of what the income transfer window currently does.</summary>
        public static PaymentEdit.IncomeTransferData BalanceAndIncomeTransfer(long patNum, Family fam, Payment regularTransferPayment
                                                                              , List <PayPlanCharge> payPlanCharges = null)
        {
            //get all paysplits associated to the family passed in
            List <PaySplit> listSplitsForPat = PaySplits.GetForPats(fam.ListPats.Select(x => x.PatNum).ToList());
            //perform unallocated transfer
            Payment unallocatedTransfer = MakePaymentNoSplits(patNum, 0, payDate: DateTime.Today);

            PaymentEdit.IncomeTransferData unallocatedResults = PaymentEdit.TransferUnallocatedSplitToUnearned(listSplitsForPat, unallocatedTransfer.PayNum);
            foreach (PaySplit split in unallocatedResults.ListSplitsCur)
            {
                if (split.SplitAmt.IsZero())
                {
                    continue;
                }
                PaySplits.Insert(split);
            }
            foreach (PaySplits.PaySplitAssociated splitAssociated in unallocatedResults.ListSplitsAssociated)
            {
                if (splitAssociated.PaySplitOrig != null && splitAssociated.PaySplitLinked != null)
                {
                    PaySplits.UpdateFSplitNum(splitAssociated.PaySplitOrig.SplitNum, splitAssociated.PaySplitLinked.SplitNum);
                }
            }
            if (payPlanCharges == null)
            {
                payPlanCharges = new List <PayPlanCharge>();
            }
            #region claim fix and transfer
            //both of these methods have objects that get immediately inserted into the database. While testing, a spcific call wil need to be made to delete.
            ClaimProcs.FixClaimsNoProcedures(fam.ListPats.Select(x => x.PatNum).ToList());             //make dummy procedures and claimprocs for claims missing procs.
            ClaimProcs.TransferClaimsAsTotalToProcedures(fam.ListPats.Select(x => x.PatNum).ToList()); //transfer AsTotals into claim procedures
            #endregion
            return(IncomeTransfer(patNum, fam, regularTransferPayment, payPlanCharges));
        }
 ///<summary>Creates micro-allocations intelligently based on most to least matching criteria of selected charges.</summary>
 private void CreateTransfers(List <AccountEntry> listPosCharges, List <AccountEntry> listNegCharges, List <AccountEntry> listAccountEntries)
 {
     //No logic that manipulates these lists should happen before the regular transfer. If necessary (like fixing incorrect unearned)
     //they will need to be made as DBMs instead or wait for another logic overhaul.
     #region transfer within payment plans first
     List <PayPlanCharge>           listCredits    = _results.ListPayPlanCharges.FindAll(x => x.ChargeType == PayPlanChargeType.Credit);
     PaymentEdit.IncomeTransferData payPlanResults = PaymentEdit.CreatePayplanLoop(listPosCharges, listNegCharges, listAccountEntries
                                                                                   , _paymentCur.PayNum, listCredits, DateTimeOD.Today);
     _listSplitsAssociated.AddRange(payPlanResults.ListSplitsAssociated);
     _listSplitsCur.AddRange(payPlanResults.ListSplitsCur);
     #endregion
     #region regular transfers
     PaymentEdit.IncomeTransferData results = PaymentEdit.CreateTransferLoop(listPosCharges, listNegCharges, listAccountEntries
                                                                             , _paymentCur.PayNum, listCredits, DateTimeOD.Today);
     _listSplitsAssociated.AddRange(results.ListSplitsAssociated);
     _listSplitsCur.AddRange(results.ListSplitsCur);
     #endregion
     if (results.HasInvalidSplits || payPlanResults.HasInvalidSplits)
     {
         MsgBox.Show(this, "Due to Rigorous Accounting, one or more invalid transactions have been cancelled.  Please fix those manually.");
     }
     else if (results.HasIvalidProcWithPayPlan || payPlanResults.HasIvalidProcWithPayPlan)
     {
         MsgBox.Show(this, "One or more over allocated paysplit was not able to be reversed.");
     }
 }
Exemplo n.º 4
0
        ///<summary>Creates micro-allocations intelligently based on most to least matching criteria of selected charges.</summary>
        private string CreateTransfers(List <AccountEntry> listPosCharges, List <AccountEntry> listNegCharges, List <AccountEntry> listAccountEntries
                                       , FamilyAccount famAccount, Payment payCur)
        {
            PaymentEdit.IncomeTransferData transferResults = new PaymentEdit.IncomeTransferData();
            List <PayPlanCharge>           listCredits     = famAccount.Account.ListPayPlanCharges.FindAll(x => x.ChargeType == PayPlanChargeType.Credit);
            string retVal = "";

            transferResults = PaymentEdit.CreatePayplanLoop(listPosCharges, listNegCharges, listAccountEntries, payCur.PayNum, listCredits, datePicker.Value);
            transferResults.MergeIncomeTransferData(PaymentEdit.CreateTransferLoop(listPosCharges, listNegCharges, listAccountEntries, payCur.PayNum
                                                                                   , listCredits, datePicker.Value, famAccount.Guarantor.PatNum));
            famAccount.ListSplits.AddRange(transferResults.ListSplitsCur);
            famAccount.ListSplitsAssociated.AddRange(transferResults.ListSplitsAssociated);
            retVal += transferResults.SummaryText;
            return(retVal);
        }
        ///<summary></summary>
        private void TransferUnallocatedToUnearned()
        {
            List <PaySplit> listSplitsForPats = PaySplits.GetForPats(_listFamilyPatNums);

            if (listSplitsForPats.IsNullOrEmpty())
            {
                return;
            }
            //Pass in an invalid payNum of 0 which will get set correctly later if there are in fact splits to transfer.
            PaymentEdit.IncomeTransferData unallocatedTransfers = PaymentEdit.TransferUnallocatedSplitToUnearned(listSplitsForPats, 0);
            if (unallocatedTransfers.ListSplitsCur.Count == 0)
            {
                return;
            }
            if (!unallocatedTransfers.ListSplitsCur.Sum(x => x.SplitAmt).IsZero())
            {
                //Display the UnearnedType and the SplitAmt for each split in the list.
                string splitInfo = string.Join("\r\n  ", unallocatedTransfers.ListSplitsCur
                                               .Select(x => $"SplitAmt: {x.SplitAmt}"));
                //Show the sum of all splits first and then give a breakdown of each individual split.
                string details = $"Sum of unallocatedTransfers.ListSplitsCur: {unallocatedTransfers.ListSplitsCur.Sum(x => x.SplitAmt)}\r\n"
                                 + $"Individual Split Info:\r\n  {splitInfo}";
                FriendlyException.Show("Error transferring unallocated paysplits.  Please call support.", new ApplicationException(details), "Close");
                //Close the window and do not let the user create transfers because something is wrong.
                DialogResult = DialogResult.Cancel;
                Close();
                return;
            }
            //There are unallocated paysplits that need to be transferred to unearned.
            _unallocatedPayNum = PaymentEdit.CreateAndInsertUnallocatedPayment(_patCur);
            foreach (PaySplit split in unallocatedTransfers.ListSplitsCur)
            {
                split.PayNum = _unallocatedPayNum;              //Set the PayNum because it was purposefully set to 0 above to save queries.
                PaySplits.Insert(split);
            }
            foreach (PaySplits.PaySplitAssociated splitAssociated in unallocatedTransfers.ListSplitsAssociated)
            {
                if (splitAssociated.PaySplitLinked != null && splitAssociated.PaySplitOrig != null)
                {
                    PaySplits.UpdateFSplitNum(splitAssociated.PaySplitOrig.SplitNum, splitAssociated.PaySplitLinked.SplitNum);
                }
            }
            SecurityLogs.MakeLogEntry(Permissions.PaymentCreate, _patCur.PatNum
                                      , $"Unallocated splits automatically transferred to unearned for payment {_unallocatedPayNum}.");
        }
Exemplo n.º 6
0
        ///<summary>Fills the main grid.  If reload Data is true, account data will be (re)fetched from the database.
        ///If false then data already in memory is used.</summary>
        private void FillGridMain()
        {
            gridMain.BeginUpdate();
            gridMain.ListGridColumns.Clear();
            GridColumn col;

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

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

            foreach (KeyValuePair <long, FamilyAccount> kvp in _dictCurrentFamilyBatch)
            {
                //Get all family members now so we cut down on memory used.
                FamilyAccount   famAccount                = kvp.Value;
                List <Patient>  listPatients              = famAccount.ListFamilyMembers;
                List <long>     listFamilyPatNums         = listPatients.Select(x => x.PatNum).ToList();
                long            guarantorNum              = kvp.Key;
                List <PaySplit> listSplitsForPats         = listSplitsForBatch.FindAll(x => x.PatNum.In(listFamilyPatNums));
                long            unallocatedTransferPayNum = PaymentEdit.CreateAndInsertUnallocatedPayment(listPatients.First(x => x.PatNum == guarantorNum));
                if (!listSplitsForPats.IsNullOrEmpty())
                {
                    PaymentEdit.IncomeTransferData txfrResults = PaymentEdit.TransferUnallocatedSplitToUnearned(listSplitsForPats, unallocatedTransferPayNum);
                    foreach (PaySplit split in txfrResults.ListSplitsCur)
                    {
                        split.PayNum = unallocatedTransferPayNum;       //Set the PayNum because it was purposefully set to 0 above to save queries.
                        PaySplits.Insert(split);                        //Need to insert in a loop to get the PrimaryKey
                    }
                    foreach (PaySplits.PaySplitAssociated splitAssociated in txfrResults.ListSplitsAssociated)
                    {
                        if (splitAssociated.PaySplitLinked != null && splitAssociated.PaySplitOrig != null)
                        {
                            PaySplits.UpdateFSplitNum(splitAssociated.PaySplitOrig.SplitNum, splitAssociated.PaySplitLinked.SplitNum);
                        }
                    }
                }
                List <ClaimProc> listClaimsAsTotalForPats = listClaimsPayAsTotalForBatch.FindAll(x => x.PatNum.In(listFamilyPatNums));
                ClaimProcs.TransferClaimsAsTotalToProcedures(listPatients.Select(x => x.PatNum).ToList(), listClaimsAsTotalForPats);
                results = PaymentEdit.ConstructAndLinkChargeCredits(listPatients.Select(x => x.PatNum).ToList(), guarantorNum, new List <PaySplit>(),
                                                                    new Payment(), new List <AccountEntry>(), true);
                famAccount.Account = results;
                List <AccountEntry> listAccountEntries = results.ListAccountCharges;
                //Get guarantor info and fill the row/grid
                Patient guarantor = listPatients.FirstOrDefault(x => x.PatNum == guarantorNum);
                row = new GridRow();
                row.Cells.Add(guarantor.GetNameLFnoPref());
                row.Cells.Add((listAccountEntries.Sum(x => x.AmountEnd)).ToString("f"));
                row.Tag = famAccount;         //Store relevant family info in the guarantor row.
                row.DropDownInitiallyDown = false;
                row.Bold = true;              //Bold parent rows to show it is giving the family balance.
                gridMain.ListGridRows.Add(row);
                //Make child rows
                foreach (Patient p in listPatients)
                {
                    GridRow rowChild = new GridRow();
                    rowChild.Cells.Add(p.GetNameLFnoPref());
                    rowChild.Cells.Add(listAccountEntries.Where(x => x.PatNum == p.PatNum).Sum(x => x.AmountEnd).ToString("f"));
                    rowChild.DropDownParent = row;
                    gridMain.ListGridRows.Add(rowChild);
                }
            }
            gridMain.EndUpdate();
            gridMain.Update();
            labelBatchCount.Text = $"Current batch: {_batchNum} Total batches: {_listBatches.Count()}";
            //Invalidate and update the label to force it to be in sync with the progress bar that is on a separate thread.
            labelBatchCount.Invalidate();
            labelBatchCount.Update();
        }
Exemplo n.º 7
0
        ///<summary>Sets given appt.AptStatus to broken.
        ///Provide procCode that should be charted, can be null but will not chart a broken procedure.
        ///Also considers various broken procedure based prefs.
        ///Makes its own securitylog entries.</summary>
        public static void BreakApptHelper(Appointment appt, Patient pat, ProcedureCode procCode)
        {
            //suppressHistory is true due to below logic creating a log with a specific HistAppointmentAction instead of the generic changed.
            DateTime datePrevious    = appt.DateTStamp;
            bool     suppressHistory = false;

            if (procCode != null)
            {
                suppressHistory = (procCode.ProcCode.In("D9986", "D9987"));
            }
            Appointments.SetAptStatus(appt, ApptStatus.Broken, suppressHistory); //Appointments S-Class handles Signalods
            if (appt.AptStatus != ApptStatus.Complete)                           //seperate log entry for completed appointments.
            {
                SecurityLogs.MakeLogEntry(Permissions.AppointmentEdit, pat.PatNum,
                                          appt.ProcDescript + ", " + appt.AptDateTime.ToString()
                                          + ", Broken from the Appts module.", appt.AptNum, datePrevious);
            }
            else
            {
                SecurityLogs.MakeLogEntry(Permissions.AppointmentCompleteEdit, pat.PatNum,
                                          appt.ProcDescript + ", " + appt.AptDateTime.ToString()
                                          + ", Broken from the Appts module.", appt.AptNum, datePrevious);
            }
            #region HL7
            //If there is an existing HL7 def enabled, send a SIU message if there is an outbound SIU message defined
            if (HL7Defs.IsExistingHL7Enabled())
            {
                //S15 - Appt Cancellation event
                MessageHL7 messageHL7 = MessageConstructor.GenerateSIU(pat, Patients.GetPat(pat.Guarantor), EventTypeHL7.S15, appt);
                //Will be null if there is no outbound SIU message defined, so do nothing
                if (messageHL7 != null)
                {
                    HL7Msg hl7Msg = new HL7Msg();
                    hl7Msg.AptNum    = appt.AptNum;
                    hl7Msg.HL7Status = HL7MessageStatus.OutPending;                  //it will be marked outSent by the HL7 service.
                    hl7Msg.MsgText   = messageHL7.ToString();
                    hl7Msg.PatNum    = pat.PatNum;
                    HL7Msgs.Insert(hl7Msg);
#if DEBUG
                    MessageBox.Show("Appointments", messageHL7.ToString());
#endif
                }
            }
            #endregion
            List <Procedure> listProcedures = new List <Procedure>();
            //splits should only exist on procs if they are using tp pre-payments
            List <PaySplit> listSplitsForApptProcs = new List <PaySplit>();
            bool            isNonRefundable        = false;
            double          brokenProcAmount       = 0;
            Procedure       brokenProcedure        = new Procedure();
            bool            wasBrokenProcDeleted   = false;
            if (PrefC.GetYN(PrefName.PrePayAllowedForTpProcs))
            {
                listProcedures = Procedures.GetProcsForSingle(appt.AptNum, false);
                if (listProcedures.Count > 0)
                {
                    listSplitsForApptProcs = PaySplits.GetPaySplitsFromProcs(listProcedures.Select(x => x.ProcNum).ToList());
                }
            }
            #region Charting the proc
            if (procCode != null)
            {
                switch (procCode.ProcCode)
                {
                case "D9986":                        //Missed
                    HistAppointments.CreateHistoryEntry(appt.AptNum, HistAppointmentAction.Missed);
                    break;

                case "D9987":                        //Cancelled
                    HistAppointments.CreateHistoryEntry(appt.AptNum, HistAppointmentAction.Cancelled);
                    break;
                }
                brokenProcedure.PatNum       = pat.PatNum;
                brokenProcedure.ProvNum      = (procCode.ProvNumDefault > 0 ? procCode.ProvNumDefault : appt.ProvNum);
                brokenProcedure.CodeNum      = procCode.CodeNum;
                brokenProcedure.ProcDate     = DateTime.Today;
                brokenProcedure.DateEntryC   = DateTime.Now;
                brokenProcedure.ProcStatus   = ProcStat.C;
                brokenProcedure.ClinicNum    = appt.ClinicNum;
                brokenProcedure.UserNum      = Security.CurUser.UserNum;
                brokenProcedure.Note         = Lans.g("AppointmentEdit", "Appt BROKEN for") + " " + appt.ProcDescript + "  " + appt.AptDateTime.ToString();
                brokenProcedure.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService);              //Default proc place of service for the Practice is used.
                List <InsSub>  listInsSubs    = InsSubs.RefreshForFam(Patients.GetFamily(pat.PatNum));
                List <InsPlan> listInsPlans   = InsPlans.RefreshForSubList(listInsSubs);
                List <PatPlan> listPatPlans   = PatPlans.Refresh(pat.PatNum);
                InsPlan        insPlanPrimary = null;
                InsSub         insSubPrimary  = null;
                if (listPatPlans.Count > 0)
                {
                    insSubPrimary  = InsSubs.GetSub(listPatPlans[0].InsSubNum, listInsSubs);
                    insPlanPrimary = InsPlans.GetPlan(insSubPrimary.PlanNum, listInsPlans);
                }
                double procFee;
                long   feeSch;
                if (insPlanPrimary == null || procCode.NoBillIns)
                {
                    feeSch = FeeScheds.GetFeeSched(0, pat.FeeSched, brokenProcedure.ProvNum);
                }
                else                  //Only take into account the patient's insurance fee schedule if the D9986 procedure is not marked as NoBillIns
                {
                    feeSch = FeeScheds.GetFeeSched(insPlanPrimary.FeeSched, pat.FeeSched, brokenProcedure.ProvNum);
                }
                procFee = Fees.GetAmount0(brokenProcedure.CodeNum, feeSch, brokenProcedure.ClinicNum, brokenProcedure.ProvNum);
                if (insPlanPrimary != null && insPlanPrimary.PlanType == "p" && !insPlanPrimary.IsMedical)         //PPO
                {
                    double provFee = Fees.GetAmount0(brokenProcedure.CodeNum, Providers.GetProv(brokenProcedure.ProvNum).FeeSched, brokenProcedure.ClinicNum,
                                                     brokenProcedure.ProvNum);
                    brokenProcedure.ProcFee = Math.Max(provFee, procFee);
                }
                else if (listSplitsForApptProcs.Count > 0 && PrefC.GetBool(PrefName.TpPrePayIsNonRefundable) && procCode.ProcCode == "D9986")
                {
                    //if there are pre-payments, non-refundable pre-payments is turned on, and the broken appointment is a missed code then auto-fill
                    //the window with the sum of the procs for the appointment. Transfer money below after broken procedure is confirmed by the user.
                    brokenProcedure.ProcFee = listSplitsForApptProcs.Sum(x => x.SplitAmt);
                    isNonRefundable         = true;
                }
                else
                {
                    brokenProcedure.ProcFee = procFee;
                }
                if (!PrefC.GetBool(PrefName.EasyHidePublicHealth))
                {
                    brokenProcedure.SiteNum = pat.SiteNum;
                }
                Procedures.Insert(brokenProcedure);
                //Now make a claimproc if the patient has insurance.  We do this now for consistency because a claimproc could get created in the future.
                List <Benefit>   listBenefits          = Benefits.Refresh(listPatPlans, listInsSubs);
                List <ClaimProc> listClaimProcsForProc = ClaimProcs.RefreshForProc(brokenProcedure.ProcNum);
                Procedures.ComputeEstimates(brokenProcedure, pat.PatNum, listClaimProcsForProc, false, listInsPlans, listPatPlans, listBenefits, pat.Age, listInsSubs);
                FormProcBroken FormPB = new FormProcBroken(brokenProcedure, isNonRefundable);
                FormPB.IsNew = true;
                FormPB.ShowDialog();
                brokenProcAmount     = FormPB.AmountTotal;
                wasBrokenProcDeleted = FormPB.IsProcDeleted;
            }
            #endregion
            #region BrokenApptAdjustment
            if (PrefC.GetBool(PrefName.BrokenApptAdjustment))
            {
                Adjustment AdjustmentCur = new Adjustment();
                AdjustmentCur.DateEntry = DateTime.Today;
                AdjustmentCur.AdjDate   = DateTime.Today;
                AdjustmentCur.ProcDate  = DateTime.Today;
                AdjustmentCur.ProvNum   = appt.ProvNum;
                AdjustmentCur.PatNum    = pat.PatNum;
                AdjustmentCur.AdjType   = PrefC.GetLong(PrefName.BrokenAppointmentAdjustmentType);
                AdjustmentCur.ClinicNum = appt.ClinicNum;
                FormAdjust FormA = new FormAdjust(pat, AdjustmentCur);
                FormA.IsNew = true;
                FormA.ShowDialog();
            }
            #endregion
            #region BrokenApptCommLog
            if (PrefC.GetBool(PrefName.BrokenApptCommLog))
            {
                Commlog commlogCur = new Commlog();
                commlogCur.PatNum       = pat.PatNum;
                commlogCur.CommDateTime = DateTime.Now;
                commlogCur.CommType     = Commlogs.GetTypeAuto(CommItemTypeAuto.APPT);
                commlogCur.Note         = Lan.g("Appointment", "Appt BROKEN for") + " " + appt.ProcDescript + "  " + appt.AptDateTime.ToString();
                commlogCur.Mode_        = CommItemMode.None;
                commlogCur.UserNum      = Security.CurUser.UserNum;
                commlogCur.IsNew        = true;
                FormCommItem FormCI = new FormCommItem(commlogCur);
                FormCI.ShowDialog();
            }
            #endregion
            #region Transfer money from TP Procedures if necessary
            //Note this MUST come after FormProcBroken since clicking cancel in that window will delete the procedure.
            if (isNonRefundable && !wasBrokenProcDeleted && listSplitsForApptProcs.Count > 0)
            {
                //transfer what the user specified in the broken appointment window.
                //transfer up to the amount specified by the user
                foreach (Procedure proc in listProcedures)
                {
                    if (brokenProcAmount == 0)
                    {
                        break;
                    }
                    List <PaySplit> listSplitsForAppointmentProcedure = listSplitsForApptProcs.FindAll(x => x.ProcNum == proc.ProcNum);
                    foreach (PaySplit split in listSplitsForAppointmentProcedure)
                    {
                        if (brokenProcAmount == 0)
                        {
                            break;
                        }
                        double amt = Math.Min(brokenProcAmount, split.SplitAmt);
                        Payments.CreateTransferForTpProcs(proc, new List <PaySplit> {
                            split
                        }, brokenProcedure, amt);
                        double amtPaidOnApt = listSplitsForApptProcs.Sum(x => x.SplitAmt);
                        if (amtPaidOnApt > amt)
                        {
                            //If the original prepayment amount is greater than the amt being specified for the appointment break, transfer
                            //the difference to an Unallocated Unearned Paysplit on the account.
                            double remainingAmt = amtPaidOnApt - amt;
                            //We have to create a new transfer payment here to correlate to the split.
                            Payment txfrPayment = new Payment();
                            txfrPayment.PayAmt    = 0;
                            txfrPayment.PayDate   = DateTime.Today;
                            txfrPayment.ClinicNum = split.ClinicNum;
                            txfrPayment.PayNote   = "Automatic transfer from treatment planned procedure prepayment.";
                            txfrPayment.PatNum    = split.PatNum;                       //ultimately where the payment ends up.
                            txfrPayment.PayType   = 0;
                            Payments.Insert(txfrPayment);
                            PaymentEdit.IncomeTransferData transferData = PaymentEdit.IncomeTransferData.CreateTransfer(split, txfrPayment.PayNum, true, remainingAmt);
                            PaySplit offset         = transferData.ListSplitsCur.FirstOrDefault(x => x.FSplitNum != 0);
                            long     offsetSplitNum = PaySplits.Insert(offset);                      //Get the FSplitNum from the offset
                            PaySplit allocation     = transferData.ListSplitsCur.FirstOrDefault(x => x.FSplitNum == 0);
                            allocation.FSplitNum = offsetSplitNum;
                            PaySplits.Insert(allocation);                            //Insert so the split is now up to date
                            SecurityLogs.MakeLogEntry(Permissions.PaymentCreate, txfrPayment.PatNum, "Automatic transfer of funds for treatment plan procedure pre-payments.");
                        }
                        brokenProcAmount -= amt;
                    }
                }
            }
            //if broken appointment procedure was deleted (user cancelled out of the window) just keep money on the original procedure.
            #endregion
            AppointmentEvent.Fire(ODEventType.AppointmentEdited, appt);
            AutomationL.Trigger(AutomationTrigger.BreakAppointment, null, pat.PatNum);
            Recalls.SynchScheduledApptFull(appt.PatNum);
        }