public void SecurityLogs_MakeLogEntry_DuplicateEntryParallel() { Patient patient = PatientT.CreatePatient(MethodBase.GetCurrentMethod().Name); //There are lots of bug submissions with exception text like "Duplicate entry 'XXXXX' for key 'PRIMARY'". //OpenDentBusiness.SecurityLogs.MakeLogEntry() seems to be the common theme for most of the submissions. //Spawn parallel threads to insert 200 security logs trying to get a duplicate entry exception. List <Action> listActions = new List <Action>(); for (int i = 0; i < 200; i++) { listActions.Add(() => SecurityLogs.MakeLogEntry(Permissions.Accounting, patient.PatNum, "", 0, DateTime.Now.AddDays(-7))); } //Parallel threads do not support Middle Tier mode when unit testing due to how we have to fake being both the client and the server. RemotingRole remotingRoleOld = RemotingClient.RemotingRole; if (RemotingClient.RemotingRole != RemotingRole.ClientDirect) { RemotingClient.RemotingRole = RemotingRole.ClientDirect; } ODThread.RunParallel(listActions, onException: (ex) => { RemotingClient.RemotingRole = remotingRoleOld; Assert.Fail(ex.Message); }); RemotingClient.RemotingRole = remotingRoleOld; }
private void menuItemDisplayFields_Click(object sender, EventArgs e) { if (!Security.IsAuthorized(Permissions.Setup)) { return; } FormDisplayFieldCategories FormD = new FormDisplayFieldCategories(true); FormD.ShowDialog(); SecurityLogs.MakeLogEntry(Permissions.Setup, 0, "Display Fields"); }
private void setupToolStripMenuItem_Click(object sender, EventArgs e) { if (!IsEditMode) { if (!Security.IsAuthorized(Permissions.GraphicalReportSetup)) { return; } SecurityLogs.MakeLogEntry(Permissions.GraphicalReportSetup, 0, "Accessed graphical reports setup controls."); } IsEditMode = !IsEditMode; }
public static void SendData(Program ProgramCur, Patient pat) { try { if (CADIWindow == null) //Only release this reference once the CADIWindow instance has closed. { CADIWindow = new CADINativeWindow(new Action(() => CADIWindow = null)); } CADIWindow.SendData(ProgramCur, pat); } catch (Exception e) { MessageBox.Show(e.Message); SecurityLogs.MakeLogEntry(Permissions.ChartModule, ODMethodsT.Coalesce(pat).PatNum, e.Message); } }
///<summary></summary> protected override void Dispose(bool disposing) { if (disposing) //managed resources { components?.Dispose(); //get rid of temp appts on pinboard. =jordan I don't see any docs on why this is here. Doesn't seem quite right, but it works. for (int i = 0; i < ListPinBoardItems.Count; i++) { if (PIn.Int(ListPinBoardItems[i].DataRowAppt["AptStatus"].ToString()) != (int)ApptStatus.UnschedList) { continue; } if (PIn.DateT(ListPinBoardItems[i].DataRowAppt["AptDateTime"].ToString()).Year > 1880) { continue; } Appointment appt = null; try{ appt = Appointments.GetOneApt(ListPinBoardItems[i].AptNum); } catch { break; //db connection no longer present. } if (appt == null) { continue; } if (appt.AptDateTime.Year > 1880) //date was updated since put on the pinboard { continue; } Appointments.Delete(appt.AptNum, true); if (Security.CurUser == null) // E.g. clicking Log Off invalidates the user. { continue; } //Make a security log if we still have a valid user logged in. string logText = Lan.g(this, "Deleted from pinboard while closing Open Dental") + ": "; if (appt.AptDateTime.Year > 1880) { logText += appt.AptDateTime.ToString() + ", "; } logText += appt.ProcDescript; SecurityLogs.MakeLogEntry(Permissions.AppointmentEdit, appt.PatNum, logText); } } base.Dispose(disposing); }
public void SecurityLogs_MakeLogEntry_DuplicateEntry() { Patient patient = PatientT.CreatePatient(MethodBase.GetCurrentMethod().Name); //There are lots of bug submissions with exception text like "Duplicate entry 'XXXXX' for key 'PRIMARY'". //OpenDentBusiness.SecurityLogs.MakeLogEntry() seems to be the common theme for most of the submissions. //Loop as fast as we can and insert 200 security logs trying to get a duplicate entry exception. for (int i = 0; i < 200; i++) { try { SecurityLogs.MakeLogEntry(Permissions.Accounting, patient.PatNum, "", 0, DateTime.Now.AddDays(-7)); } catch (Exception ex) { Assert.Fail(ex.Message); break; } } }
private void butRunAllocatorTool_Click(object sender, EventArgs e) { if (!rbutIHaveRead.Checked) { PU.MB = Lan.g(this, "You must indicate that you have read the text in the box!"); return; } if (MessageBox.Show("Do you want to run the batch allocation?", "Please Respond", MessageBoxButtons.YesNo) == DialogResult.Yes) { FormWarnToCloseComputers fwc = new FormWarnToCloseComputers(); if (fwc.ShowDialog() == DialogResult.Yes) { Reporting.Allocators.MyAllocator1_ProviderPayment allocator1 = new OpenDental.Reporting.Allocators.MyAllocator1_ProviderPayment(); SecurityLogs.MakeLogEntry(OpenDentBusiness.Permissions.Setup, 0, "Started Batch Allocation For Provider Allocation Tool"); allocator1.StartBatchAllocation(); SecurityLogs.MakeLogEntry(OpenDentBusiness.Permissions.Setup, 0, "Finished Batch Allocation For Provider Allocation Tool"); List <string> commands = new List <string>(); if (!PrefC.ContainsKey(MyAllocator1_ProviderPayment.Pref_AllocatorProvider1_ToolHasRun)) { commands.Add("INSERT INTO preference VALUES ('" + MyAllocator1_ProviderPayment.Pref_AllocatorProvider1_ToolHasRun + "','0')"); } if (!PrefC.ContainsKey(MyAllocator1_ProviderPayment.Pref_AllocatorProvider1_Use)) { commands.Add("INSERT INTO preference VALUES ('" + MyAllocator1_ProviderPayment.Pref_AllocatorProvider1_Use + "','0')"); } if (commands.Count != 0) { Db.NonQOld(commands.ToArray()); Cache.Refresh(InvalidType.Prefs); } Prefs.UpdateRaw(MyAllocator1_ProviderPayment.Pref_AllocatorProvider1_ToolHasRun, "1"); Prefs.UpdateRaw(MyAllocator1_ProviderPayment.Pref_AllocatorProvider1_Use, "1"); } } RefreshForm(); }
public static void ProcessMessage(MessageHL7 message, bool isVerboseLogging) { SegmentHL7 seg = message.GetSegment(SegmentNameHL7.PID, true); long patNum = PIn.Long(seg.GetFieldFullText(2)); Patient pat = Patients.GetPat(patNum); Patient patOld = null; bool isNewPat = pat == null; if (isNewPat) { pat = new Patient(); pat.PatNum = patNum; pat.Guarantor = patNum; pat.PriProv = PrefC.GetLong(PrefName.PracticeDefaultProv); pat.BillingType = PrefC.GetLong(PrefName.PracticeDefaultBillType); } else { patOld = pat.Copy(); } List <PatientRace> listPatRaces = new List <PatientRace>(); EcwSegmentPID.ProcessPID(pat, seg, false, listPatRaces); //IsStandalone=false because should never make it this far. //PV1-patient visit--------------------------- //seg=message.GetSegment(SegmentName.PV1,false); //if(seg!=null) { // SegmentPID.ProcessPV1(pat,seg); //} //SCH- Schedule Activity Information seg = message.GetSegment(SegmentNameHL7.SCH, true); //The documentation is wrong. SCH.01 is not the appointment ID, but is instead a sequence# (always 1) long aptNum = PIn.Long(seg.GetFieldFullText(2)); Appointment apt = Appointments.GetOneApt(aptNum); Appointment aptOld = null; bool isNewApt = apt == null; if (isNewApt) { apt = new Appointment(); apt.AptNum = aptNum; apt.PatNum = pat.PatNum; apt.AptStatus = ApptStatus.Scheduled; } else { aptOld = apt.Copy(); } if (apt.PatNum != pat.PatNum) { EventLog.WriteEntry("OpenDentHL7", "Appointment does not match patient: " + pat.FName + " " + pat.LName + ", apt.PatNum:" + apt.PatNum.ToString() + ", pat.PatNum:" + pat.PatNum.ToString() , EventLogEntryType.Error); return; //we can't process this message because wrong patnum. } apt.Note = seg.GetFieldFullText(7); //apt.Pattern=ProcessDuration(seg.GetFieldFullText(9)); //9 and 10 are not actually available, in spite of the documentation. //11-We need start time and stop time apt.AptDateTime = DateTimeParse(seg.GetFieldComponent(11, 3)); DateTime stopTime = DateTimeParse(seg.GetFieldComponent(11, 4)); apt.Pattern = ProcessPattern(apt.AptDateTime, stopTime); apt.ProvNum = pat.PriProv; //just in case there's not AIG segment. //AIG is optional, but looks like the only way to get provider for the appt----------- //PV1 seems to frequently be sent instead of AIG. SegmentHL7 segAIG = message.GetSegment(SegmentNameHL7.AIG, false); SegmentHL7 segPV = message.GetSegment(SegmentNameHL7.PV1, false); if (segAIG != null) { long provNum = EcwSegmentPID.ProvProcess(segAIG.GetField(3)); if (provNum != 0) { apt.ProvNum = provNum; pat.PriProv = provNum; } } else if (segPV != null) { long provNum = EcwSegmentPID.ProvProcess(segPV.GetField(7)); if (provNum != 0) { apt.ProvNum = provNum; pat.PriProv = provNum; } } //AIL,AIP seem to be optional, and I'm going to ignore them for now. if (pat.FName == "" || pat.LName == "") { EventLog.WriteEntry("OpenDentHL7", "Appointment not processed due to missing patient first or last name. PatNum:" + pat.PatNum.ToString() , EventLogEntryType.Information); return; //this will also skip the appt insert. } if (isNewPat) { if (isVerboseLogging) { EventLog.WriteEntry("OpenDentHL7", "Inserted patient: " + pat.FName + " " + pat.LName + ", PatNum:" + pat.PatNum.ToString() , EventLogEntryType.Information); } Patients.Insert(pat, true); SecurityLogs.MakeLogEntry(Permissions.PatientCreate, pat.PatNum, "Created from HL7 for eCW.", LogSources.HL7); } else { if (isVerboseLogging) { EventLog.WriteEntry("OpenDentHL7", "Updated patient: " + pat.FName + " " + pat.LName, EventLogEntryType.Information); } Patients.Update(pat, patOld); } //had to move this reconcile here since we might not have a PatNum for new patients until after the insert PatientRaces.Reconcile(pat.PatNum, listPatRaces); if (isNewApt) { if (isVerboseLogging) { EventLog.WriteEntry("OpenDentHL7", "Inserted appointment for: " + pat.FName + " " + pat.LName, EventLogEntryType.Information); } Appointments.InsertIncludeAptNum(apt, true); } else { if (isVerboseLogging) { EventLog.WriteEntry("OpenDentHL7", "Updated appointment for: " + pat.FName + " " + pat.LName, EventLogEntryType.Information); } Appointments.Update(apt, aptOld); } }
public static void ProcessMessage(MessageHL7 message, bool isStandalone, bool isVerboseLogging) { /*string triggerevent=message.Segments[0].GetFieldComponent(8,1); * switch(triggerevent) { * case "A01"://Admit/Visit Information * * break; * case "A04"://New Patient Information * ProcessNewPatient(message); * break; * case "A08"://Update Patient Information * * break; * case "A28"://Add Patient Information * * break; * case "A31"://Update Patient Information * * break; * }*/ //MSH-Ignore //EVN-Ignore //PID------------------------------------- SegmentHL7 seg = message.GetSegment(SegmentNameHL7.PID, true); long patNum = PIn.Long(seg.GetFieldFullText(2)); Patient pat = null; if (isStandalone) { pat = Patients.GetPatByChartNumber(patNum.ToString()); if (pat == null) { //try to find the patient in question by using name and birthdate string lName = seg.GetFieldComponent(5, 0); string fName = seg.GetFieldComponent(5, 1); DateTime birthdate = EcwSegmentPID.DateParse(seg.GetFieldFullText(7)); long patNumByName = Patients.GetPatNumByNameAndBirthday(lName, fName, birthdate); if (patNumByName == 0) //patient does not exist in OD //so pat will still be null, triggering creation of new patient further down. { } else { pat = Patients.GetPat(patNumByName); pat.ChartNumber = patNum.ToString(); //from now on, we will be able to find pat by chartNumber } } } else { pat = Patients.GetPat(patNum); } Patient patOld = null; bool isNewPat = pat == null; if (isNewPat) { pat = new Patient(); if (isStandalone) { pat.ChartNumber = patNum.ToString(); //this line does not work if isStandalone, so moved to end //pat.Guarantor=patNum; } else { pat.PatNum = patNum; pat.Guarantor = patNum; } pat.PriProv = PrefC.GetLong(PrefName.PracticeDefaultProv); pat.BillingType = PrefC.GetLong(PrefName.PracticeDefaultBillType); } else { patOld = pat.Copy(); } List <PatientRace> listPatRaces = new List <PatientRace>(); bool hasNoRaceInStandalone = (isStandalone && (pat == null || pat.PatNum == 0)); EcwSegmentPID.ProcessPID(pat, seg, isStandalone, listPatRaces); //PV1-patient visit--------------------------- //seg=message.GetSegment(SegmentName.PV1,false); //if(seg!=null) {//this seg is optional // SegmentPID.ProcessPV1(pat,seg); //} //PD1-additional patient demographics------------ //seg=message.GetSegment(SegmentName.PD1,false); //if(seg!=null) {//this seg is optional // ProcessPD1(pat,seg); //} //GT1-Guarantor------------------------------------- seg = message.GetSegment(SegmentNameHL7.GT1, true); EcwSegmentPID.ProcessGT1(pat, seg, isStandalone); //IN1-Insurance------------------------------------- //List<SegmentHL7> segments=message.GetSegments(SegmentName.IN1); //for(int i=0;i<segments.Count;i++) { // ProcessIN1(pat,seg); //} if (pat.FName == "" || pat.LName == "") { EventLog.WriteEntry("OpenDentHL7", "Patient demographics not processed due to missing first or last name. PatNum:" + pat.PatNum.ToString() , EventLogEntryType.Information); return; } if (isNewPat) { if (isVerboseLogging) { EventLog.WriteEntry("OpenDentHL7", "Inserted patient: " + pat.FName + " " + pat.LName, EventLogEntryType.Information); } pat.PatNum = Patients.Insert(pat, !isStandalone); //use existing PK if not standalone, standalone will have PatNum=0, so set PatNum here SecurityLogs.MakeLogEntry(Permissions.PatientCreate, pat.PatNum, "Created from HL7 for eCW.", LogSources.HL7); if (hasNoRaceInStandalone) { Patient patientRaceTemp = pat.Copy(); //Make a deep copy so that we do not accidentally override something. seg = message.GetSegment(SegmentNameHL7.PID, true); //We have to process the PID again in order to correct the patient race. Patient race(s) will automatically get inserted if needed. EcwSegmentPID.ProcessPID(patientRaceTemp, seg, isStandalone, listPatRaces); } if (pat.Guarantor == 0) { patOld = pat.Copy(); pat.Guarantor = pat.PatNum; Patients.Update(pat, patOld); } } else { if (isVerboseLogging) { EventLog.WriteEntry("OpenDentHL7", "Updated patient: " + pat.FName + " " + pat.LName, EventLogEntryType.Information); } Patients.Update(pat, patOld); } //had to move this reconcile here since we might not have a PatNum for new patients until after the insert PatientRaces.Reconcile(pat.PatNum, listPatRaces); }
///<summary>If relationship is self, this loop does nothing. A new pat will later change guarantor to be same as patnum. </summary> public static void ProcessGT1(Patient pat, SegmentHL7 seg, bool useChartNumber) { long guarNum = PIn.Long(seg.GetFieldFullText(2)); if (guarNum == 0) //because we have an example where they sent us this (position 2 is empty): GT1|1||^^||^^^^|||||||| { return; } if (seg.GetFieldFullText(11) == "1") //if relationship is self (according to some of their documentation) { return; } if (seg.GetFieldComponent(3, 0) == "" || //lname seg.GetFieldComponent(3, 1) == "") //fname { EventLog.WriteEntry("OpenDentHL7", "Guarantor not processed due to missing first or last name. PatNum of patient:" + pat.PatNum.ToString() , EventLogEntryType.Information); return; } Patient guar = null; Patient guarOld = null; //So guarantor is someone else if (useChartNumber) { //try to find guarantor by using chartNumber guar = Patients.GetPatByChartNumber(guarNum.ToString()); if (guar == null) { //try to find the guarantor by using name and birthdate string lName = seg.GetFieldComponent(3, 0); string fName = seg.GetFieldComponent(3, 1); DateTime birthdate = EcwSegmentPID.DateParse(seg.GetFieldFullText(8)); long guarNumByName = Patients.GetPatNumByNameAndBirthday(lName, fName, birthdate); if (guarNumByName == 0) //guarantor does not exist in OD //so guar will still be null, triggering creation of new guarantor further down. { } else { guar = Patients.GetPat(guarNumByName); guar.ChartNumber = guarNum.ToString(); //from now on, we will be able to find guar by chartNumber } } } else { guar = Patients.GetPat(guarNum); } //we can't necessarily set pat.Guarantor yet, because in Standalone mode, we might not know it yet. bool isNewGuar = guar == null; if (isNewGuar) //then we need to add guarantor to db { guar = new Patient(); if (useChartNumber) { guar.ChartNumber = guarNum.ToString(); } else { guar.PatNum = guarNum; } guar.PriProv = PrefC.GetLong(PrefName.PracticeDefaultProv); guar.BillingType = PrefC.GetLong(PrefName.PracticeDefaultBillType); } else { guarOld = guar.Copy(); } //guar.Guarantor=guarNum; guar.LName = seg.GetFieldComponent(3, 0); guar.FName = seg.GetFieldComponent(3, 1); guar.MiddleI = seg.GetFieldComponent(3, 2); guar.Address = seg.GetFieldComponent(5, 0); guar.Address2 = seg.GetFieldComponent(5, 1); guar.City = seg.GetFieldComponent(5, 2); guar.State = seg.GetFieldComponent(5, 3); guar.Zip = seg.GetFieldComponent(5, 4); guar.HmPhone = PhoneParse(seg.GetFieldFullText(6)); guar.WkPhone = PhoneParse(seg.GetFieldFullText(7)); guar.Birthdate = DateParse(seg.GetFieldFullText(8)); guar.Gender = GenderParse(seg.GetFieldFullText(9)); //11. Guarantor relationship to patient. We can't really do anything with this value guar.SSN = seg.GetFieldFullText(12); if (isNewGuar) { Patients.Insert(guar, !useChartNumber); //if using chartnumber (standalone mode), then can't insert using existing PK SecurityLogs.MakeLogEntry(Permissions.PatientCreate, guar.PatNum, "Created from HL7 for eCW.", LogSources.HL7); guarOld = guar.Copy(); guar.Guarantor = guar.PatNum; Patients.Update(guar, guarOld); } else { Patients.Update(guar, guarOld); } pat.Guarantor = guar.PatNum; }
///<summary>Most of the logic for breaking an appointment. Pass in the brokenFee (the number the user enters in the brokenAppointment window), ///Optionally pass in if the brokenappointment procedure is being deleted. Returns the broken procedure that was created.</summary> public static Procedure BreakAppointment(Appointment appt, Patient pat, ProcedureCode procCode, double feeOverride, bool isDeleteBrokenProc = false) { //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 == "D9986" || procCode.ProcCode == "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); } List <Procedure> listProcedures = Procedures.GetProcsForSingle(appt.AptNum, false); //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; if (listProcedures.Count > 0) { listSplitsForApptProcs = PaySplits.GetPaySplitsFromProcs(listProcedures.Select(x => x.ProcNum).ToList()); } Procedure brokenProcedure = new Procedure(); #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 { brokenProcedure.ProcFee = procFee; } if (!PrefC.GetBool(PrefName.EasyHidePublicHealth)) { brokenProcedure.SiteNum = pat.SiteNum; } Procedures.Insert(brokenProcedure); Procedure procOld = brokenProcedure.Copy(); //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); 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. //normally goes to the form to let the user speficy, this is the auto filled amount for the form. brokenProcedure.ProcFee = feeOverride; //listSplitsForApptProcs.Sum(x => x.SplitAmt); isNonRefundable = true; } if (isDeleteBrokenProc) { brokenProcedure.ProcStatus = ProcStat.D; } brokenProcedure.ProcFee = feeOverride; brokenProcAmount = feeOverride; Procedures.Update(brokenProcedure, procOld); } #endregion //Note this MUST come after FormProcBroken since clicking cancel in that window will delete the procedure. if (isNonRefundable && !isDeleteBrokenProc && 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); brokenProcAmount -= amt; } } } return(brokenProcedure); }