Ejemplo n.º 1
0
        ///<summary>Gets a good chunk of the data used in the TP Module.</summary>
        public static TPModuleData GetModuleData(long patNum, bool doMakeSecLog)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)           //Remoting role check here to reduce round-trips to the server.
            {
                return(Meth.GetObject <TPModuleData>(MethodBase.GetCurrentMethod(), patNum, doMakeSecLog));
            }
            TPModuleData tpData = new TPModuleData();

            tpData.Fam         = Patients.GetFamily(patNum);
            tpData.Pat         = tpData.Fam.GetPatient(patNum);
            tpData.PatPlanList = PatPlans.Refresh(patNum);
            if (!PatPlans.IsPatPlanListValid(tpData.PatPlanList))
            {
                //PatPlans had invalid references and need to be refreshed.
                tpData.PatPlanList = PatPlans.Refresh(patNum);
            }
            tpData.SubList     = InsSubs.RefreshForFam(tpData.Fam);
            tpData.InsPlanList = InsPlans.RefreshForSubList(tpData.SubList);
            tpData.BenefitList = Benefits.Refresh(tpData.PatPlanList, tpData.SubList);
            tpData.ClaimList   = Claims.Refresh(tpData.Pat.PatNum);
            tpData.HistList    = ClaimProcs.GetHistList(tpData.Pat.PatNum, tpData.BenefitList, tpData.PatPlanList, tpData.InsPlanList, DateTime.Today,
                                                        tpData.SubList);
            tpData.ListSubstLinks = SubstitutionLinks.GetAllForPlans(tpData.InsPlanList);
            TreatPlanType tpTypeCur = (tpData.Pat.DiscountPlanNum == 0?TreatPlanType.Insurance:TreatPlanType.Discount);

            TreatPlans.AuditPlans(patNum, tpTypeCur);
            tpData.ListProcedures = Procedures.Refresh(patNum);
            tpData.ListTreatPlans = TreatPlans.GetAllForPat(patNum);
            tpData.ArrProcTPs     = ProcTPs.Refresh(patNum);
            if (doMakeSecLog)
            {
                SecurityLogs.MakeLogEntry(Permissions.TPModule, patNum, "");
            }
            return(tpData);
        }
Ejemplo n.º 2
0
        ///<summary>Inserts a copy of all of the planNumOld SubstitutionLinks with the planNumNew. This should be done every time a new insplan gets created
        ///and you want to maintain the SubstitutionLink of the old insplan.</summary>
        public static void CopyLinksToNewPlan(long planNumNew, long planNumOld)
        {
            //No need to check RemotingRole; no call to db.
            //Get a list of the sub links of the old insplan. After the foreach loop below, this list will no longer contain the sub links for the old insplan.
            List <SubstitutionLink> listSubstLinksOfOldPlan = SubstitutionLinks.GetAllForPlans(planNumOld);

            foreach (SubstitutionLink subLink in listSubstLinksOfOldPlan)
            {
                //Only change the old planNum with the new planNum. Insert will "create" a new SubstitutionLink with a new primary key.
                subLink.PlanNum = planNumNew;
            }
            InsertMany(listSubstLinksOfOldPlan);
        }
Ejemplo n.º 3
0
        ///<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)));
        }
Ejemplo n.º 4
0
        ///<summary>Gets most of the data needed to load the active treatment plan.</summary>
        ///<param name="doFillHistList">If false, then LoadActiveTPData.HistList will be null.</param>
        public static LoadActiveTPData GetLoadActiveTpData(long patNum, long treatPlanNum, List <Benefit> listBenefits, List <PatPlan> listPatPlans,
                                                           List <InsPlan> listInsPlans, DateTime dateTimeTP, List <InsSub> listInsSubs, bool doFillHistList)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)           //Remoting role check here to reduce round-trips to the server.
            {
                return(Meth.GetObject <LoadActiveTPData>(MethodBase.GetCurrentMethod(), patNum, treatPlanNum, listBenefits, listPatPlans, listInsPlans, dateTimeTP,
                                                         listInsSubs, doFillHistList));
            }
            LoadActiveTPData data = new LoadActiveTPData();

            data.ListTreatPlanAttaches = TreatPlanAttaches.GetAllForTreatPlan(treatPlanNum);
            data.listProcForTP         = Procedures.GetListTPandTPi(Procedures.GetManyProc(data.ListTreatPlanAttaches.Select(x => x.ProcNum).ToList(), false),
                                                                    data.ListTreatPlanAttaches).ToList();
            //One thing to watch out for here is that we must be absolutely sure to include all claimprocs for the procedures listed,
            //regardless of status.  Needed for Procedures.ComputeEstimates.  This should be fine.
            data.ClaimProcList = ClaimProcs.RefreshForTP(patNum);
            if (doFillHistList)
            {
                data.HistList = ClaimProcs.GetHistList(patNum, listBenefits, listPatPlans, listInsPlans, -1, dateTimeTP, listInsSubs);
            }
            data.ListSubLinks = SubstitutionLinks.GetAllForPlans(listInsPlans);
            return(data);
        }
Ejemplo n.º 5
0
        ///<summary>Updates writeoff estimated for claimprocs for the passed in clinics. Called only in FormFeeSchedTools, located here to allow unit
        ///testing. Requires an ODProgressExtended to display UI updates.  If clinics are enabled and the user is not clinic restricted and chooses to run
        ///for all clinics, set doUpdatePrevClinicPref to true so that the ClinicNums will be stored in the preference table as they are finished to allow
        ///for pausing/resuming the process.</summary>
        public static long GlobalUpdateWriteoffs(List <long> listWriteoffClinicNums, ODProgressExtended progress, bool doUpdatePrevClinicPref = false)
        {
            //No need to check RemotingRole; no call to db.
            long       totalWriteoffsUpdated = 0;
            List <Fee> listFeesHQ            = Fees.GetByClinicNum(0);//All HQ fees
            Dictionary <long, List <Procedure> > dictPatProcs;
            List <FamProc> listFamProcs;
            Dictionary <long, List <ClaimProc> > dictClaimProcs;
            List <Fee>            listFeesHQandClinic;
            Lookup <FeeKey2, Fee> lookupFeesByCodeAndSched;
            List <InsSub>         listInsSubs;
            List <InsPlan>        listInsPlans;
            List <PatPlan>        listPatPlans;
            List <Benefit>        listBenefits;
            List <Action>         listActions;
            //Get all objects needed to check if procedures are linked to an orthocase here to avoid querying in loops.
            List <OrthoProcLink>             listOrthoProcLinksAll = new List <OrthoProcLink>();
            Dictionary <long, OrthoProcLink> dictOrthoProcLinksAll = new Dictionary <long, OrthoProcLink>();
            Dictionary <long, OrthoCase>     dictOrthoCases        = new Dictionary <long, OrthoCase>();
            Dictionary <long, OrthoSchedule> dictOrthoSchedules    = new Dictionary <long, OrthoSchedule>();

            OrthoCases.GetDataForAllProcLinks(ref listOrthoProcLinksAll, ref dictOrthoProcLinksAll, ref dictOrthoCases, ref dictOrthoSchedules);
            OrthoProcLink        orthoProcLink = null;
            OrthoCase            orthoCase     = null;
            OrthoSchedule        orthoSchedule = null;
            List <OrthoProcLink> listOrthoProcLinksForOrthoCase = null;

            foreach (long clinicNumCur in listWriteoffClinicNums)
            {
                progress.Fire(ODEventType.FeeSched, new ProgressBarHelper(Clinics.GetAbbr(clinicNumCur), "0%", 0, 100, ProgBarStyle.Blocks, "WriteoffProgress"));
                long   rowCurIndex = 0;               //reset for each clinic.
                object lockObj     = new object();    //used to lock rowCurIndex so the threads will correctly increment the count
                progress.Fire(ODEventType.FeeSched, new ProgressBarHelper(Lans.g("FeeSchedEvent", "Getting list to update writeoffs..."),
                                                                          progressBarEventType: ProgBarEventType.TextMsg));
                listFeesHQandClinic = Fees.GetByClinicNum(clinicNumCur);              //could be empty for some clinics that don't use overrides
                listFeesHQandClinic.AddRange(listFeesHQ);
                lookupFeesByCodeAndSched = (Lookup <FeeKey2, Fee>)listFeesHQandClinic.ToLookup(x => new FeeKey2(x.CodeNum, x.FeeSched));
                dictPatProcs             = Procedures.GetAllTp(clinicNumCur)
                                           .GroupBy(x => x.PatNum)
                                           .ToDictionary(x => x.Key, x => Procedures.SortListByTreatPlanPriority(x.ToList()).ToList());
                #region Has Paused or Cancelled
                while (progress.IsPaused)
                {
                    progress.AllowResume();
                    if (progress.IsCanceled)
                    {
                        break;
                    }
                }
                if (progress.IsCanceled)
                {
                    break;
                }
                #endregion Has Paused or Cancelled
                if (dictPatProcs.Count == 0)
                {
                    continue;
                }
                int procCount = dictPatProcs.Sum(x => x.Value.Count);
                listFamProcs = Patients.GetFamilies(dictPatProcs.Keys.ToList()).Where(x => x.Guarantor != null)
                               .Select(x => new FamProc {
                    GuarNum      = x.Guarantor.PatNum,
                    ListPatProcs = x.ListPats.Select(y => new PatProc {
                        PatNum    = y.PatNum,
                        Age       = y.Age,
                        ListProcs = dictPatProcs.TryGetValue(y.PatNum, out List <Procedure> listProcsCurr)?listProcsCurr:new List <Procedure>()
                    }).ToList()
                }).ToList();
                listPatPlans = PatPlans.GetPatPlansForPats(dictPatProcs.Keys.ToList());
                listInsSubs  = InsSubs.GetListInsSubs(dictPatProcs.Keys.ToList());
                List <long> listInsSubNums = listInsSubs.Select(x => x.InsSubNum).ToList();
                listInsSubs.AddRange(InsSubs.GetMany(listPatPlans.Select(x => x.InsSubNum).Distinct().Where(x => !listInsSubNums.Contains(x)).ToList()));
                listInsSubs  = listInsSubs.DistinctBy(x => x.InsSubNum).ToList();
                listInsPlans = InsPlans.RefreshForSubList(listInsSubs);
                listBenefits = Benefits.GetAllForPatPlans(listPatPlans, listInsSubs);
                #region Has Paused or Cancelled
                while (progress.IsPaused)
                {
                    progress.AllowResume();
                    if (progress.IsCanceled)
                    {
                        break;
                    }
                }
                if (progress.IsCanceled)
                {
                    break;
                }
                #endregion Has Paused or Cancelled
                //dictionary of key=PatNum, value=list of claimprocs, i.e. a dictionary linking each PatNum to a list of claimprocs for the given procs
                dictClaimProcs = ClaimProcs.GetForProcs(dictPatProcs.SelectMany(x => x.Value.Select(y => y.ProcNum)).ToList(), useDataReader: true)
                                 .GroupBy(x => x.PatNum)
                                 .ToDictionary(x => x.Key, x => x.ToList());
                #region Has Paused or Cancelled
                while (progress.IsPaused)
                {
                    progress.AllowResume();
                    if (progress.IsCanceled)
                    {
                        break;
                    }
                }
                if (progress.IsCanceled)
                {
                    break;
                }
                #endregion Has Paused or Cancelled
                progress.Fire(ODEventType.FeeSched, new ProgressBarHelper(Lans.g("FeeSchedEvent", "Updating writeoff estimates for patients..."),
                                                                          progressBarEventType: ProgBarEventType.TextMsg));
                listActions = listFamProcs.Select(x => new Action(() => {
                    #region Has Cancelled
                    if (progress.IsCanceled)
                    {
                        return;
                    }
                    #endregion Has Cancelled
                    List <long> listPatNums = x.ListPatProcs.Select(y => y.PatNum).ToList();
                    List <long> listInsSubNumsPatPlanCur          = listPatPlans.Where(y => y.PatNum.In(listPatNums)).Select(y => y.InsSubNum).ToList();
                    List <InsSub> listInsSubsCur                  = listInsSubs.FindAll(y => listPatNums.Contains(y.Subscriber) || y.InsSubNum.In(listInsSubNumsPatPlanCur));
                    List <long> listInsSubPlanNumsCur             = listInsSubsCur.Select(y => y.PlanNum).ToList();
                    List <InsPlan> listInsPlansCur                = listInsPlans.FindAll(y => listInsSubPlanNumsCur.Contains(y.PlanNum));
                    List <SubstitutionLink> listSubstitutionLinks = SubstitutionLinks.GetAllForPlans(listInsPlansCur);
                    List <PatPlan> listPatPlansCur;
                    List <Benefit> listBenefitsCur;
                    foreach (PatProc patProc in x.ListPatProcs)                     //foreach patient in the family
                    {
                        if (patProc.ListProcs.IsNullOrEmpty())
                        {
                            continue;
                        }
                        listPatPlansCur = listPatPlans.FindAll(y => y.PatNum == patProc.PatNum);
                        List <long> listInsPlanNumsCur = listInsPlansCur.Select(y => y.PlanNum).ToList();
                        List <long> listPatPlanNumsCur = listPatPlansCur.Select(y => y.PatPlanNum).ToList();
                        listBenefitsCur = listBenefits
                                          .FindAll(y => listInsPlanNumsCur.Contains(y.PlanNum) || listPatPlanNumsCur.Contains(y.PatPlanNum));
                        listBenefitsCur.Sort(Benefits.SortBenefits);
                        if (!dictClaimProcs.TryGetValue(patProc.PatNum, out List <ClaimProc> listClaimProcsCur))
                        {
                            listClaimProcsCur = new List <ClaimProc>();
                        }
                        foreach (Procedure procCur in patProc.ListProcs)                         //foreach proc for this patient
                        {
                            OrthoCases.FillOrthoCaseObjectsForProc(procCur.ProcNum, ref orthoProcLink, ref orthoCase, ref orthoSchedule
                                                                   , ref listOrthoProcLinksForOrthoCase, dictOrthoProcLinksAll, dictOrthoCases, dictOrthoSchedules, listOrthoProcLinksAll);
                            Procedures.ComputeEstimates(procCur, patProc.PatNum, ref listClaimProcsCur, false, listInsPlansCur, listPatPlansCur, listBenefitsCur,
                                                        null, null, true, patProc.Age, listInsSubsCur, listSubstLinks: listSubstitutionLinks, lookupFees: lookupFeesByCodeAndSched,
                                                        orthoProcLink: orthoProcLink, orthoCase: orthoCase, orthoSchedule: orthoSchedule, listOrthoProcLinksForOrthoCase: listOrthoProcLinksForOrthoCase);
                            double percentage = 0;
                            lock (lockObj) {
                                percentage = Math.Ceiling(((double)(++rowCurIndex) / procCount) * 100);
                            }
                            progress.Fire(ODEventType.FeeSched,
                                          new ProgressBarHelper(Clinics.GetAbbr(clinicNumCur), (int)percentage + "%", (int)percentage, 100, ProgBarStyle.Blocks, "WriteoffProgress"));
                        }
                    }
                })).ToList();
                ODThread.RunParallel(listActions, TimeSpan.FromHours(3),
                                     onException: new ODThread.ExceptionDelegate((ex) => {
                    //Notify the user what went wrong via the text box.
                    progress.Fire(ODEventType.FeeSched, new ProgressBarHelper("Error updating writeoffs: " + ex.Message,
                                                                              progressBarEventType: ProgBarEventType.TextMsg));
                })
                                     );
                if (listWriteoffClinicNums.Count > 1)               //only show if more than one clinic
                {
                    progress.Fire(ODEventType.FeeSched,
                                  new ProgressBarHelper(rowCurIndex + " " + Lans.g("FeeSchedTools", "procedures processed from") + " " + Clinics.GetAbbr(clinicNumCur),
                                                        progressBarEventType: ProgBarEventType.TextMsg));
                }
                totalWriteoffsUpdated += rowCurIndex;
                if (doUpdatePrevClinicPref && rowCurIndex == procCount)
                {
                    //if storing previously completed clinic and we actually completed this clinic's procs, update the pref
                    if (listWriteoffClinicNums.Last() == clinicNumCur)
                    {
                        //if this is the last clinic in the list, clear the last clinic pref so the next time it will run for all clinics
                        Prefs.UpdateString(PrefName.GlobalUpdateWriteOffLastClinicCompleted, "");
                    }
                    else
                    {
                        Prefs.UpdateString(PrefName.GlobalUpdateWriteOffLastClinicCompleted, POut.Long(clinicNumCur));
                    }
                    Signalods.SetInvalid(InvalidType.Prefs);
                }
                #region Has Cancelled
                if (progress.IsCanceled)
                {
                    break;
                }
                #endregion Has Cancelled
            }
            progress.OnProgressDone();
            progress.Fire(ODEventType.FeeSched, new ProgressBarHelper("Writeoffs updated. " + totalWriteoffsUpdated + " procedures processed.\r\nDone.",
                                                                      progressBarEventType: ProgBarEventType.TextMsg));
            return(totalWriteoffsUpdated);
        }