Exemplo n.º 1
0
        ///<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.
        }
Exemplo n.º 2
0
        ///<summary>True if we are in HQ, AvaTax is enabled, we tax the customer's state, and the procedure has a taxable proccode. Note that if the
        ///customer has an invalid zip but all other conditions are met, we will still return true because this procedure is still taxable by our rules
        ///we just know we would get an error back from Avalara. This method returning false will result in the procedure being created as before
        ///but without tax, so we need to return true for an invalid zip and let Avalara produce the error. Can execute two queries.</summary>
        public static bool DoSendProcToAvalara(Procedure proc, bool isSilent = false)
        {
            ProcedureCode procCode = ProcedureCodes.GetProcCode(proc.CodeNum);

            if (!IsEnabled())
            {
                return(false);
            }
            if (proc.ProcFee == 0)          //repeat charges for prepay use ProcFee=0
            {
                return(false);
            }
            Patient patient = Patients.GetPat(proc.PatNum);

            //don't call IsTaxable() here, because that would get pat twice, so duplicating some if its functionality:
            if (patient == null)
            {
                return(false);
            }
            if (ListTaxableStates.Count == 0)
            {
                return(false);               //no taxable states
            }
            if (!HasTaxableState(patient))   //if this patient is not in a taxable state
            {
                return(false);
            }
            if (TaxExemptPatField == null)          //no tax exempt pat field entered in setup
            {
                return(false);
            }
            PatField taxExempt = PatFields.Refresh(patient.PatNum).FirstOrDefault(x => x.FieldName == TaxExemptPatField.FieldName);

            if (taxExempt != null && PIn.Bool(taxExempt.FieldValue)) //patient field exists and is true
            {
                return(false);                                       //so not taxable
            }
            //end of the duplicated functionality from IsTaxable().
            string procTaxCode = GetTaxOverrideIfNeeded(patient, procCode); //could be an avalara code, an override, or a percent

            if (string.IsNullOrWhiteSpace(procTaxCode))                     //if there is no avalara code or percent for this proc/state
            {
                return(false);
            }
            if (!Patients.HasValidUSZipCode(patient))
            {
                if (isSilent)
                {
                    _logger.WriteLine($"Invalid ZipCode for PatNum {proc.PatNum} while running Repeat Charge Tool on {DateTime.Today}", LogLevel.Error);
                }
                else
                {
                    //Remove the message box for now to avoid it from popping up on the server, stopping anyone using middletier to continue
                    //forward, because they can't click OK in the message box.
                    //MessageBox.Show("A valid zip code is required to process sales tax on procedures in this patient's state. "
                    //+"Please update the patient information with a valid zip code before continuing.");
                }
            }
            return(true);
        }
Exemplo n.º 3
0
        ///<summary>Returns the tax estimate for this specific patient, procCode, and feeAmts.
        ///Calls AvaTax/CreateTransaction: https://developer.avalara.com/api-reference/avatax/rest/v2/methods/Transactions/CreateTransaction/ but does
        ///not save the transaction in the Avalara DB.</summary>
        public static decimal GetEstimate(long codeNum, long patNum, double procFee, bool hasExceptions = false)
        {
            if (!IsTaxable(patNum))
            {
                return(0);
            }
            ProcedureCode procCode       = ProcedureCodes.GetProcCode(codeNum);
            string        strTaxOverride = GetTaxOverrideIfNeeded(Patients.GetPat(patNum), procCode);

            if (strTaxOverride != "" && strTaxOverride.EndsWith("%"))
            {
                double percent = PIn.Double(strTaxOverride.TrimEnd('%'));
                return((decimal)(procFee * percent / 100d));
            }
            try {
                TransactionBuilder builder = SetUpTransaction(DocumentType.SalesOrder, patNum);             //Sales Order is AvaTax's way of getting an estimate
                builder.WithLine((decimal)procFee, 1, strTaxOverride, procCode.Descript, procCode.ProcCode);
                TransactionModel result = Client.CreateTransaction("Lines", builder.GetCreateTransactionModel());
                return(result.totalTax.Value);
            }
            catch (Exception ex) {
                _logger.WriteLine($"Error getting estimate from Avatax for PatNum: {patNum}", LogLevel.Error);
                if (hasExceptions)
                {
                    throw ex;                    //Loses call stack, but everywhere that catches this only cares about the message.
                }
                ex.DoNothing();
                //For now we just enter $0 because we don't have any proc or adjustment to attach this to, and we already have logging for errors
                return(0);
            }
        }
Exemplo 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(Patient pat, long treatPlanNum, List <Benefit> listBenefits, List <PatPlan> listPatPlans,
                                                           List <InsPlan> listInsPlans, DateTime dateTimeTP, List <InsSub> listInsSubs, bool doFillHistList, bool isTreatPlanSortByTooth,
                                                           List <SubstitutionLink> listSubstLinks)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)           //Remoting role check here to reduce round-trips to the server.
            {
                return(Meth.GetObject <LoadActiveTPData>(MethodBase.GetCurrentMethod(), pat, treatPlanNum, listBenefits, listPatPlans, listInsPlans, dateTimeTP,
                                                         listInsSubs, doFillHistList, isTreatPlanSortByTooth, listSubstLinks));
            }
            LoadActiveTPData data = new LoadActiveTPData();

            data.ListTreatPlanAttaches = TreatPlanAttaches.GetAllForTreatPlan(treatPlanNum);
            List <Procedure> listProcs = Procedures.GetManyProc(data.ListTreatPlanAttaches.Select(x => x.ProcNum).ToList(), false);

            data.listProcForTP = Procedures.SortListByTreatPlanPriority(listProcs.FindAll(x => x.ProcStatus == ProcStat.TP || x.ProcStatus == ProcStat.TPi)
                                                                        , isTreatPlanSortByTooth, 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(pat.PatNum);
            if (doFillHistList)
            {
                data.HistList = ClaimProcs.GetHistList(pat.PatNum, listBenefits, listPatPlans, listInsPlans, -1, dateTimeTP, listInsSubs);
            }
            List <ProcedureCode> listProcedureCodes = new List <ProcedureCode>();

            foreach (Procedure procedure in listProcs)
            {
                listProcedureCodes.Add(ProcedureCodes.GetProcCode(procedure.CodeNum));
            }
            data.ListFees = Fees.GetListFromObjects(listProcedureCodes, listProcs.Select(x => x.MedicalCode).ToList(), listProcs.Select(x => x.ProvNum).ToList(),
                                                    pat.PriProv, pat.SecProv, pat.FeeSched, listInsPlans, listProcs.Select(x => x.ClinicNum).ToList(), null,//appts can be null because provs already set
                                                    listSubstLinks, pat.DiscountPlanNum);
            return(data);
        }
Exemplo n.º 5
0
        ///<summary>Gets the note for the given provider, if one exists.  Otherwise, gets the proccode.defaultnote.
        ///Currently procStatus only supports TP or C statuses.</summary>
        public static string GetNote(long provNum, long codeNum, ProcStat procStatus, bool isGroupNote = false)
        {
            //No need to check RemotingRole; no call to db.
            List <ProcCodeNote> listProcCodeNotes = GetDeepCopy();

            for (int i = 0; i < listProcCodeNotes.Count; i++)
            {
                if (listProcCodeNotes[i].ProvNum != provNum)
                {
                    continue;
                }
                if (listProcCodeNotes[i].CodeNum != codeNum)
                {
                    continue;
                }
                //Skip provider specific notes if this is a group note and the procedure is not complete
                // OR if this is NOT a group note and the procedure does not have the desired status.
                if ((isGroupNote && listProcCodeNotes[i].ProcStatus != ProcStat.C) ||
                    (!isGroupNote && listProcCodeNotes[i].ProcStatus != procStatus))
                {
                    continue;
                }
                return(listProcCodeNotes[i].Note);
            }
            //A provider specific procedure code note could not be found, use the default for the procedure code.
            if (procStatus == ProcStat.TP)
            {
                return(ProcedureCodes.GetProcCode(codeNum).DefaultTPNote);
            }
            return(ProcedureCodes.GetProcCode(codeNum).DefaultNote);
        }
Exemplo n.º 6
0
        ///<summary>Gets the time pattern for the given provider, if one exists.  Otherwise, gets the proccode.ProcTime.</summary>
        public static string GetTimePattern(long provNum, long codeNum)
        {
            //No need to check RemotingRole; no call to db.
            ProcCodeNote procCodeNote = GetFirstOrDefault(x => x.ProvNum == provNum && x.CodeNum == codeNum);

            return(procCodeNote == null ? ProcedureCodes.GetProcCode(codeNum).ProcTime : procCodeNote.ProcTime);
        }
Exemplo n.º 7
0
 ///<summary>Returns true if the toothNum passed in has ever had an implant before. Based on the given patient procedures.</summary>
 private static bool IsToothImplant(int toothNum, List <Procedure> listProcsForPatient)
 {
     return(listProcsForPatient
            .FindAll(x => x.ToothNum == toothNum.ToString() && x.ProcStatus.In(ProcStat.C, ProcStat.EC, ProcStat.EO))
            //ProcedureCodes are cached.
            .Any(x => ProcedureCodes.GetProcCode(x.CodeNum).PaintType == ToothPaintingType.Implant));
 }
Exemplo n.º 8
0
 ///<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));
 }
Exemplo n.º 9
0
        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);
        }
Exemplo n.º 10
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> 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)));
        }
Exemplo n.º 11
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)));
        }
Exemplo n.º 12
0
        ///<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);
        }
Exemplo n.º 13
0
 ///<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);
 }
Exemplo n.º 14
0
        ///<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       = new List <ProcedureCode>();
                listProcCodeStrings.ForEach(x => listProcCodes.Add(ProcedureCodes.GetProcCode(x)));
                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);
        }
Exemplo n.º 15
0
        ///<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);
        }
Exemplo n.º 16
0
        ///<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.
        }
Exemplo n.º 17
0
        ///<summary>Copies one fee schedule to one or more fee schedules.  fromClinicNum, fromProvNum, and toProvNum can be zero.  Set listClinicNumsTo to copy to multiple clinic overrides.  If this list is null or empty, clinicNum 0 will be used.</summary>
        public static void CopyFeeSchedule(FeeSched fromFeeSched, long fromClinicNum, long fromProvNum, FeeSched toFeeSched, List <long> listClinicNumsTo, long toProvNum)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                Meth.GetVoid(MethodBase.GetCurrentMethod(), fromFeeSched, fromClinicNum, fromProvNum, toFeeSched, listClinicNumsTo, toProvNum);
                return;
            }
            if (listClinicNumsTo == null)
            {
                listClinicNumsTo = new List <long>();
            }
            if (listClinicNumsTo.Count == 0)
            {
                listClinicNumsTo.Add(0);
            }
            //Store a local copy of the fees from the old FeeSched
            List <Fee> listFeeLocalCopy = Fees.GetListExact(toFeeSched.FeeSchedNum, listClinicNumsTo, toProvNum);

            //Delete all fees that exactly match setting in "To" combo selections.
            foreach (long clinicNum in listClinicNumsTo)
            {
                Fees.DeleteFees(toFeeSched.FeeSchedNum, clinicNum, toProvNum);
            }
            //Copy:
            List <Fee>    listNewFees = Fees.GetListExact(fromFeeSched.FeeSchedNum, fromClinicNum, fromProvNum);
            int           blockValue  = 0;
            int           blockMax    = (listNewFees.Count * listClinicNumsTo.Count);
            object        locker      = new object();
            List <Action> listActions = new List <Action>();

            foreach (long clinicNumTo in listClinicNumsTo)
            {
                listActions.Add(() => {
                    foreach (Fee fee in listNewFees)
                    {
                        bool isReplacementFee = false;
                        Fee newFee            = fee.Copy();
                        newFee.FeeNum         = 0;
                        newFee.ProvNum        = toProvNum;
                        newFee.ClinicNum      = clinicNumTo;
                        newFee.FeeSched       = toFeeSched.FeeSchedNum;
                        Fees.Insert(newFee);
                        //Check to see if this replaced an old fee with the same fee details
                        Fee oldFee = listFeeLocalCopy.Where(x => x.ProvNum == newFee.ProvNum)
                                     .Where(x => x.ClinicNum == newFee.ClinicNum)
                                     .Where(x => x.CodeNum == newFee.CodeNum)
                                     .Where(x => x.FeeSched == newFee.FeeSched)
                                     .FirstOrDefault();
                        if (oldFee != null)
                        {
                            isReplacementFee = true;
                        }
                        ProcedureCode procCode = ProcedureCodes.GetProcCode(fee.CodeNum);
                        string securityLogText = "Fee Schedule \"" + fromFeeSched.Description + "\" copied to Fee Schedule \"" + toFeeSched.Description + "\", ";
                        if (clinicNumTo != 0)
                        {
                            securityLogText += "To Clinic \"" + Clinics.GetDesc(clinicNumTo) + "\", ";
                        }
                        securityLogText += "Proc Code \"" + procCode.ProcCode + "\", Fee \"" + fee.Amount + "\", ";
                        if (isReplacementFee)
                        {
                            securityLogText += "Replacing Previous Fee \"" + oldFee.Amount + "\"";
                        }
                        SecurityLogs.MakeLogEntry(Permissions.FeeSchedEdit, 0, securityLogText);
                        FeeSchedEvent.Fire(ODEventType.FeeSched,
                                           new ProgressBarHelper(Lans.g("FormFeeSchedTools", "Copying fees, please wait") + "...", blockValue: blockValue, blockMax: blockMax,
                                                                 progressStyle: ProgBarStyle.Continuous));
                        lock (locker) {
                            blockValue++;
                        }
                    }
                });
            }
            //Research and testing will determine whether we can run this on multiple threads.
            ODThread.RunParallel(listActions, TimeSpan.FromMinutes(30), numThreads: 1);
        }
Exemplo n.º 18
0
        public EB271(X12Segment segment, bool isInNetwork)
        {
            if (eb01 == null)
            {
                FillDictionaries();
            }
            Segment = segment;
            SupplementalSegments = new List <X12Segment>();
            //start pattern matching to generate closest Benefit
            EB01          eb01val  = eb01.Find(EB01MatchesCode);
            EB02          eb02val  = eb02.Find(EB02MatchesCode);
            EB03          eb03val  = eb03.Find(EB03MatchesCode);
            EB06          eb06val  = eb06.Find(EB06MatchesCode);
            EB09          eb09val  = eb09.Find(EB09MatchesCode);
            ProcedureCode proccode = null;

            if (ProcedureCodes.IsValidCode(Segment.Get(13, 2)))
            {
                proccode = ProcedureCodes.GetProcCode(Segment.Get(13, 2));
            }
            if (!eb01val.IsSupported ||
                (eb02val != null && !eb02val.IsSupported) ||
                (eb03val != null && !eb03val.IsSupported) ||
                (eb06val != null && !eb06val.IsSupported) ||
                (eb09val != null && !eb09val.IsSupported))
            {
                Benefitt = null;
                return;
            }
            if (eb01val.BenefitType == InsBenefitType.ActiveCoverage && Segment.Get(3) == "30")
            {
                Benefitt = null;
                return;
            }
            if (eb01val.BenefitType == InsBenefitType.ActiveCoverage && proccode != null)
            {
                //A code is covered.  Informational only.
                Benefitt = null;
                return;
            }
            if (Segment.Get(8) != "")           //if percentage
            //must have either a category or a proc code
            {
                if (proccode == null)                                                                                                       //if no proc code is specified
                {
                    if (eb03val == null || eb03val.ServiceType == EbenefitCategory.None || eb03val.ServiceType == EbenefitCategory.General) //and no category specified
                    {
                        Benefitt = null;
                        return;
                    }
                }
            }
            //coinsurance amounts are handled with fee schedules rather than benefits
            if (eb01val.BenefitType == InsBenefitType.CoPayment || eb01val.BenefitType == InsBenefitType.CoInsurance)
            {
                if (Segment.Get(7) != "")               //and a monetary amount specified
                {
                    Benefitt = null;
                    return;
                }
            }
            //a limitation without an amount is meaningless
            if (eb01val.BenefitType == InsBenefitType.Limitations)
            {
                if (Segment.Get(7) == "")               //no monetary amount specified
                {
                    Benefitt = null;
                    return;
                }
            }
            if (isInNetwork && Segment.Get(12) == "N")
            {
                Benefitt = null;
                return;
            }
            if (!isInNetwork && Segment.Get(12) == "Y")
            {
                Benefitt = null;
                return;
            }
            //if only a quantity is specified with no qualifier, it's meaningless
            if (Segment.Get(10) != "" && eb09val == null)
            {
                Benefitt = null;
                return;
            }
            //if only a qualifier is specified with no quantity, it's meaningless
            if (eb09val != null && Segment.Get(10) == "")
            {
                Benefitt = null;
                return;
            }
            Benefitt = new Benefit();
            //1
            Benefitt.BenefitType = eb01val.BenefitType;
            //2
            if (eb02val != null)
            {
                Benefitt.CoverageLevel = eb02val.CoverageLevel;
            }
            //3
            if (eb03val != null)
            {
                Benefitt.CovCatNum = CovCats.GetForEbenCat(eb03val.ServiceType).CovCatNum;
            }
            //4-Insurance type - we ignore.
            //5-Plan description - we ignore.
            //6
            if (eb06val != null)
            {
                Benefitt.TimePeriod = eb06val.TimePeriod;
            }
            //7
            if (Segment.Get(7) != "")
            {
                Benefitt.MonetaryAmt = PIn.Double(Segment.Get(7));              //Monetary amount. Situational
            }
            //8
            if (Segment.Get(8) != "")
            {
                Benefitt.Percent       = 100 - (int)(PIn.Double(Segment.Get(8)) * 100);    //Percent. Situational
                Benefitt.CoverageLevel = BenefitCoverageLevel.None;
            }
            //9-Quantity qualifier
            if (eb09val != null)
            {
                Benefitt.QuantityQualifier = eb09val.QuantityQualifier;
            }
            //10-Quantity
            if (Segment.Get(10) != "")
            {
                Benefitt.Quantity = (byte)PIn.Double(Segment.Get(10));              //Example: "19.0" with Quantity qualifier "S7" (age).
            }
            //11-Authorization. Ignored.
            //12-In network. Ignored.
            //13-proc
            if (proccode != null)
            {
                Benefitt.CodeNum = proccode.CodeNum;              //element 13,2
            }
        }
Exemplo n.º 19
0
        ///<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);
        }
Exemplo n.º 20
0
        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);
        }
Exemplo n.º 21
0
 /// <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, "");
     }
 }
Exemplo n.º 22
0
        public EB271(X12Segment segment, bool isInNetwork, bool isCoinsuranceInverted, X12Segment segHsd = null)
        {
            if (eb01 == null)
            {
                FillDictionaries();
            }
            Segment = segment;
            SupplementalSegments = new List <X12Segment>();
            //start pattern matching to generate closest Benefit
            EB01          eb01val  = eb01.Find(EB01MatchesCode);
            EB02          eb02val  = eb02.Find(EB02MatchesCode);
            EB03          eb03val  = eb03.Find(EB03MatchesCode);
            EB06          eb06val  = eb06.Find(EB06MatchesCode);
            EB09          eb09val  = eb09.Find(EB09MatchesCode);
            ProcedureCode proccode = null;

            if (ProcedureCodes.IsValidCode(Segment.Get(13, 2)))
            {
                proccode = ProcedureCodes.GetProcCode(Segment.Get(13, 2));
            }
            if (!eb01val.IsSupported ||
                (eb02val != null && !eb02val.IsSupported) ||
                (eb03val != null && !eb03val.IsSupported) ||
                (eb06val != null && !eb06val.IsSupported) ||
                (eb09val != null && !eb09val.IsSupported))
            {
                Benefitt = null;
                return;
            }
            if (eb01val.BenefitType == InsBenefitType.ActiveCoverage && Segment.Get(3) == "30")
            {
                Benefitt = null;
                return;
            }
            if (eb01val.BenefitType == InsBenefitType.ActiveCoverage && proccode != null)
            {
                //A code is covered.  Informational only.
                Benefitt = null;
                return;
            }
            if (Segment.Get(8) != "")           //if percentage
            //must have either a category or a proc code
            {
                if (proccode == null)                                                                                                       //if no proc code is specified
                {
                    if (eb03val == null || eb03val.ServiceType == EbenefitCategory.None || eb03val.ServiceType == EbenefitCategory.General) //and no category specified
                    {
                        Benefitt = null;
                        return;
                    }
                }
            }
            //coinsurance amounts are handled with fee schedules rather than benefits
            if (eb01val.BenefitType == InsBenefitType.CoPayment || eb01val.BenefitType == InsBenefitType.CoInsurance)
            {
                if (Segment.Get(7) != "")               //and a monetary amount specified
                {
                    Benefitt = null;
                    return;
                }
            }
            //a limitation without an amount is meaningless
            if (eb01val.BenefitType == InsBenefitType.Limitations &&
                segHsd == null)                 //Some benefits do not have monetary value but limit service in a time period.  Originally done for customer 27936.
            {
                if (Segment.Get(7) == "")       //no monetary amount specified
                {
                    Benefitt = null;
                    return;
                }
            }
            if (isInNetwork && (Segment.Get(12) == "N" || Segment.Get(12) == "U"))
            {
                Benefitt = null;
                return;
            }
            if (!isInNetwork && Segment.Get(12) == "Y")
            {
                Benefitt = null;
                return;
            }
            //if only a quantity is specified with no qualifier, it's meaningless
            if (Segment.Get(10) != "" && eb09val == null)
            {
                Benefitt = null;
                return;
            }
            //if only a qualifier is specified with no quantity, it's meaningless
            if (eb09val != null && Segment.Get(10) == "")
            {
                Benefitt = null;
                return;
            }
            Benefitt = new Benefit();
            //1
            Benefitt.BenefitType = eb01val.BenefitType;
            //2
            if (eb02val != null)
            {
                Benefitt.CoverageLevel = eb02val.CoverageLevel;
            }
            //3
            if (eb03val != null)
            {
                Benefitt.CovCatNum = CovCats.GetForEbenCat(eb03val.ServiceType).CovCatNum;
            }
            //4-Insurance type - we ignore.
            //5-Plan description - we ignore.
            //6
            if (eb06val != null)
            {
                Benefitt.TimePeriod = eb06val.TimePeriod;
            }
            //7
            if (Segment.Get(7) != "")
            {
                Benefitt.MonetaryAmt = PIn.Double(Segment.Get(7));              //Monetary amount. Situational
            }
            //8
            if (Segment.Get(8) != "")
            {
                if (isCoinsuranceInverted && Benefitt.BenefitType == InsBenefitType.CoInsurance) //Some carriers incorrectly send insurance percentage.
                {
                    Benefitt.Percent = (int)(PIn.Double(Segment.Get(8)) * 100);                  //Percent. Came to us inverted, do Not Invert.
                }
                else
                {
                    //OD shows the percentage paid by Insurance by default.
                    //Some carriers submit 271s to us showing percentage paid by Patient, so we need to invert this case to match OD expectations.
                    Benefitt.Percent = 100 - (int)(PIn.Double(Segment.Get(8)) * 100);              //Percent. Invert.
                }
                Benefitt.CoverageLevel = BenefitCoverageLevel.None;
            }
            //9-Quantity qualifier
            if (eb09val != null)
            {
                Benefitt.QuantityQualifier = eb09val.QuantityQualifier;
            }
            //10-Quantity
            if (Segment.Get(10) != "")
            {
                Benefitt.Quantity = (byte)PIn.Double(Segment.Get(10));              //Example: "19.0" with Quantity qualifier "S7" (age).
            }
            //11-Authorization. Ignored.
            //12-In network. Ignored.
            //13-proc
            if (proccode != null)
            {
                Benefitt.CodeNum = proccode.CodeNum;              //element 13,2
            }
            if (Benefitt.BenefitType == InsBenefitType.Limitations &&
                proccode != null &&               //Valid ADA code.
                segHsd != null)
            {
                if (segHsd.Elements.Length < 6 || segHsd.Elements[2] == "" || segHsd.Elements[5] == "")
                {
                    Benefitt = null;
                    return;
                }
                Benefitt.Quantity   = PIn.Byte(segHsd.Elements[2]);                                      //HSD02: Quantity.
                Benefitt.TimePeriod = eb06.FirstOrDefault(x => x.Code == segHsd.Elements[5]).TimePeriod; //HSD05: Frequency.
            }
        }
Exemplo n.º 23
0
        ///<summary>The most human-readable description possible for a single element.</summary>
        public string GetDescript(int elementPos, bool isMessageMode, bool isCoinsurancePatPays = true)
        {
            string elementCode = Segment.Get(elementPos);

            if (elementCode == "")
            {
                return("");
            }
            switch (elementPos)
            {
            case 1:
                //This is a required element, but we still won't assume it's found
                EB01 eb01val = eb01.Find(EB01MatchesCode);
                if (eb01val == null)
                {
                    return("");
                }
                if (eb01val.Code == "D" && isMessageMode)                       //D is for benefit description, which is already obvious
                {
                    return("");
                }
                return(eb01val.Descript);

            case 2:
                EB02 eb02val = eb02.Find(EB02MatchesCode);
                if (eb02val == null)
                {
                    return("");
                }
                return(eb02val.Descript);

            case 3:
                EB03 eb03val = eb03.Find(EB03MatchesCode);
                if (eb03val == null)
                {
                    return("");
                }
                return(eb03val.Descript);

            case 4:
                if (!EB04.ContainsKey(elementCode))
                {
                    return("");
                }
                return(EB04[elementCode]);

            case 5:
                return(Segment.Get(5));

            case 6:
                EB06 eb06val = eb06.Find(EB06MatchesCode);
                if (eb06val == null)
                {
                    return("");
                }
                return(eb06val.Descript);

            case 7:
                return(PIn.Double(elementCode).ToString("c"));                       //Monetary amount. Situational

            case 8:
                if (isMessageMode)                                            //delta sends 80% instead of 20% like they should
                {
                    return((PIn.Double(elementCode) * 100).ToString() + "%"); //Percent.
                }
                else
                {
                    string leadingStr = "Patient pays ";
                    if (!isCoinsurancePatPays)
                    {
                        leadingStr = "Insurance pays ";
                    }
                    return(leadingStr + (PIn.Double(elementCode) * 100).ToString() + "%");                     //Percent. Situational
                }

            case 9:                    //Quantity qualifier. Situational
                EB09 eb09val = eb09.Find(EB09MatchesCode);
                if (eb09val == null)
                {
                    return("");
                }
                return(eb09val.Descript);

            case 10:
                return(elementCode);                       //Quantity. Situational

            case 11:
                return("Authorization Required-" + elementCode); //Situational.

            case 12:                                             //Situational.
                if (elementCode == "Y")
                {
                    return("In network");
                }
                else if (elementCode == "N")
                {
                    return("Out of network");
                }
                else                          //elementCode=="U"
                {
                    return("Unknown if in network");
                }

            case 13:
                string procStr = Segment.Get(13, 2);
                if (procStr == "")
                {
                    return("");
                }
                ProcedureCode procCode = ProcedureCodes.GetProcCode(procStr);
                return(procStr + " - " + procCode.AbbrDesc);                   //ProcedureCodes.GetLaymanTerm(procCode.CodeNum);

            //Even though we don't make requests about specific procedure codes, some ins co's will send back codes.
            default:
                return("");
            }
        }
Exemplo n.º 24
0
        ///<summary>Creates a bulk estimate currently specifically for the pre-payment tool.  Takes in a special dictionary of procedurecodes mapped
        ///to a list of tuples containing the qty and single item prices for the provided procedure codes, then builds a single transaction to
        ///hold the data.  This method creates its own procedures and adjustments.</summary>
        public static void CreatePrepaymentTransaction(Dictionary <ProcedureCode, List <TransQtyAmt> > dictProcCodes, Patient patCur, List <Procedure> listCompletedProcs)
        {
            Dictionary <Procedure, int> dictProcsToCreate = new Dictionary <Procedure, int>();
            //Build the transaction for all of the items in a single transaction.
            TransactionBuilder builder = SetUpTransaction(DocumentType.SalesOrder, patCur.PatNum);         //Sales Order is AvaTax's way of getting an estimate

            foreach (ProcedureCode procCode in dictProcCodes.Keys)
            {
                Procedure procCur = new Procedure()
                {
                    PatNum       = patCur.PatNum,
                    ProvNum      = 7,             //HQ only this is jordan's provNum.
                    ProcDate     = DateTime.Today,
                    DateEntryC   = DateTime.Now,
                    DateComplete = DateTime.Now,
                    CodeNum      = procCode.CodeNum,
                    ProcStatus   = ProcStat.C
                };
                int totalCount = 0;
                foreach (TransQtyAmt pair in dictProcCodes[procCode])
                {
                    totalCount          += pair.qty;
                    procCur.BillingNote += "Rate: $" + POut.Double(pair.rate) + " Months: " + POut.Int(pair.qty) + "\r\n";
                    builder.WithLine(pair.qty * (decimal)pair.rate, (decimal)pair.qty,
                                     GetTaxOverrideIfNeeded(patCur, procCode), procCode.Descript, procCode.ProcCode);
                }
                //Add note for what day the customer has prepaid through.
                DateTime datePrepaidThrough = DateTimeOD.GetMostRecentValidDate(DateTime.Today.Year, DateTime.Today.Month, patCur.BillingCycleDay)
                                              .AddMonths(totalCount).AddDays(-1);
                if (DateTimeOD.Today.Day >= patCur.BillingCycleDay)
                {
                    datePrepaidThrough = datePrepaidThrough.AddMonths(1);
                }
                procCur.BillingNote += $"Prepaid through: {datePrepaidThrough.Date:MM/dd/yyyy}";
                dictProcsToCreate.Add(procCur, totalCount);
            }
            TransactionModel     result            = Client.CreateTransaction("Lines", builder.GetCreateTransactionModel());
            List <ProcedureCode> listDiscountCodes = AvaTax.ListDiscountProcCodes;

            //Create a single procedure and adjustment for each procCode.
            foreach (KeyValuePair <Procedure, int> entry in dictProcsToCreate)
            {
                //look for previously completed procedures that need to be included on the adjustment calculation.
                List <Procedure> listMatchingCompletedProcs = listCompletedProcs.FindAll(x => x.CodeNum == entry.Key.CodeNum);
                Procedure        procCur = entry.Key;
                int count = entry.Value + listMatchingCompletedProcs.Count();
                List <TransactionLineModel> listLines = result.lines.FindAll(x => x.itemCode.Equals(ProcedureCodes.GetProcCode(procCur.CodeNum).ProcCode));
                procCur.ProcFee = (double)listLines.Sum(x => x.lineAmount.Value);
                procCur.TaxAmt  = (double)listLines.Sum(x => x.tax.Value);
                procCur.ProcNum = Procedures.Insert(procCur, doCalcTax: false);
                if (count > 5 && listDiscountCodes.Exists(x => x.ProcCode == ProcedureCodes.GetProcCode(procCur.CodeNum).ProcCode))
                {
                    //Create a discount adjustment.
                    if (count >= 6 && count <= 11)
                    {
                        CreateDiscountAdjustment(procCur, .05, 255);                      //5% discount.  Hard coded ODHQ defnum.
                    }
                    else if (count >= 12 && count <= 23)
                    {
                        CreateDiscountAdjustment(procCur, .10, 206);                      //10% discount.  Hard coded ODHQ defnum.
                    }
                    else if (count >= 24)
                    {
                        CreateDiscountAdjustment(procCur, .15, 229);                      //15% discount.  Hard coded ODHQ defnum.
                    }
                    //Create adjustments for the previously completed procedures.
                    foreach (Procedure proc in listMatchingCompletedProcs)
                    {
                        if (count >= 6 && count <= 11)
                        {
                            CreateDiscountAdjustment(proc, .05, 255);                          //5% discount.  Hard coded ODHQ defnum.
                        }
                        else if (count >= 12 && count <= 23)
                        {
                            CreateDiscountAdjustment(proc, .10, 206);                          //10% discount.  Hard coded ODHQ defnum.
                        }
                        else if (count >= 24)
                        {
                            CreateDiscountAdjustment(proc, .15, 229);                          //15% discount.  Hard coded ODHQ defnum.
                        }
                    }
                }
            }
        }
Exemplo n.º 25
0
 /// <summary>Runs repeating charges for the date passed in, usually today. Can't use 'out' variables because this runs over Middle Tier.</summary>
 public static RepeatChargeResult RunRepeatingCharges(DateTime dateRun)
 {
     if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
     {
         return(Meth.GetObject <RepeatChargeResult>(MethodBase.GetCurrentMethod(), dateRun));
     }
     Prefs.UpdateDateT(PrefName.RepeatingChargesBeginDateTime, dateRun);
     try {
         RepeatChargeResult  result = new RepeatChargeResult();
         List <RepeatCharge> listRepeatingCharges = RepeatCharges.Refresh(0).ToList();
         if (PrefC.IsODHQ)
         {
             //Remove all eService repeating charges.
             //EService charges have already been calculated and stored in EServiceBilling table. Add those here.
             List <string> listEServiceCodes = EServiceCodeLink.GetProcCodesForAll();
             listRepeatingCharges.RemoveAll(x => listEServiceCodes.Contains(x.ProcCode));
             result.ProceduresAddedCount += EServiceBillings.AddEServiceRepeatingChargesHelper(dateRun).Count;
         }
         //Must contain all procedures that affect the date range, safe to contain too many, bad to contain too few.
         List <Procedure> listExistingProcs = Procedures.GetCompletedForDateRange(dateRun.AddMonths(-3), dateRun.AddDays(1),
                                                                                  listRepeatingCharges.Select(x => x.ProcCode).Distinct().Select(x => ProcedureCodes.GetProcCode(x).CodeNum).ToList());
         DateTime startedUsingFKs = UpdateHistories.GetDateForVersion(new Version("16.1.0.0"));              //We started using FKs from procs to repeat charges in 16.1.
         foreach (RepeatCharge repeatCharge in listRepeatingCharges)
         {
             if (!repeatCharge.IsEnabled || (repeatCharge.DateStop.Year > 1880 && repeatCharge.DateStop.AddMonths(3) < dateRun))
             {
                 continue;                        //This repeating charge is too old to possibly create a new charge. Not precise but greatly reduces calls to DB.
                 //We will filter by more stringently on the DateStop later on.
             }
             Patient         pat = null;
             List <DateTime> listBillingDates;                   //This list will have 1 or 2 dates where a repeating charge might be added
             if (PrefC.GetBool(PrefName.BillingUseBillingCycleDay))
             {
                 pat = Patients.GetPat(repeatCharge.PatNum);
                 listBillingDates = GetBillingDatesHelper(repeatCharge.DateStart, repeatCharge.DateStop, dateRun, pat.BillingCycleDay);
             }
             else
             {
                 listBillingDates = GetBillingDatesHelper(repeatCharge.DateStart, repeatCharge.DateStop, dateRun);
             }
             long codeNum = ProcedureCodes.GetCodeNum(repeatCharge.ProcCode);
             //Remove billing dates if there is a procedure from this repeat charge in that month and year
             for (int i = listBillingDates.Count - 1; i >= 0; i--)             //iterate backwards to remove elements
             {
                 DateTime billingDate = listBillingDates[i];
                 for (int j = listExistingProcs.Count - 1; j >= 0; j--)                 //iterate backwards to remove elements
                 {
                     Procedure proc = listExistingProcs[j];
                     if ((proc.RepeatChargeNum == repeatCharge.RepeatChargeNum &&                       //Check the procedure's FK first
                          IsRepeatDateHelper(repeatCharge, billingDate, proc.ProcDate, pat))
                         //Use the old logic without matching FKs only if the procedure was added before updating to 16.1
                         //Match patnum, codenum, fee, year, and month (IsRepeatDateHelper uses special logic to determine correct month)
                         || ((proc.ProcDate < startedUsingFKs || startedUsingFKs.Year < 1880) &&
                             proc.PatNum == repeatCharge.PatNum &&
                             proc.CodeNum == codeNum &&
                             IsRepeatDateHelper(repeatCharge, billingDate, proc.ProcDate, pat) &&
                             proc.ProcFee.IsEqual(repeatCharge.ChargeAmt)))
                     {
                         //This is a match to an existing procedure.
                         listBillingDates.RemoveAt(i);         //Removing so that a procedure will not get added on this date.
                         listExistingProcs.RemoveAt(j);        //Removing so that another repeat charge of the same code, date, and amount will be added.
                         break;                                //Go to the next billing date
                     }
                 }
             }
             //If any billing dates have not been filtered out, add a repeating charge on those dates
             foreach (DateTime billingDate in listBillingDates)
             {
                 Procedure    procAdded       = AddRepeatingChargeHelper(repeatCharge, billingDate, dateRun);
                 List <Claim> listClaimsAdded = new List <Claim>();
                 if (repeatCharge.CreatesClaim && !ProcedureCodes.GetProcCode(repeatCharge.ProcCode).NoBillIns)
                 {
                     listClaimsAdded = AddClaimsHelper(repeatCharge, procAdded);
                 }
                 result.ProceduresAddedCount++;
                 result.ClaimsAddedCount += listClaimsAdded.Count;
             }
         }
         return(result);
     }
     finally {
         Prefs.UpdateString(PrefName.RepeatingChargesBeginDateTime, "");
     }
 }
Exemplo n.º 26
0
        ///<summary>Changes procFee. Links procedure to an active OrthoCase. Returns new ProcLink if the procedure is linked, else returns null.
        ///Should only be used when a procedure is set complete. This will set the procedure's ProcFee but does not update the procedure in the DB.
        ///This must be done if this function returns true.</summary>
        public static OrthoProcLink LinkProcForActiveOrthoCase(Procedure proc, OrthoCase orthoCase = null, List <OrthoProcLink> listProcLinksForCase = null
                                                               , OrthoPlanLink schedulePlanLink    = null, OrthoSchedule orthoSchedule = null)
        {
            //No remoting role check; no call to db
            if (orthoCase == null)
            {
                orthoCase = OrthoCases.GetActiveForPat(proc.PatNum);
            }
            if (orthoCase == null)           //No active ortho case for pat so return.
            {
                return(null);
            }
            OrthoCase orthoCaseOld = orthoCase.Copy();

            if (listProcLinksForCase == null)
            {
                listProcLinksForCase = GetManyByOrthoCase(orthoCase.OrthoCaseNum);
            }
            List <OrthoProcLink> listAllVisitProcLinks = listProcLinksForCase.Where(x => x.ProcLinkType == OrthoProcType.Visit).ToList();

            //Don't link procs to an OrthoCase with a completed debond procedure
            if (listProcLinksForCase.FirstOrDefault(x => x.ProcLinkType == OrthoProcType.Debond) != null)
            {
                return(null);
            }
            if (!orthoCase.IsTransfer)
            {
                OrthoProcLink bandingProcLink = listProcLinksForCase.FirstOrDefault(x => x.ProcLinkType == OrthoProcType.Banding);
                //If proc being set complete is the banding, it is already linked. We just need to set the fee.
                if (bandingProcLink.ProcNum == proc.ProcNum)
                {
                    SetProcFeeForLinkedProc(orthoCase, proc, OrthoProcType.Banding, listAllVisitProcLinks);
                    orthoCase.BandingDate = proc.ProcDate;
                    OrthoCases.Update(orthoCase, orthoCaseOld);
                    return(bandingProcLink);
                }
                Procedure bandingProc = Procedures.GetOneProc(bandingProcLink.ProcNum, false);
                //If proc is not banding and banding is not complete yet, don't link procedure
                if (bandingProc.ProcStatus != ProcStat.C)
                {
                    return(null);
                }
            }
            if (listProcLinksForCase.Select(x => x.ProcNum).ToList().Contains(proc.ProcNum))
            {
                return(null);               //Procedure is not banding and is already linked so do nothing.
            }
            string        procCode        = ProcedureCodes.GetProcCode(proc.CodeNum).ProcCode;
            List <string> listDebondProcs = OrthoCases.GetListProcTypeProcCodes(PrefName.OrthoDebondCodes);
            List <string> listVisitProcs  = OrthoCases.GetListProcTypeProcCodes(PrefName.OrthoVisitCodes);

            if (listVisitProcs.Contains(procCode) || listDebondProcs.Contains(procCode))
            {
                if (schedulePlanLink == null)
                {
                    schedulePlanLink = OrthoPlanLinks.GetOneForOrthoCaseByType(orthoCase.OrthoCaseNum, OrthoPlanLinkType.OrthoSchedule);
                }
                if (orthoSchedule == null)
                {
                    orthoSchedule = OrthoSchedules.GetOne(schedulePlanLink.FKey);
                }
                //Link visit procedure
                if (listVisitProcs.Contains(procCode))
                {
                    OrthoProcLink newVisitProcLink = CreateHelper(orthoCase.OrthoCaseNum, proc.ProcNum, OrthoProcType.Visit);
                    newVisitProcLink.OrthoProcLinkNum = Insert(newVisitProcLink);
                    listAllVisitProcLinks.Add(newVisitProcLink);
                    listProcLinksForCase.Add(newVisitProcLink);
                    SetProcFeeForLinkedProc(orthoCase, proc, OrthoProcType.Visit, listAllVisitProcLinks, schedulePlanLink, orthoSchedule);
                    return(newVisitProcLink);
                }
                //Link debond procedure
                else if (listDebondProcs.Contains(procCode))
                {
                    OrthoProcLink newDebondProcLink = CreateHelper(orthoCase.OrthoCaseNum, proc.ProcNum, OrthoProcType.Debond);
                    newDebondProcLink.OrthoProcLinkNum = Insert(newDebondProcLink);
                    listProcLinksForCase.Add(newDebondProcLink);
                    OrthoCases.SetActiveState(orthoCase, schedulePlanLink, orthoSchedule, false);                 //deactivate the ortho case
                    SetProcFeeForLinkedProc(orthoCase, proc, OrthoProcType.Debond, listAllVisitProcLinks, schedulePlanLink, orthoSchedule);
                    orthoCase.DebondDate = proc.ProcDate;
                    OrthoCases.Update(orthoCase, orthoCaseOld);
                    return(newDebondProcLink);
                }
            }
            return(null);           //Procedure is not a Banding, Visit, or Debond. Do nothing.
        }
Exemplo n.º 27
0
 ///<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.
 ///Does not sort Canadian labs correctly.  Make sure there are no Canadian labs present prior to comparing.</summary>
 public static int CompareProcedures(Procedure x, Procedure y)
 {
     //We cannot sort Canadian labs within this comparer because there can be multiple labs associated to one procedure.
     //This comparer doesn't have enough information in order to sort a procedure and correctly move the corresponding lab(s) with it.
     //Therefore, Canadian labs need to be sorted as an additional step after this comparer has been invoked.
     //=========================================================================================================================
     //if(CultureInfo.CurrentCulture.Name.EndsWith("CA") && x.ProcNumLab!=y.ProcNumLab) {//This code should not impact USA users
     //	int retVal=CanadianLabSortHelper(x,y);
     //	if(retVal!=0) {
     //		return retVal;
     //	}
     //}
     //=========================================================================================================================
     //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)
     {
         //GetProcCode(...).ProcCode can be null.
         //We do not protect the second call because comparing any string to null doesn't cause an error.
         string procCode = ProcedureCodes.GetProcCode(x.CodeNum).ProcCode ?? "";
         return(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));
 }