///<summary>If a substitute exists for the given proc code, then it will give the CodeNum of that code. Otherwise, it will return the codeNum for the given procCode.</summary> public static long GetSubstituteCodeNum(string procCode, string toothNum) { //No need to check RemotingRole; no call to db. if (procCode == null || procCode == "") { return(0); } if (!ProcedureCodeC.HList.Contains(procCode)) { return(0); } ProcedureCode proc = (ProcedureCode)ProcedureCodeC.HList[procCode]; if (proc.SubstitutionCode != "" && ProcedureCodeC.HList.Contains(proc.SubstitutionCode)) { if (proc.SubstOnlyIf == SubstitutionCondition.Always) { return(((ProcedureCode)ProcedureCodeC.HList[proc.SubstitutionCode]).CodeNum); } if (proc.SubstOnlyIf == SubstitutionCondition.Molar && Tooth.IsMolar(toothNum)) { return(((ProcedureCode)ProcedureCodeC.HList[proc.SubstitutionCode]).CodeNum); } if (proc.SubstOnlyIf == SubstitutionCondition.SecondMolar && Tooth.IsSecondMolar(toothNum)) { return(((ProcedureCode)ProcedureCodeC.HList[proc.SubstitutionCode]).CodeNum); } } return(proc.CodeNum); }
///<summary></summary> public static void Update(ProcedureCode code){ if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),code); return; } Crud.ProcedureCodeCrud.Update(code); }
///<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); }
///<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); } }
///<summary>Returns a copy of this Procedurecode.</summary> public ProcedureCode Copy() { ProcedureCode p = new ProcedureCode(); p.CodeNum = CodeNum; p.ProcCode = ProcCode; p.Descript = Descript; p.AbbrDesc = AbbrDesc; p.ProcTime = ProcTime; p.ProcCat = ProcCat; p.TreatArea = TreatArea; //p.RemoveTooth=RemoveTooth; p.SetRecall = SetRecall; p.NoBillIns = NoBillIns; p.IsProsth = IsProsth; p.DefaultNote = DefaultNote; p.IsHygiene = IsHygiene; p.GTypeNum = GTypeNum; p.AlternateCode1 = AlternateCode1; p.MedicalCode = MedicalCode; p.IsTaxed = IsTaxed; p.PaintType = PaintType; p.GraphicColor = GraphicColor; p.LaymanTerm = LaymanTerm; p.IsCanadianLab = IsCanadianLab; p.PreExisting = PreExisting; p.BaseUnits = BaseUnits; p.SubstitutionCode = SubstitutionCode; p.SubstOnlyIf = SubstOnlyIf; return(p); }
///<summary>If a substitute exists for the given proc code, then it will give the CodeNum of that code. ///Otherwise, it will return the codeNum for the given procCode.</summary> public static long GetSubstituteCodeNum(string procCode, string toothNum) { //No need to check RemotingRole; no call to db. long codeNum = 0; if (string.IsNullOrEmpty(procCode)) { return(codeNum); } ODException.SwallowAnyException(() => { ProcedureCode procedureCode = _procedureCodeCache.GetOne(procCode); codeNum = procedureCode.CodeNum; if (!string.IsNullOrEmpty(procedureCode.SubstitutionCode)) { //Swallow any following exceptions because the old code would first check and make sure the key was in the dictionary. ODException.SwallowAnyException(() => { if (procedureCode.SubstOnlyIf == SubstitutionCondition.Always) { codeNum = _procedureCodeCache.GetOne(procedureCode.SubstitutionCode).CodeNum; } else if (procedureCode.SubstOnlyIf == SubstitutionCondition.Molar && Tooth.IsMolar(toothNum)) { codeNum = _procedureCodeCache.GetOne(procedureCode.SubstitutionCode).CodeNum; } else if (procedureCode.SubstOnlyIf == SubstitutionCondition.SecondMolar && Tooth.IsSecondMolar(toothNum)) { codeNum = _procedureCodeCache.GetOne(procedureCode.SubstitutionCode).CodeNum; } }); } }); return(codeNum); }
///<summary></summary> public static long Insert(ProcedureCode code) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { code.CodeNum=Meth.GetLong(MethodBase.GetCurrentMethod(),code); return code.CodeNum; } //must have already checked procCode for nonduplicate. return Crud.ProcedureCodeCrud.Insert(code); }
public static bool SimulatedProcUpdate(ProcedureCode pc) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetBool(MethodBase.GetCurrentMethod(), pc)); } return(true); }
///<summary></summary> public static bool Update(ProcedureCode procCode, ProcedureCode procCodeOld) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetBool(MethodBase.GetCurrentMethod(), procCode, procCodeOld)); } return(Crud.ProcedureCodeCrud.Update(procCode, procCodeOld)); }
///<summary></summary> public static void Update(ProcedureCode code) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), code); return; } Crud.ProcedureCodeCrud.Update(code); }
///<summary>Returns the ProcedureCode for the supplied procCode such as such as D####. ///If no ProcedureCode is found, returns a new ProcedureCode.</summary> public static ProcedureCode GetProcCode(string myCode) { //No need to check RemotingRole; no call to db. ProcedureCode procedureCode = new ProcedureCode(); ODException.SwallowAnyException(() => { procedureCode = _procedureCodeCache.GetOne(myCode); }); return(procedureCode); }
///<summary></summary> public static long Insert(ProcedureCode code) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { code.CodeNum = Meth.GetLong(MethodBase.GetCurrentMethod(), code); return(code.CodeNum); } //must have already checked procCode for nonduplicate. return(Crud.ProcedureCodeCrud.Insert(code)); }
///<summary>Checks to see if we need to replace the tax code for this state and procedure code with a different tax code. ///Returns the override, or if no override is found, returns the original tax code for the procedure. ///If there is a formatting error in the preference value, logs the offending section of the preference string, ///and attempts to find any other matching entries. If no matching entries are found after an error ///occurs, throws an exception to prevent sending incorrect Avalara transactions. ///Exceptions thrown here will bubble up and be recorded into the adjustment note, so the user can see the error message.</summary> public static string GetTaxOverrideIfNeeded(Patient patient, ProcedureCode procCode) { string overrides = ProgramProperties.GetPropVal(ProgramName.AvaTax, "Tax Code Overrides"); if (string.IsNullOrWhiteSpace(overrides)) { return(procCode.TaxCode); } string patStateLower = patient.State.ToLower(); Address addressTax = Addresses.GetOneByPatNum(patient.PatNum); if (addressTax != null) { patStateLower = addressTax.State.ToLower(); } bool stateHasPercentage = false; bool hasFormatError = false; string[] arrayOverrides = overrides.Split(','); foreach (string entry in arrayOverrides) { string[] parts = entry.Split('-'); if (parts.Count() != 3) { _logger.WriteLine("Tax Code Override entry is incorrect: " + entry + ". " + "Fix this entry in AvaTax setup to resume processing overrides.", LogLevel.Error); hasFormatError = true; continue; } string stateCode = parts[0].Trim(); string procCodeCur = parts[1].Trim(); string taxCodeCur = parts[2].Trim(); if (stateCode.ToLower() == patStateLower) { if (taxCodeCur != "" && taxCodeCur.EndsWith("%")) { stateHasPercentage = true; } } if (stateCode.ToLower() == patStateLower && //Allowing state code to be case insensitive, since our database data is really inconsistent. procCodeCur == procCode.ProcCode) //We must use case sensitive proc codes, because OD allows (ex D0120 to exist with d0120). { return(taxCodeCur); } } if (stateHasPercentage) //but matching code was not found. { return("0%"); //we don't want any other codes to be sent to Avalara } if (hasFormatError) { throw new ODException("Unable to parse tax code overrides due to formatting error."); } return(procCode.TaxCode); }
///<summary>Returns true if this code is marked as BypassIfZero and if this procFee is zero.</summary> public static bool CanBypassLockDate(long codeNum, double procFee) { bool isBypassGlobalLock = false; ProcedureCode procCode = GetFirstOrDefaultFromList(x => x.CodeNum == codeNum); if (procCode != null && procCode.BypassGlobalLock == BypassLockStatus.BypassIfZero && procFee.IsZero()) { isBypassGlobalLock = true; } return(isBypassGlobalLock); }
public static string ClearDb() { string command=@" DELETE FROM carrier; DELETE FROM claim; DELETE FROM claimproc; DELETE FROM fee; DELETE FROM feesched WHERE FeeSchedNum !=53; /*because this is the default fee schedule for providers*/ DELETE FROM insplan; DELETE FROM patient; DELETE FROM patplan; DELETE FROM procedurelog; DELETE FROM etrans; "; DataCore.NonQ(command); ProcedureCodes.RefreshCache(); ProcedureCode procCode; if(!ProcedureCodes.IsValidCode("99222")) { procCode=new ProcedureCode(); procCode.ProcCode="99222"; procCode.Descript="Lab2"; procCode.AbbrDesc="Lab2"; procCode.IsCanadianLab=true; procCode.ProcCat=256; procCode.ProcTime="/X/"; procCode.TreatArea=TreatmentArea.Mouth; ProcedureCodes.Insert(procCode); ProcedureCodes.RefreshCache(); } procCode=ProcedureCodes.GetProcCode("99111"); procCode.IsCanadianLab=true; ProcedureCodes.Update(procCode); ProcedureCodes.RefreshCache(); if(!ProcedureCodes.IsValidCode("27213")) { procCode=new ProcedureCode(); procCode.ProcCode="27213"; procCode.Descript="Crown"; procCode.AbbrDesc="Crn"; procCode.ProcCat=250; procCode.ProcTime="/X/"; procCode.TreatArea=TreatmentArea.Tooth; procCode.PaintType=ToothPaintingType.CrownLight; ProcedureCodes.Insert(procCode); ProcedureCodes.RefreshCache(); } procCode=ProcedureCodes.GetProcCode("67211"); procCode.TreatArea=TreatmentArea.Quad; ProcedureCodes.Update(procCode); ProcedureCodes.RefreshCache(); return "Database cleared of old data.\r\n"; }
///<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))); }
private string ToStringHelper(bool isLeadingIncluded = false) { //return base.ToString(); string retVal = ""; retVal += BenefitType.ToString(); //EB01: Eligibility or benefit information. Required if (CoverageLevel != BenefitCoverageLevel.None) { retVal += ", " + CoverageLevel.ToString(); //EB02: Coverage level code. Situational } EbenefitCategory ebenCat = CovCats.GetEbenCat(CovCatNum); if (ebenCat != EbenefitCategory.None) { retVal += ", " + ebenCat.ToString(); //EB03: Service type code. Situational } //EB04: Insurance type code. Situational. Not a Benefit field. We treat it as plan level. //EB05: Plan coverage description. Situational. Not a Benefit field. We treat it as plan level. if (TimePeriod != BenefitTimePeriod.None) { retVal += ", " + TimePeriod.ToString(); //EB06: Time period qualifier. Situational } if (MonetaryAmt != -1) { retVal += ", " + MonetaryAmt.ToString("c"); //EB07: Monetary amount. Situational } if (Percent != -1) { string leadingStr = ""; if (isLeadingIncluded) { leadingStr = "Insurance Pays "; } retVal += ", " + leadingStr + Percent.ToString() + "%"; //EB08: Percent. Situational } if (QuantityQualifier != BenefitQuantity.None) { retVal += ", " + QuantityQualifier.ToString(); //EB09: Quantity qualifier. Situational } if (Quantity != 0) { retVal += ", " + Quantity.ToString(); //EB10: Quantity. Situational } //EB11: Authorization Required. Situational. Not a Benefit field. //EB12: In plan network. Situational. Not a Benefit field. //EB13: Procedure identifier. Situational. We don't import this from EB, but we can show it anyway. if (CodeNum != 0) { ProcedureCode proccode = ProcedureCodes.GetProcCode(CodeNum); retVal += ", " + proccode.ProcCode + " - " + proccode.AbbrDesc; } return(retVal); }
///<summary>Returns the LaymanTerm for the supplied codeNum, or the description if none present.</summary> public static string GetLaymanTerm(long codeNum) { //No need to check RemotingRole; no call to db. string laymanTerm = ""; ProcedureCode procedureCode = GetFirstOrDefaultFromList(x => x.CodeNum == codeNum); if (procedureCode != null) { laymanTerm = (procedureCode.LaymanTerm != "" ? procedureCode.LaymanTerm : procedureCode.Descript); } return(laymanTerm); }
///<summary>Takes a ProcedureCode and returns the given arch for that code based on ADA standards. ///Returns "U" by default, an empty string for Canada, "U" for Maxillary codes and "L" for Mandibular codes. </summary> public static string GetArchSurfaceFromProcCode(ProcedureCode code) { if (CultureInfo.CurrentCulture.Name.EndsWith("CA")) { return(""); } else if (CDT.Class1.GetMandibularCodes().Any(x => x.ProcCode == code.ProcCode)) { return("L"); } //We assume that if this isn't a Mandibular code then it is Maxillary or "upper arch" return("U"); }
public static List <ProcedureCode> GetProcCodeWithDirtyProperty(ProcedureCode pc, ProcedureCode pc2) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <ProcedureCode> >(MethodBase.GetCurrentMethod(), pc, pc2)); } pc.IsNew = false; pc2.IsNew = false; pc2.ProcCat = pc.ProcCat; return(new List <ProcedureCode> { pc, pc2 }); }
///<summary>Adds procedures to the appointment.</summary> ///<returns>First item of tuple is the newly added procedures. Second item is all procedures for the appointment.</returns> public static ODTuple <List <Procedure>, List <Procedure> > QuickAddProcs(Appointment apt, Patient pat, List <string> listProcCodesToAdd, long provNum, long provHyg, List <InsSub> SubList, List <InsPlan> listInsPlans, List <PatPlan> listPatPlans, List <Benefit> listBenefits) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <ODTuple <List <Procedure>, List <Procedure> > >(MethodBase.GetCurrentMethod(), apt, pat, listProcCodesToAdd, provNum, provHyg, SubList, listInsPlans, listPatPlans, listBenefits)); } Procedures.SetDateFirstVisit(apt.AptDateTime.Date, 1, pat); List <ClaimProc> ClaimProcList = ClaimProcs.Refresh(apt.PatNum); List <ProcedureCode> listProcedureCodes = new List <ProcedureCode>(); foreach (string procCode in listProcCodesToAdd) { listProcedureCodes.Add(ProcedureCodes.GetProcCode(procCode)); } List <long> listProvNumsTreat = new List <long>(); listProvNumsTreat.Add(provNum); listProvNumsTreat.Add(provHyg); //these were both passed in List <SubstitutionLink> listSubstLinks = SubstitutionLinks.GetAllForPlans(listInsPlans); //not available in FormApptEdit List <Fee> listFees = Fees.GetListFromObjects(listProcedureCodes, null, //no procs to pull medicalCodes from listProvNumsTreat, pat.PriProv, pat.SecProv, pat.FeeSched, listInsPlans, new List <long>() { apt.ClinicNum }, null, //procNums for appt already handled above listSubstLinks, pat.DiscountPlanNum); //null,listProvNumsTreat,listProcedureCodes.Select(x=>x.ProvNumDefault).ToList(), //pat.PriProv,pat.SecProv,pat.FeeSched,listInsPlans,new List<long>(){apt.ClinicNum},listProcCodesToAdd,null);//procnums for appt already handled above List <Procedure> listAddedProcs = new List <Procedure>(); //Make a copy of apt with provNum and provHyg, in order to maintain behavior of this method prior to using Procedures.ConstructProcedureForAppt //provNum and provHyg are sent in and are the selected provs in FormApptEdit, which may be different than the current provs on apt Appointment aptCur = apt.Copy(); aptCur.ProvNum = provNum; aptCur.ProvHyg = provHyg; foreach (string procCode in listProcCodesToAdd) { ProcedureCode procCodeCur = ProcedureCodes.GetProcCode(procCode); Procedure proc = Procedures.ConstructProcedureForAppt(procCodeCur.CodeNum, aptCur, pat, listPatPlans, listInsPlans, SubList, listFees); Procedures.Insert(proc); //recall synch not required Procedures.ComputeEstimates(proc, pat.PatNum, ref ClaimProcList, true, listInsPlans, listPatPlans, listBenefits, null, null, true, pat.Age, SubList, null, false, false, listSubstLinks, false, listFees); listAddedProcs.Add(proc); } return(new ODTuple <List <Procedure>, List <Procedure> >(listAddedProcs, Procedures.GetProcsForApptEdit(apt))); }
///<summary>Gets code from db to avoid having to constantly refresh in FormProcCodes</summary> public static ProcedureCode GetProcCodeFromDb(long codeNum) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <ProcedureCode>(MethodBase.GetCurrentMethod(), codeNum)); } ProcedureCode retval = Crud.ProcedureCodeCrud.SelectOne(codeNum); if (retval == null) { //We clasically return an empty procedurecode object here instead of null. return(new ProcedureCode()); } return(retval); }
///<summary>Returns true if the procedure has a substitution code for the give tooth and InsPlans.</summary> public static bool HasSubstCodeForProcCode(ProcedureCode procCode, string toothNum, List <SubstitutionLink> listSubLinks, List <InsPlan> listPatInsPlans) { //No need to check RemotingRole; no call to db. foreach (InsPlan plan in listPatInsPlans) { //Check to see if any allow substitutions. if (HasSubstCodeForPlan(plan, procCode.CodeNum, listSubLinks)) { long subCodeNum = ProcedureCodes.GetSubstituteCodeNum(procCode.ProcCode, toothNum, plan.PlanNum, listSubLinks); //for posterior composites if (procCode.CodeNum != subCodeNum && subCodeNum > 0) { return(true); } } } return(false); }
///<summary>Checks inputs and determines if user should be prompted to pick a more applicable procedure code.</summary> ///<param name="verifyCode">This is the recommended code based on input. If it matches procCode return value will be false.</param> public static bool ShouldPromptForCodeChange(Procedure proc, ProcedureCode procCode, Patient pat, bool isMandibular, List <ClaimProc> claimProcsForProc, out long verifyCode) { //No remoting role check; no call to db and method utilizes an out parameter. verifyCode = proc.CodeNum; //these areas have no autocodes if (procCode.TreatArea == TreatmentArea.Mouth || procCode.TreatArea == TreatmentArea.Quad || procCode.TreatArea == TreatmentArea.Sextant || Procedures.IsAttachedToClaim(proc, claimProcsForProc)) { return(false); } //this represents the suggested code based on the autocodes set up. AutoCode AutoCodeCur = null; if (procCode.TreatArea == TreatmentArea.Arch) { if (string.IsNullOrEmpty(proc.Surf)) { return(false); } if (proc.Surf == "U") { verifyCode = AutoCodeItems.VerifyCode(procCode.CodeNum, "1", "", false, pat.PatNum, pat.Age, out AutoCodeCur); //max } else { verifyCode = AutoCodeItems.VerifyCode(procCode.CodeNum, "32", "", false, pat.PatNum, pat.Age, out AutoCodeCur); //mand } } else if (procCode.TreatArea == TreatmentArea.ToothRange) { //test for max or mand. verifyCode = AutoCodeItems.VerifyCode(procCode.CodeNum, (isMandibular) ? "32" : "1", "", false, pat.PatNum, pat.Age, out AutoCodeCur); } else //surf or tooth { string claimSurf = Tooth.SurfTidyForClaims(proc.Surf, proc.ToothNum); verifyCode = AutoCodeItems.VerifyCode(procCode.CodeNum, proc.ToothNum, claimSurf, false, pat.PatNum, pat.Age, out AutoCodeCur); } return(procCode.CodeNum != verifyCode); }
private void FormRpBrokenAppointments_Load(object sender,EventArgs e) { _procCodeBrokenApt=ProcedureCodes.GetProcCode("D9986"); if(_procCodeBrokenApt.CodeNum!=0){ labelDescr.Text=Lan.g(this,"Broken appointments based on ADA code D9986"); } dateStart.SelectionStart=DateTime.Today; dateEnd.SelectionStart=DateTime.Today; List<Provider> listShort=ProviderC.GetListShort(); for(int i=0;i<listShort.Count;i++) { listProvs.Items.Add(listShort[i].GetLongDesc()); listProvs.SelectedIndices.Add(i); } if(PrefC.GetBool(PrefName.EasyNoClinics)) { listClinics.Visible=false; labelClinics.Visible=false; checkAllClinics.Visible=false; } else { _listClinics=Clinics.GetForUserod(Security.CurUser); if(!Security.CurUser.ClinicIsRestricted) { listClinics.Items.Add(Lan.g(this,"Unassigned")); listClinics.SetSelected(0,true); } for(int i=0;i<_listClinics.Count;i++) { int curIndex=listClinics.Items.Add(_listClinics[i].Description); if(FormOpenDental.ClinicNum==0) { listClinics.SetSelected(curIndex,true); checkAllClinics.Checked=true; } if(_listClinics[i].ClinicNum==FormOpenDental.ClinicNum) { listClinics.SelectedIndices.Clear(); listClinics.SetSelected(curIndex,true); } } } }
private static Procedure AddRepeatingChargeHelper(RepeatCharge repeatCharge, DateTime billingDate, DateTime dateNow) { //No remoting role check; no call to db Procedure procedure = new Procedure(); ProcedureCode procCode = ProcedureCodes.GetProcCode(repeatCharge.ProcCode); Patient pat = Patients.GetPat(repeatCharge.PatNum); procedure.CodeNum = procCode.CodeNum; procedure.ClinicNum = pat.ClinicNum; procedure.DateEntryC = dateNow; procedure.PatNum = repeatCharge.PatNum; procedure.ProcDate = billingDate; procedure.DateTP = billingDate; procedure.ProcFee = repeatCharge.ChargeAmt; procedure.ProcStatus = ProcStat.C; if (procCode.ProvNumDefault == 0) { procedure.ProvNum = pat.PriProv; } else { procedure.ProvNum = procCode.ProvNumDefault; } procedure.MedicalCode = ProcedureCodes.GetProcCode(procedure.CodeNum).MedicalCode; procedure.BaseUnits = ProcedureCodes.GetProcCode(procedure.CodeNum).BaseUnits; procedure.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs); procedure.RepeatChargeNum = repeatCharge.RepeatChargeNum; procedure.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService); //Default Proc Place of Service for the Practice is used. //Check if the repeating charge has been flagged to copy it's note into the billing note of the procedure. if (repeatCharge.CopyNoteToProc) { procedure.BillingNote = repeatCharge.Note; if (repeatCharge.ErxAccountId != "") { procedure.BillingNote = "NPI=" + repeatCharge.Npi + " " + "ErxAccountId=" + repeatCharge.ErxAccountId; if (!string.IsNullOrEmpty(repeatCharge.ProviderName)) //Provider name would be empty if older and no longer updated from eRx. { procedure.BillingNote += "\r\nProviderName=" + repeatCharge.ProviderName; } if (!string.IsNullOrEmpty(repeatCharge.Note)) { procedure.BillingNote += "\r\n" + repeatCharge.Note; } } } if (!PrefC.GetBool(PrefName.EasyHidePublicHealth)) { procedure.SiteNum = pat.SiteNum; } Procedures.Insert(procedure); //no recall synch needed because dental offices don't use this feature //Using Prepayments for this Procedure if (repeatCharge.UsePrepay) { //NOTE: ProvNum=0 on these splits, so I'm pretty sure they aren't allocated to anything. List <PaySplit> prePaySplits = PaySplits.GetPrepayForFam(Patients.GetFamily(repeatCharge.PatNum)); List <PaySplit> paySplitsForPrePaySplits = PaySplits.GetSplitsForPrepay(prePaySplits); Payment payCur = new Payment(); payCur.ClinicNum = procedure.ClinicNum; payCur.DateEntry = billingDate; payCur.IsSplit = true; payCur.PatNum = repeatCharge.PatNum; payCur.PayDate = billingDate; payCur.PayType = 0; //Income transfer (will always be income transfer) payCur.PayAmt = 0; //Income transfer payment payCur.PayNum = Payments.Insert(payCur); decimal payAmt = 0; string noteText = ""; foreach (PaySplit prePaySplit in prePaySplits) { prePaySplit.SplitAmt += paySplitsForPrePaySplits.Where(x => x.FSplitNum == prePaySplit.SplitNum).Sum(y => y.SplitAmt); //Reduce prepay split amount. PaySplit split = new PaySplit(); PaySplit split2 = new PaySplit(); if (prePaySplit.SplitAmt > procedure.ProcFee - (double)payAmt) { //Split amount is more than the remainder of the procfee requires, use partial from split split.SplitAmt = procedure.ProcFee - (double)payAmt; split2.SplitAmt = 0 - (procedure.ProcFee - (double)payAmt); payAmt = (decimal)procedure.ProcFee; } else { //Split amount is less than or equal to the remainder of the procfee split.SplitAmt = prePaySplit.SplitAmt; split2.SplitAmt = 0 - prePaySplit.SplitAmt; payAmt += (decimal)prePaySplit.SplitAmt; } if (split.SplitAmt == 0) { continue; //Don't make splits for 0 amount. } //Positive split, attached to proc and for proc's prov and clinic split.DateEntry = billingDate; split.DatePay = billingDate; split.PatNum = procedure.PatNum; split.PayNum = payCur.PayNum; split.ProcNum = procedure.ProcNum; split.ProvNum = procedure.ProvNum; split.ClinicNum = procedure.ClinicNum; if (noteText != "") { noteText += ", "; } noteText += split.SplitAmt.ToString("c"); PaySplits.Insert(split); //Negative split, attached to prepay's prov and clinic, but not proc split2.DateEntry = billingDate; split2.DatePay = billingDate; split2.PatNum = procedure.PatNum; split2.PayNum = payCur.PayNum; split2.FSplitNum = prePaySplit.SplitNum; split2.ProvNum = prePaySplit.ProvNum; split2.ClinicNum = prePaySplit.ClinicNum; PaySplits.Insert(split2); if (payAmt >= (decimal)procedure.ProcFee) { //Break out of loop break; } } payCur.PayNote = "Allocated " + noteText + " prepayments to repeating charge."; Payments.Update(payCur, false); } return(procedure); }
///<summary>MUST call EntriesAreValid first. Used from OK_Click and from butSetComplete_Click</summary> private void SaveAndClose(){ if(textProcFee.Text==""){ textProcFee.Text="0"; } ProcCur.PatNum=PatCur.PatNum; //ProcCur.Code=this.textProc.Text; ProcedureCode2=ProcedureCodes.GetProcCode(textProc.Text); ProcCur.CodeNum=ProcedureCode2.CodeNum; ProcCur.MedicalCode=textMedicalCode.Text; if(_snomedBodySite==null) { ProcCur.SnomedBodySite=""; } else { ProcCur.SnomedBodySite=_snomedBodySite.SnomedCode; } ProcCur.DiagnosticCode=textDiagnosticCode.Text; ProcCur.IsPrincDiag=checkIsPrincDiag.Checked; ProcCur.CodeMod1 = textCodeMod1.Text; ProcCur.CodeMod2 = textCodeMod2.Text; ProcCur.CodeMod3 = textCodeMod3.Text; ProcCur.CodeMod4 = textCodeMod4.Text; ProcCur.UnitQty = PIn.Int(textUnitQty.Text); ProcCur.UnitQtyType=(ProcUnitQtyType)comboUnitType.SelectedIndex; ProcCur.RevCode = textRevCode.Text; ProcCur.DrugUnit=(EnumProcDrugUnit)comboDrugUnit.SelectedIndex; ProcCur.DrugQty=PIn.Float(textDrugQty.Text); if(ProcOld.ProcStatus!=ProcStat.C && ProcCur.ProcStatus==ProcStat.C){//Proc set complete. ProcCur.DateEntryC=DateTime.Now;//this triggers it to set to server time NOW(). if(ProcCur.DiagnosticCode=="") { ProcCur.DiagnosticCode=PrefC.GetString(PrefName.ICD9DefaultForNewProcs); } } ProcCur.DateTP=PIn.Date(this.textDateTP.Text); ProcCur.ProcDate=PIn.Date(this.textDate.Text); DateTime dateT=PIn.DateT(this.textTimeStart.Text); ProcCur.ProcTime=new TimeSpan(dateT.Hour,dateT.Minute,0); if(Programs.UsingOrion || PrefC.GetBool(PrefName.ShowFeatureMedicalInsurance)) { dateT=ParseTime(textTimeStart.Text); ProcCur.ProcTime=new TimeSpan(dateT.Hour,dateT.Minute,0); dateT=ParseTime(textTimeEnd.Text); ProcCur.ProcTimeEnd=new TimeSpan(dateT.Hour,dateT.Minute,0); } ProcCur.ProcFee=PIn.Double(textProcFee.Text); //ProcCur.LabFee=PIn.PDouble(textLabFee.Text); //ProcCur.LabProcCode=textLabCode.Text; //MessageBox.Show(ProcCur.ProcFee.ToString()); //Dx taken care of when radio pushed switch(ProcedureCode2.TreatArea){ case TreatmentArea.Surf: ProcCur.ToothNum=Tooth.FromInternat(textTooth.Text); ProcCur.Surf=Tooth.SurfTidyFromDisplayToDb(textSurfaces.Text,ProcCur.ToothNum); break; case TreatmentArea.Tooth: ProcCur.Surf=""; ProcCur.ToothNum=Tooth.FromInternat(textTooth.Text); break; case TreatmentArea.Mouth: ProcCur.Surf=""; ProcCur.ToothNum=""; break; case TreatmentArea.Quad: //surf set when radio pushed ProcCur.ToothNum=""; break; case TreatmentArea.Sextant: //surf taken care of when radio pushed ProcCur.ToothNum=""; break; case TreatmentArea.Arch: //don't HAVE to select arch //taken care of when radio pushed ProcCur.ToothNum=""; break; case TreatmentArea.ToothRange: if (listBoxTeeth.SelectedItems.Count<1 && listBoxTeeth2.SelectedItems.Count<1) { MessageBox.Show(Lan.g(this,"Must pick at least 1 tooth")); return; } string range=""; int idxAmer; for(int j=0;j<listBoxTeeth.SelectedIndices.Count;j++){ idxAmer=listBoxTeeth.SelectedIndices[j]; if(j!=0){ range+=","; } range+=Tooth.labelsUniversal[idxAmer]; } for(int j=0;j<listBoxTeeth2.SelectedIndices.Count;j++){ idxAmer=listBoxTeeth2.SelectedIndices[j]+16; if(j!=0){ range+=","; } range+=Tooth.labelsUniversal[idxAmer]; } ProcCur.ToothRange=range; ProcCur.Surf=""; ProcCur.ToothNum=""; break; } //Status taken care of when list pushed ProcCur.Note=this.textNotes.Text; try { SaveSignature(); } catch(Exception ex){ MessageBox.Show(Lan.g(this,"Error saving signature.")+"\r\n"+ex.Message); //and continue with the rest of this method } ProcCur.HideGraphics=checkHideGraphics.Checked; //provnum already handled. //if(comboProvNum.SelectedIndex!=-1) { // ProcCur.ProvNum=ProviderC.List[comboProvNum.SelectedIndex].ProvNum; //} //clinicNum already handled. if(comboDx.SelectedIndex!=-1) { ProcCur.Dx=DefC.Short[(int)DefCat.Diagnosis][comboDx.SelectedIndex].DefNum; } if(comboPrognosis.SelectedIndex==0) { ProcCur.Prognosis=0; } else { ProcCur.Prognosis=DefC.Short[(int)DefCat.Prognosis][comboPrognosis.SelectedIndex-1].DefNum; } if(comboPriority.SelectedIndex==0) { ProcCur.Priority=0; } else { ProcCur.Priority=DefC.Short[(int)DefCat.TxPriorities][comboPriority.SelectedIndex-1].DefNum; } ProcCur.PlaceService=(PlaceOfService)comboPlaceService.SelectedIndex; //if(comboClinic.SelectedIndex==0){ // ProcCur.ClinicNum=0; //} //else{ // ProcCur.ClinicNum=Clinics.List[comboClinic.SelectedIndex-1].ClinicNum; //} //site set when user picks from list. if(comboBillingTypeOne.SelectedIndex==0){ ProcCur.BillingTypeOne=0; } else{ ProcCur.BillingTypeOne=DefC.Short[(int)DefCat.BillingTypes][comboBillingTypeOne.SelectedIndex-1].DefNum; } if(comboBillingTypeTwo.SelectedIndex==0) { ProcCur.BillingTypeTwo=0; } else { ProcCur.BillingTypeTwo=DefC.Short[(int)DefCat.BillingTypes][comboBillingTypeTwo.SelectedIndex-1].DefNum; } ProcCur.BillingNote=textBillingNote.Text; //ProcCur.HideGraphical=checkHideGraphical.Checked; if(CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Canadian. en-CA or fr-CA ProcCur.CanadianTypeCodes=""; if(checkTypeCodeA.Checked) { ProcCur.CanadianTypeCodes+="A"; } if(checkTypeCodeB.Checked) { ProcCur.CanadianTypeCodes+="B"; } if(checkTypeCodeC.Checked) { ProcCur.CanadianTypeCodes+="C"; } if(checkTypeCodeE.Checked) { ProcCur.CanadianTypeCodes+="E"; } if(checkTypeCodeL.Checked) { ProcCur.CanadianTypeCodes+="L"; } if(checkTypeCodeS.Checked) { ProcCur.CanadianTypeCodes+="S"; } if(checkTypeCodeX.Checked) { ProcCur.CanadianTypeCodes+="X"; } double canadaLabFee1=0; if(textCanadaLabFee1.Text!="") { canadaLabFee1=PIn.Double(textCanadaLabFee1.Text); } if(canadaLabFee1==0) { if(textCanadaLabFee1.Visible && canadaLabFees.Count>0) { //Don't worry about deleting child lab fees if we are editing a lab fee. No such concept. Procedures.Delete(canadaLabFees[0].ProcNum); } } else { //canadaLabFee1!=0 if(canadaLabFees.Count>0) { //Retain the old lab code if present. Procedure labFee1Old=canadaLabFees[0].Copy(); canadaLabFees[0].ProcFee=canadaLabFee1; Procedures.Update(canadaLabFees[0],labFee1Old); } else { Procedure labFee1=new Procedure(); labFee1.PatNum=ProcCur.PatNum; labFee1.ProcDate=ProcCur.ProcDate; labFee1.ProcFee=canadaLabFee1; labFee1.ProcStatus=ProcCur.ProcStatus; labFee1.ProvNum=ProcCur.ProvNum; labFee1.DateEntryC=DateTime.Now; labFee1.ClinicNum=ProcCur.ClinicNum; labFee1.ProcNumLab=ProcCur.ProcNum; labFee1.CodeNum=ProcedureCodes.GetCodeNum("99111"); if(labFee1.CodeNum==0) { //Code does not exist. ProcedureCode code99111=new ProcedureCode(); code99111.ProcCode="99111"; code99111.Descript="+L Commercial Laboratory Procedures"; code99111.AbbrDesc="Lab Fee"; code99111.ProcCat=DefC.GetByExactNameNeverZero(DefCat.ProcCodeCats,"Adjunctive General Services"); ProcedureCodes.Insert(code99111); labFee1.CodeNum=code99111.CodeNum; } Procedures.Insert(labFee1); } } double canadaLabFee2=0; if(textCanadaLabFee2.Text!="") { canadaLabFee2=PIn.Double(textCanadaLabFee2.Text); } if(canadaLabFee2==0) { if(textCanadaLabFee2.Visible && canadaLabFees.Count>1) { //Don't worry about deleting child lab fees if we are editing a lab fee. No such concept. Procedures.Delete(canadaLabFees[1].ProcNum); } } else { //canadaLabFee2!=0 if(canadaLabFees.Count>1) { //Retain the old lab code if present. Procedure labFee2Old=canadaLabFees[1].Copy(); canadaLabFees[1].ProcFee=canadaLabFee2; Procedures.Update(canadaLabFees[1],labFee2Old); } else { Procedure labFee2=new Procedure(); labFee2.PatNum=ProcCur.PatNum; labFee2.ProcDate=ProcCur.ProcDate; labFee2.ProcFee=canadaLabFee2; labFee2.ProcStatus=ProcCur.ProcStatus; labFee2.ProvNum=ProcCur.ProvNum; labFee2.DateEntryC=DateTime.Now; labFee2.ClinicNum=ProcCur.ClinicNum; labFee2.ProcNumLab=ProcCur.ProcNum; labFee2.CodeNum=ProcedureCodes.GetCodeNum("99111"); if(labFee2.CodeNum==0) { //Code does not exist. ProcedureCode code99111=new ProcedureCode(); code99111.ProcCode="99111"; code99111.Descript="+L Commercial Laboratory Procedures"; code99111.AbbrDesc="Lab Fee"; code99111.ProcCat=DefC.GetByExactNameNeverZero(DefCat.ProcCodeCats,"Adjunctive General Services"); ProcedureCodes.Insert(code99111); labFee2.CodeNum=code99111.CodeNum; } Procedures.Insert(labFee2); } } } else { if(ProcedureCode2.IsProsth) { switch(listProsth.SelectedIndex) { case 0: ProcCur.Prosthesis=""; break; case 1: ProcCur.Prosthesis="I"; break; case 2: ProcCur.Prosthesis="R"; break; } ProcCur.DateOriginalProsth=PIn.Date(textDateOriginalProsth.Text); } else { ProcCur.Prosthesis=""; ProcCur.DateOriginalProsth=DateTime.MinValue; } } ProcCur.ClaimNote=textClaimNote.Text; //Last chance to run this code before Proc gets updated. if(Programs.UsingOrion){//Ask for an explanation. If they hit cancel here, return and don't save. OrionProcCur.DPC=(OrionDPC)comboDPC.SelectedIndex; OrionProcCur.DPCpost=(OrionDPC)comboDPCpost.SelectedIndex; OrionProcCur.DateScheduleBy=PIn.Date(textDateScheduled.Text); OrionProcCur.DateStopClock=PIn.Date(textDateStop.Text); OrionProcCur.IsOnCall=checkIsOnCall.Checked; OrionProcCur.IsEffectiveComm=checkIsEffComm.Checked; OrionProcCur.IsRepair=checkIsRepair.Checked; if(IsNew) { OrionProcs.Insert(OrionProcCur); } else {//Is not new. if(FormProcEditExplain.GetChanges(ProcCur,ProcOld,OrionProcCur,OrionProcOld)!="") {//Checks if any changes were made. Also sets static variable Changes. //If a day old and the orion procedure status did not go from TP to C, CS or CR, then show explaination window. if((ProcOld.DateTP.Date<MiscData.GetNowDateTime().Date && (OrionProcOld.Status2!=OrionStatus.TP || (OrionProcCur.Status2!=OrionStatus.C && OrionProcCur.Status2!=OrionStatus.CS && OrionProcCur.Status2!=OrionStatus.CR)))) { FormProcEditExplain FormP=new FormProcEditExplain(); FormP.dpcChange=((int)OrionProcOld.DPC!=(int)OrionProcCur.DPC); if(FormP.ShowDialog()!=DialogResult.OK) { return; } Procedure ProcPreExplain=ProcOld.Copy(); ProcOld.Note=FormProcEditExplain.Explanation; Procedures.Update(ProcOld,ProcPreExplain); Thread.Sleep(1100); } } OrionProcs.Update(OrionProcCur); //Date entry needs to be updated when status changes to cancelled or refused and at least a day old. if(ProcOld.DateTP.Date<MiscData.GetNowDateTime().Date && OrionProcCur.Status2==OrionStatus.CA_EPRD || OrionProcCur.Status2==OrionStatus.CA_PD || OrionProcCur.Status2==OrionStatus.CA_Tx || OrionProcCur.Status2==OrionStatus.R) { ProcCur.DateEntryC=MiscData.GetNowDateTime().Date; } }//End of "is not new." } //The actual update---------------------------------------------------------------------------------------------------------------------------------- Procedures.Update(ProcCur,ProcOld); if(ProcCur.AptNum>0 || ProcCur.PlannedAptNum>0) { //Update the ProcDescript on the appointment if procedure is attached to one. //The ApptProcDescript region is also in FormApptEdit.UpdateToDB() and FormDatabaseMaintenance.butApptProcs_Click() Make any changes there as well. #region ApptProcDescript Appointment apt; DataTable procTable; if(ProcCur.AptNum>0) { apt=Appointments.GetOneApt(ProcCur.AptNum); procTable=Appointments.GetProcTable(ProcCur.PatNum.ToString(),apt.AptNum.ToString(),((int)apt.AptStatus).ToString(),apt.AptDateTime.ToString()); } else { apt=Appointments.GetOneApt(ProcCur.PlannedAptNum); procTable=Appointments.GetProcTable(ProcCur.PatNum.ToString(),ProcCur.PlannedAptNum.ToString(),((int)apt.AptStatus).ToString(),apt.AptDateTime.ToString()); } Appointment aptOld=apt.Clone(); apt.ProcDescript=""; apt.ProcsColored=""; int count=0; for(int i=0;i<procTable.Rows.Count;i++) { if(procTable.Rows[i]["attached"].ToString()!="1") { continue; } string procDescOne=""; string procCode=procTable.Rows[i]["ProcCode"].ToString(); if(count>0) { apt.ProcDescript+=", "; } switch(procTable.Rows[i]["TreatArea"].ToString()) { case "1"://TreatmentArea.Surf: procDescOne+="#"+Tooth.GetToothLabel(procTable.Rows[i]["ToothNum"].ToString())+"-" +procTable.Rows[i]["Surf"].ToString()+"-";//""#12-MOD-" break; case "2"://TreatmentArea.Tooth: procDescOne+="#"+Tooth.GetToothLabel(procTable.Rows[i]["ToothNum"].ToString())+"-";//"#12-" break; default://area 3 or 0 (mouth) break; case "4"://TreatmentArea.Quad: procDescOne+=procTable.Rows[i]["Surf"].ToString()+"-";//"UL-" break; case "5"://TreatmentArea.Sextant: procDescOne+="S"+procTable.Rows[i]["Surf"].ToString()+"-";//"S2-" break; case "6"://TreatmentArea.Arch: procDescOne+=procTable.Rows[i]["Surf"].ToString()+"-";//"U-" break; case "7"://TreatmentArea.ToothRange: //strLine+=table.Rows[j][13].ToString()+" ";//don't show range break; } procDescOne+=procTable.Rows[i]["AbbrDesc"].ToString(); apt.ProcDescript+=procDescOne; //Color and previous date are determined by ProcApptColor object ProcApptColor pac=ProcApptColors.GetMatch(procCode); System.Drawing.Color pColor=System.Drawing.Color.Black; string prevDateString=""; if(pac!=null) { pColor=pac.ColorText; if(pac.ShowPreviousDate) { prevDateString=Procedures.GetRecentProcDateString(apt.PatNum,apt.AptDateTime,pac.CodeRange); if(prevDateString!="") { prevDateString=" ("+prevDateString+")"; } } } apt.ProcsColored+="<span color=\""+pColor.ToArgb().ToString()+"\">"+procDescOne+prevDateString+"</span>"; count++; } #endregion Appointments.Update(apt,aptOld); } for(int i=0;i<ClaimProcsForProc.Count;i++) { ClaimProcsForProc[i].ClinicNum=ProcCur.ClinicNum; } //Recall synch-------------------------------------------------------------------------------------------------------------------------------------- Recalls.Synch(ProcCur.PatNum); //Auto-insert default encounter --------------------------------------------------------------------------------------------------------------------------- if(ProcOld.ProcStatus!=ProcStat.C && ProcCur.ProcStatus==ProcStat.C) { Encounters.InsertDefaultEncounter(ProcCur.PatNum,ProcCur.ProvNum,ProcCur.ProcDate); } //Security logs------------------------------------------------------------------------------------------------------------------------------------ if(ProcOld.ProcStatus!=ProcStat.C && ProcCur.ProcStatus==ProcStat.C){ //if status was changed to complete SecurityLogs.MakeLogEntry(Permissions.ProcComplCreate,PatCur.PatNum, ProcedureCodes.GetProcCode(ProcCur.CodeNum).ProcCode+", " +ProcCur.ProcFee.ToString("c")); List<string> procCodeList=new List<string>(); procCodeList.Add(ProcedureCodes.GetStringProcCode(ProcCur.CodeNum)); AutomationL.Trigger(AutomationTrigger.CompleteProcedure,procCodeList,ProcCur.PatNum); } else if(IsNew && ProcCur.ProcStatus==ProcStat.C){ //if new procedure is complete SecurityLogs.MakeLogEntry(Permissions.ProcComplCreate,PatCur.PatNum, ProcedureCodes.GetProcCode(ProcCur.CodeNum).ProcCode+", " +ProcCur.ProcFee.ToString("c")); } else if(!IsNew){ if(ProcOld.ProcStatus==ProcStat.C){ SecurityLogs.MakeLogEntry(Permissions.ProcComplEdit,PatCur.PatNum, ProcedureCodes.GetProcCode(ProcCur.CodeNum).ProcCode+", " +ProcCur.ProcFee.ToString("c")); } } if((ProcCur.ProcStatus==ProcStat.C || ProcCur.ProcStatus==ProcStat.EC || ProcCur.ProcStatus==ProcStat.EO) && ProcedureCodes.GetProcCode(ProcCur.CodeNum).PaintType==ToothPaintingType.Extraction) { //if an extraction, then mark previous procs hidden //Procedures.SetHideGraphical(ProcCur);//might not matter anymore ToothInitials.SetValue(ProcCur.PatNum,ProcCur.ToothNum,ToothInitialType.Missing); } //Canadian lab fees complete----------------------------------------------------------------------------------------------------------------------- if(CultureInfo.CurrentCulture.Name.EndsWith("CA") && ProcCur.ProcStatus==ProcStat.C) {//Canada Procedures.SetCanadianLabFeesCompleteForProc(ProcCur); } //Autocodes---------------------------------------------------------------------------------------------------------------------------------------- ProcOld=ProcCur.Copy();//in case we now make more changes. //these areas have no autocodes if(ProcedureCode2.TreatArea==TreatmentArea.Mouth || ProcedureCode2.TreatArea==TreatmentArea.Quad || ProcedureCode2.TreatArea==TreatmentArea.Sextant) { DialogResult=DialogResult.OK; return; } //this represents the suggested code based on the autocodes set up. long verifyCode; AutoCode AutoCodeCur=null; if(ProcedureCode2.TreatArea==TreatmentArea.Arch){ if(ProcCur.Surf==""){ DialogResult=DialogResult.OK; return; } if(ProcCur.Surf=="U"){ verifyCode=AutoCodeItems.VerifyCode (ProcedureCode2.CodeNum,"1","",false,PatCur.PatNum,PatCur.Age,out AutoCodeCur);//max } else{ verifyCode=AutoCodeItems.VerifyCode (ProcedureCode2.CodeNum,"32","",false,PatCur.PatNum,PatCur.Age,out AutoCodeCur);//mand } } else if(ProcedureCode2.TreatArea==TreatmentArea.ToothRange){ //test for max or mand. if(listBoxTeeth.SelectedItems.Count<1) verifyCode=AutoCodeItems.VerifyCode (ProcedureCode2.CodeNum,"32","",false,PatCur.PatNum,PatCur.Age,out AutoCodeCur);//mand else verifyCode=AutoCodeItems.VerifyCode (ProcedureCode2.CodeNum,"1","",false,PatCur.PatNum,PatCur.Age,out AutoCodeCur);//max } else{//surf or tooth verifyCode=AutoCodeItems.VerifyCode (ProcedureCode2.CodeNum,ProcCur.ToothNum,ProcCur.Surf,false,PatCur.PatNum,PatCur.Age,out AutoCodeCur); } if(ProcedureCode2.CodeNum!=verifyCode){ string desc=ProcedureCodes.GetProcCode(verifyCode).Descript; FormAutoCodeLessIntrusive FormA=new FormAutoCodeLessIntrusive(); FormA.mainText=ProcedureCodes.GetProcCode(verifyCode).ProcCode +" ("+desc+") "+Lan.g(this,"is the recommended procedure code for this procedure. Change procedure code and fee?"); FormA.ShowDialog(); if(FormA.DialogResult!=DialogResult.OK){ DialogResult=DialogResult.OK; return; } //No longer allow users to hide auto code reminders from the procedure edit window. A label lets them know to change it via Auto Codes. //if(FormA.CheckedBox){ // AutoCodeCur.LessIntrusive=true; // AutoCodes.Update(AutoCodeCur); // DataValid.SetInvalid(InvalidType.AutoCodes); //} ProcCur.CodeNum=verifyCode; //ProcedureCode2=ProcedureCodes.GetProcCode(ProcCur.CodeNum); //ProcCur.Code=verifyCode; InsSub prisub=null; InsPlan priplan=null; if(PatPlanList.Count>0) { prisub=InsSubs.GetSub(PatPlanList[0].InsSubNum,SubList); priplan=InsPlans.GetPlan(prisub.PlanNum,PlanList); } double insfee=Fees.GetAmount0(ProcCur.CodeNum,Fees.GetFeeSched(PatCur,PlanList,PatPlanList,SubList)); if(priplan!=null && priplan.PlanType=="p") {//PPO double standardfee=Fees.GetAmount0(ProcCur.CodeNum,Providers.GetProv(Patients.GetProvNum(PatCur)).FeeSched); if(standardfee>insfee) { ProcCur.ProcFee=standardfee; } else { ProcCur.ProcFee=insfee; } } else { ProcCur.ProcFee=insfee; } //ProcCur.ProcFee=Fees.GetAmount0(ProcedureCode2.CodeNum,Fees.GetFeeSched(PatCur,PlanList,PatPlanList)); Procedures.Update(ProcCur,ProcOld); Recalls.Synch(ProcCur.PatNum); if(ProcCur.ProcStatus==ProcStat.C){ SecurityLogs.MakeLogEntry(Permissions.ProcComplEdit,PatCur.PatNum, PatCur.GetNameLF()+", "+ProcedureCode2.ProcCode+", " +ProcCur.ProcFee.ToString("c")); } } DialogResult=DialogResult.OK; //it is assumed that we will do an immediate refresh after closing this window. }
private void butChange_Click(object sender, System.EventArgs e) { FormProcCodes FormP=new FormProcCodes(); FormP.IsSelectionMode=true; FormP.ShowDialog(); if(FormP.DialogResult!=DialogResult.OK){ return; } ProcedureCode procCodeOld=ProcedureCodes.GetProcCode(ProcCur.CodeNum); ProcedureCode procCodeNew=ProcedureCodes.GetProcCode(FormP.SelectedCodeNum); if(procCodeOld.TreatArea != procCodeNew.TreatArea) { MsgBox.Show(this,"Not allowed due to treatment area mismatch."); return; } ProcCur.CodeNum=FormP.SelectedCodeNum; ProcedureCode2=ProcedureCodes.GetProcCode(FormP.SelectedCodeNum); textDesc.Text=ProcedureCode2.Descript; long priSubNum=PatPlans.GetInsSubNum(PatPlanList,1); InsSub prisub=InsSubs.GetSub(priSubNum,SubList);//can handle an inssubnum=0 //long priPlanNum=PatPlans.GetPlanNum(PatPlanList,1); InsPlan priplan=InsPlans.GetPlan(prisub.PlanNum,PlanList);//can handle a plannum=0 double insfee=Fees.GetAmount0(ProcCur.CodeNum,Fees.GetFeeSched(PatCur,PlanList,PatPlanList,SubList)); if(priplan!=null && priplan.PlanType=="p") {//PPO double standardfee=Fees.GetAmount0(ProcCur.CodeNum,Providers.GetProv(Patients.GetProvNum(PatCur)).FeeSched); if(standardfee>insfee) { ProcCur.ProcFee=standardfee; } else { ProcCur.ProcFee=insfee; } } else { ProcCur.ProcFee=insfee; } switch(ProcedureCode2.TreatArea){ case TreatmentArea.Quad: ProcCur.Surf="UR"; radioUR.Checked=true; break; case TreatmentArea.Sextant: ProcCur.Surf="1"; radioS1.Checked=true; break; case TreatmentArea.Arch: ProcCur.Surf="U"; radioU.Checked=true; break; } for(int i=0;i<ClaimProcsForProc.Count;i++) { if(ClaimProcsForProc[i].ClaimPaymentNum!=0) { continue;//this shouldn't be possible, but it's a good check to make. } ClaimProcs.Delete(ClaimProcsForProc[i]);//that way, completely new ones will be added back, and NoBillIns will be accurate. } ClaimProcsForProc=new List<ClaimProc>(); Procedures.ComputeEstimates(ProcCur,PatCur.PatNum,ClaimProcsForProc,false,PlanList,PatPlanList,BenefitList,PatCur.Age,SubList); FillIns(); SetControlsUpperLeft(); }
private void FormProcInfo_Load(object sender,System.EventArgs e) { //Set the title bar to show the patient's name much like the main screen does. this.Text+=" - "+PatCur.GetNameLF(); //richTextBox1.Text="This is a test of the functions of a rich text box."; //webBrowser1. //richTextBox1.Select(10,4); //richTextBox1.SelectionFont=new Font(FontFamily.GenericMonospace,8); //richTextBox1.Select(22,9); //richTextBox1.SelectionFont=new Font(FontFamily.GenericMonospace,8,FontStyle.Underline); textDateEntry.Text=ProcCur.DateEntryC.ToShortDateString(); if(PrefC.GetBool(PrefName.EasyHidePublicHealth)){ labelPlaceService.Visible=false; comboPlaceService.Visible=false; labelSite.Visible=false; textSite.Visible=false; butPickSite.Visible=false; } if(PrefC.GetLong(PrefName.UseInternationalToothNumbers)==1){ listBoxTeeth.Items.Clear(); listBoxTeeth.Items.AddRange(new string[] {"18","17","16","15","14","13","12","11","21","22","23","24","25","26","27","28"}); listBoxTeeth2.Items.Clear(); listBoxTeeth2.Items.AddRange(new string[] {"48","47","46","45","44","43","42","41","31","32","33","34","35","36","37","38"}); } if(PrefC.GetLong(PrefName.UseInternationalToothNumbers)==3){ listBoxTeeth.Items.Clear(); listBoxTeeth.Items.AddRange(new string[] {"8","7","6","5","4","3","2","1","1","2","3","4","5","6","7","8"}); listBoxTeeth2.Items.Clear(); listBoxTeeth2.Items.AddRange(new string[] {"8","7","6","5","4","3","2","1","1","2","3","4","5","6","7","8"}); } if(!Security.IsAuthorized(Permissions.ProcEditShowFee,true)){ labelAmount.Visible=false; textProcFee.Visible=false; } if(!Security.IsAuthorized(Permissions.ProcedureNote,true)) { textNotes.Enabled=false; buttonUseAutoNote.Enabled=false; } ClaimList=Claims.Refresh(PatCur.PatNum); ProcedureCode2=ProcedureCodes.GetProcCode(ProcCur.CodeNum); if(ProcCur.ProcStatus==ProcStat.C && PrefC.GetBool(PrefName.ProcLockingIsAllowed) && !ProcCur.IsLocked) { butLock.Visible=true; } else { butLock.Visible=false; } if(IsNew){ if(ProcCur.ProcStatus==ProcStat.C){ if(!Security.IsAuthorized(Permissions.ProcComplCreate)){ DialogResult=DialogResult.Cancel; return; } } //SetControls(); //return; } else{ if(ProcCur.ProcStatus==ProcStat.C){ if(ProcCur.IsLocked) {//Whether locking is currently allowed, this proc may have been locked previously. butOK.Enabled=false;//use this state to cascade permission to any form opened from here butDelete.Enabled=false; butChange.Enabled=false; butEditAnyway.Enabled=false; butSetComplete.Enabled=false; butSnomedBodySiteSelect.Enabled=false; butNoneSnomedBodySite.Enabled=false; labelLocked.Visible=true; butAppend.Visible=true; textNotes.ReadOnly=true;//just for visual cue. No way to save changes, anyway. textNotes.BackColor=SystemColors.Control; butInvalidate.Visible=true; butInvalidate.Location=butLock.Location; } else{ butInvalidate.Visible=false; //because islocked overrides security: if(!Security.IsAuthorized(Permissions.ProcComplEdit,ProcCur.DateEntryC)){ butOK.Enabled=false;//use this state to cascade permission to any form opened from here butDelete.Enabled=false; butChange.Enabled=false; butEditAnyway.Enabled=false; butSetComplete.Enabled=false; } } } } //ClaimProcList=ClaimProcs.Refresh(PatCur.PatNum); ClaimProcsForProc=ClaimProcs.RefreshForProc(ProcCur.ProcNum); PatPlanList=PatPlans.Refresh(PatCur.PatNum); BenefitList=Benefits.Refresh(PatPlanList,SubList); if(Procedures.IsAttachedToClaim(ProcCur,ClaimProcsForProc)){ StartedAttachedToClaim=true; //however, this doesn't stop someone from creating a claim while this window is open, //so this is checked at the end, too. panel1.Enabled=false; comboProcStatus.Enabled=false; checkNoBillIns.Enabled=false; butChange.Enabled=false; butDelete.Enabled=false; butEditAnyway.Visible=true; labelClaim.Visible=true; butSetComplete.Enabled=false; } if(PrefC.GetBool(PrefName.EasyHideClinical)){ labelDx.Visible=false; comboDx.Visible=false; labelPrognosis.Visible=false; comboPrognosis.Visible=false; } if(PrefC.GetBool(PrefName.EasyHideMedicaid)) { comboBillingTypeOne.Visible=false; labelBillingTypeOne.Visible=false; comboBillingTypeTwo.Visible=false; labelBillingTypeTwo.Visible=false; } if(CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Canadian. en-CA or fr-CA //groupCanadianProcType.Location=new Point(106,301); groupProsth.Visible=false; labelClaimNote.Visible=false; textClaimNote.Visible=false; butBF.Text=Lan.g(this,"B/V");//vestibular instead of facial butV.Text=Lan.g(this,"5"); if(ProcedureCode2.IsCanadianLab) { //Prevent lab fees from having lab fees attached. labelCanadaLabFee1.Visible=false; textCanadaLabFee1.Visible=false; labelCanadaLabFee2.Visible=false; textCanadaLabFee2.Visible=false; } else { canadaLabFees=Procedures.GetCanadianLabFees(ProcCur.ProcNum); if(canadaLabFees.Count>0) { textCanadaLabFee1.Text=canadaLabFees[0].ProcFee.ToString("n"); if(canadaLabFees[0].ProcStatus==ProcStat.C) { textCanadaLabFee1.ReadOnly=true; } } if(canadaLabFees.Count>1) { textCanadaLabFee2.Text=canadaLabFees[1].ProcFee.ToString("n"); if(canadaLabFees[1].ProcStatus==ProcStat.C) { textCanadaLabFee2.ReadOnly=true; } } } } else { tabControl.Controls.Remove(tabPageCanada); //groupCanadianProcType.Visible=false; } if(Programs.UsingOrion) { if(IsNew) { OrionProcCur=new OrionProc(); OrionProcCur.ProcNum=ProcCur.ProcNum; if(ProcCur.ProcStatus==ProcStat.EO) { OrionProcCur.Status2=OrionStatus.E; } else { OrionProcCur.Status2=OrionStatus.TP; } } else { OrionProcCur=OrionProcs.GetOneByProcNum(ProcCur.ProcNum); if(ProcCur.DateTP<MiscData.GetNowDateTime().Date && (OrionProcCur.Status2==OrionStatus.CA_EPRD || OrionProcCur.Status2==OrionStatus.CA_PD || OrionProcCur.Status2==OrionStatus.CA_Tx || OrionProcCur.Status2==OrionStatus.R)) {//Not allowed to edit procedures with these statuses that are older than a day. MsgBox.Show(this,"You cannot edit refused or cancelled procedures."); DialogResult=DialogResult.Cancel; } if(OrionProcCur.Status2==OrionStatus.C || OrionProcCur.Status2==OrionStatus.CR || OrionProcCur.Status2==OrionStatus.CS) { textNotes.Enabled=false; } } textDateTP.ReadOnly=true; //panelOrion.Visible=true; butAddEstimate.Visible=false; checkNoBillIns.Visible=false; gridIns.Visible=false; butAddAdjust.Visible=false; tbPay.Visible=false; tbAdj.Visible=false; comboProcStatus.Enabled=false; labelAmount.Visible=false; textProcFee.Visible=false; labelPriority.Visible=false; comboPriority.Visible=false; butSetComplete.Visible=false; labelSetComplete.Visible=false; } else { tabControl.Controls.Remove(tabPageOrion); } if(Programs.UsingOrion || PrefC.GetBool(PrefName.ShowFeatureMedicalInsurance)) { labelEndTime.Visible=true; textTimeEnd.Visible=true; butNow.Visible=true; labelTimeFinal.Visible=true; textTimeFinal.Visible=true; } if(PrefC.GetBool(PrefName.ShowFeatureEhr)) { textNotes.HideSelection=false;//When text is selected programmatically using our Search function, this causes the selection to be visible to the users. } else { butSearch.Visible=false; } IsStartingUp=true; FillControlsOnStartup(); SetControlsUpperLeft(); FillReferral(); FillIns(false); FillPayments(); FillAdj(); IsStartingUp=false; //string retVal=ProcCur.Note+ProcCur.UserNum.ToString(); //MsgBoxCopyPaste msgb=new MsgBoxCopyPaste(retVal); //msgb.ShowDialog(); }
///<summary>Test 13: EcwOldTight,EcwOldFull,EcwTight,HL7DefEcwFull: Truncate D codes to Dxxxx, if not a D code don't truncate: Insert a procedure D2332A, with treatment area surface and ProcFee=200.00. Insert another procedure 2332AA with treatment area surface and ProcFee=250.00. Add a D2332A on tooth 1 with surfaces MOD, and a 2332AA on tooth 2 with surfaces MOD to patient's chart. Schedule an appointment for patient with AptNum=600, appointment.ProvNum=ProvNum for provider DOC1 and attach the two procedures. Create a DFT message for these procedures, appointment, patient, and provider and verify that the D2332A gets truncated to D2332 and the 2332AA doesn't get changed. EcwOldStandalone,HL7DefEcwStandalone: DFT messages are not created in Standalone mode.</summary> public static string Test13(HL7TestInterfaceEnum hl7TestInterfaceEnum) { if(hl7TestInterfaceEnum==HL7TestInterfaceEnum.EcwOldStandalone || hl7TestInterfaceEnum==HL7TestInterfaceEnum.HL7DefEcwStandalone) { return "Test 13: Passed.\r\n"; } Provider prov=Providers.GetProvByEcwID("DOC1"); if(prov==null) { return "Test 13: Couldn't locate provider.\r\n"; } Appointment apt=new Appointment(); apt.AptNum=600; apt.AptDateTime=new DateTime(2012,09,06,10,0,0); apt.PatNum=10; apt.ProvNum=prov.ProvNum; Appointments.InsertIncludeAptNum(apt,true); ProcedureCode code=new ProcedureCode(); code.ProcCode="D2332A"; ProcedureCodes.Insert(code); code=new ProcedureCode(); code.ProcCode="2332AA"; ProcedureCodes.Insert(code); List<Procedure> procList=new List<Procedure>(); ProcedureCodes.RefreshCache(); //Add the 2 procs to the procedurelog table on the correct date, for the correct appointment and patient and provider. Procedure proc=new Procedure(); proc.AptNum=600; proc.PatNum=10; proc.ProcDate=new DateTime(2012,09,06); proc.CodeNum=ProcedureCodes.GetCodeNum("D2332A"); proc.ProcStatus=ProcStat.C; proc.ProvNum=prov.ProvNum; proc.ProcFee=200.00; proc.ToothNum="1"; proc.Surf="MOD"; Procedures.Insert(proc); procList.Add(proc); proc=new Procedure(); proc.AptNum=600; proc.PatNum=10; proc.ProcDate=new DateTime(2012,09,06); proc.CodeNum=ProcedureCodes.GetCodeNum("2332AA"); proc.ProcStatus=ProcStat.C; proc.ProvNum=prov.ProvNum; proc.ProcFee=250.00; proc.ToothNum="2"; proc.Surf="MOD"; Procedures.Insert(proc); procList.Add(proc); Patient pat=Patients.GetPat(10); if(pat==null) { return "Test 13: Couldn't locate patient.\r\n"; } Patient guar=Patients.GetPat(11); if(guar==null) { return "Test 13: Couldn't locate guarantor.\r\n"; } MessageHL7 msg=null; try { switch(hl7TestInterfaceEnum) { //EcwOldStandalone and HL7DefEcwStandalone were handled higher up case HL7TestInterfaceEnum.EcwOldFull: case HL7TestInterfaceEnum.EcwOldTight: OpenDentBusiness.HL7.EcwDFT dft=new OpenDentBusiness.HL7.EcwDFT(); dft.InitializeEcw(apt.AptNum,prov.ProvNum,pat,"Test Message","treatment",false); msg=new MessageHL7(dft.GenerateMessage()); break; case HL7TestInterfaceEnum.HL7DefEcwFull: case HL7TestInterfaceEnum.HL7DefEcwTight: msg=new MessageHL7(OpenDentBusiness.HL7.MessageConstructor.GenerateDFT(procList,EventTypeHL7.P03,pat,guar,apt.AptNum,"treatment","Test Message").ToString()); //msg will be null if there's not DFT defined for the def. Should handle results for those defs higher up break; default: return "Test 13: interface not found."; } } catch(Exception ex) { return "Test 13: Message creation error. "+ex+".\r\n"; } string provField=""; switch(hl7TestInterfaceEnum) { case HL7TestInterfaceEnum.EcwOldFull: case HL7TestInterfaceEnum.EcwOldTight: provField="DOC1^Albert, Brian S^^"; break; default: provField="DOC1^Albert^Brian^S"; break; } string msgtext=@"MSH|^~\&|OD||ECW||"+msg.Segments[0].GetFieldFullText(6)+"||DFT^P03||P|2.3\r\n" +"EVN|P03|"+msg.Segments[1].GetFieldFullText(2)+"|\r\n" +"PID|1|A11|10||Smith^Jane^N||19760205|F||White|421 Main St^Apt 17^Dallas^OR^97338||5035554045|5035554234||Married|||111224444|||\r\n" +"PV1|||||||"+provField+"||||||||||||600|||||||||||||||||||||||||||||||\r\n" +"FT1|1|||20120906000000|20120906000000|CG||||1.0||||||||||"+provField+"|"+provField+"|200.00|||D2332|1^MOD\r\n" +"FT1|2|||20120906000000|20120906000000|CG||||1.0||||||||||"+provField+"|"+provField+"|250.00|||2332AA|2^MOD\r\n" +"ZX1|6|PDF|PATHOLOGY^Pathology Report^L|treatment|Test Message"; MessageHL7 correctMsg=new MessageHL7(msgtext); string retval=CompareMsgs(msg,correctMsg); if(retval.Length>0) { return "Test 13: "+retval; } return "Test 13: Passed.\r\n"; }
private void FormProcInfo_Load(object sender, System.EventArgs e) { //richTextBox1.Text="This is a test of the functions of a rich text box."; //webBrowser1. //richTextBox1.Select(10,4); //richTextBox1.SelectionFont=new Font(FontFamily.GenericMonospace,8); //richTextBox1.Select(22,9); //richTextBox1.SelectionFont=new Font(FontFamily.GenericMonospace,8,FontStyle.Underline); textDateEntry.Text=ProcCur.DateEntryC.ToShortDateString(); if(PrefC.GetBool(PrefName.EasyHidePublicHealth)){ labelPlaceService.Visible=false; comboPlaceService.Visible=false; labelSite.Visible=false; textSite.Visible=false; butPickSite.Visible=false; } if(PrefC.GetLong(PrefName.UseInternationalToothNumbers)==1){ listBoxTeeth.Items.Clear(); listBoxTeeth.Items.AddRange(new string[] {"18","17","16","15","14","13","12","11","21","22","23","24","25","26","27","28"}); listBoxTeeth2.Items.Clear(); listBoxTeeth2.Items.AddRange(new string[] {"48","47","46","45","44","43","42","41","31","32","33","34","35","36","37","38"}); } if(PrefC.GetLong(PrefName.UseInternationalToothNumbers)==3){ listBoxTeeth.Items.Clear(); listBoxTeeth.Items.AddRange(new string[] {"8","7","6","5","4","3","2","1","1","2","3","4","5","6","7","8"}); listBoxTeeth2.Items.Clear(); listBoxTeeth2.Items.AddRange(new string[] {"8","7","6","5","4","3","2","1","1","2","3","4","5","6","7","8"}); } if(!Security.IsAuthorized(Permissions.ProcEditShowFee,true)){ labelAmount.Visible=false; textProcFee.Visible=false; } if(!Security.IsAuthorized(Permissions.ProcedureNote,true)) { textNotes.Enabled=false; buttonUseAutoNote.Enabled=false; } ClaimList=Claims.Refresh(PatCur.PatNum); ProcedureCode2=ProcedureCodes.GetProcCode(ProcCur.CodeNum); if(IsNew){ if(ProcCur.ProcStatus==ProcStat.C){ if(!Security.IsAuthorized(Permissions.ProcComplCreate)){ DialogResult=DialogResult.Cancel; return; } } //SetControls(); //return; } else{ if(ProcCur.ProcStatus==ProcStat.C){ if(!Security.IsAuthorized(Permissions.ProcComplEdit,ProcCur.DateEntryC)){ butOK.Enabled=false;//use this state to cascade permission to any form openned from here butDelete.Enabled=false; butChange.Enabled=false; butEditAnyway.Enabled=false; butSetComplete.Enabled=false; } } } //ClaimProcList=ClaimProcs.Refresh(PatCur.PatNum); ClaimProcsForProc=ClaimProcs.RefreshForProc(ProcCur.ProcNum); PatPlanList=PatPlans.Refresh(PatCur.PatNum); BenefitList=Benefits.Refresh(PatPlanList,SubList); if(Procedures.IsAttachedToClaim(ProcCur,ClaimProcsForProc)){ StartedAttachedToClaim=true; //however, this doesn't stop someone from creating a claim while this window is open, //so this is checked at the end, too. panel1.Enabled=false; comboProcStatus.Enabled=false; checkNoBillIns.Enabled=false; butChange.Enabled=false; butDelete.Enabled=false; butEditAnyway.Visible=true; labelClaim.Visible=true; butSetComplete.Enabled=false; } if(PrefC.GetBool(PrefName.EasyHideClinical)){ labelDx.Visible=false; comboDx.Visible=false; labelPrognosis.Visible=false; comboPrognosis.Visible=false; } if(PrefC.GetBool(PrefName.EasyHideMedicaid)) { comboBillingTypeOne.Visible=false; labelBillingTypeOne.Visible=false; comboBillingTypeTwo.Visible=false; labelBillingTypeTwo.Visible=false; } if(CultureInfo.CurrentCulture.Name.EndsWith("CA")) {//Canadian. en-CA or fr-CA groupProsth.Visible=false; labelClaimNote.Visible=false; textClaimNote.Visible=false; butBF.Text=Lan.g(this,"B/V");//vestibular instead of facial butV.Text=Lan.g(this,"5"); } else { groupCanadianProcType.Visible=false; } if(Programs.UsingOrion){ if(IsNew) { OrionProcCur=new OrionProc(); OrionProcCur.ProcNum=ProcCur.ProcNum; if(ProcCur.ProcStatus==ProcStat.EO) { OrionProcCur.Status2=OrionStatus.E; } else { OrionProcCur.Status2=OrionStatus.TP; } } else { OrionProcCur=OrionProcs.GetOneByProcNum(ProcCur.ProcNum); if(ProcCur.DateTP<MiscData.GetNowDateTime().Date && (OrionProcCur.Status2==OrionStatus.CA_EPRD || OrionProcCur.Status2==OrionStatus.CA_PD || OrionProcCur.Status2==OrionStatus.CA_Tx || OrionProcCur.Status2==OrionStatus.R)) {//Not allowed to edit procedures with these statuses that are older than a day. MsgBox.Show(this,"You cannot edit refused or cancelled procedures."); DialogResult=DialogResult.Cancel; } if(OrionProcCur.Status2==OrionStatus.C || OrionProcCur.Status2==OrionStatus.CR || OrionProcCur.Status2==OrionStatus.CS){ textNotes.Enabled=false; } } textDateTP.ReadOnly=true; panelOrion.Visible=true; butAddEstimate.Visible=false; checkNoBillIns.Visible=false; gridIns.Visible=false; butAddAdjust.Visible=false; tbPay.Visible=false; tbAdj.Visible=false; comboProcStatus.Enabled=false; labelAmount.Visible=false; textProcFee.Visible=false; labelPriority.Visible=false; comboPriority.Visible=false; butSetComplete.Visible=false; labelSetComplete.Visible=false; } if(Programs.UsingOrion || PrefC.GetBool(PrefName.ShowFeatureMedicalInsurance)) { labelEndTime.Visible=true; textTimeEnd.Visible=true; butNow.Visible=true; labelTimeFinal.Visible=true; textTimeFinal.Visible=true; } IsStartingUp=true; FillControlsOnStartup(); SetControlsUpperLeft(); FillReferral(); FillIns(false); FillPayments(); FillAdj(); IsStartingUp=false; }
private static List <TreatPlanPresenterEntry> GetListTreatPlanPresenterEntries(List <long> listClinicNums, bool isFirstPresenter, bool isPresenter , DateTime dateStart, DateTime dateEnd) { //No need to check RemotingRole; private method. List <Procedure> listProcsComplete = ReportsComplex.RunFuncOnReportServer(() => Procedures.GetCompletedForDateRangeLimited(dateStart, dateEnd, listClinicNums)); List <ProcTP> listProcTPs = ReportsComplex.RunFuncOnReportServer(() => ProcTPs.GetForProcs(listProcsComplete.Select(x => x.ProcNum).ToList())); List <Procedure> listTreatPlanProcs = listProcsComplete.Where(x => listProcTPs.Select(y => y.ProcNumOrig).Contains(x.ProcNum)).ToList(); List <TreatPlan> listSavedTreatPlans = ReportsComplex.RunFuncOnReportServer(() => TreatPlans.GetFromProcTPs(listProcTPs)); // attached proctps to treatment plans. List <ClaimProc> listClaimProcs = ReportsComplex.RunFuncOnReportServer(() => ClaimProcs.GetForProcsLimited(listTreatPlanProcs.Select(x => x.ProcNum).ToList(), ClaimProcStatus.Received, ClaimProcStatus.Supplemental, ClaimProcStatus.CapComplete, ClaimProcStatus.NotReceived)); List <Adjustment> listAdjustments = ReportsComplex.RunFuncOnReportServer(() => Adjustments.GetForProcs(listTreatPlanProcs.Select(x => x.ProcNum).ToList())); List <Userod> listUserods = ReportsComplex.RunFuncOnReportServer(() => Userods.GetAll()); List <TreatPlanPresenterEntry> listTreatPlanPresenterEntries = new List <TreatPlanPresenterEntry>(); List <ProcedureCode> listProcCodes = ProcedureCodes.GetCodesForCodeNums(listTreatPlanProcs.Select(x => x.CodeNum).ToList()); foreach (Procedure procCur in listTreatPlanProcs) { double grossProd = procCur.ProcFeeTotal; double writeOffs = listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum) .Where(x => x.Status == ClaimProcStatus.CapComplete) .Sum(x => x.WriteOff); grossProd -= writeOffs; writeOffs = listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum) .Where(x => x.Status == ClaimProcStatus.NotReceived || x.Status == ClaimProcStatus.Received || x.Status == ClaimProcStatus.Supplemental) .Sum(x => x.WriteOff); double adjustments = listAdjustments.Where(x => x.ProcNum == procCur.ProcNum).Sum(x => x.AdjAmt); double netProd = grossProd - writeOffs + adjustments; TreatPlan treatPlanCur; if (isFirstPresenter) { treatPlanCur = listSavedTreatPlans.Where(x => x.ListProcTPs.Any(y => y.ProcNumOrig == procCur.ProcNum)).OrderBy(x => x.DateTP).First(); } else //radioLastPresented { treatPlanCur = listSavedTreatPlans.Where(x => x.ListProcTPs.Any(y => y.ProcNumOrig == procCur.ProcNum)).OrderByDescending(x => x.DateTP).First(); } Userod userPresenter; if (isPresenter) { userPresenter = listUserods.FirstOrDefault(x => x.UserNum == treatPlanCur.UserNumPresenter); } else //radioEntryUser { userPresenter = listUserods.FirstOrDefault(x => x.UserNum == treatPlanCur.SecUserNumEntry); } ProcedureCode procCode = listProcCodes.First(x => x.CodeNum == procCur.CodeNum); listTreatPlanPresenterEntries.Add(new TreatPlanPresenterEntry() { Presenter = userPresenter == null?"":userPresenter.UserName, DatePresented = treatPlanCur.DateTP, DateCompleted = procCur.ProcDate, ProcDescript = procCode.Descript, GrossProd = grossProd, Adjustments = adjustments, WriteOffs = writeOffs, NetProd = netProd, UserNumPresenter = userPresenter == null?0:userPresenter.UserNum, PresentedClinic = procCur.ClinicNum }); } return(listTreatPlanPresenterEntries); }
///<summary>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(""); } }
private static string GetToothQuadOrArch(Procedure proc,ProcedureCode procCode) { switch(procCode.TreatArea){ case TreatmentArea.Arch: //if(proc.Surf=="U"){ return "00"; //} //else{ // return "01"; //} case TreatmentArea.Mouth: case TreatmentArea.None: return "00"; case TreatmentArea.Quad: if(proc.Surf=="UR"){ return "10"; } else if(proc.Surf=="UL") { return "20"; } else if(proc.Surf=="LR") { return "40"; } else{//LL return "30"; } case TreatmentArea.Sextant: if(proc.Surf=="1") { return "00"; } else if(proc.Surf=="2") { return "00"; } else if(proc.Surf=="3") { return "00"; } else if(proc.Surf=="4") { return "00"; } else if(proc.Surf=="5") { return "00"; } else{//6 return "00"; } case TreatmentArea.Surf: case TreatmentArea.Tooth: return Tooth.ToInternat(proc.ToothNum); case TreatmentArea.ToothRange: string[] range=proc.ToothRange.Split(','); if(range.Length==0 || !Tooth.IsValidDB(range[0])){ return "00"; } else if(Tooth.IsMaxillary(range[0])){ return "00"; } return "00"; } return "00";//will never happen }
private static string GetToothQuadOrArch(Procedure proc,ProcedureCode procCode){ switch(procCode.TreatArea){ case TreatmentArea.Arch: //if(proc.Surf=="U"){ return "00"; //} //else{ // return "01"; //} case TreatmentArea.Mouth: case TreatmentArea.None: return "00"; case TreatmentArea.Quad: if(proc.Surf=="UR"){ return "10"; } else if(proc.Surf=="UL") { return "20"; } else if(proc.Surf=="LR") { return "40"; } else{//LL return "30"; } case TreatmentArea.Sextant: if(proc.Surf=="1") {//Upper Right return "03"; } else if(proc.Surf=="2") {//Upper Anterior return "04"; } else if(proc.Surf=="3") {//Upper Left return "05"; } else if(proc.Surf=="4") {//Lower Left return "06"; } else if(proc.Surf=="5") {//Lower Anterior return "07"; } else if(proc.Surf=="6") {//Lower Right return "08"; } return "00";//Invalid or unspecified sextant. This is also the number that represents "whole mouth" in Canada. case TreatmentArea.Surf: case TreatmentArea.Tooth: return Tooth.ToInternat(proc.ToothNum); case TreatmentArea.ToothRange: string[] range=proc.ToothRange.Split(','); if(range.Length==0 || !Tooth.IsValidDB(range[0])){ return "00"; } else if(Tooth.IsMaxillary(range[0])){ return "00"; } return "00"; } return "00";//will never happen }
///<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); }
public static string ProcedurelogCodeNumInvalid(bool verbose,bool isCheck) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { return Meth.GetString(MethodBase.GetCurrentMethod(),verbose,isCheck); } string log=""; if(isCheck) { command="SELECT COUNT(*) FROM procedurelog WHERE NOT EXISTS (SELECT * FROM procedurecode WHERE procedurecode.CodeNum=procedurelog.CodeNum)"; int numFound=PIn.Int(Db.GetCount(command)); if(numFound>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Procedures found with invalid CodeNum")+": "+numFound+"\r\n"; } } else { long badCodeNum=0; if(!ProcedureCodes.IsValidCode("~BAD~")) { ProcedureCode badCode=new ProcedureCode(); badCode.ProcCode="~BAD~"; badCode.Descript="Invalid procedure"; badCode.AbbrDesc="Invalid procedure"; badCode.ProcCat=DefC.GetByExactNameNeverZero(DefCat.ProcCodeCats,"Never Used"); ProcedureCodes.Insert(badCode); badCodeNum=badCode.CodeNum; } else { badCodeNum=ProcedureCodes.GetCodeNum("~BAD~"); } command="UPDATE procedurelog SET CodeNum=" + POut.Long(badCodeNum) + " WHERE NOT EXISTS (SELECT * FROM procedurecode WHERE procedurecode.CodeNum=procedurelog.CodeNum)"; int numberFixed=Db.NonQ32(command); if(numberFixed>0 || verbose) { log+=Lans.g("FormDatabaseMaintenance","Procedures fixed with invalid CodeNum")+": "+numberFixed.ToString()+"\r\n"; } } return log; }
///<summary>If not using clinics then supply an empty list of clinicNums.</summary> public static DataTable GetTreatPlanPresentationStatistics(DateTime dateStart, DateTime dateEnd, bool isFirstPresented, bool hasAllClinics , bool hasClinicsEnabled, bool isPresenter, bool isGross, bool hasAllUsers, List <long> listUserNums, List <long> listClinicNums) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), dateStart, dateEnd, isFirstPresented, hasAllClinics, hasClinicsEnabled, isPresenter, isGross , hasAllUsers, listUserNums, listClinicNums)); } List <ProcTP> listProcTPsAll = ReportsComplex.RunFuncOnReportServer(() => ProcTPs.GetAllLim()); List <TreatPlan> listSavedTreatPlans = ReportsComplex.RunFuncOnReportServer(() => TreatPlans.GetAllSavedLim()); List <ProcTpTreatPlan> listProcTPTreatPlans = new List <ProcTpTreatPlan>(); listProcTPsAll.ForEach(x => { listProcTPTreatPlans.Add(new ProcTpTreatPlan() { TreatPlanCur = listSavedTreatPlans.First(y => y.TreatPlanNum == x.TreatPlanNum), ProcTPCur = x }); }); //get one entry per procedure with their first/last date of presentation based on radio buttons. if (isFirstPresented) { listProcTPTreatPlans = listProcTPTreatPlans .OrderBy(x => x.ProcTPCur.ProcNumOrig) .ThenBy(x => x.TreatPlanCur.DateTP) .ThenBy(x => x.TreatPlanCur.TreatPlanNum) .GroupBy(x => x.ProcTPCur.ProcNumOrig) .Select(x => x.First()) .ToList(); } else { listProcTPTreatPlans = listProcTPTreatPlans .OrderBy(x => x.ProcTPCur.ProcNumOrig) .ThenByDescending(x => x.TreatPlanCur.DateTP) .ThenBy(x => x.TreatPlanCur.TreatPlanNum) .GroupBy(x => x.ProcTPCur.ProcNumOrig) .Select(x => x.First()) .ToList(); } //get rid of any entries that are outside the range selected. listProcTPTreatPlans = listProcTPTreatPlans.Where(x => x.TreatPlanCur.DateTP.Date >= dateStart && x.TreatPlanCur.DateTP.Date <= dateEnd).ToList(); //Get the associated procedures, claimprocs, adjustments, users, appointments. List <Procedure> listProcsForTreatPlans = ReportsComplex.RunFuncOnReportServer(() => Procedures.GetForProcTPs(listProcTPTreatPlans.Select(x => x.ProcTPCur).ToList(), ProcStat.C, ProcStat.TP)); if (hasClinicsEnabled && !hasAllClinics) { listProcsForTreatPlans = listProcsForTreatPlans.FindAll(x => listClinicNums.Contains(x.ClinicNum)); } List <ClaimProc> listClaimProcs = ReportsComplex.RunFuncOnReportServer(() => ClaimProcs.GetForProcsLimited(listProcsForTreatPlans.Select(x => x.ProcNum).ToList(), ClaimProcStatus.CapComplete, ClaimProcStatus.NotReceived, ClaimProcStatus.Received, ClaimProcStatus.Supplemental, ClaimProcStatus.Estimate)); List <Adjustment> listAdjustments = ReportsComplex.RunFuncOnReportServer(() => Adjustments.GetForProcs(listProcsForTreatPlans.Select(x => x.ProcNum).ToList())); List <Userod> listUserods = ReportsComplex.RunFuncOnReportServer(() => Userods.GetAll()); List <TreatPlanPresenterEntry> listTreatPlanPresenterEntries = new List <TreatPlanPresenterEntry>(); List <ProcedureCode> listProcCodes = ReportsComplex.RunFuncOnReportServer(() => ProcedureCodes.GetCodesForCodeNums(listProcsForTreatPlans.Select(x => x.CodeNum).ToList())); List <Appointment> listApts = ReportsComplex.RunFuncOnReportServer(() => Appointments.GetMultApts(listProcsForTreatPlans.Select(x => x.AptNum).ToList())); double amt = listProcsForTreatPlans.Sum(x => x.ProcFee); foreach (Procedure procCur in listProcsForTreatPlans) { double grossProd = procCur.ProcFeeTotal; double writeOffs = listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum) .Where(x => x.Status == ClaimProcStatus.CapComplete) .Sum(x => x.WriteOff); grossProd -= writeOffs; if (procCur.ProcStatus == ProcStat.C) { writeOffs += listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum) .Where(x => x.Status.In(ClaimProcStatus.NotReceived, ClaimProcStatus.Received, ClaimProcStatus.Supplemental)) .Sum(x => x.WriteOff); } else { foreach (ClaimProc claimProcCur in listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum).Where(x => x.Status == ClaimProcStatus.Estimate)) { if (claimProcCur.WriteOffEstOverride == -1) { if (claimProcCur.WriteOffEst != -1) { writeOffs += claimProcCur.WriteOffEst; } } else { writeOffs += claimProcCur.WriteOffEstOverride; } } //writeOffs += listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum) // .Where(x => x.Status == ClaimProcStatus.Estimate) // .Sum(x => x.WriteOffEstOverride == -1 ? (x.WriteOffEst == -1 ? 0 : x.WriteOffEst) : x.WriteOffEstOverride); //Allen won't let me commit this nested ternary :( } double adjustments = listAdjustments.Where(x => x.ProcNum == procCur.ProcNum).Sum(x => x.AdjAmt); double netProd = grossProd - writeOffs + adjustments; TreatPlan treatPlanCur = listProcTPTreatPlans.Where(x => x.ProcTPCur.ProcNumOrig == procCur.ProcNum).First().TreatPlanCur; Userod userPresenter; if (isPresenter) { userPresenter = listUserods.FirstOrDefault(x => x.UserNum == treatPlanCur.UserNumPresenter); } else //radioEntryUser { userPresenter = listUserods.FirstOrDefault(x => x.UserNum == treatPlanCur.SecUserNumEntry); } ProcedureCode procCode = listProcCodes.First(x => x.CodeNum == procCur.CodeNum); Appointment aptCur = listApts.FirstOrDefault(x => x.AptNum == procCur.AptNum); listTreatPlanPresenterEntries.Add(new TreatPlanPresenterEntry() { Presenter = userPresenter == null ? "" : userPresenter.UserName, DatePresented = treatPlanCur.DateTP, DateCompleted = procCur.ProcDate, ProcDescript = procCode.Descript, GrossProd = grossProd, Adjustments = adjustments, WriteOffs = writeOffs, NetProd = netProd, UserNumPresenter = userPresenter == null?0:userPresenter.UserNum, PresentedClinic = procCur.ClinicNum, ProcStatus = procCur.ProcStatus, TreatPlanNum = treatPlanCur.TreatPlanNum, AptNum = procCur.AptNum, AptStatus = aptCur == null?ApptStatus.None:aptCur.AptStatus }); } DataTable table = new DataTable(); table.Columns.Add("Presenter"); table.Columns.Add("# of Plans"); table.Columns.Add("# of Procs"); table.Columns.Add("# of ProcsSched"); table.Columns.Add("# of ProcsComp"); if (isGross) { table.Columns.Add("GrossTPAmt"); table.Columns.Add("GrossSchedAmt"); table.Columns.Add("GrossCompAmt"); } else { table.Columns.Add("NetTpAmt"); table.Columns.Add("NetSchedAmt"); table.Columns.Add("NetCompAmt"); } if (!hasAllUsers) { listTreatPlanPresenterEntries = listTreatPlanPresenterEntries.Where(x => listUserNums.Contains(x.UserNumPresenter)).ToList(); } listTreatPlanPresenterEntries = listTreatPlanPresenterEntries.OrderBy(x => x.Presenter).ToList(); listTreatPlanPresenterEntries .GroupBy(x => x.Presenter).ToList().ForEach(x => { DataRow row = table.NewRow(); row["Presenter"] = x.First().Presenter == "" ? "None" : x.First().Presenter; row["# of Plans"] = x.GroupBy(y => y.TreatPlanNum).Count(); row["# of Procs"] = x.Count(); row["# of ProcsSched"] = x.Count(y => y.ProcStatus == ProcStat.TP && y.AptNum != 0 && y.AptStatus == ApptStatus.Scheduled); row["# of ProcsComp"] = x.Count(y => y.ProcStatus == ProcStat.C); if (isGross) { row["GrossTpAmt"] = x.Sum(y => y.GrossProd); row["GrossSchedAmt"] = x.Where(y => y.ProcStatus == ProcStat.TP && y.AptNum != 0 && y.AptStatus == ApptStatus.Scheduled).Sum(y => y.GrossProd); row["GrossCompAmt"] = x.Where(y => y.ProcStatus == ProcStat.C).Sum(y => y.GrossProd); } else { row["NetTpAmt"] = x.Sum(y => y.NetProd); row["NetSchedAmt"] = x.Where(y => y.ProcStatus == ProcStat.TP && y.AptNum != 0 && y.AptStatus == ApptStatus.Scheduled).Sum(y => y.NetProd); row["NetCompAmt"] = x.Where(y => y.ProcStatus == ProcStat.C).Sum(y => y.NetProd); } table.Rows.Add(row); }); //DataTable table=ReportsComplex.RunFuncOnReportServer(() => ReportsComplex.GetTable(query)); return(table); }
///<summary>Should only be called if ODHQ.</summary> private static List <Procedure> AddSmsRepeatingChargesHelper(DateTime dateRun) { //No remoting role check; no call to db DateTime dateStart = new DateTime(dateRun.AddMonths(-1).AddDays(-20).Year, dateRun.AddMonths(-1).AddDays(-20).Month, 1); DateTime dateStop = dateRun.AddDays(1); List <SmsBilling> listSmsBilling = SmsBillings.GetByDateRange(dateStart, dateStop); List <Patient> listPatients = Patients.GetMultPats(listSmsBilling.Select(x => x.CustPatNum).Distinct().ToList()).ToList(); //local cache ProcedureCode procCodeAccess = ProcedureCodes.GetProcCode("038"); ProcedureCode procCodeUsage = ProcedureCodes.GetProcCode("039"); ProcedureCode procCodeConfirm = ProcedureCodes.GetProcCode("040"); List <Procedure> listProcsAccess = Procedures.GetCompletedForDateRange(dateStart, dateStop, new List <long> { procCodeAccess.CodeNum }); List <Procedure> listProcsUsage = Procedures.GetCompletedForDateRange(dateStart, dateStop, new List <long> { procCodeUsage.CodeNum }); List <Procedure> listProcsConfirm = Procedures.GetCompletedForDateRange(dateStart, dateStop, new List <long> { procCodeConfirm.CodeNum }); List <Procedure> retVal = new List <Procedure>(); foreach (SmsBilling smsBilling in listSmsBilling) { Patient pat = listPatients.FirstOrDefault(x => x.PatNum == smsBilling.CustPatNum); if (pat == null) { EServiceSignal eSignal = new EServiceSignal { ServiceCode = (int)eServiceCode.IntegratedTexting, SigDateTime = MiscData.GetNowDateTime(), Severity = eServiceSignalSeverity.Error, Description = "Sms billing row found for non existent patient PatNum:" + smsBilling.CustPatNum }; EServiceSignals.Insert(eSignal); continue; } //Find the billing date based on the date usage. DateTime billingDate = smsBilling.DateUsage.AddMonths(1); //we always bill the month after usage posts. Example: all January usage = 01/01/2015 billingDate = new DateTime( billingDate.Year, billingDate.Month, Math.Min(pat.BillingCycleDay, DateTime.DaysInMonth(billingDate.Year, billingDate.Month))); //example: dateUsage=08/01/2015, billing cycle date=8/14/2012, billing date should be 9/14/2015. if (billingDate > dateRun || billingDate < dateRun.AddMonths(-1).AddDays(-20)) { //One month and 20 day window. Bill regardless of presence of "038" repeat charge. continue; } if (smsBilling.AccessChargeTotalUSD == 0 && smsBilling.MsgChargeTotalUSD == 0 && smsBilling.ConfirmationChargeTotalUSD == 0) { //No charges so skip this customer. continue; } //Only post confirmation charge if valid. if (smsBilling.ConfirmationChargeTotalUSD > 0 && (billingDate <= DateTime.Today || PrefC.GetBool(PrefName.FutureTransDatesAllowed) && !listProcsConfirm.Exists(x => x.PatNum == pat.PatNum && x.ProcDate.Year == billingDate.Year && x.ProcDate.Month == billingDate.Month))) { //The calculated access charge was greater than 0 and there is not an existing "038" procedure on the account for that month. Procedure procConfirm = new Procedure(); procConfirm.CodeNum = procCodeConfirm.CodeNum; procConfirm.DateEntryC = DateTime.Today; procConfirm.PatNum = pat.PatNum; procConfirm.ProcDate = billingDate; procConfirm.DateTP = billingDate; procConfirm.ProcFee = smsBilling.ConfirmationChargeTotalUSD; procConfirm.ProcStatus = ProcStat.C; procConfirm.ProvNum = PrefC.GetLong(PrefName.PracticeDefaultProv); procConfirm.MedicalCode = procCodeConfirm.MedicalCode; procConfirm.BaseUnits = procCodeConfirm.BaseUnits; procConfirm.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs); procConfirm.BillingNote = smsBilling.BillingDescConfirmation; procConfirm.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService); //Default Proc Place of Service for the Practice is used. Procedures.Insert(procConfirm); listProcsConfirm.Add(procConfirm); retVal.Add(procConfirm); } //Confirmation charges may wipe out access charges. We still want to see the $0 charge in this case so post this charge if either of the 2 are valid. if ((smsBilling.AccessChargeTotalUSD > 0 || smsBilling.ConfirmationChargeTotalUSD > 0) && (billingDate <= DateTime.Today || PrefC.GetBool(PrefName.FutureTransDatesAllowed)) && !listProcsAccess.Exists(x => x.PatNum == pat.PatNum && x.ProcDate.Year == billingDate.Year && x.ProcDate.Month == billingDate.Month)) { //The calculated access charge was greater than 0 and there is not an existing "038" procedure on the account for that month. Procedure procAccess = new Procedure(); procAccess.CodeNum = procCodeAccess.CodeNum; procAccess.DateEntryC = DateTime.Today; procAccess.PatNum = pat.PatNum; procAccess.ProcDate = billingDate; procAccess.DateTP = billingDate; procAccess.ProcFee = smsBilling.AccessChargeTotalUSD; procAccess.ProcStatus = ProcStat.C; procAccess.ProvNum = PrefC.GetLong(PrefName.PracticeDefaultProv); procAccess.MedicalCode = procCodeAccess.MedicalCode; procAccess.BaseUnits = procCodeAccess.BaseUnits; procAccess.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs); procAccess.BillingNote = smsBilling.BillingDescSms; procAccess.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService); //Default Proc Place of Service for the Practice is used. Procedures.Insert(procAccess); listProcsAccess.Add(procAccess); retVal.Add(procAccess); } //Only post usage charge if valid. if (smsBilling.MsgChargeTotalUSD > 0 && (billingDate <= DateTime.Today || PrefC.GetBool(PrefName.FutureTransDatesAllowed)) && !listProcsUsage.Exists(x => x.PatNum == pat.PatNum && x.ProcDate.Year == billingDate.Year && x.ProcDate.Month == billingDate.Month)) { //Calculated Usage charge > 0 and not already billed, may exist without access charge Procedure procUsage = new Procedure(); procUsage.CodeNum = procCodeUsage.CodeNum; procUsage.DateEntryC = DateTime.Today; procUsage.PatNum = pat.PatNum; procUsage.ProcDate = billingDate; procUsage.DateTP = billingDate; procUsage.ProcFee = smsBilling.MsgChargeTotalUSD; procUsage.ProcStatus = ProcStat.C; procUsage.ProvNum = PrefC.GetLong(PrefName.PracticeDefaultProv); procUsage.MedicalCode = procCodeUsage.MedicalCode; procUsage.BaseUnits = procCodeUsage.BaseUnits; procUsage.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs); procUsage.PlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService); //Default Proc Place of Service for the Practice is used. procUsage.BillingNote = "Texting Usage charge for " + smsBilling.DateUsage.ToString("MMMM yyyy") + "."; Procedures.Insert(procUsage); listProcsUsage.Add(procUsage); retVal.Add(procUsage); } } return(retVal); }
///<summary>Returns true if any code is marked as BypassIfZero.</summary> public static bool DoAnyBypassLockDate() { ProcedureCode procedureCode = GetFirstOrDefaultFromList(x => x.BypassGlobalLock == BypassLockStatus.BypassIfZero); return(procedureCode != null); }
private static string GetArea(Procedure proc,ProcedureCode procCode) { if(procCode.TreatArea==TreatmentArea.Arch) { if(proc.Surf=="U") { return "01"; } if(proc.Surf=="L") { return "02"; } } if(procCode.TreatArea==TreatmentArea.Mouth) { return ""; } if(procCode.TreatArea==TreatmentArea.Quad) { if(proc.Surf=="UR") { return "10"; } if(proc.Surf=="UL") { return "20"; } if(proc.Surf=="LR") { return "40"; } if(proc.Surf=="LL") { return "30"; } } if(procCode.TreatArea==TreatmentArea.Sextant) { //we will assume that these are very rarely billed to ins return ""; } if(procCode.TreatArea==TreatmentArea.Surf) { return "";//might need to enhance this } if(procCode.TreatArea==TreatmentArea.Tooth) { return "";//might need to enhance this } if(procCode.TreatArea==TreatmentArea.ToothRange) { //already checked for blank tooth range if(Tooth.IsMaxillary(proc.ToothRange.Split(',')[0])) { return "01"; } else { return "02"; } } return ""; }
///<summary>Used in SV304 (dental only).</summary> private static string GetArea(Procedure proc,ProcedureCode procCode) { //"Required when the nomenclature associated with the procedure reported in SV301-2 refers to quadrant or arch //and the area of the oral cavity is not uniquely defined by the procedure description. //Report individual tooth numbers in one or more TOO segments. //Do not use this element for reporting of individual teeth. //If it is necessary to report one or more individual teeth, use the Tooth Information (TOO) segment in this loop." if(procCode.TreatArea==TreatmentArea.Arch) { if(proc.Surf=="U") { return "01"; } if(proc.Surf=="L") { return "02"; } } if(procCode.TreatArea==TreatmentArea.Mouth) { return ""; } if(procCode.TreatArea==TreatmentArea.Quad) { if(proc.Surf=="UR") { return "10"; } if(proc.Surf=="UL") { return "20"; } if(proc.Surf=="LR") { return "40"; } if(proc.Surf=="LL") { return "30"; } } if(procCode.TreatArea==TreatmentArea.Sextant) { return ""; } if(procCode.TreatArea==TreatmentArea.Surf) { return ""; } if(procCode.TreatArea==TreatmentArea.Tooth) { return ""; } if(procCode.TreatArea==TreatmentArea.ToothRange) { return ""; } return ""; }
private void CanadaDownloadProcedureCodes() { Cursor=Cursors.WaitCursor; codeList=new List<ProcedureCode>(); string url=@"http://www.opendental.com/feescanada/procedurecodes.txt"; string tempFile=Path.GetTempFileName(); WebClient myWebClient=new WebClient(); try { myWebClient.DownloadFile(url,tempFile); } catch(Exception ex) { MessageBox.Show(Lan.g(this,"Failed to download fee schedule file")+": "+ex.Message); Cursor=Cursors.Default; return; } string codeData=File.ReadAllText(tempFile); File.Delete(tempFile); string[] codeLines=codeData.Split('\n'); for(int i=0;i<codeLines.Length;i++) { string[] fields=codeLines[i].Split('\t'); if(fields.Length<1) {//Skip blank lines if they exist. continue; } ProcedureCode procCode=new ProcedureCode(); procCode.ProcCode=PIn.String(fields[0]);//0 ProcCode procCode.Descript=PIn.String(fields[1]);//1 Description procCode.TreatArea=(TreatmentArea)PIn.Int(fields[2]);//2 TreatArea procCode.NoBillIns=PIn.Bool(fields[3]);//3 NoBillIns procCode.IsProsth=PIn.Bool(fields[4]);//4 IsProsth procCode.IsHygiene=PIn.Bool(fields[5]);//5 IsHygiene procCode.PaintType=(ToothPaintingType)PIn.Int(fields[6]);//6 PaintType procCode.ProcCatDescript=PIn.String(fields[7]);//7 ProcCatDescript procCode.ProcTime=PIn.String(fields[8]);//8 ProcTime procCode.AbbrDesc=PIn.String(fields[9]);//9 AbbrDesc codeList.Add(procCode); } Cursor=Cursors.Default; }
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. } }
/// <summary>Returns either 0,1,or 2</summary> public static string GetUL(Procedure proc,ProcedureCode procCode) { if(procCode.TreatArea==TreatmentArea.Arch) { if(proc.Surf=="U") { return "1"; } if(proc.Surf=="L") { return "2"; } return "0";//should never happen } else { return "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 } }
///<summary>Returns the code NewCrop or a code like NewCrop##, depending on which codes are already in use for the current patnum. ///The returned code is guaranteed to exist in the database, because codes are created if they do not exist.</summary> private string GetProcCodeForNewCharge(List<RepeatCharge> repeatChargesCur) { //Locate a proc code for NewCrop which is not already in use. string procCode="NewCrop"; int attempts=1; bool procCodeInUse; do { procCodeInUse=false; for(int i=0;i<repeatChargesCur.Count;i++) { if(repeatChargesCur[i].ProcCode==procCode) { procCodeInUse=true; break; } } if(procCodeInUse) { attempts++;//Should start at 2. The Codes will be "NewCrop", "NewCrop02", "NewCrop03", etc... if(attempts>99) { throw new Exception("Cannot add more than 99 NewCrop repeating charges yet. Ask programmer to increase."); } procCode="NewCrop"+(attempts.ToString().PadLeft(2,'0')); } } while(procCodeInUse); //If the selected code is not in the database already, then add it automatically. long codeNum=ProcedureCodes.GetCodeNum(procCode); if(codeNum==0) {//The selected code does not exist, so we must add it. ProcedureCode code=new ProcedureCode(); code.ProcCode=procCode; code.Descript="NewCrop Rx"; code.AbbrDesc="NewCrop"; code.ProcTime="/X/"; code.ProcCat=162;//Software code.TreatArea=TreatmentArea.Mouth; ProcedureCodes.Insert(code); ProcedureCodes.RefreshCache(); } return procCode; }
private bool AddProc(){ if(textNewCode.Text=="") { MsgBox.Show(this,"Code not allowed to be blank."); return false; } if(ProcedureCodes.IsValidCode(textNewCode.Text)){ MsgBox.Show(this,"That code already exists."); return false; } if(textDescription.Text=="") { MsgBox.Show(this,"Description not allowed to be blank."); return false; } if(textAbbreviation.Text=="") { MsgBox.Show(this,"Abbreviation not allowed to be blank."); return false; } //ok to add code----------------------------------------------------------------------------------- ProcedureCode code=new ProcedureCode(); code.ProcCode=textNewCode.Text; //code.ProcTime="/X/";//moved to contructor. //code.GraphicColor=Color.FromArgb(0);//moved to contructor. code.Descript=textDescription.Text; code.AbbrDesc=textAbbreviation.Text; code.NoBillIns=checkNoBillIns.Checked; code.IsHygiene=checkIsHygiene.Checked; code.IsProsth=checkIsProsth.Checked; code.PaintType=(ToothPaintingType)comboPaintType.SelectedIndex; code.TreatArea=(TreatmentArea)comboTreatArea.SelectedIndex+1; //if(comboCategory.SelectedIndex!=-1) code.ProcCat=DefC.Short[(int)DefCat.ProcCodeCats][comboCategory.SelectedIndex].DefNum; ProcedureCodes.Insert(code); Changed=true; SecurityLogs.MakeLogEntry(Permissions.Setup,0,"Added Procedure Code: "+code.ProcCode); return true; }
///<summary>The procedure code must have already been insterted into the database.</summary> public FormProcCodeEdit(ProcedureCode procCode) { InitializeComponent();// Required for Windows Form Designer support tbTime.CellClicked += new OpenDental.ContrTable.CellEventHandler(tbTime_CellClicked); Lan.F(this); ProcCode=procCode; }
///<summary>Helper for GenerateCCD().</summary> private void GenerateCcdSectionProcedures(bool hasProcedure) { _w.WriteComment(@" ===================================================================================================== Procedures ====================================================================================================="); List<Procedure> listProcsFiltered; if(!hasProcedure) { listProcsFiltered=new List<Procedure>(); } else { listProcsFiltered=_listProcsFiltered; } Start("component"); Start("section"); TemplateId("2.16.840.1.113883.10.20.22.2.7.1");//Procedures section with coded entries required (Page 285). _w.WriteComment("Procedures section template"); StartAndEnd("code","code","47519-4","codeSystem",strCodeSystemLoinc,"codeSystemName",strCodeSystemNameLoinc,"displayName","History of procedures"); _w.WriteElementString("title","Procedures"); Start("text");//The following text will be parsed as html with a style sheet to be human readable. if(listProcsFiltered.Count>0 && hasProcedure) { Start("table","width","100%","border","1"); Start("thead"); Start("tr"); _w.WriteElementString("th","Procedure"); _w.WriteElementString("th","Body Site"); _w.WriteElementString("th","Date"); End("tr"); End("thead"); Start("tbody"); for(int i=0;i<listProcsFiltered.Count;i++) { ProcedureCode procCode; Snomed bodySite=Snomeds.GetByCode(listProcsFiltered[i].SnomedBodySite); Snomed procCodeSnomed; if(listProcsFiltered[i].CodeNum==0) { procCode=new ProcedureCode(); procCodeSnomed=new Snomed(); } else { procCode=ProcedureCodes.GetProcCode(listProcsFiltered[i].CodeNum); procCodeSnomed=Snomeds.GetByCode(procCode.ProcCode); } if(procCodeSnomed==null) { procCodeSnomed=new Snomed(); } Start("tr"); if(!String.IsNullOrEmpty(procCodeSnomed.SnomedCode)) { _w.WriteElementString("td",procCodeSnomed.SnomedCode+" - "+procCode.Descript); } else if(!String.IsNullOrEmpty(procCode.MedicalCode)) { _w.WriteElementString("td",procCode.MedicalCode+" - "+procCode.Descript); } else { _w.WriteElementString("td",""); } if(bodySite==null || String.IsNullOrEmpty(bodySite.SnomedCode)) { _w.WriteElementString("td",""); } else { _w.WriteElementString("td",bodySite.SnomedCode+" - "+bodySite.Description); } if(listProcsFiltered[i].ProcDate.Year<1880) { _w.WriteElementString("td",""); } else { DateText("td",listProcsFiltered[i].ProcDate); } End("tr"); } End("tbody"); End("table"); } else { _w.WriteString("None"); } End("text"); if(listProcsFiltered.Count==0) {//If there are no entries in the filtered list, then we want to add a dummy entry since at least one is required. Procedure proc=new Procedure(); listProcsFiltered.Add(proc); } for(int i=0;i<listProcsFiltered.Count;i++) { ProcedureCode procCode; Snomed procCodeSnomed; if(listProcsFiltered[i].CodeNum==0) { procCode=new ProcedureCode(); procCodeSnomed=new Snomed(); } else { procCode=ProcedureCodes.GetProcCode(listProcsFiltered[i].CodeNum); procCodeSnomed=Snomeds.GetByCode(procCode.ProcCode); } if(procCodeSnomed==null) { procCodeSnomed=new Snomed(); } Start("entry","typeCode","DRIV"); Start("procedure","classCode","PROC","moodCode","EVN"); TemplateId("2.16.840.1.113883.10.20.22.4.14");//Procedure Activity Section (Page 487). _w.WriteComment("Procedure Activity Template"); Guid(); //"This code in a procedure activity SHOULD be selected from LOINC (codeSystem 2.16.840.1.113883.6.1) or SNOMED CT (CodeSystem: 2.16.840.1.113883.6.96), //and MAY be selected from CPT-4 (CodeSystem: 2.16.840.1.113883.6.12), ICD9 Procedures (CodeSystem: 2.16.840.1.113883.6.104), //ICD10 Procedure Coding System (CodeSystem: 2.16.840.1.113883.6.4) (CONF:7657)." //We already have a place for CPT codes, and that is ProcedureCode.MedicalCode. We will simply use this field for now. if(!String.IsNullOrEmpty(procCodeSnomed.SnomedCode)) { StartAndEnd("code","code",procCodeSnomed.SnomedCode,"codeSystem",strCodeSystemSnomed,"displayName",procCode.Descript,"codeSystemName",strCodeSystemNameSnomed); } else if(!String.IsNullOrEmpty(procCode.MedicalCode)) { StartAndEnd("code","code",procCode.MedicalCode,"codeSystem",strCodeSystemCpt4,"displayName",procCode.Descript,"codeSystemName",strCodeSystemNameCpt4); } else { StartAndEnd("code","nullFlavor","UNK"); } StartAndEnd("statusCode","code","completed");//Allowed values: completed, active, aborted, cancelled. if(listProcsFiltered[i].ProcDate.Year<1880) { StartAndEnd("effectiveTime","nullFlavor","UNK"); } else { DateElement("effectiveTime",listProcsFiltered[i].ProcDate); } End("procedure"); End("entry"); } End("section"); End("component"); }