///<summary>Resets the descriptions for all ADA codes to the official wording. Required by the license.</summary> public static int ResetADAdescriptions(List <ProcedureCode> codeList) { //No need to check RemotingRole; no call to db. ProcedureCode code; int count = 0; for (int i = 0; i < codeList.Count; i++) { if (!ProcedureCodes.IsValidCode(codeList[i].ProcCode)) //If this code is not in this database { continue; } code = ProcedureCodes.GetProcCode(codeList[i].ProcCode); if (code.Descript == codeList[i].Descript) { continue; } string oldDescript = code.Descript; DateTime datePrevious = code.DateTStamp; code.Descript = codeList[i].Descript; ProcedureCodes.Update(code); SecurityLogs.MakeLogEntry(Permissions.ProcCodeEdit, 0, "Code " + code.ProcCode + " changed from '" + oldDescript + "' to '" + code.Descript + "' by D-Codes Tool." , code.CodeNum, datePrevious); count++; } return(count); //don't forget to refresh procedurecodes. }
///<summary>schedI is the currently displayed index of the fee schedule to save to. If an amt of -1 is passed in, then it indicates a "blank" entry which will cause deletion of any existing fee.</summary> public static void Import(string codeText, double amt, long feeSchedNum) { //No need to check RemotingRole; no call to db. if (!ProcedureCodes.IsValidCode(codeText)) { return; //skip for now. Possibly insert a code in a future version. } long feeNum = GetFeeNum(ProcedureCodes.GetCodeNum(codeText), feeSchedNum); if (feeNum > 0) { Delete(feeNum); } if (amt == -1) { //RefreshCache(); return; } Fee fee = new Fee(); fee.Amount = amt; fee.FeeSched = feeSchedNum; fee.CodeNum = ProcedureCodes.GetCodeNum(codeText); Insert(fee); //RefreshCache();//moved this outside the loop }
///<summary>Compares two procedures and returns the order they should appear based on status, priority, toothrange, toothnum, then proccode. ///Uses the same logic as the other CompareProcedures but takes Procedure objects instead of DataRows. ///Only used for the Appointment Edit window currently.</summary> public static int CompareProcedures(Procedure x, Procedure y) { //first by status if (x.ProcStatus != y.ProcStatus) { //Cn,TP,R,EO,C,EC,D //EC procs will draw on top of C procs of same date in the 3D tooth chart, //but this is not a problem since C procs should always have a later date than EC procs. //EC must come after C so that group notes will come after their procedures in Progress Notes. int xIdx, yIdx; List <ProcStat> sortOrder = new List <ProcStat> { //The order of statuses in this list is very important and determines the sort order for procedures. ProcStat.TPi, ProcStat.Cn, ProcStat.TP, ProcStat.R, ProcStat.EO, ProcStat.C, ProcStat.EC, ProcStat.D }; xIdx = sortOrder.IndexOf(x.ProcStatus); yIdx = sortOrder.IndexOf(y.ProcStatus); return(xIdx.CompareTo(yIdx)); } //by priority if (x.Priority != y.Priority) //if priorities are different { if (x.Priority == 0) { return(1); //x is greater than y. Priorities always come first. } if (y.Priority == 0) { return(-1); //x is less than y. Priorities always come first. } return(Defs.GetOrder(DefCat.TxPriorities, x.Priority).CompareTo(Defs.GetOrder(DefCat.TxPriorities, y.Priority))); } //priorities are the same, so sort by toothrange if (x.ToothRange != y.ToothRange) { //empty toothranges come before filled toothrange values return(x.ToothRange.CompareTo(y.ToothRange)); } //toothranges are the same (usually empty), so compare toothnumbers if (x.ToothNum != y.ToothNum) { //this also puts invalid or empty toothnumbers before the others. return(Tooth.ToInt(x.ToothNum).CompareTo(Tooth.ToInt(y.ToothNum))); } //priority and toothnums are the same, so sort by proccode. if (x.CodeNum != y.CodeNum) { return(ProcedureCodes.GetProcCode(x.CodeNum).ProcCode.CompareTo(ProcedureCodes.GetProcCode(y.CodeNum).ProcCode)); } //if everything else is the same, sort by ProcNum so sort is deterministic return(x.ProcNum.CompareTo(y.ProcNum)); }
private string ToStringHelper(bool isLeadingIncluded = false) { //return base.ToString(); string retVal = ""; retVal += BenefitType.ToString(); //EB01: Eligibility or benefit information. Required if (CoverageLevel != BenefitCoverageLevel.None) { retVal += ", " + CoverageLevel.ToString(); //EB02: Coverage level code. Situational } EbenefitCategory ebenCat = CovCats.GetEbenCat(CovCatNum); if (ebenCat != EbenefitCategory.None) { retVal += ", " + ebenCat.ToString(); //EB03: Service type code. Situational } //EB04: Insurance type code. Situational. Not a Benefit field. We treat it as plan level. //EB05: Plan coverage description. Situational. Not a Benefit field. We treat it as plan level. if (TimePeriod != BenefitTimePeriod.None) { retVal += ", " + TimePeriod.ToString(); //EB06: Time period qualifier. Situational } if (MonetaryAmt != -1) { retVal += ", " + MonetaryAmt.ToString("c"); //EB07: Monetary amount. Situational } if (Percent != -1) { string leadingStr = ""; if (isLeadingIncluded) { leadingStr = "Insurance Pays "; } retVal += ", " + leadingStr + Percent.ToString() + "%"; //EB08: Percent. Situational } if (QuantityQualifier != BenefitQuantity.None) { retVal += ", " + QuantityQualifier.ToString(); //EB09: Quantity qualifier. Situational } if (Quantity != 0) { retVal += ", " + Quantity.ToString(); //EB10: Quantity. Situational } //EB11: Authorization Required. Situational. Not a Benefit field. //EB12: In plan network. Situational. Not a Benefit field. //EB13: Procedure identifier. Situational. We don't import this from EB, but we can show it anyway. if (CodeNum != 0) { ProcedureCode proccode = ProcedureCodes.GetProcCode(CodeNum); retVal += ", " + proccode.ProcCode + " - " + proccode.AbbrDesc; } return(retVal); }
///<summary>Adds procedures to the appointment.</summary> ///<returns>First item of tuple is the newly added procedures. Second item is all procedures for the appointment.</returns> public static ODTuple <List <Procedure>, List <Procedure> > QuickAddProcs(Appointment apt, Patient pat, List <string> listCodesToAdd, long provNum, long provHyg, List <InsSub> SubList, List <InsPlan> listInsPlans, List <PatPlan> listPatPlans, List <Benefit> listBenefits) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <ODTuple <List <Procedure>, List <Procedure> > >(MethodBase.GetCurrentMethod(), apt, pat, listCodesToAdd, provNum, provHyg, SubList, listInsPlans, listPatPlans, listBenefits)); } Procedures.SetDateFirstVisit(apt.AptDateTime.Date, 1, pat); List <ClaimProc> ClaimProcList = ClaimProcs.Refresh(apt.PatNum); List <Procedure> listAddedProcs = new List <Procedure>(); foreach (string code in listCodesToAdd) { Procedure proc = new Procedure(); proc.PatNum = apt.PatNum; ProcedureCode procCodeCur = ProcedureCodes.GetProcCode(code); proc.CodeNum = procCodeCur.CodeNum; proc.ProcDate = apt.AptDateTime.Date; proc.DateTP = DateTime.Today; #region ProvNum proc.ProvNum = provNum; if (procCodeCur.ProvNumDefault != 0) //Override provider for procedures with a default provider //This provider might be restricted to a different clinic than this user. { proc.ProvNum = procCodeCur.ProvNumDefault; } else if (procCodeCur.IsHygiene && provHyg != 0) { proc.ProvNum = provHyg; } #endregion ProvNum proc.ClinicNum = apt.ClinicNum; proc.MedicalCode = procCodeCur.MedicalCode; proc.ProcFee = Procedures.GetProcFee(pat, listPatPlans, SubList, listInsPlans, proc.CodeNum, proc.ProvNum, proc.ClinicNum, proc.MedicalCode); proc.ProcStatus = ProcStat.TP; proc.SiteNum = pat.SiteNum; proc.RevCode = procCodeCur.RevenueCodeDefault; proc.BaseUnits = procCodeCur.BaseUnits; proc.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs); proc.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService); //Default Proc Place of Service for the Practice is used. if (Userods.IsUserCpoe(Security.CurUser)) { //This procedure is considered CPOE because the provider is the one that has added it. proc.IsCpoe = true; } proc.Note = ProcCodeNotes.GetNote(proc.ProvNum, proc.CodeNum, proc.ProcStatus); Procedures.Insert(proc); //recall synch not required Procedures.ComputeEstimates(proc, pat.PatNum, ClaimProcList, false, listInsPlans, listPatPlans, listBenefits, pat.Age, SubList); listAddedProcs.Add(proc); } return(new ODTuple <List <Procedure>, List <Procedure> >(listAddedProcs, Procedures.GetProcsForApptEdit(apt))); }
///<summary>Adds procedures to the appointment.</summary> ///<returns>First item of tuple is the newly added procedures. Second item is all procedures for the appointment.</returns> public static ODTuple <List <Procedure>, List <Procedure> > QuickAddProcs(Appointment apt, Patient pat, List <string> listProcCodesToAdd, long provNum, long provHyg, List <InsSub> SubList, List <InsPlan> listInsPlans, List <PatPlan> listPatPlans, List <Benefit> listBenefits) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <ODTuple <List <Procedure>, List <Procedure> > >(MethodBase.GetCurrentMethod(), apt, pat, listProcCodesToAdd, provNum, provHyg, SubList, listInsPlans, listPatPlans, listBenefits)); } Procedures.SetDateFirstVisit(apt.AptDateTime.Date, 1, pat); List <ClaimProc> ClaimProcList = ClaimProcs.Refresh(apt.PatNum); List <ProcedureCode> listProcedureCodes = new List <ProcedureCode>(); foreach (string procCode in listProcCodesToAdd) { listProcedureCodes.Add(ProcedureCodes.GetProcCode(procCode)); } List <long> listProvNumsTreat = new List <long>(); listProvNumsTreat.Add(provNum); listProvNumsTreat.Add(provHyg); //these were both passed in List <SubstitutionLink> listSubstLinks = SubstitutionLinks.GetAllForPlans(listInsPlans); //not available in FormApptEdit List <Fee> listFees = Fees.GetListFromObjects(listProcedureCodes, null, //no procs to pull medicalCodes from listProvNumsTreat, pat.PriProv, pat.SecProv, pat.FeeSched, listInsPlans, new List <long>() { apt.ClinicNum }, null, //procNums for appt already handled above listSubstLinks, pat.DiscountPlanNum); //null,listProvNumsTreat,listProcedureCodes.Select(x=>x.ProvNumDefault).ToList(), //pat.PriProv,pat.SecProv,pat.FeeSched,listInsPlans,new List<long>(){apt.ClinicNum},listProcCodesToAdd,null);//procnums for appt already handled above List <Procedure> listAddedProcs = new List <Procedure>(); //Make a copy of apt with provNum and provHyg, in order to maintain behavior of this method prior to using Procedures.ConstructProcedureForAppt //provNum and provHyg are sent in and are the selected provs in FormApptEdit, which may be different than the current provs on apt Appointment aptCur = apt.Copy(); aptCur.ProvNum = provNum; aptCur.ProvHyg = provHyg; foreach (string procCode in listProcCodesToAdd) { ProcedureCode procCodeCur = ProcedureCodes.GetProcCode(procCode); Procedure proc = Procedures.ConstructProcedureForAppt(procCodeCur.CodeNum, aptCur, pat, listPatPlans, listInsPlans, SubList, listFees); Procedures.Insert(proc); //recall synch not required Procedures.ComputeEstimates(proc, pat.PatNum, ref ClaimProcList, true, listInsPlans, listPatPlans, listBenefits, null, null, true, pat.Age, SubList, null, false, false, listSubstLinks, false, listFees); listAddedProcs.Add(proc); } return(new ODTuple <List <Procedure>, List <Procedure> >(listAddedProcs, Procedures.GetProcsForApptEdit(apt))); }
///<summary>Gets a list of procedureCodes from the cache using a comma-delimited list of ProcCodes. ///Returns a new list is the passed in string is empty.</summary> public static List <ProcedureCode> GetFromCommaDelimitedList(string codeStr) { List <ProcedureCode> retVal = new List <ProcedureCode>(); if (String.IsNullOrEmpty(codeStr)) { return(retVal); } string[] arrayProcCodes = codeStr.Split(new char[] { ',' }); foreach (string code in arrayProcCodes) { retVal.Add(ProcedureCodes.GetProcCode(code)); } return(retVal); }
///<summary>Returns a distinct list of valid ProcCodes for the given eBenefitCat.</summary> public static List <string> GetValidCodesForEbenCat(EbenefitCategory eBenefitCat) { //No need to check RemotingRole; no call to db. List <string> listValidStrings = new List <string>(); List <CovCat> listCovCats = CovCats.GetWhere(x => x.EbenefitCat == eBenefitCat, true); foreach (CovCat covCat in listCovCats) { CovSpan[] arrayCovSpans = CovSpans.GetForCat(covCat.CovCatNum); listValidStrings.AddRange( ProcedureCodes.GetWhere(x => CovSpans.IsCodeInSpans(x.ProcCode, arrayCovSpans), true).Select(x => x.ProcCode).ToList() ); } return(listValidStrings.Distinct().ToList()); }
///<summary>Construct a payplanproductionentry item for a procedure. Calculates pat portion.</summary> public PayPlanProductionEntry(Procedure proc, PayPlanLink credit, List <ClaimProc> listClaimProcs, List <Adjustment> listAdjustments) { ProductionTag = proc; LinkedCredit = credit; ProductionDate = proc.ProcDate; PriKey = proc.ProcNum; ProvNum = proc.ProvNum; ClinicNum = proc.ClinicNum; PatNum = proc.PatNum; AmountOriginal = ClaimProcs.GetPatPortion(proc, listClaimProcs, listAdjustments); AmountOverride = (decimal)credit.AmountOverride; AmountRemaining = (AmountOverride == 0)?AmountOriginal:AmountOverride; CreditDate = credit.SecDateTEntry; Description = $"{ProcedureCodes.GetStringProcCode(proc.CodeNum)} - {ProcedureCodes.GetLaymanTerm(proc.CodeNum)}"; LinkType = PayPlanLinkType.Procedure; }
///<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>Gets the note for the given provider, if one exists. Otherwise, gets the proccode.defaultnote.</summary> public static string GetNote(long provNum, long codeNum) { //No need to check RemotingRole; no call to db. for (int i = 0; i < Listt.Count; i++) { if (Listt[i].ProvNum != provNum) { continue; } if (Listt[i].CodeNum != codeNum) { continue; } return(Listt[i].Note); } return(ProcedureCodes.GetProcCode(codeNum).DefaultNote); }
///<summary>Returns true if the procedure has a substitution code for the give tooth and InsPlans.</summary> public static bool HasSubstCodeForProcCode(ProcedureCode procCode, string toothNum, List <SubstitutionLink> listSubLinks, List <InsPlan> listPatInsPlans) { //No need to check RemotingRole; no call to db. foreach (InsPlan plan in listPatInsPlans) { //Check to see if any allow substitutions. if (HasSubstCodeForPlan(plan, procCode.CodeNum, listSubLinks)) { long subCodeNum = ProcedureCodes.GetSubstituteCodeNum(procCode.ProcCode, toothNum, plan.PlanNum, listSubLinks); //for posterior composites if (procCode.CodeNum != subCodeNum && subCodeNum > 0) { return(true); } } } return(false); }
///<summary>Returns the time pattern for the specified appointment type (time pattern returned will always be in 5 min increments). ///If the Pattern variable is not set on the appointment type object then the pattern will be dynamically calculated. ///Optionally pass in provider information in order to use specific provider time patterns.</summary> public static string GetTimePatternForAppointmentType(AppointmentType appointmentType, long provNumDentist = 0, long provNumHyg = 0) { //No need to check RemotingRole; no call to db. string timePattern = ""; if (string.IsNullOrEmpty(appointmentType.Pattern)) { //Dynamically calculate the timePattern from the procedure codes associated to the appointment type passed in. List <string> listProcCodeStrings = appointmentType.CodeStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); List <ProcedureCode> listProcCodes = ProcedureCodes.GetProcCodes(listProcCodeStrings); timePattern = OpenDentBusiness.Appointments.CalculatePattern(provNumDentist, provNumHyg, listProcCodes.Select(x => x.CodeNum).ToList(), true); } else { timePattern = appointmentType.Pattern; //Already in 5 minute increment so no conversion required. } return(timePattern); }
///<summary>Pass in list of procedures and covCat, return the sum of all CanadaTimeUnits of the procedures in that covCat as a double.</summary> public static double GetAmtUsedForCat(List <Procedure> listProcs, CovCat covCat) { List <ProcedureCode> listProcCodes = new List <ProcedureCode>(); for (int i = 0; i < listProcs.Count; i++) { listProcCodes.Add(ProcedureCodes.GetProcCode(listProcs[i].CodeNum)); //turn list of procedures into list of procedurecodes. } double total = 0; //CanadaTimeUnits can be decimal numbers, like 0.5. for (int i = 0; i < listProcCodes.Count; i++) //for every procedurecode { List <CovCat> listCovCatsForProc = GetCovCats(CovSpans.GetCats(listProcCodes[i].ProcCode)); if (listCovCatsForProc.Any(x => x.CovCatNum == covCat.CovCatNum)) { total += listProcCodes[i].CanadaTimeUnits; //add the Canada time units to the total. } } return(total); }
///<summary>This method will remove and/or add a fee for the fee information passed in. ///codeText will typically be one valid procedure code. E.g. D1240 ///If an amt of -1 is passed in, then it indicates a "blank" entry which will cause deletion of any existing fee. ///Returns listFees back after importing the passed in fee information. ///Does not make any database calls. This is left up to the user to take action on the list of fees returned. ///Also, makes security log entries based on how the fee changed. Does not make a log for codes that were removed (user already warned)</summary> public static List <Fee> Import(string codeText, double amt, long feeSchedNum, long clinicNum, long provNum, List <Fee> listFees) { //No need to check RemotingRole; no call to db. if (!ProcedureCodes.IsValidCode(codeText)) { return(listFees); //skip for now. Possibly insert a code in a future version. } string feeOldStr = ""; long codeNum = ProcedureCodes.GetCodeNum(codeText); Fee fee = listFees.FirstOrDefault(x => x.CodeNum == codeNum && x.FeeSched == feeSchedNum && x.ClinicNum == clinicNum && x.ProvNum == provNum); DateTime datePrevious = DateTime.MinValue; if (fee != null) { feeOldStr = Lans.g("FormFeeSchedTools", "Old Fee") + ": " + fee.Amount.ToString("c") + ", "; datePrevious = fee.SecDateTEdit; listFees.Remove(fee); } if (amt == -1) { return(listFees); } fee = new Fee(); fee.Amount = amt; fee.FeeSched = feeSchedNum; fee.CodeNum = ProcedureCodes.GetCodeNum(codeText); fee.ClinicNum = clinicNum; //Either 0 because you're importing on an HQ schedule or local clinic because the feesched is localizable. fee.ProvNum = provNum; listFees.Add(fee); //Insert new fee specific to the active clinic. SecurityLogs.MakeLogEntry(Permissions.ProcFeeEdit, 0, Lans.g("FormFeeSchedTools", "Procedure") + ": " + codeText + ", " + feeOldStr + Lans.g("FormFeeSchedTools", "New Fee") + ": " + amt.ToString("c") + ", " + Lans.g("FormFeeSchedTools", "Fee Schedule") + ": " + FeeScheds.GetDescription(feeSchedNum) + ". " + Lans.g("FormFeeSchedTools", "Fee changed using the Import button in the Fee Tools window."), ProcedureCodes.GetCodeNum(codeText), DateTime.MinValue); SecurityLogs.MakeLogEntry(Permissions.LogFeeEdit, 0, "Fee changed", fee.FeeNum, datePrevious); return(listFees); }
///<summary>Resets the descriptions for all ADA codes to the official wording. Required by the license.</summary> public static int ResetADAdescriptions(List <ProcedureCode> codeList) { //No need to check RemotingRole; no call to db. ProcedureCode code; int count = 0; for (int i = 0; i < codeList.Count; i++) { if (!ProcedureCodes.IsValidCode(codeList[i].ProcCode)) //If this code is not in this database { continue; } code = ProcedureCodes.GetProcCode(codeList[i].ProcCode); if (code.Descript == codeList[i].Descript) { continue; } code.Descript = codeList[i].Descript; ProcedureCodes.Update(code); count++; } return(count); //don't forget to refresh procedurecodes. }
///<summary>only if ClientWeb</summary> public static void FillCache(DataSet ds, params InvalidType[] arrayITypes) { List <InvalidType> listITypes = arrayITypes.ToList(); bool isAll = false; if (listITypes.Contains(InvalidType.AllLocal)) { isAll = true; } //All Internal OD Tables that are cached go here if (PrefC.IsODHQ) { if (listITypes.Contains(InvalidType.JobPermission) || isAll) { ds.Tables.Add(JobPermissions.RefreshCache()); } if (listITypes.Contains(InvalidType.PhoneComps) || isAll) { PhoneComps.FillCacheFromTable(ds.Tables["PhoneComp"]); } } if (listITypes.Contains(InvalidType.AccountingAutoPays) || isAll) { AccountingAutoPays.FillCacheFromTable(ds.Tables["AccountingAutoPay"]); } //if(listITypes.Contains(InvalidType.AlertItems) || isAll) {//THIS IS NOT CACHED. But is used to make server run the alert logic in OpenDentalService. // AlertSubs.FillCache(ds.Tables["AlertItem"]); //} if (listITypes.Contains(InvalidType.AlertCategories) || isAll) { AlertCategories.FillCacheFromTable(ds.Tables["AlertCategory"]); } if (listITypes.Contains(InvalidType.AlertCategoryLinks) || isAll) { AlertCategoryLinks.FillCacheFromTable(ds.Tables["AlertCategoryLink"]); } if (listITypes.Contains(InvalidType.AppointmentTypes) || isAll) { AppointmentTypes.FillCacheFromTable(ds.Tables["AppointmentType"]); } if (listITypes.Contains(InvalidType.AutoCodes) || isAll) { AutoCodes.FillCacheFromTable(ds.Tables["AutoCode"]); AutoCodeItems.FillCacheFromTable(ds.Tables["AutoCodeItem"]); AutoCodeConds.FillCacheFromTable(ds.Tables["AutoCodeCond"]); } if (listITypes.Contains(InvalidType.Automation) || isAll) { Automations.FillCacheFromTable(ds.Tables["Automation"]); } if (listITypes.Contains(InvalidType.AutoNotes) || isAll) { AutoNotes.FillCacheFromTable(ds.Tables["AutoNote"]); AutoNoteControls.FillCacheFromTable(ds.Tables["AutoNoteControl"]); } if (listITypes.Contains(InvalidType.Carriers) || isAll) { Carriers.FillCacheFromTable(ds.Tables["Carrier"]); //run on startup, after telephone reformat, after list edit. } if (listITypes.Contains(InvalidType.ClaimForms) || isAll) { ClaimFormItems.FillCacheFromTable(ds.Tables["ClaimFormItem"]); ClaimForms.FillCacheFromTable(ds.Tables["ClaimForm"]); } if (listITypes.Contains(InvalidType.ClearHouses) || isAll) { Clearinghouses.FillCacheFromTable(ds.Tables["Clearinghouse"]); } if (listITypes.Contains(InvalidType.ClinicErxs) || isAll) { ClinicErxs.FillCacheFromTable(ds.Tables["ClinicErx"]); } if (listITypes.Contains(InvalidType.ClinicPrefs) || isAll) { ClinicPrefs.FillCacheFromTable(ds.Tables["ClinicPref"]); } if (listITypes.Contains(InvalidType.Computers) || isAll) { Computers.FillCacheFromTable(ds.Tables["Computer"]); Printers.FillCacheFromTable(ds.Tables["Printer"]); } if (listITypes.Contains(InvalidType.Defs) || isAll) { Defs.FillCacheFromTable(ds.Tables["Def"]); } if (listITypes.Contains(InvalidType.DentalSchools) || isAll) { SchoolClasses.FillCacheFromTable(ds.Tables["SchoolClass"]); SchoolCourses.FillCacheFromTable(ds.Tables["SchoolCourse"]); } if (listITypes.Contains(InvalidType.DictCustoms) || isAll) { DictCustoms.FillCacheFromTable(ds.Tables["DictCustom"]); } if (listITypes.Contains(InvalidType.Diseases) || isAll) { DiseaseDefs.FillCacheFromTable(ds.Tables["DiseaseDef"]); ICD9s.FillCacheFromTable(ds.Tables["ICD9"]); } if (listITypes.Contains(InvalidType.DisplayFields) || isAll) { DisplayFields.FillCacheFromTable(ds.Tables["DisplayField"]); } if (listITypes.Contains(InvalidType.DisplayReports) || isAll) { DisplayReports.FillCacheFromTable(ds.Tables["DisplayReport"]); } if (listITypes.Contains(InvalidType.Ebills) || isAll) { Ebills.FillCacheFromTable(ds.Tables["Ebill"]); } if (listITypes.Contains(InvalidType.ElectIDs) || isAll) { ElectIDs.FillCacheFromTable(ds.Tables["ElectID"]); } if (listITypes.Contains(InvalidType.Email) || isAll) { EmailAddresses.FillCacheFromTable(ds.Tables["EmailAddress"]); EmailTemplates.FillCacheFromTable(ds.Tables["EmailTemplate"]); } if (listITypes.Contains(InvalidType.Employees) || isAll) { Employees.FillCacheFromTable(ds.Tables["Employee"]); PayPeriods.FillCacheFromTable(ds.Tables["PayPeriod"]); } if (listITypes.Contains(InvalidType.Employers) || isAll) { Employers.FillCacheFromTable(ds.Tables["Employer"]); } if (listITypes.Contains(InvalidType.Fees) || isAll) { Fees.FillCacheFromTable(ds.Tables["Fee"]); } if (listITypes.Contains(InvalidType.FeeScheds) || isAll) { FeeScheds.FillCacheFromTable(ds.Tables["FeeSched"]); } if (listITypes.Contains(InvalidType.HL7Defs) || isAll) { HL7Defs.FillCacheFromTable(ds.Tables["HL7Def"]); HL7DefMessages.FillCacheFromTable(ds.Tables["HL7DefMessage"]); HL7DefSegments.FillCacheFromTable(ds.Tables["HL7DefSegment"]); HL7DefFields.FillCacheFromTable(ds.Tables["HL7DefField"]); } if (listITypes.Contains(InvalidType.InsCats) || isAll) { CovCats.FillCacheFromTable(ds.Tables["CovCat"]); CovSpans.FillCacheFromTable(ds.Tables["CovSpan"]); } if (listITypes.Contains(InvalidType.InsFilingCodes) || isAll) { InsFilingCodes.FillCacheFromTable(ds.Tables["InsFilingCode"]); InsFilingCodeSubtypes.FillCacheFromTable(ds.Tables["InsFilingCodeSubtype"]); } if (listITypes.Contains(InvalidType.Languages) || isAll) { Lans.FillCacheFromTable(ds.Tables["Language"]); } if (listITypes.Contains(InvalidType.Letters) || isAll) { Letters.FillCacheFromTable(ds.Tables["Letter"]); } if (listITypes.Contains(InvalidType.LetterMerge) || isAll) { LetterMergeFields.FillCacheFromTable(ds.Tables["LetterMergeField"]); LetterMerges.FillCacheFromTable(ds.Tables["LetterMerge"]); } if (listITypes.Contains(InvalidType.Medications) || isAll) { Medications.FillCacheFromTable(ds.Tables["Medication"]); } if (listITypes.Contains(InvalidType.Operatories) || isAll) { Operatories.FillCacheFromTable(ds.Tables["Operatory"]); } if (listITypes.Contains(InvalidType.OrthoChartTabs) || isAll) { OrthoChartTabs.FillCacheFromTable(ds.Tables["OrthoChartTab"]); OrthoChartTabLinks.FillCacheFromTable(ds.Tables["OrthoChartTabLink"]); } if (listITypes.Contains(InvalidType.PatFields) || isAll) { PatFieldDefs.FillCacheFromTable(ds.Tables["PatFieldDef"]); ApptFieldDefs.FillCacheFromTable(ds.Tables["ApptFieldDef"]); } if (listITypes.Contains(InvalidType.Pharmacies) || isAll) { Pharmacies.FillCacheFromTable(ds.Tables["Pharmacy"]); } if (listITypes.Contains(InvalidType.Prefs) || isAll) { Prefs.FillCacheFromTable(ds.Tables["Pref"]); } if (listITypes.Contains(InvalidType.ProcButtons) || isAll) { ProcButtons.FillCacheFromTable(ds.Tables["ProcButton"]); ProcButtonItems.FillCacheFromTable(ds.Tables["ProcButtonItem"]); } if (listITypes.Contains(InvalidType.ProcCodes) || isAll) { ProcedureCodes.FillCacheFromTable(ds.Tables["ProcedureCode"]); ProcCodeNotes.FillCacheFromTable(ds.Tables["ProcCodeNote"]); } if (listITypes.Contains(InvalidType.Programs) || isAll) { Programs.FillCacheFromTable(ds.Tables["Program"]); ProgramProperties.FillCacheFromTable(ds.Tables["ProgramProperty"]); } if (listITypes.Contains(InvalidType.ProviderErxs) || isAll) { ProviderErxs.FillCacheFromTable(ds.Tables["ProviderErx"]); } if (listITypes.Contains(InvalidType.ProviderIdents) || isAll) { ProviderIdents.FillCacheFromTable(ds.Tables["ProviderIdent"]); } if (listITypes.Contains(InvalidType.Providers) || isAll) { Providers.FillCacheFromTable(ds.Tables["Provider"]); //Refresh the clinics as well because InvalidType.Providers has a comment that says "also includes clinics". Also, there currently isn't an itype for Clinics. Clinics.FillCacheFromTable(ds.Tables["clinic"]); //Case must match the table name in Clinics.RefrechCache(). } if (listITypes.Contains(InvalidType.QuickPaste) || isAll) { QuickPasteNotes.FillCacheFromTable(ds.Tables["QuickPasteNote"]); QuickPasteCats.FillCacheFromTable(ds.Tables["QuickPasteCat"]); } if (listITypes.Contains(InvalidType.RecallTypes) || isAll) { RecallTypes.FillCacheFromTable(ds.Tables["RecallType"]); RecallTriggers.FillCacheFromTable(ds.Tables["RecallTrigger"]); } if (listITypes.Contains(InvalidType.ReplicationServers) || isAll) { ReplicationServers.FillCacheFromTable(ds.Tables["ReplicationServer"]); } //if(itypes.Contains(InvalidType.RequiredFields) || isAll) { // RequiredFields.FillCache(ds.Tables["RequiredField"]); //} if (listITypes.Contains(InvalidType.Security) || isAll) { Userods.FillCacheFromTable(ds.Tables["Userod"]); UserGroups.FillCacheFromTable(ds.Tables["UserGroup"]); UserGroupAttaches.FillCacheFromTable(ds.Tables["UserGroupAttach"]); } if (listITypes.Contains(InvalidType.Sheets) || isAll) { SheetDefs.FillCacheFromTable(ds.Tables["SheetDef"]); SheetFieldDefs.FillCacheFromTable(ds.Tables["SheetFieldDef"]); } if (listITypes.Contains(InvalidType.SigMessages) || isAll) { SigElementDefs.FillCacheFromTable(ds.Tables["SigElementDef"]); SigButDefs.FillCacheFromTable(ds.Tables["SigButDef"]); } if (listITypes.Contains(InvalidType.Sites) || isAll) { Sites.FillCacheFromTable(ds.Tables["Site"]); if (PrefC.IsODHQ) { SiteLinks.FillCacheFromTable(ds.Tables["SiteLink"]); } } if (listITypes.Contains(InvalidType.SmsBlockPhones) || isAll) { SmsBlockPhones.FillCacheFromTable(ds.Tables["SmsBlockPhone"]); } if (listITypes.Contains(InvalidType.SmsPhones) || isAll) { SmsPhones.FillCacheFromTable(ds.Tables["SmsPhone"]); } if (listITypes.Contains(InvalidType.Sops) || isAll) { Sops.FillCacheFromTable(ds.Tables["Sop"]); } if (listITypes.Contains(InvalidType.StateAbbrs) || isAll) { StateAbbrs.FillCacheFromTable(ds.Tables["StateAbbr"]); } if (listITypes.Contains(InvalidType.TimeCardRules) || isAll) { TimeCardRules.FillCacheFromTable(ds.Tables["TimeCardRule"]); } //InvalidTypes.Tasks not handled here. if (listITypes.Contains(InvalidType.ToolBut) || isAll) { ToolButItems.FillCacheFromTable(ds.Tables["ToolButItem"]); } if (listITypes.Contains(InvalidType.UserClinics) || isAll) { UserClinics.FillCacheFromTable(ds.Tables["UserClinic"]); } if (listITypes.Contains(InvalidType.UserQueries) || isAll) { UserQueries.FillCacheFromTable(ds.Tables["UserQuery"]); } if (listITypes.Contains(InvalidType.Vaccines) || isAll) { VaccineDefs.FillCacheFromTable(ds.Tables["VaccineDef"]); DrugManufacturers.FillCacheFromTable(ds.Tables["DrugManufacturer"]); DrugUnits.FillCacheFromTable(ds.Tables["DrugUnit"]); } if (listITypes.Contains(InvalidType.Views) || isAll) { ApptViews.FillCacheFromTable(ds.Tables["ApptView"]); ApptViewItems.FillCacheFromTable(ds.Tables["ApptViewItem"]); AppointmentRules.FillCacheFromTable(ds.Tables["AppointmentRule"]); ProcApptColors.FillCacheFromTable(ds.Tables["ProcApptColor"]); } if (listITypes.Contains(InvalidType.Wiki) || isAll) { WikiListHeaderWidths.FillCacheFromTable(ds.Tables["WikiListHeaderWidth"]); WikiPages.FillCache(ds.Tables["WikiPage"]); } if (listITypes.Contains(InvalidType.ZipCodes) || isAll) { ZipCodes.FillCacheFromTable(ds.Tables["ZipCode"]); } }
private static List <TreatPlanPresenterEntry> GetListTreatPlanPresenterEntries(List <long> listClinicNums, bool isFirstPresenter, bool isPresenter , DateTime dateStart, DateTime dateEnd) { //No need to check RemotingRole; private method. List <Procedure> listProcsComplete = ReportsComplex.RunFuncOnReportServer(() => Procedures.GetCompletedForDateRangeLimited(dateStart, dateEnd, listClinicNums)); List <ProcTP> listProcTPs = ReportsComplex.RunFuncOnReportServer(() => ProcTPs.GetForProcs(listProcsComplete.Select(x => x.ProcNum).ToList())); List <Procedure> listTreatPlanProcs = listProcsComplete.Where(x => listProcTPs.Select(y => y.ProcNumOrig).Contains(x.ProcNum)).ToList(); List <TreatPlan> listSavedTreatPlans = ReportsComplex.RunFuncOnReportServer(() => TreatPlans.GetFromProcTPs(listProcTPs)); // attached proctps to treatment plans. List <ClaimProc> listClaimProcs = ReportsComplex.RunFuncOnReportServer(() => ClaimProcs.GetForProcsLimited(listTreatPlanProcs.Select(x => x.ProcNum).ToList(), ClaimProcStatus.Received, ClaimProcStatus.Supplemental, ClaimProcStatus.CapComplete, ClaimProcStatus.NotReceived)); List <Adjustment> listAdjustments = ReportsComplex.RunFuncOnReportServer(() => Adjustments.GetForProcs(listTreatPlanProcs.Select(x => x.ProcNum).ToList())); List <Userod> listUserods = ReportsComplex.RunFuncOnReportServer(() => Userods.GetAll()); List <TreatPlanPresenterEntry> listTreatPlanPresenterEntries = new List <TreatPlanPresenterEntry>(); List <ProcedureCode> listProcCodes = ProcedureCodes.GetCodesForCodeNums(listTreatPlanProcs.Select(x => x.CodeNum).ToList()); foreach (Procedure procCur in listTreatPlanProcs) { double grossProd = procCur.ProcFeeTotal; double writeOffs = listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum) .Where(x => x.Status == ClaimProcStatus.CapComplete) .Sum(x => x.WriteOff); grossProd -= writeOffs; writeOffs = listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum) .Where(x => x.Status == ClaimProcStatus.NotReceived || x.Status == ClaimProcStatus.Received || x.Status == ClaimProcStatus.Supplemental) .Sum(x => x.WriteOff); double adjustments = listAdjustments.Where(x => x.ProcNum == procCur.ProcNum).Sum(x => x.AdjAmt); double netProd = grossProd - writeOffs + adjustments; TreatPlan treatPlanCur; if (isFirstPresenter) { treatPlanCur = listSavedTreatPlans.Where(x => x.ListProcTPs.Any(y => y.ProcNumOrig == procCur.ProcNum)).OrderBy(x => x.DateTP).First(); } else //radioLastPresented { treatPlanCur = listSavedTreatPlans.Where(x => x.ListProcTPs.Any(y => y.ProcNumOrig == procCur.ProcNum)).OrderByDescending(x => x.DateTP).First(); } Userod userPresenter; if (isPresenter) { userPresenter = listUserods.FirstOrDefault(x => x.UserNum == treatPlanCur.UserNumPresenter); } else //radioEntryUser { userPresenter = listUserods.FirstOrDefault(x => x.UserNum == treatPlanCur.SecUserNumEntry); } ProcedureCode procCode = listProcCodes.First(x => x.CodeNum == procCur.CodeNum); listTreatPlanPresenterEntries.Add(new TreatPlanPresenterEntry() { Presenter = userPresenter == null?"":userPresenter.UserName, DatePresented = treatPlanCur.DateTP, DateCompleted = procCur.ProcDate, ProcDescript = procCode.Descript, GrossProd = grossProd, Adjustments = adjustments, WriteOffs = writeOffs, NetProd = netProd, UserNumPresenter = userPresenter == null?0:userPresenter.UserNum, PresentedClinic = procCur.ClinicNum }); } return(listTreatPlanPresenterEntries); }
///<summary>Surrond with Try/Catch. Error messages will be thrown to caller.</summary> public static bool IsGlobalDateLock(Permissions perm, DateTime date, bool isSilent = false, long codeNum = 0, double procFee = -1, long sheetDefNum = 0) { if (!(new[] { Permissions.AdjustmentCreate , Permissions.AdjustmentEdit , Permissions.PaymentCreate , Permissions.PaymentEdit , Permissions.ProcComplCreate , Permissions.ProcComplEdit , Permissions.ProcExistingEdit //,Permissions.ProcComplEditLimited //,Permissions.ImageDelete , Permissions.InsPayCreate , Permissions.InsPayEdit //,Permissions.InsWriteOffEdit//per Nathan 7/5/2016 this should not be affected by the global date lock , Permissions.SheetEdit , Permissions.SheetDelete , Permissions.CommlogEdit //,Permissions.ClaimDelete //per Nathan 01/18/2018 this should not be affected by the global date lock , Permissions.PayPlanEdit //,Permissions.ClaimHistoryEdit //per Nathan & Mark 03/01/2018 this should not be affected by the global lock date, not financial data. }).Contains(perm)) { return(false); //permission being checked is not affected by global lock date. } if (date.Year == 1) { return(false); //Invalid or MinDate passed in. } if (!PrefC.GetBool(PrefName.SecurityLockIncludesAdmin) && GroupPermissions.HasPermission(Security.CurUser, Permissions.SecurityAdmin, 0)) { return(false); //admins are never affected by global date limitation when preference is false. } if (perm.In(Permissions.ProcComplCreate, Permissions.ProcComplEdit, Permissions.ProcExistingEdit) && ProcedureCodes.CanBypassLockDate(codeNum, procFee)) { return(false); } if (perm.In(Permissions.SheetEdit, Permissions.SheetDelete) && sheetDefNum > 0 && SheetDefs.CanBypassLockDate(sheetDefNum)) { return(false); } //If global lock is Date based. if (date <= PrefC.GetDate(PrefName.SecurityLockDate)) { if (!isSilent) { MessageBox.Show(Lans.g("Security", "Locked by Administrator before ") + PrefC.GetDate(PrefName.SecurityLockDate).ToShortDateString()); } return(true); } //If global lock is days based. int lockDays = PrefC.GetInt(PrefName.SecurityLockDays); if (lockDays > 0 && date <= DateTime.Today.AddDays(-lockDays)) { if (!isSilent) { MessageBox.Show(Lans.g("Security", "Locked by Administrator before ") + lockDays.ToString() + " days."); } return(true); } return(false); }
///<summary>Should only be called if ODHQ.</summary> private static List <Procedure> AddSmsRepeatingChargesHelper(DateTime dateRun) { //No remoting role check; no call to db DateTime dateStart = new DateTime(dateRun.AddMonths(-1).AddDays(-20).Year, dateRun.AddMonths(-1).AddDays(-20).Month, 1); DateTime dateStop = dateRun.AddDays(1); List <SmsBilling> listSmsBilling = SmsBillings.GetByDateRange(dateStart, dateStop); List <Patient> listPatients = Patients.GetMultPats(listSmsBilling.Select(x => x.CustPatNum).Distinct().ToList()).ToList(); //local cache ProcedureCode procCodeAccess = ProcedureCodes.GetProcCode("038"); ProcedureCode procCodeUsage = ProcedureCodes.GetProcCode("039"); ProcedureCode procCodeConfirm = ProcedureCodes.GetProcCode("040"); List <Procedure> listProcsAccess = Procedures.GetCompletedForDateRange(dateStart, dateStop, new List <long> { procCodeAccess.CodeNum }); List <Procedure> listProcsUsage = Procedures.GetCompletedForDateRange(dateStart, dateStop, new List <long> { procCodeUsage.CodeNum }); List <Procedure> listProcsConfirm = Procedures.GetCompletedForDateRange(dateStart, dateStop, new List <long> { procCodeConfirm.CodeNum }); List <Procedure> retVal = new List <Procedure>(); foreach (SmsBilling smsBilling in listSmsBilling) { Patient pat = listPatients.FirstOrDefault(x => x.PatNum == smsBilling.CustPatNum); if (pat == null) { EServiceSignal eSignal = new EServiceSignal { ServiceCode = (int)eServiceCode.IntegratedTexting, SigDateTime = MiscData.GetNowDateTime(), Severity = eServiceSignalSeverity.Error, Description = "Sms billing row found for non existent patient PatNum:" + smsBilling.CustPatNum }; EServiceSignals.Insert(eSignal); continue; } //Find the billing date based on the date usage. DateTime billingDate = smsBilling.DateUsage.AddMonths(1); //we always bill the month after usage posts. Example: all January usage = 01/01/2015 billingDate = new DateTime( billingDate.Year, billingDate.Month, Math.Min(pat.BillingCycleDay, DateTime.DaysInMonth(billingDate.Year, billingDate.Month))); //example: dateUsage=08/01/2015, billing cycle date=8/14/2012, billing date should be 9/14/2015. if (billingDate > dateRun || billingDate < dateRun.AddMonths(-1).AddDays(-20)) { //One month and 20 day window. Bill regardless of presence of "038" repeat charge. continue; } if (smsBilling.AccessChargeTotalUSD == 0 && smsBilling.MsgChargeTotalUSD == 0 && smsBilling.ConfirmationChargeTotalUSD == 0) { //No charges so skip this customer. continue; } //Only post confirmation charge if valid. if (smsBilling.ConfirmationChargeTotalUSD > 0 && (billingDate <= DateTime.Today || PrefC.GetBool(PrefName.FutureTransDatesAllowed) && !listProcsConfirm.Exists(x => x.PatNum == pat.PatNum && x.ProcDate.Year == billingDate.Year && x.ProcDate.Month == billingDate.Month))) { //The calculated access charge was greater than 0 and there is not an existing "038" procedure on the account for that month. Procedure procConfirm = new Procedure(); procConfirm.CodeNum = procCodeConfirm.CodeNum; procConfirm.DateEntryC = DateTime.Today; procConfirm.PatNum = pat.PatNum; procConfirm.ProcDate = billingDate; procConfirm.DateTP = billingDate; procConfirm.ProcFee = smsBilling.ConfirmationChargeTotalUSD; procConfirm.ProcStatus = ProcStat.C; procConfirm.ProvNum = PrefC.GetLong(PrefName.PracticeDefaultProv); procConfirm.MedicalCode = procCodeConfirm.MedicalCode; procConfirm.BaseUnits = procCodeConfirm.BaseUnits; procConfirm.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs); procConfirm.BillingNote = smsBilling.BillingDescConfirmation; procConfirm.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService); //Default Proc Place of Service for the Practice is used. Procedures.Insert(procConfirm); listProcsConfirm.Add(procConfirm); retVal.Add(procConfirm); } //Confirmation charges may wipe out access charges. We still want to see the $0 charge in this case so post this charge if either of the 2 are valid. if ((smsBilling.AccessChargeTotalUSD > 0 || smsBilling.ConfirmationChargeTotalUSD > 0) && (billingDate <= DateTime.Today || PrefC.GetBool(PrefName.FutureTransDatesAllowed)) && !listProcsAccess.Exists(x => x.PatNum == pat.PatNum && x.ProcDate.Year == billingDate.Year && x.ProcDate.Month == billingDate.Month)) { //The calculated access charge was greater than 0 and there is not an existing "038" procedure on the account for that month. Procedure procAccess = new Procedure(); procAccess.CodeNum = procCodeAccess.CodeNum; procAccess.DateEntryC = DateTime.Today; procAccess.PatNum = pat.PatNum; procAccess.ProcDate = billingDate; procAccess.DateTP = billingDate; procAccess.ProcFee = smsBilling.AccessChargeTotalUSD; procAccess.ProcStatus = ProcStat.C; procAccess.ProvNum = PrefC.GetLong(PrefName.PracticeDefaultProv); procAccess.MedicalCode = procCodeAccess.MedicalCode; procAccess.BaseUnits = procCodeAccess.BaseUnits; procAccess.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs); procAccess.BillingNote = smsBilling.BillingDescSms; procAccess.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService); //Default Proc Place of Service for the Practice is used. Procedures.Insert(procAccess); listProcsAccess.Add(procAccess); retVal.Add(procAccess); } //Only post usage charge if valid. if (smsBilling.MsgChargeTotalUSD > 0 && (billingDate <= DateTime.Today || PrefC.GetBool(PrefName.FutureTransDatesAllowed)) && !listProcsUsage.Exists(x => x.PatNum == pat.PatNum && x.ProcDate.Year == billingDate.Year && x.ProcDate.Month == billingDate.Month)) { //Calculated Usage charge > 0 and not already billed, may exist without access charge Procedure procUsage = new Procedure(); procUsage.CodeNum = procCodeUsage.CodeNum; procUsage.DateEntryC = DateTime.Today; procUsage.PatNum = pat.PatNum; procUsage.ProcDate = billingDate; procUsage.DateTP = billingDate; procUsage.ProcFee = smsBilling.MsgChargeTotalUSD; procUsage.ProcStatus = ProcStat.C; procUsage.ProvNum = PrefC.GetLong(PrefName.PracticeDefaultProv); procUsage.MedicalCode = procCodeUsage.MedicalCode; procUsage.BaseUnits = procCodeUsage.BaseUnits; procUsage.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs); procUsage.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService); //Default Proc Place of Service for the Practice is used. procUsage.BillingNote = "Texting Usage charge for " + smsBilling.DateUsage.ToString("MMMM yyyy") + "."; Procedures.Insert(procUsage); listProcsUsage.Add(procUsage); retVal.Add(procUsage); } } return(retVal); }
///<summary>Gets all possible fees associated with the various objects passed in. Gets fees from db based on code and fee schedule combos. Includes all provider overrides. Includes default/no clinic as well as any specified clinic overrides. Although the list always includes extra fees from scheds that we don't need, it's still a very small list. That list is then used repeatedly by other code in loops to find the actual individual fee amounts.</summary> public static List <Fee> GetListFromObjects(List <ProcedureCode> listProcedureCodes, List <string> listMedicalCodes, List <long> listProvNumsTreat, long patPriProv, long patSecProv, long patFeeSched, List <InsPlan> listInsPlans, List <long> listClinicNums, List <Appointment> listAppts, List <SubstitutionLink> listSubstLinks, long discountPlan //listCodeNums,listProvNumsTreat,listProcCodesProvNumDefault,patPriProv,patSecProv,patFeeSched,listInsPlans,listClinicNums //List<long> listProcCodesProvNumDefault ) { //listMedicalCodes: it already automatically gets the medical codes from procCodes. This is just for procs. If no procs yet, it will be null. //listMedicalCodes can be done by: listProcedures.Select(x=>x.MedicalCode).ToList(); //this is just the strings //One way to get listProvNumsTreat is listProcedures.Select(x=>x.ProvNum).ToList() //One way to specify a single provNum in listProvNumsTreat is new List<long>(){provNum} //One way to get clinicNums is listProcedures.Select(x=>x.ClinicNum).ToList() //Another way to get clinicNums is new List<long>(){clinicNum}. //These objects will be cleaned up, so they can have duplicates, zeros, invalid keys, nulls, etc //In some cases, we need to pass in a list of appointments to make sure we've included all possible providers, both ProvNum and ProvHyg //In that case, it's common to leave listProvNumsTreat null because we clearly do not have any of those providers set yet. if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <Fee> >(MethodBase.GetCurrentMethod(), listProcedureCodes, listMedicalCodes, listProvNumsTreat, patPriProv, patSecProv, patFeeSched, listInsPlans, listClinicNums, listAppts, listSubstLinks, discountPlan)); } if (listProcedureCodes == null) { return(new List <Fee>()); } List <long> listCodeNumsOut = new List <long>(); foreach (ProcedureCode procedureCode in listProcedureCodes) { if (procedureCode == null) { continue; } if (!listCodeNumsOut.Contains(procedureCode.CodeNum)) { listCodeNumsOut.Add(procedureCode.CodeNum); } if (ProcedureCodes.IsValidCode(procedureCode.MedicalCode)) { long codeNumMed = ProcedureCodes.GetCodeNum(procedureCode.MedicalCode); if (!listCodeNumsOut.Contains(codeNumMed)) { listCodeNumsOut.Add(codeNumMed); } } if (ProcedureCodes.IsValidCode(procedureCode.SubstitutionCode)) { long codeNumSub = ProcedureCodes.GetCodeNum(procedureCode.SubstitutionCode); if (!listCodeNumsOut.Contains(codeNumSub)) { listCodeNumsOut.Add(codeNumSub); } } } if (listMedicalCodes != null) { foreach (string strMedCode in listMedicalCodes) { if (ProcedureCodes.IsValidCode(strMedCode)) { long codeNumMed = ProcedureCodes.GetCodeNum(strMedCode); if (!listCodeNumsOut.Contains(codeNumMed)) { listCodeNumsOut.Add(codeNumMed); } } } } if (listSubstLinks != null) { foreach (SubstitutionLink substitutionLink in listSubstLinks) //Grab all subst codes, since we don't know which ones we will need. { if (ProcedureCodes.IsValidCode(substitutionLink.SubstitutionCode)) { long codeNum = ProcedureCodes.GetCodeNum(substitutionLink.SubstitutionCode); if (!listCodeNumsOut.Contains(codeNum)) { listCodeNumsOut.Add(codeNum); } } } } //Fee schedules. Will potentially include many.======================================================================================= List <long> listFeeScheds = new List <long>(); //Add feesched for first provider (See Claims.CalculateAndUpdate)--------------------------------------------------------------------- Provider provFirst = Providers.GetFirst(); if (provFirst != null && provFirst.FeeSched != 0 && !listFeeScheds.Contains(provFirst.FeeSched)) { listFeeScheds.Add(provFirst.FeeSched); } //Add feesched for PracticeDefaultProv------------------------------------------------------------------------------------------------ Provider provPracticeDefault = Providers.GetProv(PrefC.GetLong(PrefName.PracticeDefaultProv)); if (provPracticeDefault != null && provPracticeDefault.FeeSched != 0 && !listFeeScheds.Contains(provPracticeDefault.FeeSched)) { listFeeScheds.Add(provPracticeDefault.FeeSched); } //Add feescheds for all treating providers--------------------------------------------------------------------------------------------- if (listProvNumsTreat != null) { foreach (long provNumTreat in listProvNumsTreat) { Provider provTreat = Providers.GetProv(provNumTreat); if (provTreat != null && provTreat.FeeSched != 0 && !listFeeScheds.Contains(provTreat.FeeSched)) { listFeeScheds.Add(provTreat.FeeSched); //treating provs fee scheds } } } //Add feescheds for the patient's primary and secondary providers---------------------------------------------------------------------- Provider providerPatPri = Providers.GetProv(patPriProv); if (providerPatPri != null && providerPatPri.FeeSched != 0 && !listFeeScheds.Contains(providerPatPri.FeeSched)) { listFeeScheds.Add(providerPatPri.FeeSched); } Provider providerPatSec = Providers.GetProv(patSecProv); if (providerPatSec != null && providerPatSec.FeeSched != 0 && !listFeeScheds.Contains(providerPatSec.FeeSched)) { listFeeScheds.Add(providerPatSec.FeeSched); } //Add feescheds for all procedurecode.ProvNumDefaults--------------------------------------------------------------------------------- foreach (ProcedureCode procedureCode in listProcedureCodes) { if (procedureCode == null) { continue; } long provNumDefault = procedureCode.ProvNumDefault; if (provNumDefault == 0) { continue; } Provider provDefault = Providers.GetProv(provNumDefault); if (provDefault != null && provDefault.FeeSched != 0 && !listFeeScheds.Contains(provDefault.FeeSched)) { listFeeScheds.Add(provDefault.FeeSched); } } //Add feescheds for appointment providers--------------------------------------------------------------------------------------------- if (listAppts != null) { foreach (Appointment appointment in listAppts) { Provider provAppt = Providers.GetProv(appointment.ProvNum); if (provAppt != null && provAppt.FeeSched != 0 && !listFeeScheds.Contains(provAppt.FeeSched)) { listFeeScheds.Add(provAppt.FeeSched); } Provider provApptHyg = Providers.GetProv(appointment.ProvHyg); if (provApptHyg != null && provApptHyg.FeeSched != 0 && !listFeeScheds.Contains(provApptHyg.FeeSched)) { listFeeScheds.Add(provApptHyg.FeeSched); } } } //Add feesched for patient. Rare. -------------------------------------------------------------------------------------------------- if (patFeeSched != 0) { if (!listFeeScheds.Contains(patFeeSched)) { listFeeScheds.Add(patFeeSched); } } //Add feesched for each insplan, both reg and allowed-------------------------------------------------------------------------------- if (listInsPlans != null) { foreach (InsPlan insPlan in listInsPlans) { if (insPlan.FeeSched != 0 && !listFeeScheds.Contains(insPlan.FeeSched)) { listFeeScheds.Add(insPlan.FeeSched); //insplan feeSched } if (insPlan.AllowedFeeSched != 0 && !listFeeScheds.Contains(insPlan.AllowedFeeSched)) { listFeeScheds.Add(insPlan.AllowedFeeSched); //allowed feeSched } if (insPlan.CopayFeeSched != 0 && !listFeeScheds.Contains(insPlan.CopayFeeSched)) { listFeeScheds.Add(insPlan.CopayFeeSched); //copay feeSched } } } if (discountPlan != 0) { long discountPlanFeeSched = DiscountPlans.GetPlan(discountPlan).FeeSchedNum; if (!listFeeScheds.Contains(discountPlanFeeSched)) { listFeeScheds.Add(discountPlanFeeSched); } } //ClinicNums======================================================================================================================== List <long> listClinicNumsOut = new List <long>(); //usually empty or one entry if (listClinicNums != null) { foreach (long clinicNum in listClinicNums) { if (clinicNum != 0 && !listClinicNumsOut.Contains(clinicNum)) { listClinicNumsOut.Add(clinicNum); //proc ClinicNums } } } if (listFeeScheds.Count == 0 || listProcedureCodes.Count == 0) { return(new List <Fee>()); } string command = "SELECT * FROM fee WHERE ("; for (int i = 0; i < listFeeScheds.Count; i++) { if (i > 0) { command += " OR "; } command += "FeeSched=" + POut.Long(listFeeScheds[i]); } command += ") AND ("; for (int i = 0; i < listCodeNumsOut.Count; i++) { if (i > 0) { command += " OR "; } command += "CodeNum=" + POut.Long(listCodeNumsOut[i]); } command += ") AND (ClinicNum=0"; for (int i = 0; i < listClinicNumsOut.Count; i++) { command += " OR ClinicNum=" + POut.Long(listClinicNumsOut[i]); } command += ")"; return(Crud.FeeCrud.SelectMany(command)); }
private static Procedure AddRepeatingChargeHelper(RepeatCharge repeatCharge, DateTime billingDate, DateTime dateNow) { //No remoting role check; no call to db Procedure procedure = new Procedure(); ProcedureCode procCode = ProcedureCodes.GetProcCode(repeatCharge.ProcCode); Patient pat = Patients.GetPat(repeatCharge.PatNum); procedure.CodeNum = procCode.CodeNum; procedure.ClinicNum = pat.ClinicNum; procedure.DateEntryC = dateNow; procedure.PatNum = repeatCharge.PatNum; procedure.ProcDate = billingDate; procedure.DateTP = billingDate; procedure.ProcFee = repeatCharge.ChargeAmt; procedure.ProcStatus = ProcStat.C; if (procCode.ProvNumDefault == 0) { procedure.ProvNum = pat.PriProv; } else { procedure.ProvNum = procCode.ProvNumDefault; } procedure.MedicalCode = ProcedureCodes.GetProcCode(procedure.CodeNum).MedicalCode; procedure.BaseUnits = ProcedureCodes.GetProcCode(procedure.CodeNum).BaseUnits; procedure.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs); procedure.RepeatChargeNum = repeatCharge.RepeatChargeNum; procedure.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService); //Default Proc Place of Service for the Practice is used. //Check if the repeating charge has been flagged to copy it's note into the billing note of the procedure. if (repeatCharge.CopyNoteToProc) { procedure.BillingNote = repeatCharge.Note; if (repeatCharge.ErxAccountId != "") { procedure.BillingNote = "NPI=" + repeatCharge.Npi + " " + "ErxAccountId=" + repeatCharge.ErxAccountId; if (!string.IsNullOrEmpty(repeatCharge.ProviderName)) //Provider name would be empty if older and no longer updated from eRx. { procedure.BillingNote += "\r\nProviderName=" + repeatCharge.ProviderName; } if (!string.IsNullOrEmpty(repeatCharge.Note)) { procedure.BillingNote += "\r\n" + repeatCharge.Note; } } } if (!PrefC.GetBool(PrefName.EasyHidePublicHealth)) { procedure.SiteNum = pat.SiteNum; } Procedures.Insert(procedure); //no recall synch needed because dental offices don't use this feature //Using Prepayments for this Procedure if (repeatCharge.UsePrepay) { //NOTE: ProvNum=0 on these splits, so I'm pretty sure they aren't allocated to anything. List <PaySplit> prePaySplits = PaySplits.GetPrepayForFam(Patients.GetFamily(repeatCharge.PatNum)); List <PaySplit> paySplitsForPrePaySplits = PaySplits.GetSplitsForPrepay(prePaySplits); Payment payCur = new Payment(); payCur.ClinicNum = procedure.ClinicNum; payCur.DateEntry = billingDate; payCur.IsSplit = true; payCur.PatNum = repeatCharge.PatNum; payCur.PayDate = billingDate; payCur.PayType = 0; //Income transfer (will always be income transfer) payCur.PayAmt = 0; //Income transfer payment payCur.PayNum = Payments.Insert(payCur); decimal payAmt = 0; string noteText = ""; foreach (PaySplit prePaySplit in prePaySplits) { prePaySplit.SplitAmt += paySplitsForPrePaySplits.Where(x => x.FSplitNum == prePaySplit.SplitNum).Sum(y => y.SplitAmt); //Reduce prepay split amount. PaySplit split = new PaySplit(); PaySplit split2 = new PaySplit(); if (prePaySplit.SplitAmt > procedure.ProcFee - (double)payAmt) { //Split amount is more than the remainder of the procfee requires, use partial from split split.SplitAmt = procedure.ProcFee - (double)payAmt; split2.SplitAmt = 0 - (procedure.ProcFee - (double)payAmt); payAmt = (decimal)procedure.ProcFee; } else { //Split amount is less than or equal to the remainder of the procfee split.SplitAmt = prePaySplit.SplitAmt; split2.SplitAmt = 0 - prePaySplit.SplitAmt; payAmt += (decimal)prePaySplit.SplitAmt; } if (split.SplitAmt == 0) { continue; //Don't make splits for 0 amount. } //Positive split, attached to proc and for proc's prov and clinic split.DateEntry = billingDate; split.DatePay = billingDate; split.PatNum = procedure.PatNum; split.PayNum = payCur.PayNum; split.ProcNum = procedure.ProcNum; split.ProvNum = procedure.ProvNum; split.ClinicNum = procedure.ClinicNum; if (noteText != "") { noteText += ", "; } noteText += split.SplitAmt.ToString("c"); PaySplits.Insert(split); //Negative split, attached to prepay's prov and clinic, but not proc split2.DateEntry = billingDate; split2.DatePay = billingDate; split2.PatNum = procedure.PatNum; split2.PayNum = payCur.PayNum; split2.FSplitNum = prePaySplit.SplitNum; split2.ProvNum = prePaySplit.ProvNum; split2.ClinicNum = prePaySplit.ClinicNum; PaySplits.Insert(split2); if (payAmt >= (decimal)procedure.ProcFee) { //Break out of loop break; } } payCur.PayNote = "Allocated " + noteText + " prepayments to repeating charge."; Payments.Update(payCur, false); } return(procedure); }
/// <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>If ClientWeb, then this method is instead run on the server, and the result passed back to the client. And since it's ClientWeb, FillCache will be run on the client.</summary> public static DataSet GetCacheDs(bool doRefreshServerCache, params InvalidType[] arrayITypes) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetDS(MethodBase.GetCurrentMethod(), doRefreshServerCache, arrayITypes)); } Logger.LogToPath("", LogPath.Signals, LogPhase.Start, "InvalidType(s): " + string.Join(" - ", arrayITypes.OrderBy(x => x.ToString()))); List <InvalidType> listITypes = arrayITypes.ToList(); //so this part below only happens if direct or server------------------------------------------------ bool isAll = false; if (listITypes.Contains(InvalidType.AllLocal)) { isAll = true; } DataSet ds = new DataSet(); //All Internal OD Tables that are cached go here if (PrefC.IsODHQ) { if (listITypes.Contains(InvalidType.JobPermission) || isAll) { ds.Tables.Add(JobPermissions.RefreshCache()); } if (listITypes.Contains(InvalidType.PhoneComps) || isAll) { ds.Tables.Add(PhoneComps.GetTableFromCache(doRefreshServerCache)); } } //All cached public tables go here if (listITypes.Contains(InvalidType.AccountingAutoPays) || isAll) { ds.Tables.Add(AccountingAutoPays.GetTableFromCache(doRefreshServerCache)); } //if(listITypes.Contains(InvalidType.AlertItems) || isAll) {//THIS IS NOT CACHED. But is used to make server run the alert logic in OpenDentalService. // ds.Tables.Add(AlertItems.RefreshCache()); //} if (listITypes.Contains(InvalidType.AlertCategories) || isAll) { ds.Tables.Add(AlertCategories.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.AlertCategoryLinks) || isAll) { ds.Tables.Add(AlertCategoryLinks.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.AppointmentTypes) || isAll) { ds.Tables.Add(AppointmentTypes.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.AutoCodes) || isAll) { ds.Tables.Add(AutoCodes.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(AutoCodeItems.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(AutoCodeConds.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Automation) || isAll) { ds.Tables.Add(Automations.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.AutoNotes) || isAll) { ds.Tables.Add(AutoNotes.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(AutoNoteControls.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Carriers) || isAll) { ds.Tables.Add(Carriers.GetTableFromCache(doRefreshServerCache)); //run on startup, after telephone reformat, after list edit. } if (listITypes.Contains(InvalidType.ClaimForms) || isAll) { ds.Tables.Add(ClaimFormItems.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(ClaimForms.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.ClearHouses) || isAll) { ds.Tables.Add(Clearinghouses.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.ClinicErxs) || isAll) { ds.Tables.Add(ClinicErxs.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.ClinicPrefs) || isAll) { ds.Tables.Add(ClinicPrefs.GetTableFromCache(doRefreshServerCache)); } //InvalidType.Clinics see InvalidType.Providers if (listITypes.Contains(InvalidType.Computers) || isAll) { ds.Tables.Add(Computers.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(Printers.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Defs) || isAll) { ds.Tables.Add(Defs.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.DentalSchools) || isAll) { ds.Tables.Add(SchoolClasses.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(SchoolCourses.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.DictCustoms) || isAll) { ds.Tables.Add(DictCustoms.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Diseases) || isAll) { ds.Tables.Add(DiseaseDefs.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(ICD9s.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.DisplayFields) || isAll) { ds.Tables.Add(DisplayFields.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.DisplayReports) || isAll) { ds.Tables.Add(DisplayReports.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Ebills) || isAll) { ds.Tables.Add(Ebills.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.EhrCodes)) { EhrCodes.UpdateList(); //Unusual pattern for an unusual "table". Not really a table, but a mishmash of hard coded partial code systems that are needed for CQMs. } if (listITypes.Contains(InvalidType.ElectIDs) || isAll) { ds.Tables.Add(ElectIDs.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Email) || isAll) { ds.Tables.Add(EmailAddresses.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(EmailTemplates.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(EmailAutographs.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Employees) || isAll) { ds.Tables.Add(Employees.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(PayPeriods.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Employers) || isAll) { ds.Tables.Add(Employers.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Fees) || isAll) { //Fee Cache follows an unusual pattern. This fills the cache with the HQ fees, and whatever clinics happen to be currently cached. ds.Tables.Add(Fees.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.FeeScheds) || isAll) { ds.Tables.Add(FeeScheds.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.HL7Defs) || isAll) { ds.Tables.Add(HL7Defs.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(HL7DefMessages.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(HL7DefSegments.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(HL7DefFields.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.InsCats) || isAll) { ds.Tables.Add(CovCats.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(CovSpans.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.InsFilingCodes) || isAll) { ds.Tables.Add(InsFilingCodes.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(InsFilingCodeSubtypes.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Languages) || isAll) { if (CultureInfo.CurrentCulture.Name != "en-US") { ds.Tables.Add(Lans.GetTableFromCache(doRefreshServerCache)); } } if (listITypes.Contains(InvalidType.Letters) || isAll) { ds.Tables.Add(Letters.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.LetterMerge) || isAll) { ds.Tables.Add(LetterMergeFields.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(LetterMerges.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Medications) || isAll) { ds.Tables.Add(Medications.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Operatories) || isAll) { ds.Tables.Add(Operatories.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.OrthoChartTabs) || isAll) { ds.Tables.Add(OrthoChartTabs.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(OrthoChartTabLinks.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.PatFields) || isAll) { ds.Tables.Add(PatFieldDefs.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(ApptFieldDefs.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Pharmacies) || isAll) { ds.Tables.Add(Pharmacies.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Prefs) || isAll) { ds.Tables.Add(Prefs.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.ProcButtons) || isAll) { ds.Tables.Add(ProcButtons.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(ProcButtonItems.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.ProcCodes) || isAll) { ds.Tables.Add(ProcedureCodes.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(ProcCodeNotes.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Programs) || isAll) { ds.Tables.Add(Programs.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(ProgramProperties.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.ProviderErxs) || isAll) { ds.Tables.Add(ProviderErxs.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.ProviderIdents) || isAll) { ds.Tables.Add(ProviderIdents.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Providers) || isAll) { ds.Tables.Add(Providers.GetTableFromCache(doRefreshServerCache)); //Refresh the clinics as well because InvalidType.Providers has a comment that says "also includes clinics". Also, there currently isn't an itype for Clinics. ds.Tables.Add(Clinics.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.QuickPaste) || isAll) { ds.Tables.Add(QuickPasteNotes.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(QuickPasteCats.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.RecallTypes) || isAll) { ds.Tables.Add(RecallTypes.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(RecallTriggers.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.ReplicationServers) || isAll) { ds.Tables.Add(ReplicationServers.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.RequiredFields) || isAll) { ds.Tables.Add(RequiredFields.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(RequiredFieldConditions.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Security) || isAll) { ds.Tables.Add(Userods.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(UserGroups.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(GroupPermissions.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(UserGroupAttaches.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Sheets) || isAll) { ds.Tables.Add(SheetDefs.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(SheetFieldDefs.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.SigMessages) || isAll) { ds.Tables.Add(SigElementDefs.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(SigButDefs.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Sites) || isAll) { ds.Tables.Add(Sites.GetTableFromCache(doRefreshServerCache)); if (PrefC.IsODHQ) { ds.Tables.Add(SiteLinks.GetTableFromCache(doRefreshServerCache)); } } if (listITypes.Contains(InvalidType.SmsBlockPhones) || isAll) { ds.Tables.Add(SmsBlockPhones.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.SmsPhones) || isAll) { ds.Tables.Add(SmsPhones.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Sops) || isAll) //InvalidType.Sops is currently never used 11/14/2014 { ds.Tables.Add(Sops.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.StateAbbrs) || isAll) { ds.Tables.Add(StateAbbrs.GetTableFromCache(doRefreshServerCache)); } //InvalidTypes.Tasks not handled here. if (listITypes.Contains(InvalidType.TimeCardRules) || isAll) { ds.Tables.Add(TimeCardRules.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.ToolBut) || isAll) { ds.Tables.Add(ToolButItems.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.UserClinics) || isAll) { ds.Tables.Add(UserClinics.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.UserQueries) || isAll) { ds.Tables.Add(UserQueries.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Vaccines) || isAll) { ds.Tables.Add(VaccineDefs.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(DrugManufacturers.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(DrugUnits.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Views) || isAll) { ds.Tables.Add(ApptViews.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(ApptViewItems.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(AppointmentRules.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(ProcApptColors.GetTableFromCache(doRefreshServerCache)); } if (listITypes.Contains(InvalidType.Wiki) || isAll) { ds.Tables.Add(WikiListHeaderWidths.GetTableFromCache(doRefreshServerCache)); ds.Tables.Add(WikiPages.RefreshCache()); } if (listITypes.Contains(InvalidType.ZipCodes) || isAll) { ds.Tables.Add(ZipCodes.GetTableFromCache(doRefreshServerCache)); } Logger.LogToPath("", LogPath.Signals, LogPhase.End); return(ds); }
/// <summary>Deletes the current recalltype and recalltrigger tables and fills them with our default. Typically ran to switch T codes to D codes.</summary> public static void SetToDefault() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod()); return; } string command = "DELETE FROM recalltype"; Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,TimePattern,Procedures) VALUES (1,'Prophy',393217,'/XXXX/','D0120,D1110')"; Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,TimePattern,Procedures) VALUES (2,'Child Prophy',0,'XXX','D0120,D1120,D1203')"; Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,TimePattern,Procedures) VALUES (3,'Perio',262144,'/XXXX/','D4910')"; Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,Procedures) VALUES (4,'4BW',16777216,'D0274')"; Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,Procedures) VALUES (5,'Pano',83886080,'D0330')"; Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,Procedures) VALUES (6,'FMX',83886080,'D0210')"; Db.NonQ(command); command = "DELETE FROM recalltrigger"; Db.NonQ(command); //command="INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (1,1,"+ProcedureCodes.GetCodeNum("D0415")+")";//collection of microorg for culture //Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (1,1," + ProcedureCodes.GetCodeNum("D0150") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (2,4," + ProcedureCodes.GetCodeNum("D0274") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (3,5," + ProcedureCodes.GetCodeNum("D0330") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (4,6," + ProcedureCodes.GetCodeNum("D0210") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (5,1," + ProcedureCodes.GetCodeNum("D1110") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (6,1," + ProcedureCodes.GetCodeNum("D1120") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (7,3," + ProcedureCodes.GetCodeNum("D4910") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (8,3," + ProcedureCodes.GetCodeNum("D4341") + ")"; Db.NonQ(command); //Update the special types in preference table. command = "UPDATE preference SET ValueString='1' WHERE PrefName='RecallTypeSpecialProphy'"; Db.NonQ(command); command = "UPDATE preference SET ValueString='2' WHERE PrefName='RecallTypeSpecialChildProphy'"; Db.NonQ(command); command = "UPDATE preference SET ValueString='3' WHERE PrefName='RecallTypeSpecialPerio'"; Db.NonQ(command); command = "UPDATE preference SET ValueString='1,2,3' WHERE PrefName='RecallTypesShowingInList'"; Db.NonQ(command); }
public static DataTable GetUnearnedAllocationData(List <long> listClinicNums, List <long> listProvNums, List <long> listUnearnedTypeNums, bool isExcludeNetZeroUnearned) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), listClinicNums, listProvNums, listUnearnedTypeNums, isExcludeNetZeroUnearned)); } //get all families that have an unallocated unearned balance. //from those, remove families that have not had procedures charted/completed after the unearned amount. //All families //DatePay = the earliest date of unallocated unearned. //Unallocated Amt = the total unallocated amt for the patient. string command = @" SELECT patient.Guarantor, MIN(paysplit.DatePay) DatePay, SUM(COALESCE(paysplit.SplitAmt,0)) + SUM(COALESCE(alloc.AllocAmt,0)) UnallocAmt FROM paysplit LEFT JOIN ( SELECT paysplit.FSplitNum,SUM(paysplit.SplitAmt) AllocAmt FROM paysplit WHERE paysplit.FSplitNum != 0 GROUP BY paysplit.FSplitNum )alloc ON paysplit.SplitNum = alloc.FSplitNum INNER JOIN patient ON patient.PatNum = paysplit.PatNum " ; if (listClinicNums.Count > 0 || listProvNums.Count > 0) { command += @" INNER JOIN patient guar ON guar.PatNum = patient.Guarantor " ; if (listClinicNums.Count > 0) { command += @" AND guar.ClinicNum IN (" + string.Join(",", listClinicNums.Select(x => POut.Long(x))) + ") "; } if (listProvNums.Count > 0) { command += @" AND guar.PriProv IN (" + string.Join(",", listProvNums.Select(x => POut.Long(x))) + ") "; } } command += @" WHERE paysplit.UnearnedType != 0 " ; if (listUnearnedTypeNums.Count > 0) { command += @" AND paysplit.UnearnedType IN (" + string.Join(",", listUnearnedTypeNums.Select(x => POut.Long(x))) + ") "; } command += @" AND paysplit.FSplitNum = 0 AND (ABS(paysplit.SplitAmt + alloc.AllocAmt) > 0.005 OR alloc.AllocAmt IS NULL) GROUP BY patient.Guarantor " ; if (isExcludeNetZeroUnearned) { command += @" HAVING ABS(UnallocAmt) > 0.005 " ; } //one row per family DataTable tableUnallocatedUnearned = ReportsComplex.RunFuncOnReportServer(() => Db.GetTable(command)); List <long> listGuarantors = tableUnallocatedUnearned.Rows.OfType <DataRow>().Select(x => PIn.Long(x["Guarantor"].ToString())).ToList(); //all procedures for the families that have not been explicitly paid off. //Key: GuarantorNum | Val:ListRemainingProcsForFam List <UnearnedProc> listRemProcs = ReportsComplex.RunFuncOnReportServer(() => Procedures.GetRemainingProcsForFamilies(listGuarantors)); Dictionary <long, List <UnearnedProc> > dictFamRemainingProcs = listRemProcs.GroupBy(x => x.GuarNum) .ToDictionary(x => x.Key, y => y.ToList()); Dictionary <long, double> dictFamilyBalances = ReportsComplex.RunFuncOnReportServer(() => Ledgers.GetBalancesForFamilies(listGuarantors)); Dictionary <long, string> dictPatNames = ReportsComplex.RunFuncOnReportServer(() => Patients.GetPatientNames(Patients.GetAllFamilyPatNums(listGuarantors))); List <ProcedureCode> listProcCodes = ReportsComplex.RunFuncOnReportServer(() => ProcedureCodes.GetAllCodes()); DataTable retVal = new DataTable(); retVal.Columns.Add("Guar"); retVal.Columns.Add("FamBal"); retVal.Columns.Add("FamUnearned"); retVal.Columns.Add("FamRemAmt"); retVal.Columns.Add("Patient"); retVal.Columns.Add("Code"); retVal.Columns.Add("Date"); retVal.Columns.Add("Fee"); retVal.Columns.Add("RemAmt"); foreach (DataRow guarRowCur in tableUnallocatedUnearned.Rows) { long guarNum = PIn.Long(guarRowCur["Guarantor"].ToString()); DateTime dateFirstUnalloc = PIn.Date(guarRowCur["DatePay"].ToString()); double unallocAmt = PIn.Double(guarRowCur["UnallocAmt"].ToString()); List <UnearnedProc> listUnearnedProcsForGuar; if (!dictFamRemainingProcs.TryGetValue(guarNum, out listUnearnedProcsForGuar)) { continue; //This family does not have any procedures that need to have money allocated to. } listUnearnedProcsForGuar = listUnearnedProcsForGuar.Where(x => x.Proc.ProcDate >= dateFirstUnalloc).OrderBy(x => x.Proc.ProcDate).ToList(); if (listUnearnedProcsForGuar.Count == 0) { continue; //We only want to show families where the procedure was completed after the unallocated prepayment. } decimal famRemAmt = listUnearnedProcsForGuar.Sum(x => x.UnallocatedAmt); DataRow guarRow = retVal.NewRow(); string guarName; double famBal; dictPatNames.TryGetValue(guarNum, out guarName); dictFamilyBalances.TryGetValue(guarNum, out famBal); guarRow["Guar"] = guarName; guarRow["FamBal"] = famBal.ToString("f"); guarRow["FamUnearned"] = unallocAmt.ToString("f"); guarRow["FamRemAmt"] = famRemAmt.ToString("f"); retVal.Rows.Add(guarRow); foreach (UnearnedProc unearnedProc in listUnearnedProcsForGuar) { DataRow newRow = retVal.NewRow(); dictPatNames.TryGetValue(guarNum, out guarName); string patName; if (dictPatNames.TryGetValue(unearnedProc.Proc.PatNum, out patName)) { newRow["Patient"] = patName; } newRow["Code"] = ProcedureCodes.GetStringProcCode(unearnedProc.Proc.CodeNum, listProcCodes); newRow["Date"] = unearnedProc.Proc.ProcDate.ToShortDateString(); newRow["Fee"] = (unearnedProc.Proc.ProcFee * (unearnedProc.Proc.UnitQty + unearnedProc.Proc.BaseUnits)).ToString("f"); newRow["RemAmt"] = unearnedProc.UnallocatedAmt.ToString("f"); retVal.Rows.Add(newRow); } } return(retVal); }
/// <summary>Deletes the current recalltype and recalltrigger tables and fills them with our default. Typically ran to switch T codes to D codes.</summary> public static void SetToDefault() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod()); return; } string command = "DELETE FROM recalltype WHERE RecallTypeNum >= 1 AND RecallTypeNum <= 6"; //Don't delete manually added recall types Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,TimePattern,Procedures) VALUES (1,'Prophy',393217,'/XXXX/','D0120,D1110')"; Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,TimePattern,Procedures) VALUES (2,'Child Prophy',0,'XXX','D0120,D1120,D1208')"; Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,TimePattern,Procedures) VALUES (3,'Perio',262144,'/XXXX/','D4910')"; Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,Procedures,AppendToSpecial) VALUES (4,'4BW',16777216,'D0274',1)"; Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,Procedures,AppendToSpecial) VALUES (5,'Pano',83886080,'D0330',1)"; Db.NonQ(command); command = "INSERT INTO recalltype (RecallTypeNum,Description,DefaultInterval,Procedures,AppendToSpecial) VALUES (6,'FMX',83886080,'D0210',1)"; Db.NonQ(command); command = "DELETE FROM recalltrigger"; //OK to delete triggers for manually added recalls, because deleting the triggers disables the recall type. Db.NonQ(command); //command="INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (1,1,"+ProcedureCodes.GetCodeNum("D0415")+")";//collection of microorg for culture //Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (1,1," + ProcedureCodes.GetCodeNum("D0150") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (2,4," + ProcedureCodes.GetCodeNum("D0274") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (3,5," + ProcedureCodes.GetCodeNum("D0330") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (4,6," + ProcedureCodes.GetCodeNum("D0210") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (5,1," + ProcedureCodes.GetCodeNum("D1110") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (6,1," + ProcedureCodes.GetCodeNum("D1120") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (7,3," + ProcedureCodes.GetCodeNum("D4910") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (8,3," + ProcedureCodes.GetCodeNum("D4341") + ")"; Db.NonQ(command); command = "INSERT INTO recalltrigger (RecallTriggerNum,RecallTypeNum,CodeNum) VALUES (9,1," + ProcedureCodes.GetCodeNum("D0120") + ")"; Db.NonQ(command); //Update the special types in preference table. command = "UPDATE preference SET ValueString='1' WHERE PrefName='RecallTypeSpecialProphy'"; Db.NonQ(command); command = "UPDATE preference SET ValueString='2' WHERE PrefName='RecallTypeSpecialChildProphy'"; Db.NonQ(command); command = "UPDATE preference SET ValueString='3' WHERE PrefName='RecallTypeSpecialPerio'"; Db.NonQ(command); command = "UPDATE preference SET ValueString='1,2,3' WHERE PrefName='RecallTypesShowingInList'"; Db.NonQ(command); //Delete recalls for manually added recall types. This is the same strategy we use in FormRecallTypeEdit //Types 1 through 6 were reinserted above, and thus the foreign keys will still be correct. command = "DELETE FROM recall WHERE RecallTypeNum < 1 OR RecallTypeNum > 6"; Db.NonQ(command); }
public static DataTable GetUnearnedAllocationData(List <long> listClinicNums, List <long> listProvNums, List <long> listUnearnedTypeNums, bool isExcludeNetZeroUnearned, bool showProvider) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), listClinicNums, listProvNums, listUnearnedTypeNums, isExcludeNetZeroUnearned, showProvider)); } List <long> listHiddenUnearnedDefNums = ReportsComplex.RunFuncOnReportServer(() => Defs.GetDefsNoCache(DefCat.PaySplitUnearnedType).FindAll(x => !string.IsNullOrEmpty(x.ItemValue)).Select(x => x.DefNum).ToList() ); //get all families that have an unallocated unearned balance. //from those, remove families that have not had procedures charted/completed after the unearned amount. //All families //DatePay = the earliest date of unallocated unearned. //Unallocated Amt = the total unallocated amt for the patient. string command = $@" SELECT patient.Guarantor, MIN(paysplit.DatePay) DatePay, SUM(paysplit.SplitAmt) UnallocAmt{(showProvider ? ", provider.Abbr" : "")} FROM paysplit INNER JOIN patient ON patient.PatNum = paysplit.PatNum " ; if (listClinicNums.Count > 0 || listProvNums.Count > 0) { command += "INNER JOIN patient guar ON guar.PatNum = patient.Guarantor "; if (listClinicNums.Count > 0) { command += "AND guar.ClinicNum IN (" + string.Join(",", listClinicNums.Select(x => POut.Long(x))) + ") "; } if (listProvNums.Count > 0) { command += "AND guar.PriProv IN (" + string.Join(",", listProvNums.Select(x => POut.Long(x))) + ") "; } } if (showProvider) { command += "LEFT JOIN provider ON provider.ProvNum = paysplit.ProvNum "; } command += "WHERE paysplit.UnearnedType != 0 "; if (listUnearnedTypeNums.Count > 0) { command += "AND paysplit.UnearnedType IN (" + string.Join(",", listUnearnedTypeNums.Select(x => POut.Long(x))) + ") "; } if (listHiddenUnearnedDefNums.Count > 0) { command += $"AND paysplit.UnearnedType NOT IN ({string.Join(",",listHiddenUnearnedDefNums)}) "; } command += $"GROUP BY patient.Guarantor{(showProvider ? ", provider.Abbr" : "")} "; if (isExcludeNetZeroUnearned) { command += "HAVING ABS(UnallocAmt) > 0.005 "; } //one row per family DataTable tableUnallocatedUnearned = ReportsComplex.RunFuncOnReportServer(() => Db.GetTable(command)); List <long> listGuarantors = tableUnallocatedUnearned.Rows.OfType <DataRow>().Select(x => PIn.Long(x["Guarantor"].ToString())).ToList(); //all procedures for the families that have not been explicitly paid off. //Key: GuarantorNum | Val:ListRemainingProcsForFam List <UnearnedProc> listRemProcs = ReportsComplex.RunFuncOnReportServer(() => Procedures.GetRemainingProcsForFamilies(listGuarantors)); Dictionary <long, List <UnearnedProc> > dictFamRemainingProcs = listRemProcs.GroupBy(x => x.GuarNum) .ToDictionary(x => x.Key, y => y.ToList()); Dictionary <long, double> dictFamilyBalances = ReportsComplex.RunFuncOnReportServer(() => Ledgers.GetBalancesForFamilies(listGuarantors)); Dictionary <long, string> dictPatNames = ReportsComplex.RunFuncOnReportServer(() => Patients.GetPatientNames(Patients.GetAllFamilyPatNums(listGuarantors))); List <ProcedureCode> listProcCodes = ReportsComplex.RunFuncOnReportServer(() => ProcedureCodes.GetAllCodes()); DataTable retVal = new DataTable(); retVal.Columns.Add("Guar"); retVal.Columns.Add("FamBal"); retVal.Columns.Add("FamUnearned"); retVal.Columns.Add("FamRemAmt"); if (showProvider) { retVal.Columns.Add("Prov"); } retVal.Columns.Add("Patient"); retVal.Columns.Add("Code"); retVal.Columns.Add("Date"); retVal.Columns.Add("Fee"); retVal.Columns.Add("RemAmt"); int rowCount = tableUnallocatedUnearned.Rows.Count; //For brevity //This has to be a for-loop instead of foreach so we can access the guarantor number from the next iteration //prior to adding the procedures to the report (to validate whether or not we should add another guarantor row //for a provider for (int i = 0; i < rowCount; i++) { DataRow guarRowCur = tableUnallocatedUnearned.Rows[i]; int nextIndex = i + 1; long guarNum = PIn.Long(guarRowCur["Guarantor"].ToString()); DateTime dateFirstUnalloc = PIn.Date(guarRowCur["DatePay"].ToString()); double unallocAmt = PIn.Double(guarRowCur["UnallocAmt"].ToString()); List <UnearnedProc> listUnearnedProcsForGuar; if (!dictFamRemainingProcs.TryGetValue(guarNum, out listUnearnedProcsForGuar)) { continue; //This family does not have any procedures that need to have money allocated to. } listUnearnedProcsForGuar = listUnearnedProcsForGuar.Where(x => x.Proc.ProcDate >= dateFirstUnalloc).OrderBy(x => x.Proc.ProcDate).ToList(); if (listUnearnedProcsForGuar.Count == 0) { continue; //We only want to show families where the procedure was completed after the unallocated prepayment. } decimal famRemAmt = listUnearnedProcsForGuar.Sum(x => x.UnallocatedAmt); DataRow guarRow = retVal.NewRow(); string guarName; double famBal; dictPatNames.TryGetValue(guarNum, out guarName); dictFamilyBalances.TryGetValue(guarNum, out famBal); guarRow["Guar"] = guarName; guarRow["FamBal"] = famBal.ToString("f"); guarRow["FamUnearned"] = unallocAmt.ToString("f"); guarRow["FamRemAmt"] = famRemAmt.ToString("f"); if (showProvider) { guarRow["Prov"] = guarRowCur["Abbr"]; } retVal.Rows.Add(guarRow); //If the next row has the same guarantor, then we know that it is another provider for this account and we should not populate the procedures yet if (nextIndex < rowCount && guarNum == PIn.Long(tableUnallocatedUnearned.Rows[nextIndex]["Guarantor"].ToString())) { continue; } foreach (UnearnedProc unearnedProc in listUnearnedProcsForGuar) { DataRow newRow = retVal.NewRow(); dictPatNames.TryGetValue(guarNum, out guarName); string patName; if (dictPatNames.TryGetValue(unearnedProc.Proc.PatNum, out patName)) { newRow["Patient"] = patName; } newRow["Code"] = ProcedureCodes.GetStringProcCode(unearnedProc.Proc.CodeNum, listProcCodes); newRow["Date"] = unearnedProc.Proc.ProcDate.ToShortDateString(); newRow["Fee"] = unearnedProc.Proc.ProcFeeTotal.ToString("f"); newRow["RemAmt"] = unearnedProc.UnallocatedAmt.ToString("f"); retVal.Rows.Add(newRow); } } return(retVal); }
public static DataTable GetData(long feeSchedNum, long clinicNum, long provNum, bool isCategories, bool includeBlanks) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), feeSchedNum, clinicNum, provNum, isCategories, includeBlanks)); } DataTable data = GetDataSet(feeSchedNum, clinicNum, provNum); DataTable retVal = new DataTable("ProcCodes"); if (isCategories) { retVal.Columns.Add(new DataColumn("Category")); } retVal.Columns.Add(new DataColumn("Code")); retVal.Columns.Add(new DataColumn("Desc")); retVal.Columns.Add(new DataColumn("Abbr")); retVal.Columns.Add(new DataColumn("Fee")); List <ProcedureCode> listProcCodes = new List <ProcedureCode>(); if (isCategories) { Def[][] arrayDefs = ReportsComplex.RunFuncOnReportServer(() => Defs.GetArrayShortNoCache()); listProcCodes = ReportsComplex.RunFuncOnReportServer(() => ProcedureCodes.GetProcList(arrayDefs)) .OrderBy(x => x.ProcCat).ThenBy(x => x.ProcCode).ToList(); //Ordered by category } else { listProcCodes = ReportsComplex.RunFuncOnReportServer(() => ProcedureCodes.GetAllCodes()); //Ordered by ProcCode, used for the non-category version of the report if they want blanks. } bool isFound; List <Def> listDefs = Defs.GetDefsNoCache(DefCat.ProcCodeCats); for (int i = 0; i < listProcCodes.Count; i++) { isFound = false; DataRow row = retVal.NewRow(); if (isCategories) { //reports should no longer use the cache. Def def = listDefs.FirstOrDefault(x => x.DefNum == listProcCodes[i].ProcCat); row[0] = def == null ? "" : def.ItemName; row[1] = listProcCodes[i].ProcCode; row[2] = listProcCodes[i].Descript; row[3] = listProcCodes[i].AbbrDesc; } else { row[0] = listProcCodes[i].ProcCode; row[1] = listProcCodes[i].Descript; row[2] = listProcCodes[i].AbbrDesc; } for (int j = 0; j < data.Rows.Count; j++) { if (data.Rows[j]["ProcCode"].ToString() == listProcCodes[i].ProcCode) { isFound = true; double amt = PIn.Double(data.Rows[j]["Amount"].ToString()); if (isCategories) { if (amt == -1) { row[4] = ""; isFound = false; } else { row[4] = amt.ToString("n"); } } else { if (amt == -1) { row[3] = ""; isFound = false; } else { row[3] = amt.ToString("n"); } } break; } } if (includeBlanks && !isFound) { retVal.Rows.Add(row); //Including a row that has a blank fee. } else if (isFound) { retVal.Rows.Add(row); } //All other rows (empty rows where we don't want blanks) are not added to the dataset. } return(retVal); }
///<summary>Gets all patplans with DateNextClaims that are today or in the past.</summary> public static DataTable GetOutstandingOrtho() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod())); } if (DataConnection.DBtype == DatabaseType.Oracle) { throw new ApplicationException("Currently not Oracle compatible. Please call support."); } byte orthoMonthsTreat = PrefC.GetByte(PrefName.OrthoDefaultMonthsTreat); long orthoDefaultAutoCodeNum = PrefC.GetLong(PrefName.OrthoAutoProcCodeNum); List <long> listOrthoBandingCodeNums = ProcedureCodes.GetOrthoBandingCodeNums(); string command = @" SELECT CONCAT(patient.LName,', ', patient.FName) Patient, patient.PatNum, carrier.CarrierName, patplan.OrthoAutoNextClaimDate, IF(patientnote.OrthoMonthsTreatOverride=-1, " + orthoMonthsTreat + @", patientnote.OrthoMonthsTreatOverride) MonthsTreat, patclaims.LastSent, patclaims.NumSent, IF(insplan.OrthoAutoProcCodeNumOverride = 0, " + orthoDefaultAutoCodeNum + @", insplan.OrthoAutoProcCodeNumOverride) AS AutoCodeNum, banding.DateBanding, banding.ProvNum, banding.ClinicNum, patplan.PatPlanNum, inssub.InsSubNum, insplan.PlanNum FROM patplan INNER JOIN inssub ON inssub.InsSubNum = patplan.InsSubNum INNER JOIN insplan ON insplan.PlanNum = inssub.PlanNum AND insplan.OrthoType = " + POut.Int((int)OrthoClaimType.InitialPlusPeriodic) + @" INNER JOIN carrier ON carrier.CarrierNum = insplan.CarrierNum INNER JOIN patient ON patient.PatNum = patplan.PatNum LEFT JOIN patientnote ON patientnote.PatNum = patient.PatNum LEFT JOIN ( SELECT MAX(claim.DateSent) LastSent, COUNT(claim.ClaimNum) NumSent, claim.PatNum, claim.InsSubNum, procedurelog.CodeNum FROM claim INNER JOIN claimproc ON claimproc.ClaimNum = claim.ClaimNum INNER JOIN insplan ON claim.PlanNum = insplan.PlanNum INNER JOIN procedurelog ON procedurelog.ProcNum = claimproc.ProcNum AND procedurelog.CodeNum = IF(insplan.OrthoAutoProcCodeNumOverride = 0, " + orthoDefaultAutoCodeNum + @", insplan.OrthoAutoProcCodeNumOverride) WHERE claim.ClaimStatus IN ('S','R') GROUP BY claim.PatNum, claim.InsSubNum )patclaims ON patclaims.PatNum = patplan.PatNum AND patclaims.InsSubNum = patplan.InsSubNum LEFT JOIN ( SELECT procedurelog.PatNum, MIN(procedurelog.ProcDate) AS DateBanding, procedurelog.ProvNum, procedurelog.ClinicNum FROM procedurelog " ; if (listOrthoBandingCodeNums.Count == 0) //The first rendition of ortho auto codes looked for hard coded D codes. { command += @"INNER JOIN procedurecode ON procedurecode.CodeNum = procedurelog.CodeNum AND(procedurecode.ProcCode LIKE 'D8080%' OR procedurecode.ProcCode LIKE 'D8090%') " ; } command += @"WHERE procedurelog.ProcStatus = " + POut.Int((int)ProcStat.C) + " "; if (listOrthoBandingCodeNums.Count > 0) { command += @"AND procedurelog.CodeNum IN ( " + String.Join(",", listOrthoBandingCodeNums) + @") "; } command += @" GROUP BY procedurelog.PatNum )banding ON banding.PatNum = patplan.PatNum WHERE (patplan.OrthoAutoNextClaimDate > " + POut.Date(new DateTime(1880, 1, 1)) + " AND patplan.OrthoAutoNextClaimDate <= " + DbHelper.Curdate() + @") AND patplan.Ordinal IN (1,2) " ; //TODO: Consider the edge case where an office falls behind and the patient really needs to create multiple claims. //E.g. NextClaimDate = 11/01/2016, today is 12/16/2016, this query would only show the Nov. row, but needs to also show a row for 12/01/2016. return(Db.GetTable(command)); }