///<summary>Must be called after Preference cache has been filled. ///Deletes all signals older than 2 days if this has not been run within the last week. Will fail silently if anything goes wrong.</summary> public static void ClearOldSignals() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod()); return; } try { if (Prefs.GetContainsKey(PrefName.SignalLastClearedDate.ToString()) && PrefC.GetDateT(PrefName.SignalLastClearedDate) > MiscData.GetNowDateTime().AddDays(-7)) //Has already been run in the past week. This is all server based time. { return; //Do not run this process again. } string command = ""; if (DataConnection.DBtype == DatabaseType.MySql) //easier to read that using the DbHelper Functions and it also matches the ConvertDB3 script { command = "DELETE FROM signalod WHERE SigDateTime < DATE_ADD(NOW(),INTERVAL -2 DAY)"; //Itypes only older than 2 days Db.NonQ(command); } else //oracle { command = "DELETE FROM signalod WHERE SigDateTime < CURRENT_TIMESTAMP -2"; //Itypes only older than 2 days Db.NonQ(command); } SigMessages.ClearOldSigMessages(); //Clear messaging buttons which use to be stored in the signal table. //SigElements.DeleteOrphaned(); Prefs.UpdateDateT(PrefName.SignalLastClearedDate, MiscData.GetNowDateTime()); //Set Last cleared to now. } catch (Exception) { //fail silently } }
public static void RetrieveReportsAutomatic(bool isAllClinics) { List <long> listClinicNums = new List <long>(); if (isAllClinics) { listClinicNums = Clinics.GetDeepCopy(true).Select(x => x.ClinicNum).ToList(); } else { listClinicNums = new List <long> { Clinics.ClinicNum }; } string errMsg; bool isTimeToRetrieve = IsTimeToRetrieveReports(true, out errMsg); if (isTimeToRetrieve) { Prefs.UpdateDateT(PrefName.ClaimReportReceiveLastDateTime, DateTime.Now); } List <Clearinghouse> listClearinghousesHq = GetDeepCopy(); long defaultClearingHouseNum = PrefC.GetLong(PrefName.ClearinghouseDefaultDent); for (int i = 0; i < listClearinghousesHq.Count; i++) { Clearinghouse clearinghouseHq = listClearinghousesHq[i]; Clearinghouse clearinghouseClin; for (int j = 0; j < listClinicNums.Count; j++) { clearinghouseClin = OverrideFields(clearinghouseHq, listClinicNums[j]); RetrieveReportsAutomaticHelper(clearinghouseClin, clearinghouseHq, defaultClearingHouseNum, isTimeToRetrieve); } } }
///<summary></summary> public static string RetrieveAndImport(Clearinghouse clearinghouseClin, bool isAutomaticMode, IODProgressExtended progress = null , bool isTimeToRetrieve = false) { progress = progress ?? new ODProgressExtendedNull(); string errorMessage = ""; bool doRetrieveReports = isTimeToRetrieve || (!isAutomaticMode && IsTimeToRetrieveReports(isAutomaticMode, out errorMessage, progress)); if (doRetrieveReports) //Timer interval OK. Now we can retrieve the reports from web services. { if (!isAutomaticMode) { Prefs.UpdateDateT(PrefName.ClaimReportReceiveLastDateTime, DateTime.Now); } errorMessage = RetrieveReports(clearinghouseClin, isAutomaticMode, progress); if (errorMessage != "") { progress.UpdateProgress(Lans.g(progress.LanThis, "Error getting reports, attempting to import manually downloaded reports.")); } progress.UpdateProgress(Lans.g(progress.LanThis, "Report retrieval successful. Attempting to import.")); //Don't return yet even if there was an error. This is so that Open Dental will automatically import reports that have been manually //downloaded to the Reports folder. } if (isAutomaticMode && clearinghouseClin.ResponsePath.Trim() == "") { return(""); //The user opened FormClaimsSend, or FormOpenDental called this function automatically. } if (progress.IsPauseOrCancel()) { progress.UpdateProgress(Lans.g(progress.LanThis, "Canceled by user.")); return(errorMessage); } string importErrors = ImportReportFiles(clearinghouseClin, progress); if (!string.IsNullOrWhiteSpace(importErrors)) { if (string.IsNullOrWhiteSpace(errorMessage)) { errorMessage = importErrors; progress.UpdateProgress(Lans.g(progress.LanThis, "Error importing.")); } else { errorMessage += "\r\n" + importErrors; } } if (string.IsNullOrWhiteSpace(errorMessage) && string.IsNullOrWhiteSpace(importErrors)) { progress.UpdateProgress(Lans.g(progress.LanThis, "Import successful.")); } return(errorMessage); }
/// <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>Called by local practice db to query HQ for EService setup info. Must remain very lite and versionless. Will be used by signup portal. ///If HasClinics==true then any SignupOut.EServices entries where ClinicNum==0 are invalid and should be ignored. ///If HasClinics==false then SignupOut.EServices should only pay attention items where ClinicNum==0. ///This list is kept completely unfiltered by ClinicNum for forward compatibility reasons. ///The ClinicNum 0 items are always used by the Signup portal to determine default signup preferences. ///However, these items are only used for validation and billing in the case where HasClinics==true.</summary> public static EServiceSetup.SignupOut GetEServiceSetupFull(SignupPortalPermission permission, bool isSwitchClinicPref = false) { //Clinics will be stored in this order at HQ to allow signup portal to display them in proper order. List <Clinic> clinics = Clinics.GetDeepCopy().OrderBy(x => x.ItemOrder).ToList(); if (PrefC.GetBool(PrefName.ClinicListIsAlphabetical)) { clinics = clinics.OrderBy(x => x.Abbr).ToList(); } #if DEBUG bool isMockChanged = false; if (WebServiceMainHQProxy.MockWebServiceMainHQ == null) { WebServiceMainHQProxy.MockWebServiceMainHQ = new WebServiceMainHQMockDemo(); isMockChanged = true; } #endif EServiceSetup.SignupOut signupOut = ReadXml <EServiceSetup.SignupOut> ( WebSerializer.DeserializePrimitiveOrThrow <string> ( GetWebServiceMainHQInstance().EServiceSetup ( CreateWebServiceHQPayload ( WriteXml(new EServiceSetup.SignupIn() { MethodNameInt = (int)EServiceSetup.SetupMethod.GetSignupOutFull, HasClinics = PrefC.HasClinicsEnabled, //ClinicNum is not currently used as input. ClinicNum = 0, ProgramVersionStr = PrefC.GetString(PrefName.ProgramVersion), SignupPortalPermissionInt = (int)permission, Clinics = clinics .Select(x => new EServiceSetup.SignupIn.ClinicLiteIn() { ClinicNum = x.ClinicNum, ClinicTitle = x.Abbr, IsHidden = x.IsHidden, }).ToList(), IsSwitchClinicPref = isSwitchClinicPref, }), eServiceCode.Undefined ) ) ) ); #if DEBUG if (isMockChanged) { WebServiceMainHQProxy.MockWebServiceMainHQ = null; } #endif //We just got the latest sync info from HQ so update the local db to reflect what HQ says is true. #region Reconcile Phones List <SmsPhone> listPhonesHQ = signupOut.Phones.Select(x => new SmsPhone() { ClinicNum = x.ClinicNum, CountryCode = x.CountryCode, DateTimeActive = x.DateTimeActive, DateTimeInactive = x.DateTimeInactive, InactiveCode = x.InactiveCode, PhoneNumber = x.PhoneNumber, }).ToList(); SmsPhones.UpdateOrInsertFromList(listPhonesHQ); #endregion #region Reconcile practice and clinics List <EServiceSetup.SignupOut.SignupOutSms> smsSignups = GetSignups <EServiceSetup.SignupOut.SignupOutSms>(signupOut, eServiceCode.IntegratedTexting); bool isCacheInvalid = false; bool isSmsEnabled = false; if (PrefC.HasClinicsEnabled) //Clinics are ON so loop through all clinics and reconcile with HQ. { List <Clinic> listClinicsAll = Clinics.GetDeepCopy(); foreach (Clinic clinicDb in listClinicsAll) { WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms clinicSignup = smsSignups.FirstOrDefault(x => x.ClinicNum == clinicDb.ClinicNum) ?? new WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms() { //Not found so turn it off. SmsContractDate = DateTime.MinValue, MonthlySmsLimit = 0, IsEnabled = false, }; Clinic clinicNew = clinicDb.Copy(); clinicNew.SmsContractDate = clinicSignup.SmsContractDate; clinicNew.SmsMonthlyLimit = clinicSignup.MonthlySmsLimit; isCacheInvalid |= Clinics.Update(clinicNew, clinicDb); isSmsEnabled |= clinicSignup.IsEnabled; } } else //Clinics are off so ClinicNum 0 is the practice clinic. { WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms practiceSignup = smsSignups.FirstOrDefault(x => x.ClinicNum == 0) ?? new WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms() { //Not found so turn it off. SmsContractDate = DateTime.MinValue, MonthlySmsLimit = 0, IsEnabled = false, }; isCacheInvalid |= Prefs.UpdateDateT(PrefName.SmsContractDate, practiceSignup.SmsContractDate) | Prefs.UpdateLong(PrefName.TextingDefaultClinicNum, 0) | Prefs.UpdateDouble(PrefName.SmsMonthlyLimit, practiceSignup.MonthlySmsLimit); isSmsEnabled |= practiceSignup.IsEnabled; } #endregion #region Reconcile CallFire //Turn off CallFire if SMS has been activated. //This only happens the first time SMS is turned on and CallFire is still activated. if (isSmsEnabled && Programs.IsEnabled(ProgramName.CallFire)) { Program callfire = Programs.GetCur(ProgramName.CallFire); if (callfire != null) { callfire.Enabled = false; Programs.Update(callfire); Signalods.Insert(new Signalod() { IType = InvalidType.Providers }); signupOut.Prompts.Add("Call Fire has been disabled. Cancel Integrated Texting and access program properties to retain Call Fire."); } } #endregion #region eConfirmations if (Prefs.UpdateBool(PrefName.ApptConfirmAutoSignedUp, IsEServiceActive(signupOut, eServiceCode.ConfirmationRequest))) { //HQ does not match the local pref. Make it match with HQ. isCacheInvalid = true; SecurityLogs.MakeLogEntry(Permissions.Setup, 0, "Automated appointment eConfirmations automatically changed by HQ. Local pref set to " + IsEServiceActive(signupOut, eServiceCode.ConfirmationRequest).ToString() + "."); } #endregion if (isCacheInvalid) //Something changed in the db. Alert other workstations and change this workstation immediately. { Signalods.Insert(new Signalod() { IType = InvalidType.Prefs }); Prefs.RefreshCache(); Signalods.Insert(new Signalod() { IType = InvalidType.Providers }); Providers.RefreshCache(); Clinics.RefreshCache(); } return(signupOut); }
/// <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, ""); } }