/// <summary>Helper method to send given appt to the unscheduled list. /// Creates SecurityLogs and considers HL7.</summary> public static void SetApptUnschedHelper(Appointment appt, Patient pat = null, bool doFireApptEvent = true) { DateTime datePrevious = appt.DateTStamp; Appointments.SetAptStatus(appt, ApptStatus.UnschedList); //Appointments S-Class handles Signalods #region SecurityLogs if (appt.AptStatus != ApptStatus.Complete) //seperate log entry for editing completed appts. { SecurityLogs.MakeLogEntry(Permissions.AppointmentMove, appt.PatNum, appt.ProcDescript + ", " + appt.AptDateTime.ToString() + ", Sent to Unscheduled List", appt.AptNum, datePrevious); } else { SecurityLogs.MakeLogEntry(Permissions.AppointmentCompleteEdit, appt.PatNum, appt.ProcDescript + ", " + appt.AptDateTime.ToString() + ", Sent to Unscheduled List", appt.AptNum, datePrevious); } #endregion #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()) { if (pat == null) { pat = Patients.GetPat(appt.PatNum); } //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 if (doFireApptEvent) { AppointmentEvent.Fire(ODEventType.AppointmentEdited, appt); } Recalls.SynchScheduledApptFull(appt.PatNum); }
///<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); }