///<summary>Inserts a new RepeatCharge if none found for patNum/procCode. Otherwise updates existing. ///If dateStart is not explicitly provided, then it will default to DateTime.Today. ///If RepeatCharge already exists then chargeAmt, dateStart, createsClaim, copyNoteToProc inputs will be ignored and RepeatCharge will simply be re-enabled. ///Use RepeatCharges.Update() if you want to specify new input values.</summary> public static void EnableRepeatCharge(long patNum, float chargeAmt, string procCode, DateTime dateStart = new DateTime(), bool createsClaim = false, bool copyNoteToProc = false) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), patNum, chargeAmt, procCode, dateStart, createsClaim, copyNoteToProc); return; } if (dateStart.Year < 1880) //Default to today if none provided. { dateStart = DateTime.Today; } RepeatCharge[] repeateCharges = RepeatCharges.Refresh(patNum); RepeatCharge repeatCharge = null; if (repeateCharges != null) { repeatCharge = repeateCharges.FirstOrDefault(x => x.ProcCode == procCode); } if (repeatCharge == null) { repeatCharge = new RepeatCharge(); repeatCharge.ProcCode = procCode; repeatCharge.PatNum = patNum; repeatCharge.IsEnabled = true; repeatCharge.DateStart = dateStart; repeatCharge.CreatesClaim = createsClaim; repeatCharge.CopyNoteToProc = copyNoteToProc; repeatCharge.ChargeAmt = chargeAmt; repeatCharge.RepeatChargeNum = RepeatCharges.Insert(repeatCharge); } repeatCharge.IsEnabled = true; repeatCharge.DateStop = System.DateTime.MinValue; RepeatCharges.Update(repeatCharge); }
///<summary>Should only be called if ODHQ.</summary> public static List <Procedure> AddEServiceRepeatingChargesHelper(DateTime dateRun, List <RepeatCharge> listRepeatCharges) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <Procedure> >(MethodBase.GetCurrentMethod(), dateRun, listRepeatCharges)); } DateTime monthRun = new DateTime(dateRun.Year, dateRun.Month, 1); //Get all bills that are due to be posted as of this date. string command = "SELECT * FROM eservicebilling " + "WHERE DateOfBill <= " + POut.Date(dateRun.Date, true) + " AND DateTimeProceduresPosted = '0001-01-01 00:00:00'"; List <EServiceBilling> listBillsDue = Crud.EServiceBillingCrud.SelectMany(command); //This table will all ProcedureCodes which are included in the EServiceCodeLink table. command = "SELECT * FROM procedurecode " + "INNER JOIN eservicecodelink ON procedurecode.CodeNum=eservicecodelink.CodeNum"; List <ProcedureCode> listProcCodes = OpenDentBusiness.Crud.ProcedureCodeCrud.TableToList(DataCore.GetTable(command)); //Get completed procedures that have already been posted. List <Procedure> listProcsComplete = Procedures.GetCompletedForDateRange(monthRun, dateRun, listProcCodes.Select(x => x.CodeNum).ToList()); List <Procedure> retVal = new List <Procedure>(); foreach (EServiceBilling eServiceBilling in listBillsDue) { //List of procedures for this billing cycle was serialized to EServiceBilling.ProceduresJson by AccountMaint thread. Deserialize and post them. List <Procedure> listProcs = JsonConvert.DeserializeObject <List <Procedure> >(eServiceBilling.ProceduresJson); foreach (Procedure proc in listProcs) { //For a short time in May 2017 this procedure would have been checked against procedures already posted for the same month for the same eService. //If a duplicate was found then this procedure would have been skipped. This blocking code was removed and now a similar procedure can be posted on the same month. //This needs to be allowed to happen so that the first month can have 2 charges. //1) For the pro-rated few days until their next BillingCycleDay is reached. // Note, pro-rating is a future feature that may be allowed to happen via the signup portal. It is not currently but this particular code would no longer prevent it. //2) For their typicaly BillingCycleDay charge. Procedures.Insert(proc); retVal.Add(proc); listProcsComplete.Add(proc); RepeatCharge repeatCharge = listRepeatCharges.Where(x => x.PatNum == proc.PatNum) .FirstOrDefault(x => x.ProcCode == ProcedureCodes.GetStringProcCode(proc.CodeNum, listProcCodes)); if (repeatCharge != null) { RepeatCharges.AllocateUnearned(repeatCharge, proc, dateRun); } } eServiceBilling.DateTimeProceduresPosted = DateTime.Now; Crud.EServiceBillingCrud.Update(eServiceBilling); } return(retVal); }
/// <summary>Runs repeating charges for the date passed in, usually today. Can't use 'out' variables because this runs over Middle Tier.</summary> public static RepeatChargeResult RunRepeatingCharges(DateTime dateRun) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <RepeatChargeResult>(MethodBase.GetCurrentMethod(), dateRun)); } Prefs.UpdateDateT(PrefName.RepeatingChargesBeginDateTime, dateRun); try { RepeatChargeResult result = new RepeatChargeResult(); List <RepeatCharge> listRepeatingCharges = RepeatCharges.Refresh(0).ToList(); if (PrefC.IsODHQ) { //Remove all eService repeating charges. //EService charges have already been calculated and stored in EServiceBilling table. Add those here. List <string> listEServiceCodes = EServiceCodeLink.GetProcCodesForAll(); listRepeatingCharges.RemoveAll(x => listEServiceCodes.Contains(x.ProcCode)); result.ProceduresAddedCount += EServiceBillings.AddEServiceRepeatingChargesHelper(dateRun).Count; } DateTime startedUsingFKs = UpdateHistories.GetDateForVersion(new Version("16.1.0.0")); //We started using FKs from procs to repeat charges in 16.1. foreach (RepeatCharge repeatCharge in listRepeatingCharges) { if (!repeatCharge.IsEnabled || (repeatCharge.DateStop.Year > 1880 && repeatCharge.DateStop.AddMonths(3) < dateRun)) { continue; //This repeating charge is too old to possibly create a new charge. Not precise but greatly reduces calls to DB. //We will filter by more stringently on the DateStop later on. } long codeNum = ProcedureCodes.GetCodeNum(repeatCharge.ProcCode); //Must contain all procedures that affect the date range. DateTime procRangeStart = repeatCharge.DateStart.AddMonths(-1); //Minus 1 month to catch accounts that have changed their billing date List <Procedure> listExistingProcs = Procedures.GetCompletedForDateRange(procRangeStart, dateRun, new List <long> { codeNum }, new List <long> { repeatCharge.PatNum }); for (int j = listExistingProcs.Count - 1; j >= 0; j--) //iterate backwards to remove elements { Procedure proc = listExistingProcs[j]; if (((proc.RepeatChargeNum == repeatCharge.RepeatChargeNum) //Check the procedure's FK first //Use the old logic without matching FKs only if the procedure was added before updating to 16.1 //Match patnum, codenum, fee, year, and month (IsRepeatDateHelper uses special logic to determine correct month) //Procedures with the ProcDate prior to the RepeatCharge.StartDate should not be considered as valid procedures //associated to the current repeat charge. || ((proc.ProcDate < startedUsingFKs || startedUsingFKs.Year < 1880) && proc.PatNum == repeatCharge.PatNum && proc.CodeNum == codeNum && proc.ProcFee.IsEqual(repeatCharge.ChargeAmt))) && (proc.ProcDate >= repeatCharge.DateStart || //Consider procedures that fall on or after the repeat charge start date. proc.ProcDate.Day != repeatCharge.DateStart.Day)) //Consider procs only when days are not the same. Catches procs that have changed their billing date { continue; //This existing procedure needs to be counted for this repeat charge. } listExistingProcs.RemoveAt(j); //Removing so that another repeat charge of the same code, date, and amount will be added. } List <DateTime> listBillingDates; //This list will have 1 or 2 dates where a repeating charge might be added if (PrefC.GetBool(PrefName.BillingUseBillingCycleDay)) { listBillingDates = GetBillingDatesHelper(repeatCharge.DateStart, repeatCharge.DateStop, dateRun, listExistingProcs, repeatCharge, Patients.GetPat(repeatCharge.PatNum).BillingCycleDay); } else { listBillingDates = GetBillingDatesHelper(repeatCharge.DateStart, repeatCharge.DateStop, dateRun, listExistingProcs, repeatCharge); } listBillingDates.RemoveAll(x => x.Date > DateTime.Today.Date && !PrefC.GetBool(PrefName.FutureTransDatesAllowed)); //If any billing dates have not been filtered out, add a repeating charge on those dates foreach (DateTime billingDate in listBillingDates) { Procedure procAdded = AddRepeatingChargeHelper(repeatCharge, billingDate, dateRun); List <Claim> listClaimsAdded = new List <Claim>(); if (repeatCharge.CreatesClaim && !ProcedureCodes.GetProcCode(repeatCharge.ProcCode).NoBillIns) { listClaimsAdded = AddClaimsHelper(repeatCharge, procAdded); } result.ProceduresAddedCount++; result.ClaimsAddedCount += listClaimsAdded.Count; } } return(result); } finally { Prefs.UpdateString(PrefName.RepeatingChargesBeginDateTime, ""); } }
/// <summary>Runs repeating charges for the date passed in, usually today. Can't use 'out' variables because this runs over Middle Tier.</summary> public static RepeatChargeResult RunRepeatingCharges(DateTime dateRun) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <RepeatChargeResult>(MethodBase.GetCurrentMethod(), dateRun)); } Prefs.UpdateDateT(PrefName.RepeatingChargesBeginDateTime, dateRun); try { RepeatChargeResult result = new RepeatChargeResult(); List <RepeatCharge> listRepeatingCharges = RepeatCharges.Refresh(0).ToList(); if (PrefC.IsODHQ) { //Remove all eService repeating charges. //EService charges have already been calculated and stored in EServiceBilling table. Add those here. List <string> listEServiceCodes = EServiceCodeLink.GetProcCodesForAll(); listRepeatingCharges.RemoveAll(x => listEServiceCodes.Contains(x.ProcCode)); result.ProceduresAddedCount += EServiceBillings.AddEServiceRepeatingChargesHelper(dateRun).Count; } //Must contain all procedures that affect the date range, safe to contain too many, bad to contain too few. List <Procedure> listExistingProcs = Procedures.GetCompletedForDateRange(dateRun.AddMonths(-3), dateRun.AddDays(1), listRepeatingCharges.Select(x => x.ProcCode).Distinct().Select(x => ProcedureCodes.GetProcCode(x).CodeNum).ToList()); DateTime startedUsingFKs = UpdateHistories.GetDateForVersion(new Version("16.1.0.0")); //We started using FKs from procs to repeat charges in 16.1. foreach (RepeatCharge repeatCharge in listRepeatingCharges) { if (!repeatCharge.IsEnabled || (repeatCharge.DateStop.Year > 1880 && repeatCharge.DateStop.AddMonths(3) < dateRun)) { continue; //This repeating charge is too old to possibly create a new charge. Not precise but greatly reduces calls to DB. //We will filter by more stringently on the DateStop later on. } Patient pat = null; List <DateTime> listBillingDates; //This list will have 1 or 2 dates where a repeating charge might be added if (PrefC.GetBool(PrefName.BillingUseBillingCycleDay)) { pat = Patients.GetPat(repeatCharge.PatNum); listBillingDates = GetBillingDatesHelper(repeatCharge.DateStart, repeatCharge.DateStop, dateRun, pat.BillingCycleDay); } else { listBillingDates = GetBillingDatesHelper(repeatCharge.DateStart, repeatCharge.DateStop, dateRun); } long codeNum = ProcedureCodes.GetCodeNum(repeatCharge.ProcCode); //Remove billing dates if there is a procedure from this repeat charge in that month and year for (int i = listBillingDates.Count - 1; i >= 0; i--) //iterate backwards to remove elements { DateTime billingDate = listBillingDates[i]; for (int j = listExistingProcs.Count - 1; j >= 0; j--) //iterate backwards to remove elements { Procedure proc = listExistingProcs[j]; if ((proc.RepeatChargeNum == repeatCharge.RepeatChargeNum && //Check the procedure's FK first IsRepeatDateHelper(repeatCharge, billingDate, proc.ProcDate, pat)) //Use the old logic without matching FKs only if the procedure was added before updating to 16.1 //Match patnum, codenum, fee, year, and month (IsRepeatDateHelper uses special logic to determine correct month) || ((proc.ProcDate < startedUsingFKs || startedUsingFKs.Year < 1880) && proc.PatNum == repeatCharge.PatNum && proc.CodeNum == codeNum && IsRepeatDateHelper(repeatCharge, billingDate, proc.ProcDate, pat) && proc.ProcFee.IsEqual(repeatCharge.ChargeAmt))) { //This is a match to an existing procedure. listBillingDates.RemoveAt(i); //Removing so that a procedure will not get added on this date. listExistingProcs.RemoveAt(j); //Removing so that another repeat charge of the same code, date, and amount will be added. break; //Go to the next billing date } } } //If any billing dates have not been filtered out, add a repeating charge on those dates foreach (DateTime billingDate in listBillingDates) { Procedure procAdded = AddRepeatingChargeHelper(repeatCharge, billingDate, dateRun); List <Claim> listClaimsAdded = new List <Claim>(); if (repeatCharge.CreatesClaim && !ProcedureCodes.GetProcCode(repeatCharge.ProcCode).NoBillIns) { listClaimsAdded = AddClaimsHelper(repeatCharge, procAdded); } result.ProceduresAddedCount++; result.ClaimsAddedCount += listClaimsAdded.Count; } } return(result); } finally { Prefs.UpdateString(PrefName.RepeatingChargesBeginDateTime, ""); } }