///<summary>Will throw an error if not authorized and message not suppressed.</summary> public static bool IsAuthorized(Permissions perm, DateTime date, bool suppressMessage, long userGroupNum) { //No need to check RemotingRole; no call to db. if (!GroupPermissions.HasPermission(userGroupNum, perm)) { if (!suppressMessage) { throw new Exception(Lans.g("Security", "Not authorized for") + "\r\n" + GroupPermissions.GetDesc(perm)); } return(false); } if (perm == Permissions.AccountingCreate || perm == Permissions.AccountingEdit) { if (date <= PrefC.GetDate(PrefName.AccountingLockDate)) { if (!suppressMessage) { throw new Exception(Lans.g("Security", "Locked by Administrator.")); } return(false); } } //Check the global security lock------------------------------------------------------------------------------------ //the list below is NOT the list of permissions that take dates. See GroupPermissions.PermTakesDates(). if (perm == Permissions.AdjustmentCreate || perm == Permissions.AdjustmentEdit || perm == Permissions.PaymentCreate || perm == Permissions.PaymentEdit || perm == Permissions.ProcComplCreate || perm == Permissions.ProcComplEdit //|| perm==Permissions.ImageDelete || perm == Permissions.InsPayCreate || perm == Permissions.InsPayEdit || perm == Permissions.SheetEdit || perm == Permissions.CommlogEdit ) { //If the global lock is date-based: if (date.Year > 1 && //if a valid date was passed in date <= PrefC.GetDate(PrefName.SecurityLockDate)) //and that date is earlier than the lock { if (PrefC.GetBool(PrefName.SecurityLockIncludesAdmin) || //if admins are locked out too !GroupPermissions.HasPermission(userGroupNum, Permissions.SecurityAdmin)) //or is not an admin { if (!suppressMessage) { throw new Exception(Lans.g("Security", "Locked by Administrator before ") + PrefC.GetDate(PrefName.SecurityLockDate).ToShortDateString()); } return(false); } } //If the global lock is days-based: if (date.Year > 1 && //if a valid date was passed in PrefC.GetInt(PrefName.SecurityLockDays) > 0 && date <= DateTime.Today.AddDays(-PrefC.GetInt(PrefName.SecurityLockDays))) //and that date is earlier than the lock { if (PrefC.GetBool(PrefName.SecurityLockIncludesAdmin) || //if admins are locked out too !GroupPermissions.HasPermission(userGroupNum, Permissions.SecurityAdmin)) //or is not an admin { if (!suppressMessage) { throw new Exception(Lans.g("Security", "Locked by Administrator before ") + PrefC.GetInt(PrefName.SecurityLockDays).ToString() + " days."); } return(false); } } } //Check date/days limits on individual permission---------------------------------------------------------------- if (!GroupPermissions.PermTakesDates(perm)) { return(true); } DateTime dateLimit = GetDateLimit(perm, userGroupNum); if (date > dateLimit) //authorized { return(true); } //Prevents certain bugs when 1/1/1 dates are passed in and compared---------------------------------------------- //Handling of min dates. There might be others, but we have to handle them individually to avoid introduction of bugs. if (perm == Permissions.ClaimSentEdit || //no date sent was entered before setting claim received perm == Permissions.ProcComplEdit || //a completed procedure with a min date. perm == Permissions.InsPayEdit || //a claim payment with no date. perm == Permissions.TreatPlanEdit || perm == Permissions.AdjustmentEdit || perm == Permissions.CommlogEdit || //usually from a conversion perm == Permissions.ProcDelete) //because older versions did not set the DateEntryC. { if (date.Year < 1880 && dateLimit.Year < 1880) { return(true); } } if (!suppressMessage) { throw new Exception(Lans.g("Security", "Not authorized for") + "\r\n" + GroupPermissions.GetDesc(perm) + "\r\n" + Lans.g("Security", "Date limitation")); } return(false); }
public static DataTable GetProvList(DateTime dt) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), dt)); } #if DEBUG _elapsedTimeProvList = ""; System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); System.Diagnostics.Stopwatch stopWatchTotal = new System.Diagnostics.Stopwatch(); _elapsedTimeProvList = "Elapsed time for GetProvList:\r\n"; stopWatch.Restart(); stopWatchTotal.Restart(); #endif Random rnd = new Random(); string rndStr = rnd.Next(1000000).ToString(); string command; command = "DROP TABLE IF EXISTS tempdash" + rndStr + @";"; Db.NonQ(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProvList += "DROP TABLE: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif command = @"CREATE TABLE tempdash" + rndStr + @" ( ProvNum bigint NOT NULL PRIMARY KEY, production decimal NOT NULL, income decimal NOT NULL ) DEFAULT CHARSET=utf8" ; Db.NonQ(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProvList += "CREATE TABLE: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif //providers command = @"INSERT INTO tempdash" + rndStr + @" (ProvNum) SELECT ProvNum FROM provider WHERE IsHidden=0 ORDER BY ItemOrder" ; Db.NonQ(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProvList += "providers: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif //production-------------------------------------------------------------------- //procs command = @"UPDATE tempdash" + rndStr + @" SET production=(SELECT SUM(ProcFee*(UnitQty+BaseUnits)) FROM procedurelog WHERE procedurelog.ProvNum=tempdash" + rndStr + @".ProvNum AND procedurelog.ProcStatus=" + POut.Int((int)ProcStat.C) + @" AND ProcDate=" + POut.Date(dt) + ")"; Db.NonQ(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProvList += "production - procs: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif //capcomplete writeoffs were skipped //adjustments command = @"UPDATE tempdash" + rndStr + @" SET production=production+(SELECT IFNULL(SUM(AdjAmt),0) FROM adjustment WHERE adjustment.ProvNum=tempdash" + rndStr + @".ProvNum AND AdjDate=" + POut.Date(dt) + ")"; Db.NonQ(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProvList += "production - adjustments: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif //insurance writeoffs if (PrefC.GetBool(PrefName.ReportsPPOwriteoffDefaultToProcDate)) //use procdate { command = @"UPDATE tempdash" + rndStr + @" SET production=production-(SELECT IFNULL(SUM(WriteOff),0) FROM claimproc WHERE claimproc.ProvNum=tempdash" + rndStr + @".ProvNum AND ProcDate=" + POut.Date(dt) + @" AND (claimproc.Status=1 OR claimproc.Status=4 OR claimproc.Status=0) )" ; //received or supplemental or notreceived } else { command = @"UPDATE tempdash" + rndStr + @" SET production=production-(SELECT IFNULL(SUM(WriteOff),0) FROM claimproc WHERE claimproc.ProvNum=tempdash" + rndStr + @".ProvNum AND DateCP=" + POut.Date(dt) + @" AND (claimproc.Status=1 OR claimproc.Status=4) )" ;//received or supplemental } Db.NonQ(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProvList += "production - writeoffs: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif //income------------------------------------------------------------------------ //patient income command = @"UPDATE tempdash" + rndStr + @" SET income=(SELECT SUM(SplitAmt) FROM paysplit WHERE paysplit.ProvNum=tempdash" + rndStr + @".ProvNum AND DatePay=" + POut.Date(dt) + ")"; Db.NonQ(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProvList += "income - patient: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif //ins income command = @"UPDATE tempdash" + rndStr + @" SET income=income+(SELECT IFNULL(SUM(InsPayAmt),0) FROM claimproc WHERE claimproc.ProvNum=tempdash" + rndStr + @".ProvNum AND DateCP=" + POut.Date(dt) + ")"; Db.NonQ(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProvList += "income - insurance: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif //final queries command = "SELECT * FROM tempdash" + rndStr + @""; DataTable table = Db.GetTable(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProvList += "SELECT * : " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif command = "DROP TABLE IF EXISTS tempdash" + rndStr + @";"; Db.NonQ(command); #if DEBUG stopWatch.Stop(); stopWatchTotal.Stop(); _elapsedTimeProvList += "DROP TABLE: " + stopWatch.Elapsed.ToString() + "\r\n"; _elapsedTimeProvList += "Total: " + stopWatchTotal.Elapsed.ToString(); if (_showElapsedTimesForDebug) { System.Windows.Forms.MessageBox.Show(_elapsedTimeProvList); } #endif return(table); }
///<summary>Returns the status code of the web call made to Podium. ///200-299 indicates a successful response, >=300 indicates a Podium error response, negative status codes indicate an Open Dental error.</summary> private static int MakeWebCall(string apiToken, string apiUrl, string locationId, string phoneNumber, Patient pat) { int retVal = -100; if (pat.TxtMsgOk == YN.No || (pat.TxtMsgOk == YN.Unknown && PrefC.GetBool(PrefName.TextMsgOkStatusTreatAsNo))) //Use email. { retVal = -200; //Our code for 'no email address' phoneNumber = ""; //Ensure that there is no way we send a phone number to Podium if the patient doesn't approve text messages. if (string.IsNullOrEmpty(pat.Email)) { return(retVal); //Will be -200, meaning no email and can't text. } } if (string.IsNullOrWhiteSpace(phoneNumber) && string.IsNullOrWhiteSpace(pat.Email)) { return(retVal); } //We either have a phoneNumber or email (or both), so send it to Podium. string isTestString = "false"; #if DEBUG isTestString = "true"; #endif try { using (WebClientEx client = new WebClientEx()) { client.Headers[HttpRequestHeader.Accept] = "application/json"; client.Headers[HttpRequestHeader.ContentType] = "application/json"; client.Headers[HttpRequestHeader.Authorization] = "Token token=\"" + apiToken + "\""; client.Encoding = UnicodeEncoding.UTF8; string bodyJson = string.Format(@" {{ ""locationId"": ""{0}"", ""lastName"": ""{3}"", ""firstName"": ""{2}"", ""email"": ""{4}"", ""phoneNumber"": ""{1}"", ""integrationName"": ""opendental"", ""test"": {5} }}" , locationId, phoneNumber, pat.FName, pat.LName, pat.Email, isTestString); //Post with Authorization headers and a body comprised of a JSON serialized anonymous type. client.UploadString(apiUrl, "POST", bodyJson); retVal = (int)(client.StatusCode); } } catch (WebException we) { if (we.Response.GetType() == typeof(HttpWebResponse)) { retVal = (int)((HttpWebResponse)we.Response).StatusCode; } } catch (Exception) { //Do nothing because a verbose commlog will be made below if all phone numbers fail. } return(retVal); //Sample Request: //Accept: 'application/json's //Content-Type: 'application/json' //Authorization: 'Token token="my_dummy_token"' //Body: //{ // "location_id": "54321", // "phone_number": "1234567890", // "customer": { // "first_name": "Johnny", // "last_name": "Appleseed", // "email": "*****@*****.**" // }, // "test": true //} //NOTE: There will never be a value after "customer": although it was initially interpreted that there would be a "new" flag there. }
///<summary>Surrond with Try/Catch. Error messages will be thrown to caller.</summary> public static bool IsGlobalDateLock(Permissions perm, DateTime date, bool isSilent = false, long codeNum = 0, double procFee = -1, long sheetDefNum = 0) { if (!(new[] { Permissions.AdjustmentCreate , Permissions.AdjustmentEdit , Permissions.PaymentCreate , Permissions.PaymentEdit , Permissions.ProcComplCreate , Permissions.ProcComplEdit , Permissions.ProcExistingEdit //,Permissions.ProcComplEditLimited //,Permissions.ImageDelete , Permissions.InsPayCreate , Permissions.InsPayEdit //,Permissions.InsWriteOffEdit//per Nathan 7/5/2016 this should not be affected by the global date lock , Permissions.SheetEdit , Permissions.SheetDelete , Permissions.CommlogEdit //,Permissions.ClaimDelete //per Nathan 01/18/2018 this should not be affected by the global date lock , Permissions.PayPlanEdit //,Permissions.ClaimHistoryEdit //per Nathan & Mark 03/01/2018 this should not be affected by the global lock date, not financial data. }).Contains(perm)) { return(false); //permission being checked is not affected by global lock date. } if (date.Year == 1) { return(false); //Invalid or MinDate passed in. } if (!PrefC.GetBool(PrefName.SecurityLockIncludesAdmin) && GroupPermissions.HasPermission(Security.CurUser, Permissions.SecurityAdmin, 0)) { return(false); //admins are never affected by global date limitation when preference is false. } if (perm.In(Permissions.ProcComplCreate, Permissions.ProcComplEdit, Permissions.ProcExistingEdit) && ProcedureCodes.CanBypassLockDate(codeNum, procFee)) { return(false); } if (perm.In(Permissions.SheetEdit, Permissions.SheetDelete) && sheetDefNum > 0 && SheetDefs.CanBypassLockDate(sheetDefNum)) { return(false); } //If global lock is Date based. if (date <= PrefC.GetDate(PrefName.SecurityLockDate)) { if (!isSilent) { MessageBox.Show(Lans.g("Security", "Locked by Administrator before ") + PrefC.GetDate(PrefName.SecurityLockDate).ToShortDateString()); } return(true); } //If global lock is days based. int lockDays = PrefC.GetInt(PrefName.SecurityLockDays); if (lockDays > 0 && date <= DateTime.Today.AddDays(-lockDays)) { if (!isSilent) { MessageBox.Show(Lans.g("Security", "Locked by Administrator before ") + lockDays.ToString() + " days."); } return(true); } return(false); }
public static DataTable GetProvList(DateTime dt) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), dt)); } string command; command = "DROP TABLE IF EXISTS tempdash;"; Db.NonQ(command); command = @"CREATE TABLE tempdash ( ProvNum bigint NOT NULL PRIMARY KEY, production decimal NOT NULL, income decimal NOT NULL ) DEFAULT CHARSET=utf8" ; Db.NonQ(command); //providers command = @"INSERT INTO tempdash (ProvNum) SELECT ProvNum FROM provider WHERE IsHidden=0 ORDER BY ItemOrder" ; Db.NonQ(command); //production-------------------------------------------------------------------- //procs command = @"UPDATE tempdash SET production=(SELECT SUM(ProcFee*(UnitQty+BaseUnits)) FROM procedurelog WHERE procedurelog.ProvNum=tempdash.ProvNum AND procedurelog.ProcStatus=" + POut.Int((int)ProcStat.C) + @" AND ProcDate=" + POut.Date(dt) + ")"; Db.NonQ(command); //capcomplete writeoffs were skipped //adjustments command = @"UPDATE tempdash SET production=production+(SELECT IFNULL(SUM(AdjAmt),0) FROM adjustment WHERE adjustment.ProvNum=tempdash.ProvNum AND AdjDate=" + POut.Date(dt) + ")"; Db.NonQ(command); //insurance writeoffs if (PrefC.GetBool(PrefName.ReportsPPOwriteoffDefaultToProcDate)) //use procdate { command = @"UPDATE tempdash SET production=production-(SELECT IFNULL(SUM(WriteOff),0) FROM claimproc WHERE claimproc.ProvNum=tempdash.ProvNum AND ProcDate=" + POut.Date(dt) + @" AND (claimproc.Status=1 OR claimproc.Status=4 OR claimproc.Status=0) )" ; //received or supplemental or notreceived } else { command = @"UPDATE tempdash SET production=production-(SELECT IFNULL(SUM(WriteOff),0) FROM claimproc WHERE claimproc.ProvNum=tempdash.ProvNum AND DateCP=" + POut.Date(dt) + @" AND (claimproc.Status=1 OR claimproc.Status=4) )" ;//received or supplemental } Db.NonQ(command); //income------------------------------------------------------------------------ //patient income command = @"UPDATE tempdash SET income=(SELECT SUM(SplitAmt) FROM paysplit WHERE paysplit.ProvNum=tempdash.ProvNum AND DatePay=" + POut.Date(dt) + ")"; Db.NonQ(command); //ins income command = @"UPDATE tempdash SET income=income+(SELECT IFNULL(SUM(InsPayAmt),0) FROM claimproc WHERE claimproc.ProvNum=tempdash.ProvNum AND DateCP=" + POut.Date(dt) + ")"; Db.NonQ(command); //final queries command = "SELECT * FROM tempdash"; DataTable table = Db.GetTable(command); command = "DROP TABLE IF EXISTS tempdash;"; Db.NonQ(command); 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>Gets the DataTable to display for treatment finder report</summary> ///<param name="listProviders">Include '0' in the list to get for all providers.</param> ///<param name="listBilling">Include '0' in the list to get for all billing types.</param> ///<param name="listClinicNums">Pass in an empty list to get for all clinics.</param> public static DataTable GetTreatmentFinderList(bool noIns, bool patsWithAppts, int monthStart, DateTime dateSince, double aboveAmount, List <long> listProviders, List <long> listBilling, string code1, string code2, List <long> listClinicNums, bool isProcsGeneral) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), noIns, patsWithAppts, monthStart, dateSince, aboveAmount, listProviders, listBilling, code1, code2, listClinicNums, isProcsGeneral)); } #if DEBUG Stopwatch sw = Stopwatch.StartNew(); #endif DataTable table = new DataTable(); DataRow row; //columns that start with lowercase are altered for display rather than being raw data. table.Columns.Add("PatNum"); table.Columns.Add("LName"); table.Columns.Add("FName"); table.Columns.Add("contactMethod"); table.Columns.Add("address"); table.Columns.Add("City"); table.Columns.Add("State"); table.Columns.Add("Zip"); table.Columns.Add("annualMaxInd"); table.Columns.Add("annualMaxFam"); table.Columns.Add("amountUsedInd"); table.Columns.Add("amountUsedFam"); table.Columns.Add("amountPendingInd"); table.Columns.Add("amountPendingFam"); table.Columns.Add("amountRemainingInd"); table.Columns.Add("amountRemainingFam"); table.Columns.Add("treatmentPlan"); table.Columns.Add("carrierName"); table.Columns.Add("clinicAbbr"); List <DataRow> rows = new List <DataRow>(); string command = ""; string joinAnnualMax = ""; string joinCoverageInfo = ""; string joinIndInfo = ""; string joinFamInfo = ""; string subSelectPlanned = ""; string cmdFutureApt = @" AND patient.PatNum NOT IN ( SELECT PatNum FROM appointment WHERE AptStatus=" + POut.Int((int)ApptStatus.Scheduled) + @" AND AptDateTime>=" + DbHelper.Curdate() + ")"; DateTime renewDate = BenefitLogic.ComputeRenewDate(DateTime.Now, monthStart); List <long> listPatNums = new List <long>(); if ((!listProviders.Contains(0) || !listBilling.Contains(0) || listClinicNums.Count > 0)) { string cmdPatients = "SELECT PatNum from patient "; string patWhere = ""; if (!listProviders.Contains(0)) { patWhere = " AND patient.PriProv IN (" + string.Join(",", listProviders) + ") "; } if (!listBilling.Contains(0)) { patWhere = " AND patient.BillingType IN (" + string.Join(",", listBilling) + ") "; } if (listClinicNums.Count > 0) { patWhere += " AND patient.ClinicNum IN (" + string.Join(",", listClinicNums) + ") "; } if (!patsWithAppts) { patWhere += cmdFutureApt; } cmdPatients += "WHERE TRUE " + patWhere; listPatNums = Db.GetListLong(cmdPatients); if (listPatNums.Count == 0) { return(table); } } joinCoverageInfo = @" SELECT patplan.PatPlanNum,claimproc.InsSubNum, SUM(CASE WHEN claimproc.Status=" + POut.Int((int)ClaimProcStatus.NotReceived) + @" AND claimproc.InsPayAmt=0 THEN claimproc.InsPayEst ELSE 0 END) AmtPending, SUM(CASE WHEN claimproc.Status IN (" + POut.Int((int)ClaimProcStatus.Received) + "," + POut.Int((int)ClaimProcStatus.Adjustment) + "," + POut.Int((int)ClaimProcStatus.Supplemental) + @" ) THEN claimproc.InsPayAmt ELSE 0 END) AmtUsed FROM claimproc INNER JOIN patient ON patient.PatNum=claimproc.PatNum LEFT JOIN patplan ON patplan.PatNum=claimproc.PatNum AND patplan.InsSubNum=claimproc.InsSubNum LEFT JOIN procedurelog pl ON pl.ProcNum=claimproc.ProcNum LEFT JOIN procedurecode pc ON pc.CodeNum=pl.CodeNum " ; if (!isProcsGeneral) { joinCoverageInfo += @" LEFT JOIN ( SELECT isub.InsSubNum, COALESCE(cp.FromCode,pc.ProcCode) AS FromCode, COALESCE(cp.ToCode,pc.ProcCode) AS ToCode FROM inssub isub INNER JOIN benefit b ON b.PlanNum=isub.PlanNum AND b.BenefitType=" + (int)InsBenefitType.Limitations + @" AND b.QuantityQualifier=" + (int)BenefitQuantity.None + @" AND b.TimePeriod IN (" + (int)BenefitTimePeriod.ServiceYear + "," + (int)BenefitTimePeriod.CalendarYear + @") LEFT JOIN covcat cc ON cc.CovCatNum=b.CovCatNum LEFT JOIN covspan cp ON cp.CovCatNum=cc.CovCatNum LEFT JOIN procedurecode pc ON pc.CodeNum=b.CodeNum WHERE (cc.CovCatNum IS NOT NULL OR b.CodeNum!=0) )ProcCheck ON ProcCheck.InsSubNum=claimproc.InsSubNum AND pc.ProcCode BETWEEN ProcCheck.FromCode AND ProcCheck.ToCode " ; } joinCoverageInfo += "WHERE claimproc.Status IN (" + (int)ClaimProcStatus.NotReceived + ", " + (int)ClaimProcStatus.Received + ", " + (int)ClaimProcStatus.Adjustment + ", " + (int)ClaimProcStatus.Supplemental + ") "; if (!isProcsGeneral) { joinCoverageInfo += "AND ProcCheck.InsSubNum IS NULL "; } joinCoverageInfo += "AND claimproc.ProcDate BETWEEN " + POut.Date(renewDate) + @" AND " + POut.Date(renewDate.AddYears(1)) + @" "; if (listPatNums.Count > 0) { joinCoverageInfo += @"AND patient.PatNum IN (" + string.Join(",", listPatNums) + ") "; } else if (!patsWithAppts) { joinCoverageInfo += cmdFutureApt; } joinIndInfo = joinCoverageInfo + " GROUP BY patplan.PatPlanNum "; joinFamInfo = joinCoverageInfo + " GROUP BY claimproc.InsSubNum "; subSelectPlanned = @" (SELECT COALESCE(SUM(ProcFee),0) AmtPlanned FROM procedurelog " ; if (code1 != "") { subSelectPlanned += "INNER JOIN procedurecode ON procedurecode.CodeNum=procedurelog.CodeNum "; } subSelectPlanned += "WHERE ProcStatus=" + (int)ProcStat.TP + " "; if (code1 != "") { subSelectPlanned += "AND procedurecode.ProcCode>='" + POut.String(code1) + "' " + " AND procedurecode.ProcCode<='" + POut.String(code2) + "' "; } if (dateSince.Year > 1880) { subSelectPlanned += "AND procedurelog.DateTP>=" + POut.DateT(dateSince) + " "; } subSelectPlanned += "AND PatNum=patient.PatNum "; subSelectPlanned += "GROUP BY PatNum) "; joinAnnualMax = @" SELECT insplan.PlanNum, MAX(CASE WHEN CoverageLevel!=" + POut.Int((int)BenefitCoverageLevel.Family) + @" THEN MonetaryAmt ELSE -1 END) AnnualMaxInd/*for oracle in case there's more than one*/, MAX(CASE WHEN CoverageLevel=" + POut.Int((int)BenefitCoverageLevel.Family) + @" THEN MonetaryAmt ELSE -1 END) AnnualMaxFam/*for oracle in case there's more than one*/ FROM benefit INNER JOIN insplan ON insplan.PlanNum=benefit.PlanNum INNER JOIN inssub ON inssub.PlanNum=benefit.PlanNum INNER JOIN patplan ON patplan.InsSubNum=inssub.InsSubNum INNER JOIN patient ON patient.PatNum=patplan.PatNum LEFT JOIN covcat ON benefit.CovCatNum=covcat.CovCatNum WHERE (covcat.EbenefitCat=" + (int)EbenefitCategory.General + @" OR ISNULL(covcat.EbenefitCat)) AND benefit.BenefitType=" + (int)InsBenefitType.Limitations + @" AND benefit.MonetaryAmt > 0 AND benefit.QuantityQualifier=" + (int)BenefitQuantity.None + " "; if (listPatNums.Count > 0) { joinAnnualMax += @"AND patient.PatNum IN (" + string.Join(",", listPatNums) + ") "; } else if (!patsWithAppts) { joinAnnualMax += cmdFutureApt; } joinAnnualMax += @"GROUP BY insplan.PlanNum"; command = @"SELECT patient.PatNum, patient.LName, patient.FName, patient.Email, patient.HmPhone, patient.PreferRecallMethod, patient.WirelessPhone, patient.WkPhone, patient.Address, patient.Address2, patient.City, patient.State, patient.Zip, patient.PriProv, patient.BillingType, COALESCE(annualMax.AnnualMaxInd,0) ""AnnualMaxInd"", COALESCE(annualMax.AnnualMaxFam,0) ""AnnualMaxFam"", IndividualInfo.AmtUsed ""AmountUsedInd"", FamilyInfo.AmtUsed ""AmountUsedFam"", IndividualInfo.AmtPending ""AmountPendingInd"", FamilyInfo.AmtPending ""AmountPendingFam"", COALESCE(annualMax.AnnualMaxInd,0)-COALESCE(IndividualInfo.AmtUsed,0)-COALESCE(IndividualInfo.AmtPending,0) AS ""$AmtRemainingInd"", COALESCE(annualMax.AnnualMaxFam,0)-COALESCE(FamilyInfo.AmtUsed,0)-COALESCE(FamilyInfo.AmtPending,0) AS ""$AmtRemainingFam""," + subSelectPlanned + @"""$TreatmentPlan"", carrier.CarrierName,COALESCE(clinic.Abbr,'Unassigned') clinicAbbr FROM patient LEFT JOIN patplan ON patient.PatNum=patplan.PatNum LEFT JOIN inssub ON patplan.InsSubNum=inssub.InsSubNum LEFT JOIN insplan ON insplan.PlanNum=inssub.PlanNum LEFT JOIN carrier ON insplan.CarrierNum=carrier.CarrierNum LEFT JOIN (" + joinIndInfo + @")IndividualInfo ON IndividualInfo.PatPlanNum=patplan.PatPlanNum LEFT JOIN (" + joinFamInfo + @")FamilyInfo ON FamilyInfo.InsSubNum=inssub.InsSubNum LEFT JOIN (" + joinAnnualMax + @") annualMax ON annualMax.PlanNum=inssub.PlanNum AND (annualMax.AnnualMaxInd>0 OR annualMax.AnnualMaxFam>0)/*may not be necessary*/ LEFT JOIN clinic ON clinic.ClinicNum=patient.ClinicNum WHERE TRUE AND patient.PatStatus=" + POut.Int((int)PatientStatus.Patient) + " "; if (!noIns) //if we don't want patients without insurance { command += " AND patplan.Ordinal=1 AND insplan.MonthRenew=" + POut.Int(monthStart) + " "; } if (aboveAmount > 0) { command += " AND (annualMax.PlanNum IS NULL OR ((annualMax.AnnualMaxInd=-1 OR annualMax.AnnualMaxInd-COALESCE(IndividualInfo.AmtUsed,0) > " + POut.Double(aboveAmount) + @") AND (annualMax.AnnualMaxFam=-1 OR annualMax.AnnualMaxFam-COALESCE(FamilyInfo.AmtUsed,0) > " + POut.Double(aboveAmount) + "))) "; } if (listPatNums.Count > 0) { command += " AND patient.PatNum IN (" + string.Join(",", listPatNums) + ") "; } else if (!patsWithAppts) { command += cmdFutureApt; } command += @"HAVING $TreatmentPlan > 0 "; command += @"ORDER BY $TreatmentPlan DESC"; DataTable rawtable = Db.GetTable(command); #if DEBUG sw.Stop(); Console.WriteLine("Finishing retreiving query: {0}", sw.ElapsedMilliseconds); sw = Stopwatch.StartNew(); #endif ContactMethod contmeth; for (int i = 0; i < rawtable.Rows.Count; i++) { row = table.NewRow(); row["PatNum"] = PIn.Long(rawtable.Rows[i]["PatNum"].ToString()); row["LName"] = rawtable.Rows[i]["LName"].ToString(); row["FName"] = rawtable.Rows[i]["FName"].ToString(); contmeth = (ContactMethod)PIn.Long(rawtable.Rows[i]["PreferRecallMethod"].ToString()); if (contmeth == ContactMethod.None) { if (PrefC.GetBool(PrefName.RecallUseEmailIfHasEmailAddress)) //if user only wants to use email if contact method is email { if (rawtable.Rows[i]["Email"].ToString() != "") { row["contactMethod"] = rawtable.Rows[i]["Email"].ToString(); } else { row["contactMethod"] = Lans.g("FormRecallList", "Hm:") + rawtable.Rows[i]["HmPhone"].ToString(); } } else { row["contactMethod"] = Lans.g("FormRecallList", "Hm:") + rawtable.Rows[i]["HmPhone"].ToString(); } } else if (contmeth == ContactMethod.HmPhone) { row["contactMethod"] = Lans.g("FormRecallList", "Hm:") + rawtable.Rows[i]["HmPhone"].ToString(); } else if (contmeth == ContactMethod.WkPhone) { row["contactMethod"] = Lans.g("FormRecallList", "Wk:") + rawtable.Rows[i]["WkPhone"].ToString(); } else if (contmeth == ContactMethod.WirelessPh) { row["contactMethod"] = Lans.g("FormRecallList", "Cell:") + rawtable.Rows[i]["WirelessPhone"].ToString(); } else if (contmeth == ContactMethod.Email) { row["contactMethod"] = rawtable.Rows[i]["Email"].ToString(); } else if (contmeth == ContactMethod.Mail) { row["contactMethod"] = Lans.g("FormRecallList", "Mail"); } else if (contmeth == ContactMethod.DoNotCall || contmeth == ContactMethod.SeeNotes) { row["contactMethod"] = Lans.g("enumContactMethod", contmeth.ToString()); } row["address"] = rawtable.Rows[i]["Address"].ToString(); if (rawtable.Rows[i]["Address2"].ToString() != "") { row["address"] += "\r\n" + rawtable.Rows[i]["Address2"].ToString(); } row["City"] = rawtable.Rows[i]["City"].ToString(); row["State"] = rawtable.Rows[i]["State"].ToString(); row["Zip"] = rawtable.Rows[i]["Zip"].ToString(); row["annualMaxInd"] = (PIn.Double(rawtable.Rows[i]["AnnualMaxInd"].ToString())).ToString("N"); row["annualMaxFam"] = (PIn.Double(rawtable.Rows[i]["AnnualMaxFam"].ToString())).ToString("N"); row["amountUsedInd"] = (PIn.Double(rawtable.Rows[i]["AmountUsedInd"].ToString())).ToString("N"); row["amountUsedFam"] = (PIn.Double(rawtable.Rows[i]["AmountUsedFam"].ToString())).ToString("N"); row["amountPendingInd"] = (PIn.Double(rawtable.Rows[i]["AmountPendingInd"].ToString())).ToString("N"); row["amountPendingFam"] = (PIn.Double(rawtable.Rows[i]["AmountPendingFam"].ToString())).ToString("N"); row["amountRemainingInd"] = (PIn.Double(rawtable.Rows[i]["$AmtRemainingInd"].ToString())).ToString("N"); row["amountRemainingFam"] = (PIn.Double(rawtable.Rows[i]["$AmtRemainingFam"].ToString())).ToString("N"); row["treatmentPlan"] = (PIn.Double(rawtable.Rows[i]["$TreatmentPlan"].ToString())).ToString("N"); row["carrierName"] = rawtable.Rows[i]["CarrierName"].ToString(); row["clinicAbbr"] = rawtable.Rows[i]["clinicAbbr"].ToString(); rows.Add(row); } for (int i = 0; i < rows.Count; i++) { table.Rows.Add(rows[i]); } #if DEBUG sw.Stop(); Console.WriteLine("Finished Filling query result: {0}", sw.ElapsedMilliseconds); #endif return(table); }
/// <summary>Runs repeating charges for the date passed in, usually today. Can't use 'out' variables because this runs over Middle Tier.</summary> public static RepeatChargeResult RunRepeatingCharges(DateTime dateRun) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <RepeatChargeResult>(MethodBase.GetCurrentMethod(), dateRun)); } Prefs.UpdateDateT(PrefName.RepeatingChargesBeginDateTime, dateRun); try { RepeatChargeResult result = new RepeatChargeResult(); List <RepeatCharge> listRepeatingCharges = RepeatCharges.Refresh(0).ToList(); if (PrefC.IsODHQ) { //Remove all eService repeating charges. //EService charges have already been calculated and stored in EServiceBilling table. Add those here. List <string> listEServiceCodes = EServiceCodeLink.GetProcCodesForAll(); listRepeatingCharges.RemoveAll(x => listEServiceCodes.Contains(x.ProcCode)); result.ProceduresAddedCount += EServiceBillings.AddEServiceRepeatingChargesHelper(dateRun).Count; } //Must contain all procedures that affect the date range, safe to contain too many, bad to contain too few. List <Procedure> listExistingProcs = Procedures.GetCompletedForDateRange(dateRun.AddMonths(-3), dateRun.AddDays(1), listRepeatingCharges.Select(x => x.ProcCode).Distinct().Select(x => ProcedureCodes.GetProcCode(x).CodeNum).ToList()); DateTime startedUsingFKs = UpdateHistories.GetDateForVersion(new Version("16.1.0.0")); //We started using FKs from procs to repeat charges in 16.1. foreach (RepeatCharge repeatCharge in listRepeatingCharges) { if (!repeatCharge.IsEnabled || (repeatCharge.DateStop.Year > 1880 && repeatCharge.DateStop.AddMonths(3) < dateRun)) { continue; //This repeating charge is too old to possibly create a new charge. Not precise but greatly reduces calls to DB. //We will filter by more stringently on the DateStop later on. } Patient pat = null; List <DateTime> listBillingDates; //This list will have 1 or 2 dates where a repeating charge might be added if (PrefC.GetBool(PrefName.BillingUseBillingCycleDay)) { pat = Patients.GetPat(repeatCharge.PatNum); listBillingDates = GetBillingDatesHelper(repeatCharge.DateStart, repeatCharge.DateStop, dateRun, pat.BillingCycleDay); } else { listBillingDates = GetBillingDatesHelper(repeatCharge.DateStart, repeatCharge.DateStop, dateRun); } long codeNum = ProcedureCodes.GetCodeNum(repeatCharge.ProcCode); //Remove billing dates if there is a procedure from this repeat charge in that month and year for (int i = listBillingDates.Count - 1; i >= 0; i--) //iterate backwards to remove elements { DateTime billingDate = listBillingDates[i]; for (int j = listExistingProcs.Count - 1; j >= 0; j--) //iterate backwards to remove elements { Procedure proc = listExistingProcs[j]; if ((proc.RepeatChargeNum == repeatCharge.RepeatChargeNum && //Check the procedure's FK first IsRepeatDateHelper(repeatCharge, billingDate, proc.ProcDate, pat)) //Use the old logic without matching FKs only if the procedure was added before updating to 16.1 //Match patnum, codenum, fee, year, and month (IsRepeatDateHelper uses special logic to determine correct month) || ((proc.ProcDate < startedUsingFKs || startedUsingFKs.Year < 1880) && proc.PatNum == repeatCharge.PatNum && proc.CodeNum == codeNum && IsRepeatDateHelper(repeatCharge, billingDate, proc.ProcDate, pat) && proc.ProcFee.IsEqual(repeatCharge.ChargeAmt))) { //This is a match to an existing procedure. listBillingDates.RemoveAt(i); //Removing so that a procedure will not get added on this date. listExistingProcs.RemoveAt(j); //Removing so that another repeat charge of the same code, date, and amount will be added. break; //Go to the next billing date } } } //If any billing dates have not been filtered out, add a repeating charge on those dates foreach (DateTime billingDate in listBillingDates) { Procedure procAdded = AddRepeatingChargeHelper(repeatCharge, billingDate, dateRun); List <Claim> listClaimsAdded = new List <Claim>(); if (repeatCharge.CreatesClaim && !ProcedureCodes.GetProcCode(repeatCharge.ProcCode).NoBillIns) { listClaimsAdded = AddClaimsHelper(repeatCharge, procAdded); } result.ProceduresAddedCount++; result.ClaimsAddedCount += listClaimsAdded.Count; } } return(result); } finally { Prefs.UpdateString(PrefName.RepeatingChargesBeginDateTime, ""); } }
///<summary>Returns 1 or 2 dates to be billed given the date range. Only filtering based on date range has been performed.</summary> private static List <DateTime> GetBillingDatesHelper(DateTime dateStart, DateTime dateStop, DateTime dateRun, int billingCycleDay = 0) { //No remoting role check; no call to db List <DateTime> retVal = new List <DateTime>(); if (!PrefC.GetBool(PrefName.BillingUseBillingCycleDay)) { billingCycleDay = dateStart.Day; } //Add dates on the first of each of the last three months retVal.Add(new DateTime(dateRun.AddMonths(-0).Year, dateRun.AddMonths(-0).Month, 1)); //current month -0 retVal.Add(new DateTime(dateRun.AddMonths(-1).Year, dateRun.AddMonths(-1).Month, 1)); //current month -1 retVal.Add(new DateTime(dateRun.AddMonths(-2).Year, dateRun.AddMonths(-2).Month, 1)); //current month -2 //This loop fixes day of month, taking into account billing day past the end of the month. for (int i = 0; i < retVal.Count; i++) { int billingDay = Math.Min(retVal[i].AddMonths(1).AddDays(-1).Day, billingCycleDay); retVal[i] = new DateTime(retVal[i].Year, retVal[i].Month, billingDay); //This re-adds the billing date with the proper day of month. } //Remove billing dates that are calulated before repeat charge started. retVal.RemoveAll(x => x < dateStart); //Remove billing dates older than one month and 20 days ago. retVal.RemoveAll(x => x < dateRun.AddMonths(-1).AddDays(-20)); //Remove any dates after today retVal.RemoveAll(x => x > dateRun); //Remove billing dates past the end of the dateStop int monthAdd = 0; //To account for a partial month, add a charge after the repeat charge stop date in certain circumstances (for each of these scenarios, the //billingCycleDay will be 11): //--Scenario #1: The start day is before the stop day which is before the billing day. Ex: Start: 12/08, Stop 12/09 //--Scenario #2: The start day is after the billing day which is after the stop day. Ex: Start: 11/25 Stop 12/01 //--Scenario #3: The start day is before the stop day but before the billing day. Ex: Start: 11/25, Stop 11/27 //--Scenario #4: The start day is the same as the stop day but after the billing day. Ex: Start: 10/13, Stop 11/13 //--Scenario #5: The start day is the same as the stop day but before the billing day. Ex: Start: 11/10, Stop 12/10 //Each of these repeat charges will post a charge on 12/11 even though it is after the stop date. if (PrefC.GetBool(PrefName.BillingUseBillingCycleDay)) { if (dateStart.Day < billingCycleDay) { if ((dateStop.Day < billingCycleDay && dateStart.Day < dateStop.Day) || //Scenario #1 dateStart.Day == dateStop.Day) //Scenario #5 { monthAdd = 1; } } else if (dateStart.Day > billingCycleDay) { if (dateStart.Day <= dateStop.Day || //Scenario #3 and #4 dateStop.Day < billingCycleDay) //Scenario #2 { monthAdd = 1; } } } if (dateStop.Year > 1880) { retVal.RemoveAll(x => x > dateStop.AddMonths(monthAdd)); } retVal.Sort(); //Order by oldest first return(retVal); }
public static string Validate(Clearinghouse clearhouse, Carrier carrier, Provider billProv, Clinic clinic, InsPlan insPlan, Patient subscriber, InsSub insSub) { StringBuilder strb = new StringBuilder(); X12Validate.ISA(clearhouse, strb); X12Validate.Carrier(carrier, strb); if (carrier.ElectID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Electronic ID"); } if (billProv.SSN.Length != 9) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Prov TIN 9 digits"); } X12Validate.BillProv(billProv, strb); if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { X12Validate.BillingAddress(strb); } else if (clinic == null) { X12Validate.PracticeAddress(strb); } else { X12Validate.Clinic(clinic, strb); } if (insSub.SubscriberID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("SubscriberID"); } if (subscriber.Birthdate.Year < 1880) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Subscriber Birthdate"); } if (insPlan.GroupNum == "") { if (strb.Length != 0) { strb.Append(","); } strb.Append("Group Number"); } return(strb.ToString()); }
///<summary>this code is similar to code in the phone tracking server. But here, we frequently only change clockStatus and ColorBar by setting employeeNum=-1. If employeeNum is not -1, then EmployeeName also gets set. If employeeNum==0, then clears employee from that row.</summary> public static void SetPhoneStatus(ClockStatusEnum clockStatus, int extens, long employeeNum) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), clockStatus, extens, employeeNum); return; } string command = @"SELECT phoneempdefault.EmployeeNum,phoneempdefault.IsTriageOperator,Description,phoneempdefault.EmpName,HasColor,phone.ClockStatus " + "FROM phone " + "LEFT JOIN phoneempdefault ON phone.Extension=phoneempdefault.PhoneExt " + "WHERE phone.Extension=" + POut.Long(extens); DataTable tablePhone = Db.GetTable(command); if (tablePhone.Rows.Count == 0) { //It would be nice if we could create a phone row for this extension. return; } long empNum = PIn.Long(tablePhone.Rows[0]["EmployeeNum"].ToString()); bool isTriageOperator = PIn.Bool(tablePhone.Rows[0]["IsTriageOperator"].ToString()); string empName = PIn.String(tablePhone.Rows[0]["EmpName"].ToString()); string clockStatusDb = PIn.String(tablePhone.Rows[0]["ClockStatus"].ToString()); Employee emp = Employees.GetEmp(employeeNum); if (emp != null) //A new employee is going to take over this extension. { empName = emp.FName; empNum = emp.EmployeeNum; } else if (employeeNum == 0) //Clear the employee from that row. { empName = ""; empNum = 0; } //if these values are null because of missing phoneempdefault row, they will default to false //PhoneEmpStatusOverride statusOverride=(PhoneEmpStatusOverride)PIn.Int(tablePhone.Rows[0]["StatusOverride"].ToString()); bool hasColor = PIn.Bool(tablePhone.Rows[0]["HasColor"].ToString()); #region DateTimeStart //When a user shows up as a color on the phone panel, we want a timer to be constantly going to show how long they've been off the phone. string dateTimeStart = ""; //It's possible that a new user has never clocked in before, therefore their clockStatus will be empty. Simply set it to the status that they are trying to go to. if (clockStatusDb == "") { clockStatusDb = clockStatus.ToString(); } if (clockStatus == ClockStatusEnum.Break || clockStatus == ClockStatusEnum.Lunch) { //The user is going on Lunch or Break. Start the DateTimeStart counter so we know how long they have been gone. dateTimeStart = "DateTimeStart=NOW(), "; } else if (clockStatus == ClockStatusEnum.Home) { //User is going Home. Always clear the DateTimeStart column no matter what. dateTimeStart = "DateTimeStart='0001-01-01', "; } else //User shows as a color on big phones and is not going to a status of Home, Lunch, or Break. Example: Available, Training etc. //Get the current clock status from the database. { ClockStatusEnum clockStatusCur = (ClockStatusEnum)Enum.Parse(typeof(ClockStatusEnum), clockStatusDb); //Start the clock if the user is going from a break status to any other non-break status. if (clockStatusCur == ClockStatusEnum.Home || clockStatusCur == ClockStatusEnum.Lunch || clockStatusCur == ClockStatusEnum.Break) { //The user is clocking in from home, lunch, or break. Start the timer up. if (hasColor) //Only start up the timer when someone with color clocks in. { dateTimeStart = "DateTimeStart=NOW(), "; } else //Someone with no color then reset the timer. They are back from break, that's all we need to know. { dateTimeStart = "DateTimeStart='0001-01-01', "; } } } #endregion //Update the phone row to reflect the new clock status of the user. string clockStatusNew = clockStatus.ToString(); if (clockStatus == ClockStatusEnum.None) { clockStatusNew = ""; } command = "UPDATE phone SET ClockStatus='" + POut.String(clockStatusNew) + "', " + dateTimeStart //+"ColorBar=-1, " //ColorBar is now determined at runtime by OD using Phones.GetPhoneColor. + "EmployeeNum=" + POut.Long(empNum) + ", " + "EmployeeName='" + POut.String(empName) + "' " + "WHERE Extension=" + extens; Db.NonQ(command); if (PrefC.GetBool(PrefName.DockPhonePanelShow)) //hq only //Zero out any duplicate phone table rows for this employee. //This is possible if a user logged off and another employee logs into their computer. This would cause duplicate entries in the big phones window. { UpdatePhoneToEmpty(employeeNum, extens); } }
///<summary>If not using clinics then supply an empty list of clinicNums. listClinicNums must have at least one item if using clinics. ///The table returned has the following columns in this order: ///PatientName, ProcDate, Descript, ProcFee, ProcNum, ClinicNum, PatNum, IsInProcess</summary> public static DataTable GetProcsNotBilled(List <long> listClinicNums, bool includeMedProcs, DateTime dateStart, DateTime dateEnd, bool showProcsBeforeIns, bool hasMultiVisitProcs) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), listClinicNums, includeMedProcs, dateStart, dateEnd, showProcsBeforeIns, hasMultiVisitProcs)); } string query = "SELECT "; if (PrefC.GetBool(PrefName.ReportsShowPatNum)) { query += DbHelper.Concat("CAST(PatNum AS CHAR)", "'-'", "LName", "', '", "FName", "' '", "MiddleI"); } else { query += DbHelper.Concat("LName", "', '", "FName", "' '", "MiddleI"); } query += " AS 'PatientName',Stat,ProcDate,Descript,procFee,ProcNum,ClinicNum,PatNum " + "FROM (SELECT patient.LName,patient.FName,patient.MiddleI," + "CASE WHEN procmultivisit.ProcMultiVisitNum IS NULL " + "THEN '" + Lans.g("enumProcStat", ProcStat.C.ToString()) + "' ELSE '" + Lans.g("enumProcStat", ProcStatExt.InProcess) + "' END Stat," + "procedurelog.ProcDate,procedurecode.Descript,procedurelog.ProcFee*(procedurelog.UnitQty+procedurelog.BaseUnits) procFee," + "procedurelog.ProcNum,procedurelog.ClinicNum,patient.PatNum,insplan.PlanNum,MAX(insplan.IsMedical) isMedical," + "CASE WHEN MIN(insplan.IsMedical)=0 THEN 1 ELSE 0 END hasDental " + "FROM patient " + "INNER JOIN procedurelog ON procedurelog.PatNum = patient.PatNum " + "AND procedurelog.ProcFee>0 " + "AND procedurelog.procstatus=" + (int)ProcStat.C + " " + "AND procedurelog.ProcDate BETWEEN "+ POut.Date(dateStart) + " AND " + POut.Date(dateEnd) + " " + "INNER JOIN procedurecode ON procedurecode.CodeNum = procedurelog.CodeNum "; if (CultureInfo.CurrentCulture.Name.EndsWith("CA")) { query += "AND procedurecode.IsCanadianLab=0 "; //ignore Canadian labs } query += "LEFT JOIN claimproc ON claimproc.ProcNum = procedurelog.ProcNum " + "LEFT JOIN insplan ON insplan.PlanNum = claimproc.PlanNum " + "LEFT JOIN procmultivisit ON procmultivisit.ProcNum=procedurelog.ProcNum AND procmultivisit.IsInProcess=1 " + "WHERE EXISTS(SELECT 1 FROM patplan WHERE patplan.PatNum=patient.PatNum) " + "AND ((claimproc.NoBillIns=0 AND claimproc.Status=" + (int)ClaimProcStatus.Estimate + ") "; if (showProcsBeforeIns) { query += "OR claimproc.ClaimProcNum IS NULL "; } query += ") "; if (!hasMultiVisitProcs) { query += "AND (procmultivisit.ProcMultiVisitNum IS NULL) "; } if (listClinicNums.Count > 0) { query += "AND procedurelog.ClinicNum IN (" + String.Join(",", listClinicNums) + ") "; } query += "GROUP BY procedurelog.ProcNum " + ") procnotbilled "; //End of the main query which is treated like a sub query in order to process includeMedProcs and showProcsBeforeIns. //Having the "AND insplan.IsMedical=0" check within the WHERE clause of the main query causes slowness for large databases. //MySQL will freak out when looking for what index to use which causes full row scans to take place instead of simply filtering the results. //This problem can be resolved by putting the insplan.IsMedical=0 check into the LEFT JOIN clause and performing a corresponding NULL check. //However, the "OR insplan.PlanNum IS NULL" complicates the query enough to where it is easier to just put the old WHERE clause outside. //This sub query trick improved the following report for a large office from ~55 seconds to ~5 seconds. query += "WHERE (procnotbilled.hasDental=1 "; //Always include procedures when the patient has dental insurance. if (includeMedProcs) { query += "OR procnotbilled.isMedical=1 "; } if (showProcsBeforeIns) { query += "OR procnotbilled.PlanNum IS NULL "; } query += ") ORDER BY LName,FName,PatNum,ProcDate"; return(Db.GetTable(query)); }
public static ApptReminderRule CreateDefaultReminderRule(ApptReminderType ruleType, long clinicNum = 0, bool isBeforeAppointment = true) { ApptReminderRule rule = null; switch (ruleType) { case ApptReminderType.Reminder: rule = new ApptReminderRule() { ClinicNum = clinicNum, //works with practice too because _listClinics[0] is a spoofed "Practice/Defaults" clinic with ClinicNum=0 TypeCur = ApptReminderType.Reminder, TSPrior = TimeSpan.FromHours(3), TemplateSMS = "Appointment Reminder: [NameF] is scheduled for [ApptTime] on [ApptDate] at [ClinicName]. If you have questions call [ClinicPhone].", //default message TemplateEmail = @"[NameF], Your appointment is scheduled for [ApptTime] on [ApptDate] at [OfficeName]. If you have questions, call <a href=""tel:[OfficePhone]"">[OfficePhone]</a>.", TemplateEmailSubject = "Appointment Reminder", //default subject TemplateSMSAggShared = "Appointment Reminder:\n[Appts]\nIf you have questions call [ClinicPhone].", TemplateSMSAggPerAppt = "[NameF] is scheduled for [ApptTime] on [ApptDate] at [ClinicName].", TemplateEmailSubjAggShared = "Appointment Reminder", TemplateEmailAggShared = @"[Appts] If you have questions, call <a href=""tel:[OfficePhone]"">[OfficePhone]</a>.", TemplateEmailAggPerAppt = "[NameF] is scheduled for [ApptTime] on [ApptDate] at [ClinicName].", //SendOrder="0,1,2" //part of ctor }; break; case ApptReminderType.ConfirmationFutureDay: rule = new ApptReminderRule() { ClinicNum = clinicNum, //works with practice too because _listClinics[0] is a spoofed "Practice/Defaults" clinic with ClinicNum=0 TypeCur = ApptReminderType.ConfirmationFutureDay, TSPrior = TimeSpan.FromDays(7), TemplateSMS = "[NameF] is scheduled for [ApptTime] on [ApptDate] at [OfficeName]. Reply [ConfirmCode] to confirm or call [OfficePhone].", //default message TemplateEmail = @"[NameF], Your appointment is scheduled for [ApptTime] on [ApptDate] at [OfficeName]. Click <a href=""[ConfirmURL]"">[ConfirmURL]</a> to confirm " + @"or call <a href=""tel:[OfficePhone]"">[OfficePhone]</a>.", TemplateEmailSubject = "Appointment Confirmation", //default subject TemplateSMSAggShared = "[Appts]\nReply [ConfirmCode] to confirm or call [OfficePhone].", TemplateSMSAggPerAppt = "[NameF] is scheduled for [ApptTime] on [ApptDate] at [ClinicName].", TemplateEmailSubjAggShared = "Appointment Confirmation", TemplateEmailAggShared = @"[Appts] Click <a href=""[ConfirmURL]"">[ConfirmURL]</a> to confirm or call <a href=""tel:[OfficePhone]"">[OfficePhone]</a>.", TemplateEmailAggPerAppt = "[NameF] is scheduled for [ApptTime] on [ApptDate] at [ClinicName].", //SendOrder="0,1,2" //part of ctor DoNotSendWithin = TimeSpan.FromDays(1).Add(TimeSpan.FromHours(10)), TemplateAutoReply = "Thank you for confirming your appointment with [OfficeName]. We look forward to seeing you.", TemplateAutoReplyAgg = "Thank you for confirming your appointments with [OfficeName]. We look forward to seeing you", IsAutoReplyEnabled = true, }; break; case ApptReminderType.PatientPortalInvite: if (isBeforeAppointment) { rule = new ApptReminderRule() { ClinicNum = clinicNum, TypeCur = ApptReminderType.PatientPortalInvite, TSPrior = TimeSpan.FromDays(7), TemplateEmail = @"[NameF], In preparation for your upcoming dental appointment at [OfficeName], we invite you to log in to our Patient Portal. " + @" There you can view your scheduled appointments, view your treatment plan, send a message to your provider, and view your account balance. " + @" Visit our <a href=""[PatientPortalURL]"">Patient Portal</a> and use this temporary user name and password to log in: User name: [UserName] Password: [Password] If you have any questions, please give us a call at <a href=""tel:[OfficePhone]"">[OfficePhone]</a>, and we would be happy to answer any of your questions.", TemplateEmailSubject = "Patient Portal Invitation", TemplateEmailSubjAggShared = "Patient Portal Invitation", TemplateEmailAggShared = @"[NameF], In preparation for your upcoming dental appointments at [OfficeName], we invite you to log in to our Patient Portal. " + @" There you can view your scheduled appointments, view your treatment plan, send a message to your provider, and view your account balance. " + @" Visit our <a href=""[PatientPortalURL]"">Patient Portal</a> and use these temporary user names and passwords to log in: [Credentials] If you have any questions, please give us a call at <a href=""tel:[OfficePhone]"">[OfficePhone]</a>, and we would be happy to answer any of your questions.", TemplateEmailAggPerAppt = @"[NameF] User name: [UserName] Password: [Password] ", SendOrder = "2" //Email only }; break; } else //Same day { rule = new ApptReminderRule() { ClinicNum = clinicNum, TypeCur = ApptReminderType.PatientPortalInvite, TSPrior = new TimeSpan(-1, 0, 0), //Send 1 hour after the appointment TemplateEmail = @"[NameF], Thank you for coming in to visit [OfficeName] today. As a follow up to your appointment, we invite you to log in to our Patient Portal. " + @" There you can view your scheduled appointments, view your treatment plan, send a message to your provider, and view your account balance. " + @" Visit <a href=""[PatientPortalURL]"">Patient Portal</a> and use this temporary user name and password to log in: User name: [UserName] Password: [Password] If you have any questions, please give us a call at <a href=""tel:[OfficePhone]"">[OfficePhone]</a>, and we would be happy to answer any of your questions.", TemplateEmailSubject = "Patient Portal Invitation", TemplateEmailSubjAggShared = "Patient Portal Invitation", TemplateEmailAggShared = @"[NameF], Thank you for coming in to visit [OfficeName] today. As a follow up to your appointment, we invite you to log in to our Patient Portal. " + @" There you can view your scheduled appointments, view your treatment plan, send a message to your provider, and view your account balance. " + @" Visit <a href=""[PatientPortalURL]"">Patient Portal</a> and use these temporary user names and passwords to log in: [Credentials] If you have any questions, please give us a call at <a href=""tel:[OfficePhone]"">[OfficePhone]</a>, and we would be happy to answer any of your questions.", TemplateEmailAggPerAppt = @"[NameF] User name: [UserName] Password: [Password] ", SendOrder = "2" //Email only }; break; } case ApptReminderType.ScheduleThankYou: rule = new ApptReminderRule() { ClinicNum = clinicNum, //works with practice too because _listClinics[0] is a spoofed "Practice/Defaults" clinic with ClinicNum=0 TypeCur = ApptReminderType.ScheduleThankYou, TSPrior = new TimeSpan(-1, 0, 0), //default to send thank you 1 hour after creating appointment. TemplateSMS = "[NameF], thank you for scheduling with [OfficeName] on [ApptDate] at [ApptTime].", //default message TemplateEmail = @"[NameF], Thank you for scheduling your appointment with [OfficeName] on [ApptDate] at [ApptTime]. If you have questions, call <a href=""tel:[OfficePhone]"">[OfficePhone]</a>.", TemplateEmailSubject = "Appointment Thank You", //default subject TemplateSMSAggShared = "Thank you for scheduling these appointments: [Appts]", TemplateSMSAggPerAppt = "[NameF] for [ApptTime] on [ApptDate] at [ClinicName]", TemplateEmailSubjAggShared = "Appointment Thank You", TemplateEmailAggShared = @"Thank you for scheduling these appointments: [Appts] If you have questions, call <a href=""tel:[OfficePhone]"">[OfficePhone]</a>.", TemplateEmailAggPerAppt = "[NameF] is scheduled for [ApptTime] on [ApptDate] at [ClinicName].", //SendOrder="0,1,2" //part of ctor DoNotSendWithin = new TimeSpan(2, 0, 0), //Do not send within 2 hours of appointment.AptDateTime. }; break; } if (PrefC.GetBool(PrefName.EmailDisclaimerIsOn)) { rule.TemplateEmail += "\r\n\r\n\r\n[EmailDisclaimer]"; rule.TemplateEmailAggShared += "\r\n\r\n\r\n[EmailDisclaimer]"; } return(rule); }
///<summary>If not using clinics then supply an empty list of clinicNums. listClinicNums must have at least one item if using clinics.</summary> public static DataTable GetProcsNotBilled(List <long> listClinicNums, bool includeMedProcs, DateTime dateStart, DateTime dateEnd, bool showProcsBeforeIns) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), listClinicNums, includeMedProcs, dateStart, dateEnd, showProcsBeforeIns)); } string query = "SELECT "; if (PrefC.GetBool(PrefName.ReportsShowPatNum)) { query += DbHelper.Concat("CAST(patient.PatNum AS CHAR)", "'-'", "patient.LName", "', '", "patient.FName", "' '", "patient.MiddleI"); } else { query += DbHelper.Concat("patient.LName", "', '", "patient.FName", "' '", "patient.MiddleI"); } query += " AS 'PatientName',procedurelog.ProcDate,procedurecode.Descript,procedurelog.ProcFee*(procedurelog.UnitQty+procedurelog.BaseUnits)," + "procedurelog.ProcNum,procedurelog.ClinicNum " + "FROM patient " + "INNER JOIN procedurelog ON procedurelog.PatNum = patient.PatNum " + "AND procedurelog.ProcFee>0 " + "AND procedurelog.procstatus=" + (int)ProcStat.C + " " + "AND procedurelog.ProcDate BETWEEN "+ POut.Date(dateStart) + " AND " + POut.Date(dateEnd) + " " + "INNER JOIN ( " + "SELECT PatNum FROM patplan GROUP BY PatNum " + " )HasIns ON HasIns.PatNum = patient.PatNum "; if (listClinicNums.Count > 0) { query += "AND procedurelog.ClinicNum IN (" + String.Join(",", listClinicNums) + ") "; } query += "INNER JOIN procedurecode ON procedurecode.CodeNum = procedurelog.CodeNum "; if (CultureInfo.CurrentCulture.Name.EndsWith("CA")) { query += "AND procedurecode.IsCanadianLab=0 "; //ignore Canadian labs } query += "LEFT JOIN claimproc ON claimproc.ProcNum = procedurelog.ProcNum " + "LEFT JOIN insplan ON insplan.PlanNum = claimproc.PlanNum "; if (showProcsBeforeIns) { query += "WHERE ((claimproc.NoBillIns=0 " + "AND claimproc.Status=" + (int)ClaimProcStatus.Estimate + ") " + "OR claimproc.ClaimProcNum IS NULL) "; } else { query += "WHERE claimproc.NoBillIns=0 " + "AND claimproc.Status=" + (int)ClaimProcStatus.Estimate + " "; } if (!includeMedProcs) { query += "AND (insplan.IsMedical=0 "; if (showProcsBeforeIns) { query += "OR insplan.PlanNum IS NULL "; } query += ") "; } query += "GROUP BY procedurelog.ProcNum " + "ORDER BY patient.LName,patient.FName,patient.PatNum,procedurelog.ProcDate"; return(Db.GetTable(query)); }
/// <summary>Runs repeating charges for the date passed in, usually today. Can't use 'out' variables because this runs over Middle Tier.</summary> public static RepeatChargeResult RunRepeatingCharges(DateTime dateRun) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <RepeatChargeResult>(MethodBase.GetCurrentMethod(), dateRun)); } Prefs.UpdateDateT(PrefName.RepeatingChargesBeginDateTime, dateRun); try { RepeatChargeResult result = new RepeatChargeResult(); List <RepeatCharge> listRepeatingCharges = RepeatCharges.Refresh(0).ToList(); if (PrefC.IsODHQ) { //Remove all eService repeating charges. //EService charges have already been calculated and stored in EServiceBilling table. Add those here. List <string> listEServiceCodes = EServiceCodeLink.GetProcCodesForAll(); listRepeatingCharges.RemoveAll(x => listEServiceCodes.Contains(x.ProcCode)); result.ProceduresAddedCount += EServiceBillings.AddEServiceRepeatingChargesHelper(dateRun).Count; } DateTime startedUsingFKs = UpdateHistories.GetDateForVersion(new Version("16.1.0.0")); //We started using FKs from procs to repeat charges in 16.1. foreach (RepeatCharge repeatCharge in listRepeatingCharges) { if (!repeatCharge.IsEnabled || (repeatCharge.DateStop.Year > 1880 && repeatCharge.DateStop.AddMonths(3) < dateRun)) { continue; //This repeating charge is too old to possibly create a new charge. Not precise but greatly reduces calls to DB. //We will filter by more stringently on the DateStop later on. } long codeNum = ProcedureCodes.GetCodeNum(repeatCharge.ProcCode); //Must contain all procedures that affect the date range. DateTime procRangeStart = repeatCharge.DateStart.AddMonths(-1); //Minus 1 month to catch accounts that have changed their billing date List <Procedure> listExistingProcs = Procedures.GetCompletedForDateRange(procRangeStart, dateRun, new List <long> { codeNum }, new List <long> { repeatCharge.PatNum }); for (int j = listExistingProcs.Count - 1; j >= 0; j--) //iterate backwards to remove elements { Procedure proc = listExistingProcs[j]; if (((proc.RepeatChargeNum == repeatCharge.RepeatChargeNum) //Check the procedure's FK first //Use the old logic without matching FKs only if the procedure was added before updating to 16.1 //Match patnum, codenum, fee, year, and month (IsRepeatDateHelper uses special logic to determine correct month) //Procedures with the ProcDate prior to the RepeatCharge.StartDate should not be considered as valid procedures //associated to the current repeat charge. || ((proc.ProcDate < startedUsingFKs || startedUsingFKs.Year < 1880) && proc.PatNum == repeatCharge.PatNum && proc.CodeNum == codeNum && proc.ProcFee.IsEqual(repeatCharge.ChargeAmt))) && (proc.ProcDate >= repeatCharge.DateStart || //Consider procedures that fall on or after the repeat charge start date. proc.ProcDate.Day != repeatCharge.DateStart.Day)) //Consider procs only when days are not the same. Catches procs that have changed their billing date { continue; //This existing procedure needs to be counted for this repeat charge. } listExistingProcs.RemoveAt(j); //Removing so that another repeat charge of the same code, date, and amount will be added. } List <DateTime> listBillingDates; //This list will have 1 or 2 dates where a repeating charge might be added if (PrefC.GetBool(PrefName.BillingUseBillingCycleDay)) { listBillingDates = GetBillingDatesHelper(repeatCharge.DateStart, repeatCharge.DateStop, dateRun, listExistingProcs, repeatCharge, Patients.GetPat(repeatCharge.PatNum).BillingCycleDay); } else { listBillingDates = GetBillingDatesHelper(repeatCharge.DateStart, repeatCharge.DateStop, dateRun, listExistingProcs, repeatCharge); } listBillingDates.RemoveAll(x => x.Date > DateTime.Today.Date && !PrefC.GetBool(PrefName.FutureTransDatesAllowed)); //If any billing dates have not been filtered out, add a repeating charge on those dates foreach (DateTime billingDate in listBillingDates) { Procedure procAdded = AddRepeatingChargeHelper(repeatCharge, billingDate, dateRun); List <Claim> listClaimsAdded = new List <Claim>(); if (repeatCharge.CreatesClaim && !ProcedureCodes.GetProcCode(repeatCharge.ProcCode).NoBillIns) { listClaimsAdded = AddClaimsHelper(repeatCharge, procAdded); } result.ProceduresAddedCount++; result.ClaimsAddedCount += listClaimsAdded.Count; } } return(result); } finally { Prefs.UpdateString(PrefName.RepeatingChargesBeginDateTime, ""); } }
///<summary>Called by local practice db to query HQ for EService setup info. Must remain very lite and versionless. Will be used by signup portal. ///If HasClinics==true then any SignupOut.EServices entries where ClinicNum==0 are invalid and should be ignored. ///If HasClinics==false then SignupOut.EServices should only pay attention items where ClinicNum==0. ///This list is kept completely unfiltered by ClinicNum for forward compatibility reasons. ///The ClinicNum 0 items are always used by the Signup portal to determine default signup preferences. ///However, these items are only used for validation and billing in the case where HasClinics==true.</summary> public static EServiceSetup.SignupOut GetEServiceSetupFull(SignupPortalPermission permission, bool isSwitchClinicPref = false) { //Clinics will be stored in this order at HQ to allow signup portal to display them in proper order. List <Clinic> clinics = Clinics.GetDeepCopy().OrderBy(x => x.ItemOrder).ToList(); if (PrefC.GetBool(PrefName.ClinicListIsAlphabetical)) { clinics = clinics.OrderBy(x => x.Abbr).ToList(); } #if DEBUG bool isMockChanged = false; if (WebServiceMainHQProxy.MockWebServiceMainHQ == null) { WebServiceMainHQProxy.MockWebServiceMainHQ = new WebServiceMainHQMockDemo(); isMockChanged = true; } #endif EServiceSetup.SignupOut signupOut = ReadXml <EServiceSetup.SignupOut> ( WebSerializer.DeserializePrimitiveOrThrow <string> ( GetWebServiceMainHQInstance().EServiceSetup ( CreateWebServiceHQPayload ( WriteXml(new EServiceSetup.SignupIn() { MethodNameInt = (int)EServiceSetup.SetupMethod.GetSignupOutFull, HasClinics = PrefC.HasClinicsEnabled, //ClinicNum is not currently used as input. ClinicNum = 0, ProgramVersionStr = PrefC.GetString(PrefName.ProgramVersion), SignupPortalPermissionInt = (int)permission, Clinics = clinics .Select(x => new EServiceSetup.SignupIn.ClinicLiteIn() { ClinicNum = x.ClinicNum, ClinicTitle = x.Abbr, IsHidden = x.IsHidden, }).ToList(), IsSwitchClinicPref = isSwitchClinicPref, }), eServiceCode.Undefined ) ) ) ); #if DEBUG if (isMockChanged) { WebServiceMainHQProxy.MockWebServiceMainHQ = null; } #endif //We just got the latest sync info from HQ so update the local db to reflect what HQ says is true. #region Reconcile Phones List <SmsPhone> listPhonesHQ = signupOut.Phones.Select(x => new SmsPhone() { ClinicNum = x.ClinicNum, CountryCode = x.CountryCode, DateTimeActive = x.DateTimeActive, DateTimeInactive = x.DateTimeInactive, InactiveCode = x.InactiveCode, PhoneNumber = x.PhoneNumber, }).ToList(); SmsPhones.UpdateOrInsertFromList(listPhonesHQ); #endregion #region Reconcile practice and clinics List <EServiceSetup.SignupOut.SignupOutSms> smsSignups = GetSignups <EServiceSetup.SignupOut.SignupOutSms>(signupOut, eServiceCode.IntegratedTexting); bool isCacheInvalid = false; bool isSmsEnabled = false; if (PrefC.HasClinicsEnabled) //Clinics are ON so loop through all clinics and reconcile with HQ. { List <Clinic> listClinicsAll = Clinics.GetDeepCopy(); foreach (Clinic clinicDb in listClinicsAll) { WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms clinicSignup = smsSignups.FirstOrDefault(x => x.ClinicNum == clinicDb.ClinicNum) ?? new WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms() { //Not found so turn it off. SmsContractDate = DateTime.MinValue, MonthlySmsLimit = 0, IsEnabled = false, }; Clinic clinicNew = clinicDb.Copy(); clinicNew.SmsContractDate = clinicSignup.SmsContractDate; clinicNew.SmsMonthlyLimit = clinicSignup.MonthlySmsLimit; isCacheInvalid |= Clinics.Update(clinicNew, clinicDb); isSmsEnabled |= clinicSignup.IsEnabled; } } else //Clinics are off so ClinicNum 0 is the practice clinic. { WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms practiceSignup = smsSignups.FirstOrDefault(x => x.ClinicNum == 0) ?? new WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms() { //Not found so turn it off. SmsContractDate = DateTime.MinValue, MonthlySmsLimit = 0, IsEnabled = false, }; isCacheInvalid |= Prefs.UpdateDateT(PrefName.SmsContractDate, practiceSignup.SmsContractDate) | Prefs.UpdateLong(PrefName.TextingDefaultClinicNum, 0) | Prefs.UpdateDouble(PrefName.SmsMonthlyLimit, practiceSignup.MonthlySmsLimit); isSmsEnabled |= practiceSignup.IsEnabled; } #endregion #region Reconcile CallFire //Turn off CallFire if SMS has been activated. //This only happens the first time SMS is turned on and CallFire is still activated. if (isSmsEnabled && Programs.IsEnabled(ProgramName.CallFire)) { Program callfire = Programs.GetCur(ProgramName.CallFire); if (callfire != null) { callfire.Enabled = false; Programs.Update(callfire); Signalods.Insert(new Signalod() { IType = InvalidType.Providers }); signupOut.Prompts.Add("Call Fire has been disabled. Cancel Integrated Texting and access program properties to retain Call Fire."); } } #endregion #region eConfirmations if (Prefs.UpdateBool(PrefName.ApptConfirmAutoSignedUp, IsEServiceActive(signupOut, eServiceCode.ConfirmationRequest))) { //HQ does not match the local pref. Make it match with HQ. isCacheInvalid = true; SecurityLogs.MakeLogEntry(Permissions.Setup, 0, "Automated appointment eConfirmations automatically changed by HQ. Local pref set to " + IsEServiceActive(signupOut, eServiceCode.ConfirmationRequest).ToString() + "."); } #endregion if (isCacheInvalid) //Something changed in the db. Alert other workstations and change this workstation immediately. { Signalods.Insert(new Signalod() { IType = InvalidType.Prefs }); Prefs.RefreshCache(); Signalods.Insert(new Signalod() { IType = InvalidType.Providers }); Providers.RefreshCache(); Clinics.RefreshCache(); } return(signupOut); }
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>Only called from Chart for now. No validation is performed here. Validate before calling. There are many validtion checks, including the NPI must be exactly 10 digits.</summary> public static string BuildClickThroughXml(Provider prov, Employee emp, Patient pat) { NCScript ncScript = new NCScript(); ncScript.Credentials = new CredentialsType(); ncScript.Credentials.partnerName = NewCropPartnerName; ncScript.Credentials.name = NewCropAccountName; ncScript.Credentials.password = NewCropAccountPasssword; ncScript.Credentials.productName = NewCropProductName; ncScript.Credentials.productVersion = NewCropProductVersion; ncScript.UserRole = new UserRoleType(); if (emp == null) { ncScript.UserRole.user = UserType.LicensedPrescriber; ncScript.UserRole.role = RoleType.doctor; } else { ncScript.UserRole.user = UserType.Staff; ncScript.UserRole.role = RoleType.nurse; } ncScript.Destination = new DestinationType(); ncScript.Destination.requestedPage = RequestedPageType.compose; //This is the tab that the user will want 90% of the time. string practiceTitle = PrefC.GetString(PrefName.PracticeTitle); //May be blank. string practicePhone = PrefC.GetString(PrefName.PracticePhone); //Validated to be 10 digits within the chart. string practiceFax = PrefC.GetString(PrefName.PracticeFax); //Validated to be 10 digits within the chart. string practiceAddress = PrefC.GetString(PrefName.PracticeAddress); //Validated to exist in chart. string practiceAddress2 = PrefC.GetString(PrefName.PracticeAddress2); //May be blank. string practiceCity = PrefC.GetString(PrefName.PracticeCity); //Validated to exist in chart. string practiceState = PrefC.GetString(PrefName.PracticeST); //Validated to be a US state code in chart. string practiceZip = Regex.Replace(PrefC.GetString(PrefName.PracticeZip), "[^0-9]*", ""); //Zip with all non-numeric characters removed. Validated to be 9 digits in chart. string practiceZip4 = practiceZip.Substring(5); //Last 4 digits of zip. practiceZip = practiceZip.Substring(0, 5); //First 5 digits of zip. string country = "US"; //Always United States for now. //if(CultureInfo.CurrentCulture.Name.Length>=2) { // country=CultureInfo.CurrentCulture.Name.Substring(CultureInfo.CurrentCulture.Name.Length-2); //} ncScript.Account = new AccountTypeRx(); //Each LicensedPrescriberID must be unique within an account. Since we send ProvNum for LicensedPrescriberID, each OD database must have a unique AccountID. ncScript.Account.ID = PrefC.GetString(PrefName.NewCropAccountId); //Customer account number then a dash then a random alpha-numeric string of 3 characters, followed by 2 digits. ncScript.Account.accountName = practiceTitle; //May be blank. ncScript.Account.siteID = "1"; //Always send 1. For each AccountID/SiteID pair, a separate database will be created in NewCrop. ncScript.Account.AccountAddress = new AddressType(); ncScript.Account.AccountAddress.address1 = practiceAddress; //Validated to exist in chart. ncScript.Account.AccountAddress.address2 = practiceAddress2; //May be blank. ncScript.Account.AccountAddress.city = practiceCity; //Validated to exist in chart. ncScript.Account.AccountAddress.state = practiceState; //Validated to be a US state code in chart. ncScript.Account.AccountAddress.zip = practiceZip; //Validated to be 9 digits in chart. First 5 digits go in this field. ncScript.Account.AccountAddress.zip4 = practiceZip4; //Validated to be 9 digits in chart. Last 4 digits go in this field. ncScript.Account.AccountAddress.country = country; //Validated above. ncScript.Account.accountPrimaryPhoneNumber = practicePhone; //Validated to be 10 digits within the chart. ncScript.Account.accountPrimaryFaxNumber = practiceFax; //Validated to be 10 digits within the chart. ncScript.Location = new LocationType(); if (PrefC.GetBool(PrefName.EasyNoClinics) || pat.ClinicNum == 0) //No clinics. { ncScript.Location.ID = "0"; //Always 0, since clinicnums must be >= 1, will never overlap with a clinic if the office turns clinics on after first use. ncScript.Location.locationName = practiceTitle; //May be blank. ncScript.Location.LocationAddress = new AddressType(); ncScript.Location.LocationAddress.address1 = practiceAddress; //Validated to exist in chart. ncScript.Location.LocationAddress.address2 = practiceAddress2; //May be blank. ncScript.Location.LocationAddress.city = practiceCity; //Validated to exist in chart. ncScript.Location.LocationAddress.state = practiceState; //Validated to be a US state code in chart. ncScript.Location.LocationAddress.zip = practiceZip; //Validated to be 9 digits in chart. First 5 digits go in this field. ncScript.Location.LocationAddress.zip4 = practiceZip4; //Validated to be 9 digits in chart. Last 4 digits go in this field. ncScript.Location.LocationAddress.country = country; //Validated above. ncScript.Location.primaryPhoneNumber = practicePhone; //Validated to be 10 digits within the chart. ncScript.Location.primaryFaxNumber = practiceFax; //Validated to be 10 digits within the chart. ncScript.Location.pharmacyContactNumber = practicePhone; //Validated to be 10 digits within the chart. } else //Using clinics. { Clinic clinic = Clinics.GetClinic(pat.ClinicNum); ncScript.Location.ID = clinic.ClinicNum.ToString(); //A positive integer. ncScript.Location.locationName = clinic.Description; //May be blank. ncScript.Location.LocationAddress = new AddressType(); ncScript.Location.LocationAddress.address1 = clinic.Address; //Validated to exist in chart. ncScript.Location.LocationAddress.address2 = clinic.Address2; //May be blank. ncScript.Location.LocationAddress.city = clinic.City; //Validated to exist in chart. ncScript.Location.LocationAddress.state = clinic.State; //Validated to be a US state code in chart. string clinicZip = Regex.Replace(clinic.Zip, "[^0-9]*", ""); //Zip with all non-numeric characters removed. Validated to be 9 digits in chart. string clinicZip4 = clinicZip.Substring(5); //Last 4 digits of zip. clinicZip = clinicZip.Substring(0, 5); //First 5 digits of zip. ncScript.Location.LocationAddress.zip = clinicZip; //Validated to be 9 digits in chart. First 5 digits go in this field. ncScript.Location.LocationAddress.zip4 = clinicZip4; //Validated to be 9 digits in chart. Last 4 digits go in this field. ncScript.Location.LocationAddress.country = country; //Validated above. ncScript.Location.primaryPhoneNumber = clinic.Phone; //Validated to be 10 digits within the chart. ncScript.Location.primaryFaxNumber = clinic.Fax; //Validated to be 10 digits within the chart. ncScript.Location.pharmacyContactNumber = clinic.Phone; //Validated to be 10 digits within the chart. } ncScript.LicensedPrescriber = new LicensedPrescriberType(); //Each unique provider ID sent to NewCrop will cause a billing charge. //Some customer databases have provider duplicates, because they have one provider record per clinic with matching NPIs. //We send NPI as the ID to prevent extra NewCrop charges. //Conversation with NewCrop: //Question: If one of our customers clicks through to NewCrop with 2 different LicensedPrescriber.ID values, // but with the same provider name and NPI, will Open Dental be billed twice or just one time for the NPI used? //Answer: "They would be billed twice. The IDs you send us should always be maintained and unique. // Users are always identified by LicensedPrescriber ID, since their name or credentials could potentially change." ncScript.LicensedPrescriber.ID = prov.NationalProvID; //UPIN is obsolete ncScript.LicensedPrescriber.LicensedPrescriberName = new PersonNameType(); ncScript.LicensedPrescriber.LicensedPrescriberName.last = prov.LName.Trim(); //Cannot be blank. ncScript.LicensedPrescriber.LicensedPrescriberName.first = prov.FName.Trim(); //Cannot be blank. ncScript.LicensedPrescriber.LicensedPrescriberName.middle = prov.MI; //May be blank. ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.DDS; //There is no blank or none option, so we have to pick a default value. DDS=0, so would be default anyway. string[] suffixes = prov.Suffix.ToUpper().Split(' ', '.'); for (int i = 0; i < suffixes.Length; i++) { if (suffixes[i] == "I") { ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.I; break; } else if (suffixes[i] == "II") { ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.II; break; } else if (suffixes[i] == "III") { ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.III; break; } else if (suffixes[i] == "JR") { ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.Jr; break; } else if (suffixes[i] == "SR") { ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.Sr; break; } } if (prov.DEANum.ToLower() == "none") { ncScript.LicensedPrescriber.dea = "NONE"; } else { ncScript.LicensedPrescriber.dea = prov.DEANum; } ncScript.LicensedPrescriber.licenseState = prov.StateWhereLicensed; //Validated to be a US state code in the chart. ncScript.LicensedPrescriber.licenseNumber = prov.StateLicense; //Validated to exist in chart. ncScript.LicensedPrescriber.npi = prov.NationalProvID; //Validated to be 10 digits in chart. //ncScript.LicensedPrescriber.freeformCredentials=;//This is where DDS and DMD should go, but we don't support this yet. Probably not necessary anyway. if (emp != null) { ncScript.Staff = new StaffType(); ncScript.Staff.ID = "emp" + emp.EmployeeNum.ToString(); //A positive integer. Returned in the ExternalUserID field when retreiving prescriptions from NewCrop. Also, provider ID is returned in the same field if a provider created the prescription, so that we can create a distintion between employee IDs and provider IDs. ncScript.Staff.StaffName = new PersonNameType(); ncScript.Staff.StaffName.first = emp.FName; //First name or last name will not be blank. Validated in Chart. ncScript.Staff.StaffName.last = emp.LName; //First name or last name will not be blank. Validated in Chart. ncScript.Staff.StaffName.middle = emp.MiddleI; //May be blank. } ncScript.Patient = new PatientType(); ncScript.Patient.ID = pat.PatNum.ToString(); //A positive integer. ncScript.Patient.PatientName = new PersonNameType(); ncScript.Patient.PatientName.last = pat.LName; //Validated to exist in Patient Edit window. ncScript.Patient.PatientName.first = pat.FName; //May be blank. ncScript.Patient.PatientName.middle = pat.MiddleI; //May be blank. ncScript.Patient.medicalRecordNumber = pat.PatNum.ToString(); //A positive integer. //NewCrop specifically requested that we do not send SSN. //ncScript.Patient.socialSecurityNumber=Regex.Replace(pat.SSN,"[^0-9]*","");//Removes all non-numerical characters. ncScript.Patient.PatientAddress = new AddressOptionalType(); ncScript.Patient.PatientAddress.address1 = pat.Address; //May be blank. ncScript.Patient.PatientAddress.address2 = pat.Address2; //May be blank. ncScript.Patient.PatientAddress.city = pat.City; //May be blank. ncScript.Patient.PatientAddress.state = pat.State; //May be blank. Validated in chart to be blank or to be a valid US state code. ncScript.Patient.PatientAddress.zip = pat.Zip; //May be blank. ncScript.Patient.PatientAddress.country = country; //Validated above. ncScript.Patient.PatientContact = new ContactType(); ncScript.Patient.PatientContact.homeTelephone = pat.HmPhone; //May be blank. Does not need to be 10 digits. ncScript.Patient.PatientCharacteristics = new PatientCharacteristicsType(); ncScript.Patient.PatientCharacteristics.dob = pat.Birthdate.ToString("yyyyMMdd"); //DOB must be in CCYYMMDD format. if (pat.Gender == PatientGender.Male) { ncScript.Patient.PatientCharacteristics.gender = GenderType.M; } else if (pat.Gender == PatientGender.Female) { ncScript.Patient.PatientCharacteristics.gender = GenderType.F; } else { ncScript.Patient.PatientCharacteristics.gender = GenderType.U; } ncScript.Patient.PatientCharacteristics.genderSpecified = true; //NewCrop programmer's comments regarding other fields we are not currently using (these fields are sent back when fetching prescriptions in the Chart): //ExternalPrescriptionId = your unique identifier for the prescription, only to be used if you are generating the prescription on your own UI. // This is referenced by NewCrop, and cannot be populated with any other value. //EncounterIdentifier = unique ID for the patient visit (e.g. John Doe, 11/11/2013). // This is used by NewCrop for reporting events against a visit, but otherwise does not impact the session. //EpisodeIdentifier = unique ID for the patient’s issue (e.g. John Doe’s broken leg) which may include multiple visits. // Currently not used by NewCrop except for being echoed back; it is possible this functionality would be expanded in the future based on its intent as noted. //ExternalSource = a codified field noting the origin of the prescription. This may not be used. //Serialize MemoryStream memoryStream = new MemoryStream(); XmlSerializer xmlSerializer = new XmlSerializer(typeof(NCScript)); xmlSerializer.Serialize(memoryStream, ncScript); byte[] memoryStreamInBytes = memoryStream.ToArray(); return(Encoding.UTF8.GetString(memoryStreamInBytes, 0, memoryStreamInBytes.Length)); }
///<summary>Gets the DataTable to display for treatment finder report</summary> ///<param name="listProviders">Include '0' in the list to get for all providers.</param> ///<param name="listBilling">Include '0' in the list to get for all billing types.</param> ///<param name="listClinicNums">Pass in an empty list to get for all clinics.</param> public static DataTable GetTreatmentFinderList(bool noIns, bool patsWithAppts, int monthStart, DateTime dateSince, double aboveAmount, List <long> listProviders, List <long> listBilling, string code1, string code2, List <long> listClinicNums, bool isProcsGeneral) { //No remoting role check; no call to db Stopwatch sw = null; Stopwatch sTotal = null; if (ODBuild.IsDebug()) { sw = Stopwatch.StartNew(); sTotal = Stopwatch.StartNew(); } DataTable table = new DataTable(); //columns that start with lowercase are altered for display rather than being raw data. table.Columns.Add("PatNum"); table.Columns.Add("LName"); table.Columns.Add("FName"); table.Columns.Add("contactMethod"); table.Columns.Add("address"); table.Columns.Add("City"); table.Columns.Add("State"); table.Columns.Add("Zip"); table.Columns.Add("annualMaxInd"); table.Columns.Add("annualMaxFam"); table.Columns.Add("amountUsedInd"); table.Columns.Add("amountUsedFam"); table.Columns.Add("amountPendingInd"); table.Columns.Add("amountPendingFam"); table.Columns.Add("amountRemainingInd"); table.Columns.Add("amountRemainingFam"); table.Columns.Add("treatmentPlan"); table.Columns.Add("carrierName"); table.Columns.Add("clinicAbbr"); //dictionary with Key=PatNum, Value=AmtPlanned Dictionary <long, double> dictAmtPlanned = new Dictionary <long, double>(); using (DataTable tablePlanned = GetDictAmtPlanned(patsWithAppts, dateSince, listProviders, listBilling, code1, code2, listClinicNums)) { if (ODBuild.IsDebug()) { sw.Stop(); Console.WriteLine("Get tablePlanned: " + sw.Elapsed.TotalSeconds + " sec, Rows: " + tablePlanned.Rows.Count); sw = Stopwatch.StartNew(); } if (tablePlanned.Rows.Count == 0) { return(table); } dictAmtPlanned = tablePlanned.Select().ToDictionary(x => PIn.Long(x["PatNum"].ToString()), x => PIn.Double(x["AmtPlanned"].ToString())); } string patNumStr = string.Join(",", dictAmtPlanned.Keys.Select(x => POut.Long(x))); DateTime renewDate = BenefitLogic.ComputeRenewDate(DateTime.Now, monthStart); //dictionary with Key=PatPlanNum, Value=Tuple(AmtPending,AmtUsed) Dictionary <long, Tuple <double, double> > dictPatInfo = new Dictionary <long, Tuple <double, double> >(); using (DataTable tablePat = GetPatInfo(isProcsGeneral, renewDate, patNumStr)) { dictPatInfo = tablePat.Select().ToDictionary(x => PIn.Long(x["PatPlanNum"].ToString()), x => Tuple.Create(PIn.Double(x["AmtPending"].ToString()), PIn.Double(x["AmtUsed"].ToString()))); } if (ODBuild.IsDebug()) { sw.Stop(); Console.WriteLine("Get dictPatInfo: " + sw.Elapsed.TotalSeconds + " sec, Count: " + dictPatInfo.Count); sw = Stopwatch.StartNew(); } //dictionary with Key=InsSubNum, Value=Tuple(AmtPending,AmtUsed) Dictionary <long, Tuple <double, double> > dictFamInfo = new Dictionary <long, Tuple <double, double> >(); using (DataTable tableFam = GetFamInfo(isProcsGeneral, renewDate, patNumStr)) { dictFamInfo = tableFam.Select().ToDictionary(x => PIn.Long(x["InsSubNum"].ToString()), x => Tuple.Create(PIn.Double(x["AmtPending"].ToString()), PIn.Double(x["AmtUsed"].ToString()))); } if (ODBuild.IsDebug()) { sw.Stop(); Console.WriteLine("Get dictFamInfo: " + sw.Elapsed.TotalSeconds + " sec, Rows: " + dictFamInfo.Count); sw = Stopwatch.StartNew(); } //dictionary with Key=PlanNum, Value=Tuple(AnnualMaxInd,AnnualMaxFam) Dictionary <long, Tuple <double, double> > dictAnnualMax = new Dictionary <long, Tuple <double, double> >(); using (DataTable tableAnnualMax = GetAnnualMaxInfo(patNumStr)) { dictAnnualMax = tableAnnualMax.Select().ToDictionary(x => PIn.Long(x["PlanNum"].ToString()), x => Tuple.Create(PIn.Double(x["AnnualMaxInd"].ToString()), PIn.Double(x["AnnualMaxFam"].ToString()))); } if (ODBuild.IsDebug()) { sw.Stop(); Console.WriteLine("Get dictAnnualMax: " + sw.Elapsed.TotalSeconds + " sec, Rows: " + dictAnnualMax.Count); sw = Stopwatch.StartNew(); } using (DataTable rawtable = GetTableRaw(noIns, monthStart, patNumStr)) { if (ODBuild.IsDebug()) { sw.Stop(); Console.WriteLine("Get RawTable: " + sw.Elapsed.TotalSeconds + " sec, Rows: " + rawtable.Rows.Count); sw = Stopwatch.StartNew(); } DataRow row; foreach (DataRow rawRow in rawtable.Rows) { row = table.NewRow(); long patNum = PIn.Long(rawRow["PatNum"].ToString()); long patPlanNum = PIn.Long(rawRow["PatPlanNum"].ToString()); long planNum = PIn.Long(rawRow["PlanNum"].ToString()); long insSubNum = PIn.Long(rawRow["InsSubNum"].ToString()); double amtPlanned = dictAmtPlanned.TryGetValue(patNum, out amtPlanned)?amtPlanned:0; Tuple <double, double> tuplePatInfo = dictPatInfo.TryGetValue(patPlanNum, out tuplePatInfo)?tuplePatInfo:Tuple.Create(0d, 0d); double patAmtPending = tuplePatInfo.Item1; double patAmtUsed = tuplePatInfo.Item2; Tuple <double, double> tupleFamInfo = dictFamInfo.TryGetValue(insSubNum, out tupleFamInfo)?tupleFamInfo:Tuple.Create(0d, 0d); double famAmtPending = tupleFamInfo.Item1; double famAmtUsed = tupleFamInfo.Item2; Tuple <double, double> tupleAnnualMax = dictAnnualMax.TryGetValue(planNum, out tupleAnnualMax)?tupleAnnualMax:Tuple.Create(0d, 0d); double patAnnualMax = tupleAnnualMax.Item1; double famAnnualMax = tupleAnnualMax.Item2; if (aboveAmount > 0) { if (dictAnnualMax.ContainsKey(planNum) && ((patAnnualMax != -1 && patAnnualMax - patAmtUsed <= aboveAmount) || (famAnnualMax != -1 && famAnnualMax - famAmtUsed <= aboveAmount))) { continue; } } row["PatNum"] = patNum; row["LName"] = rawRow["LName"].ToString(); row["FName"] = rawRow["FName"].ToString(); ContactMethod contmeth = PIn.Enum <ContactMethod>(rawRow["PreferRecallMethod"].ToString()); switch (contmeth) { case ContactMethod.None: if (PrefC.GetBool(PrefName.RecallUseEmailIfHasEmailAddress) && !string.IsNullOrEmpty(rawRow["Email"].ToString())) { row["contactMethod"] = rawRow["Email"].ToString(); } else { row["contactMethod"] = Lans.g("FormRecallList", "Hm:") + rawRow["HmPhone"].ToString(); } break; case ContactMethod.HmPhone: row["contactMethod"] = Lans.g("FormRecallList", "Hm:") + rawRow["HmPhone"].ToString(); break; case ContactMethod.WkPhone: row["contactMethod"] = Lans.g("FormRecallList", "Wk:") + rawRow["WkPhone"].ToString(); break; case ContactMethod.WirelessPh: row["contactMethod"] = Lans.g("FormRecallList", "Cell:") + rawRow["WirelessPhone"].ToString(); break; case ContactMethod.Email: row["contactMethod"] = rawRow["Email"].ToString(); break; case ContactMethod.Mail: case ContactMethod.DoNotCall: case ContactMethod.SeeNotes: row["contactMethod"] = Lans.g("enumContactMethod", contmeth.ToString()); break; } row["address"] = rawRow["Address"].ToString() + (string.IsNullOrEmpty(rawRow["Address2"].ToString())?"":("\r\n" + rawRow["Address2"].ToString())); row["City"] = rawRow["City"].ToString(); row["State"] = rawRow["State"].ToString(); row["Zip"] = rawRow["Zip"].ToString(); row["annualMaxInd"] = patAnnualMax.ToString("N"); row["annualMaxFam"] = famAnnualMax.ToString("N"); row["amountUsedInd"] = patAmtUsed.ToString("N"); row["amountUsedFam"] = famAmtUsed.ToString("N"); row["amountPendingInd"] = patAmtPending.ToString("N"); row["amountPendingFam"] = famAmtPending.ToString("N"); row["amountRemainingInd"] = (patAnnualMax - patAmtUsed - patAmtPending).ToString("N"); row["amountRemainingFam"] = (famAnnualMax - famAmtUsed - famAmtPending).ToString("N"); row["treatmentPlan"] = amtPlanned.ToString("N"); row["carrierName"] = rawRow["carrierName"].ToString(); if (PrefC.HasClinicsEnabled) { row["clinicAbbr"] = rawRow["clinicAbbr"].ToString(); } table.Rows.Add(row); } } if (ODBuild.IsDebug()) { sw.Stop(); sTotal.Stop(); Console.WriteLine("Finished Filling DataTable: {0}\r\n\tTotal time: {1}\r\n\tRows: {2}", (sw.Elapsed.Minutes > 0?(sw.Elapsed.Minutes + " min "):"") + (sw.Elapsed.TotalSeconds - sw.Elapsed.Minutes * 60) + " sec", (sTotal.Elapsed.Minutes > 0?(sTotal.Elapsed.Minutes + " min "):"") + (sTotal.Elapsed.TotalSeconds - sTotal.Elapsed.Minutes * 60) + " sec", table.Rows.Count); } return(table); }
public static List <DisplayField> GetAllAvailableList(DisplayFieldCategory category) { //No need to check RemotingRole; no call to db. List <DisplayField> list = new List <DisplayField>(); if (category == DisplayFieldCategory.None) //Currently only used for ChartViews { list.Add(new DisplayField("Date", 67, category)); list.Add(new DisplayField("Time", 40, category)); list.Add(new DisplayField("Th", 27, category)); list.Add(new DisplayField("Surf", 40, category)); list.Add(new DisplayField("Dx", 28, category)); list.Add(new DisplayField("Description", 218, category)); list.Add(new DisplayField("Stat", 25, category)); list.Add(new DisplayField("Prov", 42, category)); list.Add(new DisplayField("Amount", 48, category)); list.Add(new DisplayField("ADA Code", 62, category)); list.Add(new DisplayField("User", 62, category)); list.Add(new DisplayField("Signed", 55, category)); list.Add(new DisplayField("Priority", 44, category)); list.Add(new DisplayField("Date TP", 67, category)); list.Add(new DisplayField("Date Entry", 67, category)); list.Add(new DisplayField("Prognosis", 60, category)); list.Add(new DisplayField("Length", 40, category)); list.Add(new DisplayField("Abbr", 50, category)); list.Add(new DisplayField("Locked", 50, category)); if (Programs.UsingOrion) { list.Add(new DisplayField("DPC", 33, category)); list.Add(new DisplayField("Schedule By", 72, category)); list.Add(new DisplayField("Stop Clock", 67, category)); list.Add(new DisplayField("Stat 2", 36, category)); list.Add(new DisplayField("On Call", 45, category)); list.Add(new DisplayField("Effective Comm", 90, category)); list.Add(new DisplayField("End Time", 56, category)); //not visible unless orion list.Add(new DisplayField("Quadrant", 55, category)); //behavior is specific to orion list.Add(new DisplayField("DPCpost", 52, category)); } } else if (category == DisplayFieldCategory.PatientSelect) { list.Add(new DisplayField("LastName", 75, category)); list.Add(new DisplayField("First Name", 75, category)); list.Add(new DisplayField("MI", 25, category)); list.Add(new DisplayField("Pref Name", 60, category)); list.Add(new DisplayField("Age", 30, category)); list.Add(new DisplayField("SSN", 65, category)); list.Add(new DisplayField("Hm Phone", 90, category)); list.Add(new DisplayField("Wk Phone", 90, category)); if (PrefC.GetBool(PrefName.DistributorKey)) //if for OD HQ { list.Add(new DisplayField("OtherPhone", 90, category)); } list.Add(new DisplayField("PatNum", 80, category)); list.Add(new DisplayField("ChartNum", 60, category)); list.Add(new DisplayField("Address", 100, category)); list.Add(new DisplayField("Status", 65, category)); list.Add(new DisplayField("Bill Type", 90, category)); list.Add(new DisplayField("City", 80, category)); list.Add(new DisplayField("State", 55, category)); list.Add(new DisplayField("Pri Prov", 85, category)); list.Add(new DisplayField("Birthdate", 70, category)); list.Add(new DisplayField("Site", 90, category)); list.Add(new DisplayField("Email", 90, category)); } else if (category == DisplayFieldCategory.PatientInformation) { list.Add(new DisplayField("Last", 0, category)); list.Add(new DisplayField("First", 0, category)); list.Add(new DisplayField("Middle", 0, category)); list.Add(new DisplayField("Preferred", 0, category)); list.Add(new DisplayField("Title", 0, category)); list.Add(new DisplayField("Salutation", 0, category)); list.Add(new DisplayField("Status", 0, category)); list.Add(new DisplayField("Gender", 0, category)); list.Add(new DisplayField("Position", 0, category)); list.Add(new DisplayField("Birthdate", 0, category)); list.Add(new DisplayField("Age", 0, category)); list.Add(new DisplayField("SS#", 0, category)); list.Add(new DisplayField("Address", 0, category)); list.Add(new DisplayField("Address2", 0, category)); list.Add(new DisplayField("City", 0, category)); list.Add(new DisplayField("State", 0, category)); if (PrefC.GetBool(PrefName.DockPhonePanelShow)) { list.Add(new DisplayField("Country", 0, category)); } list.Add(new DisplayField("Zip", 0, category)); list.Add(new DisplayField("Hm Phone", 0, category)); list.Add(new DisplayField("Wk Phone", 0, category)); list.Add(new DisplayField("Wireless Ph", 0, category)); list.Add(new DisplayField("E-mail", 0, category)); list.Add(new DisplayField("Contact Method", 0, category)); list.Add(new DisplayField("ABC0", 0, category)); list.Add(new DisplayField("Chart Num", 0, category)); list.Add(new DisplayField("Billing Type", 0, category)); list.Add(new DisplayField("Ward", 0, category)); list.Add(new DisplayField("AdmitDate", 0, category)); list.Add(new DisplayField("Primary Provider", 0, category)); list.Add(new DisplayField("Sec. Provider", 0, category)); list.Add(new DisplayField("Payor Types", 0, category)); list.Add(new DisplayField("Language", 0, category)); list.Add(new DisplayField("Clinic", 0, category)); list.Add(new DisplayField("ResponsParty", 0, category)); list.Add(new DisplayField("Referrals", 0, category)); list.Add(new DisplayField("Addr/Ph Note", 0, category)); list.Add(new DisplayField("PatFields", 0, category)); list.Add(new DisplayField("Guardians", 0, category)); list.Add(new DisplayField("Arrive Early", 0, category)); list.Add(new DisplayField("Super Head", 0, category)); if (PrefC.GetBool(PrefName.DistributorKey)) { list.Add(new DisplayField("References", 0, category)); } } else if (category == DisplayFieldCategory.AccountModule) { list.Add(new DisplayField("Date", 65, category)); list.Add(new DisplayField("Patient", 100, category)); list.Add(new DisplayField("Prov", 40, category)); list.Add(new DisplayField("Clinic", 50, category)); list.Add(new DisplayField("Code", 46, category)); list.Add(new DisplayField("Tth", 26, category)); list.Add(new DisplayField("Description", 270, category)); list.Add(new DisplayField("Charges", 60, category)); list.Add(new DisplayField("Credits", 60, category)); list.Add(new DisplayField("Balance", 60, category)); } else if (category == DisplayFieldCategory.RecallList) { list.Add(new DisplayField("Due Date", 75, category)); list.Add(new DisplayField("Patient", 120, category)); list.Add(new DisplayField("Age", 30, category)); list.Add(new DisplayField("Type", 60, category)); list.Add(new DisplayField("Interval", 50, category)); list.Add(new DisplayField("#Remind", 55, category)); list.Add(new DisplayField("LastRemind", 75, category)); list.Add(new DisplayField("Contact", 120, category)); list.Add(new DisplayField("Status", 130, category)); list.Add(new DisplayField("Note", 215, category)); list.Add(new DisplayField("BillingType", 100, category)); } else if (category == DisplayFieldCategory.ChartPatientInformation) { list.Add(new DisplayField("Age", 0, category)); list.Add(new DisplayField("ABC0", 0, category)); list.Add(new DisplayField("Billing Type", 0, category)); list.Add(new DisplayField("Referred From", 0, category)); list.Add(new DisplayField("Date First Visit", 0, category)); list.Add(new DisplayField("Prov. (Pri, Sec)", 0, category)); list.Add(new DisplayField("Pri Ins", 0, category)); list.Add(new DisplayField("Sec Ins", 0, category)); list.Add(new DisplayField("Payor Types", 0, category)); if (PrefC.GetBool(PrefName.DistributorKey)) { list.Add(new DisplayField("Registration Keys", 0, category)); list.Add(new DisplayField("Ehr Provider Keys", 0, category)); list.Add(new DisplayField("References", 0, category)); } list.Add(new DisplayField("Premedicate", 0, category)); list.Add(new DisplayField("Problems", 0, category)); list.Add(new DisplayField("Med Urgent", 0, category)); list.Add(new DisplayField("Medical Summary", 0, category)); list.Add(new DisplayField("Service Notes", 0, category)); list.Add(new DisplayField("Medications", 0, category)); list.Add(new DisplayField("Allergies", 0, category)); list.Add(new DisplayField("PatFields", 0, category)); list.Add(new DisplayField("Birthdate", 0, category)); list.Add(new DisplayField("City", 0, category)); list.Add(new DisplayField("AskToArriveEarly", 0, category)); list.Add(new DisplayField("Super Head", 0, category)); list.Add(new DisplayField("Patient Portal", 0, category)); } else if (category == DisplayFieldCategory.ProcedureGroupNote) { list.Add(new DisplayField("Date", 67, category)); list.Add(new DisplayField("Th", 27, category)); list.Add(new DisplayField("Surf", 40, category)); list.Add(new DisplayField("Description", 218, category)); list.Add(new DisplayField("Stat", 25, category)); list.Add(new DisplayField("Prov", 42, category)); list.Add(new DisplayField("Amount", 48, category)); list.Add(new DisplayField("ADA Code", 62, category)); if (Programs.UsingOrion) { list.Add(new DisplayField("Stat 2", 36, category)); list.Add(new DisplayField("On Call", 45, category)); list.Add(new DisplayField("Effective Comm", 90, category)); list.Add(new DisplayField("Repair", 45, category)); list.Add(new DisplayField("DPCpost", 52, category)); } } else if (category == DisplayFieldCategory.TreatmentPlanModule) { list.Add(new DisplayField("Done", 50, category)); list.Add(new DisplayField("Priority", 50, category)); list.Add(new DisplayField("Tth", 40, category)); list.Add(new DisplayField("Surf", 45, category)); list.Add(new DisplayField("Code", 50, category)); list.Add(new DisplayField("Description", 235, category)); list.Add(new DisplayField("Fee", 50, category)); list.Add(new DisplayField("Pri Ins", 50, category)); list.Add(new DisplayField("Sec Ins", 50, category)); list.Add(new DisplayField("Discount", 55, category)); list.Add(new DisplayField("Pat", 50, category)); list.Add(new DisplayField("Prognosis", 60, category)); list.Add(new DisplayField("Dx", 28, category)); } else if (category == DisplayFieldCategory.OrthoChart) { list = GetForCategory(DisplayFieldCategory.OrthoChart); //The display fields that the user has already saved List <OrthoChart> listDistinctOrthoCharts = OrthoCharts.GetByDistinctFieldNames(); for (int i = 0; i < listDistinctOrthoCharts.Count; i++) { bool addToList = true; for (int j = 0; j < list.Count; j++) { if (list[j].Description == listDistinctOrthoCharts[i].FieldName) { addToList = false; } } if (addToList) { DisplayField df = new DisplayField("", 20, DisplayFieldCategory.OrthoChart); df.Description = listDistinctOrthoCharts[i].FieldName; list.Add(df); } } } return(list); }
///<summary>For orderBy, use 0 for BillingType and 1 for PatientName.</summary> public static DataTable GetBilling(bool isSent, int orderBy, DateTime dateFrom, DateTime dateTo, long clinicNum) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), isSent, orderBy, dateFrom, dateTo, clinicNum)); } DataTable table = new DataTable(); DataRow row; //columns that start with lowercase are altered for display rather than being raw data. table.Columns.Add("amountDue"); table.Columns.Add("balTotal"); table.Columns.Add("billingType"); table.Columns.Add("insEst"); table.Columns.Add("IsSent"); table.Columns.Add("lastStatement"); table.Columns.Add("mode"); table.Columns.Add("name"); table.Columns.Add("PatNum"); table.Columns.Add("payPlanDue"); table.Columns.Add("StatementNum"); List <DataRow> rows = new List <DataRow>(); string command = "SELECT BalTotal,BillingType,FName,InsEst,statement.IsSent," + "IFNULL(MAX(s2.DateSent)," + POut.Date(DateTime.MinValue) + ") LastStatement," + "LName,MiddleI,statement.Mode_,PayPlanDue,Preferred," + "statement.PatNum,statement.StatementNum " + "FROM statement " + "LEFT JOIN patient ON statement.PatNum=patient.PatNum " + "LEFT JOIN statement s2 ON s2.PatNum=patient.PatNum " + "AND s2.IsSent=1 "; if (PrefC.GetBool(PrefName.BillingIgnoreInPerson)) { command += "AND s2.Mode_ !=1 "; } if (orderBy == 0) //BillingType { command += "LEFT JOIN definition ON patient.BillingType=definition.DefNum "; } command += "WHERE statement.IsSent=" + POut.Bool(isSent) + " "; //if(dateFrom.Year>1800){ command += "AND statement.DateSent>=" + POut.Date(dateFrom) + " "; //greater than midnight this morning //} //if(dateFrom.Year>1800){ command += "AND statement.DateSent<" + POut.Date(dateTo.AddDays(1)) + " "; //less than midnight tonight //} if (clinicNum > 0) { command += "AND patient.ClinicNum=" + clinicNum + " "; } command += "GROUP BY BalTotal,BillingType,FName,InsEst,statement.IsSent," + "LName,MiddleI,statement.Mode_,PayPlanDue,Preferred," + "statement.PatNum,statement.StatementNum "; if (orderBy == 0) //BillingType { command += "ORDER BY definition.ItemOrder,LName,FName,MiddleI,PayPlanDue"; } else { command += "ORDER BY LName,FName"; } DataTable rawTable = Db.GetTable(command); Patient pat; StatementMode mode; double balTotal; double insEst; double payPlanDue; DateTime lastStatement; for (int i = 0; i < rawTable.Rows.Count; i++) { row = table.NewRow(); balTotal = PIn.Double(rawTable.Rows[i]["BalTotal"].ToString()); insEst = PIn.Double(rawTable.Rows[i]["InsEst"].ToString()); payPlanDue = PIn.Double(rawTable.Rows[i]["PayPlanDue"].ToString()); row["amountDue"] = (balTotal - insEst).ToString("F"); row["balTotal"] = balTotal.ToString("F");; row["billingType"] = DefC.GetName(DefCat.BillingTypes, PIn.Long(rawTable.Rows[i]["BillingType"].ToString())); if (insEst == 0) { row["insEst"] = ""; } else { row["insEst"] = insEst.ToString("F"); } row["IsSent"] = rawTable.Rows[i]["IsSent"].ToString(); lastStatement = PIn.Date(rawTable.Rows[i]["LastStatement"].ToString()); if (lastStatement.Year < 1880) { row["lastStatement"] = ""; } else { row["lastStatement"] = lastStatement.ToShortDateString(); } mode = (StatementMode)PIn.Long(rawTable.Rows[i]["Mode_"].ToString()); row["mode"] = Lans.g("enumStatementMode", mode.ToString()); pat = new Patient(); pat.LName = rawTable.Rows[i]["LName"].ToString(); pat.FName = rawTable.Rows[i]["FName"].ToString(); pat.Preferred = rawTable.Rows[i]["Preferred"].ToString(); pat.MiddleI = rawTable.Rows[i]["MiddleI"].ToString(); row["name"] = pat.GetNameLF(); row["PatNum"] = rawTable.Rows[i]["PatNum"].ToString(); if (payPlanDue == 0) { row["payPlanDue"] = ""; } else { row["payPlanDue"] = payPlanDue.ToString("F"); } row["StatementNum"] = rawTable.Rows[i]["StatementNum"].ToString(); rows.Add(row); } for (int i = 0; i < rows.Count; i++) { table.Rows.Add(rows[i]); } return(table); }
public static List <DisplayField> GetDefaultList(DisplayFieldCategory category) { //No need to check RemotingRole; no call to db. List <DisplayField> list = new List <DisplayField>(); if (category == DisplayFieldCategory.None) { list.Add(new DisplayField("Date", 67, category)); //list.Add(new DisplayField("Time",40)); list.Add(new DisplayField("Th", 27, category)); list.Add(new DisplayField("Surf", 40, category)); list.Add(new DisplayField("Dx", 28, category)); list.Add(new DisplayField("Description", 218, category)); list.Add(new DisplayField("Stat", 25, category)); list.Add(new DisplayField("Prov", 42, category)); list.Add(new DisplayField("Amount", 48, category)); list.Add(new DisplayField("ADA Code", 62, category)); list.Add(new DisplayField("User", 62, category)); list.Add(new DisplayField("Signed", 55, category)); //list.Add(new DisplayField("Priority",65,category)); //list.Add(new DisplayField("Date TP",67,category)); //list.Add(new DisplayField("Date Entry",67,category)); //list.Add(new DisplayField("Prognosis",60,category)); //list.Add(new DisplayField("Length",40,category)); //list.Add(new DisplayField("Abbr",50,category)); //list.Add(new DisplayField("Locked",50,category)); //if(Programs.UsingOrion){ //list.Add(new DisplayField("DPC",33,category)); //list.Add(new DisplayField("Schedule By",72,category)); //list.Add(new DisplayField("Stop Clock",67,category)); //list.Add(new DisplayField("Stat 2",36,category)); //list.Add(new DisplayField("On Call",45,category)); //list.Add(new DisplayField("Effective Comm",90,category)); //list.Add(new DisplayField("End Time",56,category)); //list.Add(new DisplayField("Quadrant",55,category)); //list.Add(new DisplayField("DPCpost",52,category)); //} } else if (category == DisplayFieldCategory.PatientSelect) { list.Add(new DisplayField("LastName", 75, category)); list.Add(new DisplayField("First Name", 75, category)); //list.Add(new DisplayField("MI",25,category)); list.Add(new DisplayField("Pref Name", 60, category)); list.Add(new DisplayField("Age", 30, category)); list.Add(new DisplayField("SSN", 65, category)); list.Add(new DisplayField("Hm Phone", 90, category)); list.Add(new DisplayField("Wk Phone", 90, category)); if (PrefC.GetBool(PrefName.DistributorKey)) //if for OD HQ //list.Add(new DisplayField("OtherPhone",90,category)); { } list.Add(new DisplayField("PatNum", 80, category)); //list.Add(new DisplayField("ChartNum",60,category)); list.Add(new DisplayField("Address", 100, category)); list.Add(new DisplayField("Status", 65, category)); //list.Add(new DisplayField("Bill Type",90,category)); //list.Add(new DisplayField("City",80,category)); //list.Add(new DisplayField("State",55,category)); //list.Add(new DisplayField("Pri Prov",85,category)); //list.Add(new DisplayField("Birthdate",70,category)); //list.Add(new DisplayField("Site",90,category)); //list.Add(new DisplayField("Email",90,category)); } else if (category == DisplayFieldCategory.PatientInformation) { list.Add(new DisplayField("Last", 0, category)); list.Add(new DisplayField("First", 0, category)); list.Add(new DisplayField("Middle", 0, category)); list.Add(new DisplayField("Preferred", 0, category)); list.Add(new DisplayField("Title", 0, category)); list.Add(new DisplayField("Salutation", 0, category)); list.Add(new DisplayField("Status", 0, category)); list.Add(new DisplayField("Gender", 0, category)); list.Add(new DisplayField("Position", 0, category)); list.Add(new DisplayField("Birthdate", 0, category)); list.Add(new DisplayField("Age", 0, category)); list.Add(new DisplayField("SS#", 0, category)); list.Add(new DisplayField("Address", 0, category)); list.Add(new DisplayField("Address2", 0, category)); list.Add(new DisplayField("City", 0, category)); list.Add(new DisplayField("State", 0, category)); if (PrefC.GetBool(PrefName.DockPhonePanelShow)) { list.Add(new DisplayField("Country", 0, category)); } list.Add(new DisplayField("Zip", 0, category)); list.Add(new DisplayField("Hm Phone", 0, category)); list.Add(new DisplayField("Wk Phone", 0, category)); list.Add(new DisplayField("Wireless Ph", 0, category)); list.Add(new DisplayField("E-mail", 0, category)); list.Add(new DisplayField("Contact Method", 0, category)); list.Add(new DisplayField("ABC0", 0, category)); //list.Add(new DisplayField("Chart Num",0,category)); list.Add(new DisplayField("Billing Type", 0, category)); //list.Add(new DisplayField("Ward",0,category)); //list.Add(new DisplayField("AdmitDate",0,category)); list.Add(new DisplayField("Primary Provider", 0, category)); list.Add(new DisplayField("Sec. Provider", 0, category)); list.Add(new DisplayField("Payor Types", 0, category)); list.Add(new DisplayField("Language", 0, category)); //list.Add(new DisplayField("Clinic",0,category)); //list.Add(new DisplayField("ResponsParty",0,category)); list.Add(new DisplayField("Referrals", 0, category)); list.Add(new DisplayField("Addr/Ph Note", 0, category)); list.Add(new DisplayField("PatFields", 0, category)); //list.Add(new DisplayField("Guardians",0,category)); //list.Add(new DisplayField("Arrive Early",0,category)); //list.Add(new DisplayField("Super Head",0,category)); if (PrefC.GetBool(PrefName.DistributorKey)) { list.Add(new DisplayField("References", 0, category)); } } else if (category == DisplayFieldCategory.AccountModule) { list.Add(new DisplayField("Date", 65, category)); list.Add(new DisplayField("Patient", 100, category)); list.Add(new DisplayField("Prov", 40, category)); //list.Add(new DisplayField("Clinic",50,category)); list.Add(new DisplayField("Code", 46, category)); list.Add(new DisplayField("Tth", 26, category)); list.Add(new DisplayField("Description", 270, category)); list.Add(new DisplayField("Charges", 60, category)); list.Add(new DisplayField("Credits", 60, category)); list.Add(new DisplayField("Balance", 60, category)); } else if (category == DisplayFieldCategory.RecallList) { list.Add(new DisplayField("Due Date", 75, category)); list.Add(new DisplayField("Patient", 120, category)); list.Add(new DisplayField("Age", 30, category)); list.Add(new DisplayField("Type", 60, category)); list.Add(new DisplayField("Interval", 50, category)); list.Add(new DisplayField("#Remind", 55, category)); list.Add(new DisplayField("LastRemind", 75, category)); list.Add(new DisplayField("Contact", 120, category)); list.Add(new DisplayField("Status", 130, category)); list.Add(new DisplayField("Note", 215, category)); //list.Add(new DisplayField("BillingType",100,category)); } else if (category == DisplayFieldCategory.ChartPatientInformation) { list.Add(new DisplayField("Age", 0, category)); list.Add(new DisplayField("ABC0", 0, category)); list.Add(new DisplayField("Billing Type", 0, category)); list.Add(new DisplayField("Referred From", 0, category)); list.Add(new DisplayField("Date First Visit", 0, category)); list.Add(new DisplayField("Prov. (Pri, Sec)", 0, category)); list.Add(new DisplayField("Pri Ins", 0, category)); list.Add(new DisplayField("Sec Ins", 0, category)); list.Add(new DisplayField("Payor Types", 0, category)); if (PrefC.GetBool(PrefName.DistributorKey)) { list.Add(new DisplayField("Registration Keys", 0, category)); list.Add(new DisplayField("Ehr Provider Keys", 0, category)); list.Add(new DisplayField("References", 0, category)); } //different default list for eCW: if (!Programs.UsingEcwTightOrFullMode()) { list.Add(new DisplayField("Premedicate", 0, category)); list.Add(new DisplayField("Problems", 0, category)); list.Add(new DisplayField("Med Urgent", 0, category)); list.Add(new DisplayField("Medical Summary", 0, category)); list.Add(new DisplayField("Service Notes", 0, category)); list.Add(new DisplayField("Medications", 0, category)); list.Add(new DisplayField("Allergies", 0, category)); } //list.Add(new DisplayField("PatFields",0,category)); //list.Add(new DisplayField("Birthdate",0,category)); //list.Add(new DisplayField("City",0,category)); //list.Add(new DisplayField("AskToArriveEarly",0,category)); //list.Add(new DisplayField("Super Head",0,category)); //list.Add(new DisplayField("Patient Portal",0,category)); } else if (category == DisplayFieldCategory.ProcedureGroupNote) { list.Add(new DisplayField("Date", 67, category)); list.Add(new DisplayField("Th", 27, category)); list.Add(new DisplayField("Surf", 40, category)); list.Add(new DisplayField("Description", 203, category)); list.Add(new DisplayField("Stat", 25, category)); list.Add(new DisplayField("Prov", 42, category)); list.Add(new DisplayField("Amount", 48, category)); list.Add(new DisplayField("ADA Code", 62, category)); //if(Programs.UsingOrion){ // list.Add(new DisplayField("Stat 2",36,category)); // list.Add(new DisplayField("On Call",45,category)); // list.Add(new DisplayField("Effective Comm",90,category)); // list.Add(new DisplayField("Repair",45,category)); // list.Add(new DisplayField("DPCpost",52,category)); //} } else if (category == DisplayFieldCategory.TreatmentPlanModule) { list.Add(new DisplayField("Done", 50, category)); list.Add(new DisplayField("Priority", 50, category)); list.Add(new DisplayField("Tth", 40, category)); list.Add(new DisplayField("Surf", 45, category)); list.Add(new DisplayField("Code", 50, category)); list.Add(new DisplayField("Description", 235, category)); list.Add(new DisplayField("Fee", 50, category)); list.Add(new DisplayField("Pri Ins", 50, category)); list.Add(new DisplayField("Sec Ins", 50, category)); list.Add(new DisplayField("Discount", 55, category)); list.Add(new DisplayField("Pat", 50, category)); //list.Add(new DisplayField("Prognosis",60,category)); //list.Add(new DisplayField("Dx",28,category)); } else if (category == DisplayFieldCategory.OrthoChart) { //Ortho chart has no default columns. User must explicitly set up columns. } return(list); }
/// <summary>Only Called only from FormPayment.butOK click. Only called if the user did not enter any splits. Usually just adds one split for the current patient. But if that would take the balance negative, then it loops through all other family members and creates splits for them. It might still take the current patient negative once all other family members are zeroed out.</summary> public static List <PaySplit> Allocate(Payment pay) //double amtTot,int patNum,Payment payNum){ { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <PaySplit> >(MethodBase.GetCurrentMethod(), pay)); } string command = "SELECT Guarantor FROM patient " + "WHERE PatNum = " + POut.Long(pay.PatNum); DataTable table = Db.GetTable(command); if (table.Rows.Count == 0) { return(new List <PaySplit>()); } command = "SELECT patient.PatNum,EstBalance,PriProv,SUM(InsPayEst)+SUM(Writeoff) insEst_ " + "FROM patient " + "LEFT JOIN claimproc ON patient.PatNum=claimproc.PatNum " + "AND Status=0 " //NotReceived + "WHERE Guarantor = " + table.Rows[0][0].ToString() + " " + "GROUP BY patient.PatNum,EstBalance,PriProv"; //+" ORDER BY PatNum!="+POut.PInt(pay.PatNum);//puts current patient in position 0 //Oracle does not allow table = Db.GetTable(command); List <Patient> pats = new List <Patient>(); Patient pat; //first, put the current patient at position 0. for (int i = 0; i < table.Rows.Count; i++) { if (table.Rows[i]["PatNum"].ToString() == pay.PatNum.ToString()) { pat = new Patient(); pat.PatNum = PIn.Long(table.Rows[i][0].ToString()); pat.EstBalance = PIn.Double(table.Rows[i][1].ToString()); if (!PrefC.GetBool(PrefName.BalancesDontSubtractIns)) { pat.EstBalance -= PIn.Double(table.Rows[i]["insEst_"].ToString()); } pat.PriProv = PIn.Long(table.Rows[i][2].ToString()); pats.Add(pat.Copy()); } } //then, do all the rest of the patients. for (int i = 0; i < table.Rows.Count; i++) { if (table.Rows[i]["PatNum"].ToString() == pay.PatNum.ToString()) { continue; } pat = new Patient(); pat.PatNum = PIn.Long(table.Rows[i][0].ToString()); pat.EstBalance = PIn.Double(table.Rows[i][1].ToString()); if (!PrefC.GetBool(PrefName.BalancesDontSubtractIns)) { pat.EstBalance -= PIn.Double(table.Rows[i]["insEst_"].ToString()); } pat.PriProv = PIn.Long(table.Rows[i][2].ToString()); pats.Add(pat.Copy()); } //first calculate all the amounts double amtRemain = pay.PayAmt; //start off with the full amount double[] amtSplits = new double[pats.Count]; //loop through each family member, starting with current for (int i = 0; i < pats.Count; i++) { if (pats[i].EstBalance == 0 || pats[i].EstBalance < 0) { continue; //don't apply paysplits to anyone with a negative balance } if (amtRemain < pats[i].EstBalance) //entire remainder can be allocated to this patient { amtSplits[i] = amtRemain; amtRemain = 0; break; } else //amount remaining is more than or equal to the estBal for this family member { amtSplits[i] = pats[i].EstBalance; amtRemain -= pats[i].EstBalance; } } //add any remainder to the split for this patient amtSplits[0] += amtRemain; //now create a split for each non-zero amount PaySplit PaySplitCur; List <PaySplit> retVal = new List <PaySplit>(); for (int i = 0; i < pats.Count; i++) { if (amtSplits[i] == 0) { continue; } PaySplitCur = new PaySplit(); PaySplitCur.PatNum = pats[i].PatNum; PaySplitCur.PayNum = pay.PayNum; PaySplitCur.DatePay = pay.PayDate; PaySplitCur.ClinicNum = pay.ClinicNum; PaySplitCur.ProvNum = Patients.GetProvNum(pats[i]); PaySplitCur.SplitAmt = Math.Round(amtSplits[i], CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalDigits); //PaySplitCur.InsertOrUpdate(true); retVal.Add(PaySplitCur); } //finally, adjust each EstBalance, but no need to do current patient //This no longer works here. Must do it when closing payment window somehow /*for(int i=1;i<pats.Length;i++){ * if(amtSplits[i]==0){ * continue; * } * command="UPDATE patient SET EstBalance=EstBalance-"+POut.PDouble(amtSplits[i]) +" WHERE PatNum="+POut.PInt(pats[i].PatNum); * Db.NonQ(command); * }*/ return(retVal); }
///<summary>Returns a SerializableDictionary with key=PatNum, value=PatAgingData with the filters applied.</summary> public static SerializableDictionary <long, PatAgingData> GetAgingData(bool isSinglePatient, bool includeChanged, bool excludeInsPending, bool excludeIfUnsentProcs, bool isSuperBills, List <long> listClinicNums) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <SerializableDictionary <long, PatAgingData> >(MethodBase.GetCurrentMethod(), isSinglePatient, includeChanged, excludeInsPending, excludeIfUnsentProcs, isSuperBills, listClinicNums)); } SerializableDictionary <long, PatAgingData> dictPatAgingData = new SerializableDictionary <long, PatAgingData>(); string command = ""; string guarOrPat = "guar"; if (isSinglePatient) { guarOrPat = "patient"; } string whereAndClinNum = ""; if (!listClinicNums.IsNullOrEmpty()) { whereAndClinNum = $@"AND {guarOrPat}.ClinicNum IN ({string.Join(",",listClinicNums)})"; } if (includeChanged || excludeIfUnsentProcs) { command = $@"SELECT {guarOrPat}.PatNum,{guarOrPat}.ClinicNum,MAX(procedurelog.ProcDate) MaxProcDate"; if (excludeIfUnsentProcs) { command += ",MAX(CASE WHEN insplan.IsMedical=1 THEN 0 ELSE COALESCE(claimproc.ProcNum,0) END)>0 HasUnsentProcs"; } command += $@" FROM patient INNER JOIN patient guar ON guar.PatNum=patient.Guarantor INNER JOIN procedurelog ON procedurelog.PatNum = patient.PatNum " ; if (excludeIfUnsentProcs) { command += $@"LEFT JOIN claimproc ON claimproc.ProcNum = procedurelog.ProcNum AND claimproc.NoBillIns=0 AND claimproc.Status = {POut.Int((int)ClaimProcStatus.Estimate)} AND procedurelog.ProcDate > CURDATE()-INTERVAL 6 MONTH LEFT JOIN insplan ON insplan.PlanNum=claimproc.PlanNum " ; } command += $@"WHERE procedurelog.ProcFee > 0 AND procedurelog.ProcStatus = {POut.Int((int)ProcStat.C)} {whereAndClinNum} GROUP BY {guarOrPat}.PatNum ORDER BY NULL" ; using (DataTable tableChangedAndUnsent = Db.GetTable(command)) { foreach (DataRow row in tableChangedAndUnsent.Rows) { long patNum = PIn.Long(row["PatNum"].ToString()); if (!dictPatAgingData.ContainsKey(patNum)) { dictPatAgingData[patNum] = new PatAgingData(PIn.Long(row["ClinicNum"].ToString())); } if (includeChanged) { dictPatAgingData[patNum].ListPatAgingTransactions .Add(new PatAgingTransaction(PatAgingTransaction.TransactionTypes.Procedure, PIn.Date(row["MaxProcDate"].ToString()))); } if (excludeIfUnsentProcs) { dictPatAgingData[patNum].HasUnsentProcs = PIn.Bool(row["HasUnsentProcs"].ToString()); } } } } if (includeChanged) { command = $@"SELECT {guarOrPat}.PatNum,{guarOrPat}.ClinicNum,MAX(claimproc.DateCP) maxDateCP FROM claimproc INNER JOIN patient ON patient.PatNum = claimproc.PatNum INNER JOIN patient guar ON guar.PatNum=patient.Guarantor WHERE claimproc.InsPayAmt > 0 {whereAndClinNum} GROUP BY {guarOrPat}.PatNum" ; using (DataTable tableMaxPayDate = Db.GetTable(command)) { foreach (DataRow row in tableMaxPayDate.Rows) { long patNum = PIn.Long(row["PatNum"].ToString()); if (!dictPatAgingData.ContainsKey(patNum)) { dictPatAgingData[patNum] = new PatAgingData(PIn.Long(row["ClinicNum"].ToString())); } dictPatAgingData[patNum].ListPatAgingTransactions .Add(new PatAgingTransaction(PatAgingTransaction.TransactionTypes.ClaimProc, PIn.Date(row["maxDateCP"].ToString()))); } } command = $@"SELECT {guarOrPat}.PatNum,{guarOrPat}.ClinicNum,MAX(payplancharge.ChargeDate) maxDatePPC, MAX(payplancharge.SecDateTEntry) maxDatePPCSDTE FROM payplancharge INNER JOIN patient ON patient.PatNum = payplancharge.PatNum INNER JOIN patient guar ON guar.PatNum=patient.Guarantor INNER JOIN payplan ON payplan.PayPlanNum = payplancharge.PayPlanNum AND payplan.PlanNum = 0 " //don't want insurance payment plans to make patients appear in the billing list + $@"WHERE payplancharge.Principal + payplancharge.Interest>0 AND payplancharge.ChargeType = {(int)PayPlanChargeType.Debit} " //include all charges in the past or due 'PayPlanBillInAdvance' days into the future. + $@"AND payplancharge.ChargeDate <= {POut.Date(DateTime.Today.AddDays(PrefC.GetDouble(PrefName.PayPlansBillInAdvanceDays)))} {whereAndClinNum} GROUP BY {guarOrPat}.PatNum" ; using (DataTable tableMaxPPCDate = Db.GetTable(command)) { foreach (DataRow row in tableMaxPPCDate.Rows) { long patNum = PIn.Long(row["PatNum"].ToString()); if (!dictPatAgingData.ContainsKey(patNum)) { dictPatAgingData[patNum] = new PatAgingData(PIn.Long(row["ClinicNum"].ToString())); } dictPatAgingData[patNum].ListPatAgingTransactions .Add(new PatAgingTransaction( PatAgingTransaction.TransactionTypes.PayPlanCharge, PIn.Date(row["maxDatePPC"].ToString()), secDateTEntryTrans: PIn.Date(row["maxDatePPCSDTE"].ToString())) ); } } } if (excludeInsPending) { command = $@"SELECT {guarOrPat}.PatNum,{guarOrPat}.ClinicNum FROM claim INNER JOIN patient ON patient.PatNum=claim.PatNum INNER JOIN patient guar ON guar.PatNum=patient.Guarantor WHERE claim.ClaimStatus IN ('U','H','W','S') AND claim.ClaimType IN ('P','S','Other') {whereAndClinNum} GROUP BY {guarOrPat}.PatNum" ; using (DataTable tableInsPending = Db.GetTable(command)) { foreach (DataRow row in tableInsPending.Rows) { long patNum = PIn.Long(row["PatNum"].ToString()); if (!dictPatAgingData.ContainsKey(patNum)) { dictPatAgingData[patNum] = new PatAgingData(PIn.Long(row["ClinicNum"].ToString())); } dictPatAgingData[patNum].HasPendingIns = true; } } } DateTime dateAsOf = DateTime.Today; //used to determine when the balance on this date began if (PrefC.GetBool(PrefName.AgingCalculatedMonthlyInsteadOfDaily)) //if aging calculated monthly, use the last aging date instead of today { dateAsOf = PrefC.GetDate(PrefName.DateLastAging); } List <PatComm> listPatComms = new List <PatComm>(); using (DataTable tableDateBalsBegan = Ledgers.GetDateBalanceBegan(null, dateAsOf, isSuperBills, listClinicNums)) { foreach (DataRow row in tableDateBalsBegan.Rows) { long patNum = PIn.Long(row["PatNum"].ToString()); if (!dictPatAgingData.ContainsKey(patNum)) { dictPatAgingData[patNum] = new PatAgingData(PIn.Long(row["ClinicNum"].ToString())); } dictPatAgingData[patNum].DateBalBegan = PIn.Date(row["DateAccountAge"].ToString()); dictPatAgingData[patNum].DateBalZero = PIn.Date(row["DateZeroBal"].ToString()); } listPatComms = Patients.GetPatComms(tableDateBalsBegan.Select().Select(x => PIn.Long(x["PatNum"].ToString())).ToList(), null); } foreach (PatComm pComm in listPatComms) { if (!dictPatAgingData.ContainsKey(pComm.PatNum)) { dictPatAgingData[pComm.PatNum] = new PatAgingData(pComm.ClinicNum); } dictPatAgingData[pComm.PatNum].PatComm = pComm; } return(dictPatAgingData); }
public static DataTable GetPatientFormsTable(long patNum) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), patNum)); } //DataConnection dcon=new DataConnection(); DataTable table = new DataTable(""); DataRow row; //columns that start with lowercase are altered for display rather than being raw data. table.Columns.Add("date"); table.Columns.Add("dateOnly", typeof(DateTime)); //to help with sorting table.Columns.Add("dateTime", typeof(DateTime)); table.Columns.Add("description"); table.Columns.Add("DocNum"); table.Columns.Add("imageCat"); table.Columns.Add("SheetNum"); table.Columns.Add("showInTerminal"); table.Columns.Add("time"); table.Columns.Add("timeOnly", typeof(TimeSpan)); //to help with sorting //but we won't actually fill this table with rows until the very end. It's more useful to use a List<> for now. List <DataRow> rows = new List <DataRow>(); //sheet--------------------------------------------------------------------------------------- string command = "SELECT DateTimeSheet,SheetNum,Description,ShowInTerminal " + "FROM sheet WHERE IsDeleted=0 " + "AND PatNum =" + POut.Long(patNum) + " " + "AND (SheetType=" + POut.Long((int)SheetTypeEnum.PatientForm) + " OR SheetType=" + POut.Long((int)SheetTypeEnum.MedicalHistory); if (PrefC.GetBool(PrefName.PatientFormsShowConsent)) { command += " OR SheetType=" + POut.Long((int)SheetTypeEnum.Consent); //Show consent forms if pref is true. } command += ")"; //+"ORDER BY ShowInTerminal";//DATE(DateTimeSheet),ShowInTerminal,TIME(DateTimeSheet)"; DataTable rawSheet = Db.GetTable(command); DateTime dateT; for (int i = 0; i < rawSheet.Rows.Count; i++) { row = table.NewRow(); dateT = PIn.DateT(rawSheet.Rows[i]["DateTimeSheet"].ToString()); row["date"] = dateT.ToShortDateString(); row["dateOnly"] = dateT.Date; row["dateTime"] = dateT; row["description"] = rawSheet.Rows[i]["Description"].ToString(); row["DocNum"] = "0"; row["imageCat"] = ""; row["SheetNum"] = rawSheet.Rows[i]["SheetNum"].ToString(); if (rawSheet.Rows[i]["ShowInTerminal"].ToString() == "0") { row["showInTerminal"] = ""; } else { row["showInTerminal"] = rawSheet.Rows[i]["ShowInTerminal"].ToString(); } if (dateT.TimeOfDay != TimeSpan.Zero) { row["time"] = dateT.ToString("h:mm") + dateT.ToString("%t").ToLower(); } row["timeOnly"] = dateT.TimeOfDay; rows.Add(row); } //document--------------------------------------------------------------------------------------- command = "SELECT DateCreated,DocCategory,DocNum,Description " + "FROM document,definition " + "WHERE document.DocCategory=definition.DefNum" + " AND PatNum =" + POut.Long(patNum) + " AND definition.ItemValue LIKE '%F%'"; //+" ORDER BY DateCreated"; DataTable rawDoc = Db.GetTable(command); long docCat; for (int i = 0; i < rawDoc.Rows.Count; i++) { row = table.NewRow(); dateT = PIn.DateT(rawDoc.Rows[i]["DateCreated"].ToString()); row["date"] = dateT.ToShortDateString(); row["dateOnly"] = dateT.Date; row["dateTime"] = dateT; row["description"] = rawDoc.Rows[i]["Description"].ToString(); row["DocNum"] = rawDoc.Rows[i]["DocNum"].ToString(); docCat = PIn.Long(rawDoc.Rows[i]["DocCategory"].ToString()); row["imageCat"] = Defs.GetName(DefCat.ImageCats, docCat); row["SheetNum"] = "0"; row["showInTerminal"] = ""; if (dateT.TimeOfDay != TimeSpan.Zero) { row["time"] = dateT.ToString("h:mm") + dateT.ToString("%t").ToLower(); } row["timeOnly"] = dateT.TimeOfDay; rows.Add(row); } //Sorting for (int i = 0; i < rows.Count; i++) { table.Rows.Add(rows[i]); } DataView view = table.DefaultView; view.Sort = "dateOnly,showInTerminal,timeOnly"; table = view.ToTable(); return(table); }
///<summary>In progress. Probably needs a different name. Info must be validated first. ///Set dependent to the currently selected patient, compares dependent.PatNum to subscriber.PatNum to either contruct a subscriber based or dependent based benefit request.</summary> public static string GenerateMessageText(Clearinghouse clearinghouseClin, Carrier carrier, Provider billProv, Clinic clinic, InsPlan insPlan, Patient subscriber, InsSub insSub, Patient patForRequest) { bool isSubscriberRequest = (subscriber.PatNum == patForRequest.PatNum); int batchNum = Clearinghouses.GetNextBatchNumber(clearinghouseClin); string groupControlNumber = batchNum.ToString(); //Must be unique within file. We will use batchNum int transactionNum = 1; StringBuilder strb = new StringBuilder(); //Interchange Control Header strb.Append("ISA*00* *"); //ISA01,ISA02: 00 + 10 spaces if (IsEmdeonDental(clearinghouseClin)) { strb.Append("00*" + Sout(clearinghouseClin.Password, 10, 10) + "*" //ISA03,ISA04: 00 + emdeon password padded to 10 characters + clearinghouseClin.ISA05 + "*" //ISA05: Sender ID type: ZZ=mutually defined. 30=TIN. Validated + "316:" + Sout(clearinghouseClin.LoginID, 11, 11) + "*" //ISA06: Emdeon vendor number + username + clearinghouseClin.ISA07 + "*" //ISA07: Receiver ID type: ZZ=mutually defined. 30=TIN. Validated + Sout("EMDEONDENTAL", 15, 15) + "*"); //ISA08: Receiver ID. Validated to make sure length is at least 2. } else { strb.Append("00* *" //ISA03,ISA04: 00 + 10 spaces + clearinghouseClin.ISA05 + "*" //ISA05: Sender ID type: ZZ=mutually defined. 30=TIN. Validated + X12Generator.GetISA06(clearinghouseClin) + "*" //ISA06: Sender ID(TIN). Or might be TIN of Open Dental + clearinghouseClin.ISA07 + "*" //ISA07: Receiver ID type: ZZ=mutually defined. 30=TIN. Validated + Sout(clearinghouseClin.ISA08, 15, 15) + "*"); //ISA08: Receiver ID. Validated to make sure length is at least 2. } strb.AppendLine(DateTime.Today.ToString("yyMMdd") + "*" //ISA09: today's date + DateTime.Now.ToString("HHmm") + "*" //ISA10: current time + "U*00401*" //ISA11 and ISA12. //ISA13: interchange control number, right aligned: + batchNum.ToString().PadLeft(9, '0') + "*" + "0*" //ISA14: no acknowledgment requested + clearinghouseClin.ISA15 + "*" //ISA15: T=Test P=Production. Validated. + ":~"); //ISA16: use ':' //Functional Group Header if (IsEmdeonDental(clearinghouseClin)) { strb.Append("GS*HS*" //GS01: HS for 270 benefit inquiry + X12Generator.GetGS02(clearinghouseClin) + "*" //GS02: Senders Code. Sometimes Jordan Sparks. Sometimes the sending clinic. + Sout("EMDEONDENTAL", 15, 15) + "*"); //GS03: Application Receiver's Code } else { strb.Append("GS*HS*" //GS01: HS for 270 benefit inquiry + X12Generator.GetGS02(clearinghouseClin) + "*" //GS02: Senders Code. Sometimes Jordan Sparks. Sometimes the sending clinic. + Sout(clearinghouseClin.GS03, 15, 2) + "*"); //GS03: Application Receiver's Code } strb.AppendLine(DateTime.Today.ToString("yyyyMMdd") + "*" //GS04: today's date + DateTime.Now.ToString("HHmm") + "*" //GS05: current time + groupControlNumber + "*" //GS06: Group control number. Max length 9. No padding necessary. + "X*" //GS07: X + "004010X092~"); //GS08: Version //Beginning of transaction-------------------------------------------------------------------------------- int seg = 0; //count segments for the ST-SE transaction //Transaction Set Header //ST02 Transact. control #. Must be unique within ISA seg++; strb.AppendLine("ST*270*" //ST01 + transactionNum.ToString().PadLeft(4, '0') + "~"); //ST02 seg++; strb.AppendLine("BHT*0022*13*" //BHT02: 13=request + transactionNum.ToString().PadLeft(4, '0') + "*" //BHT03. Can be same as ST02 + DateTime.Now.ToString("yyyyMMdd") + "*" //BHT04: Date + DateTime.Now.ToString("HHmmss") + "~"); //BHT05: Time, BHT06: not used //HL Loops----------------------------------------------------------------------------------------------- int HLcount = 1; //2000A HL: Information Source-------------------------------------------------------------------------- seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. Here, it's always 1. + "*" //HL02: No parent. Not used + "20*" //HL03: Heirarchical level code. 20=Information source + "1~"); //HL04: Heirarchical child code. 1=child HL present //2100A NM1 seg++; strb.AppendLine("NM1*PR*" //NM101: PR=Payer + "2*" //NM102: 2=Non person + Sout(carrier.CarrierName, 35) + "*" //NM103: Name Last. + "****" //NM104-07 not used + "PI*" //NM108: PI=PayorID + Sout(carrier.ElectID, 80, 2) + "~"); //NM109: PayorID. Validated to be at least length of 2. HLcount++; //2000B HL: Information Receiver------------------------------------------------------------------------ seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. Here, it's always 2. + "1*" //HL02: Heirarchical parent id number. 1 in this simple message. + "21*" //HL03: Heirarchical level code. 21=Information receiver + "1~"); //HL04: Heirarchical child code. 1=child HL present seg++; //2100B NM1: Information Receiver Name strb.AppendLine("NM1*1P*" //NM101: 1P=Provider + (billProv.IsNotPerson?"2":"1") + "*" //NM102: 1=person,2=non-person + Sout(billProv.LName, 35) + "*" //NM103: Last name + Sout(billProv.FName, 25) + "*" //NM104: First name + Sout(billProv.MI, 25, 1) + "*" //NM105: Middle name + "*" //NM106: not used + "*" //NM107: Name suffix. not used + "XX*" //NM108: ID code qualifier. 24=EIN. 34=SSN, XX=NPI + Sout(billProv.NationalProvID, 80) + "~"); //NM109: ID code. NPI validated //2100B REF: Information Receiver ID if (IsEmdeonDental(clearinghouseClin) && IsDentiCalCarrier(carrier)) { string ref4aSegment = ""; Clearinghouse clearinghouseDentiCalHQ = Clearinghouses.GetFirstOrDefault(x => IsDentiCalClearinghouse(x), true); if (clearinghouseDentiCalHQ != null) { Clearinghouse clearinghouseDentiCalClin = Clearinghouses.OverrideFields(clearinghouseDentiCalHQ, clearinghouseClin.ClinicNum); if (clearinghouseDentiCalClin != null) { ref4aSegment = clearinghouseDentiCalClin.Password; } } seg++; strb.Append("REF*4A*" + ref4aSegment + "~"); } seg++; strb.Append("REF*"); if (billProv.UsingTIN) { strb.Append("TJ*"); //REF01: qualifier. TJ=Federal TIN } else //SSN { strb.Append("SY*"); //REF01: qualifier. SY=SSN } strb.AppendLine(Sout(billProv.SSN, 30) + "~"); //REF02: ID //2100B N3: Information Receiver Address seg++; if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { strb.Append("N3*" + Sout(PrefC.GetString(PrefName.PracticeBillingAddress), 55)); //N301: Address } else if (clinic == null) { strb.Append("N3*" + Sout(PrefC.GetString(PrefName.PracticeAddress), 55)); //N301: Address } else { strb.Append("N3*" + Sout(clinic.Address, 55)); //N301: Address } if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { if (PrefC.GetString(PrefName.PracticeBillingAddress2) == "") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*" + Sout(PrefC.GetString(PrefName.PracticeBillingAddress2), 55) + "~"); } } else if (clinic == null) { if (PrefC.GetString(PrefName.PracticeAddress2) == "") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*" + Sout(PrefC.GetString(PrefName.PracticeAddress2), 55) + "~"); } } else { if (clinic.Address2 == "") { strb.AppendLine("~"); } else { //N302: Address2. Optional. strb.AppendLine("*" + Sout(clinic.Address2, 55) + "~"); } } //2100B N4: Information Receiver City/State/Zip seg++; if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { strb.AppendLine("N4*" + Sout(PrefC.GetString(PrefName.PracticeBillingCity), 30) + "*" //N401: City + Sout(PrefC.GetString(PrefName.PracticeBillingST), 2) + "*" //N402: State + Sout(PrefC.GetString(PrefName.PracticeBillingZip).Replace("-", ""), 15) + "~"); //N403: Zip } else if (clinic == null) { strb.AppendLine("N4*" + Sout(PrefC.GetString(PrefName.PracticeCity), 30) + "*" //N401: City + Sout(PrefC.GetString(PrefName.PracticeST), 2) + "*" //N402: State + Sout(PrefC.GetString(PrefName.PracticeZip).Replace("-", ""), 15) + "~"); //N403: Zip } else { strb.AppendLine("N4*" + Sout(clinic.City, 30) + "*" //N401: City + Sout(clinic.State, 2) + "*" //N402: State + Sout(clinic.Zip.Replace("-", ""), 15) + "~"); //N403: Zip } //2100B PRV: Information Receiver Provider Info seg++; //PRV*PE*ZZ*1223G0001X~ strb.AppendLine("PRV*PE*" //PRV01: Provider Code. PE=Performing. There are many other choices. + "ZZ*" //PRV02: ZZ=Mutually defined = health care provider taxonomy code + X12Generator.GetTaxonomy(billProv) + "~"); //PRV03: Specialty code HLcount++; //2000C HL: Subscriber----------------------------------------------------------------------------------- seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. Here, it's always 3. + "2*" //HL02: Heirarchical parent id number. 2 in this simple message. + "22*" //HL03: Heirarchical level code. 22=Subscriber + (isSubscriberRequest?"0~":"1~")); //HL04: Heirarchical child code. 0=no child HL present (no dependent) else 1 //2000C TRN: Subscriber Trace Number seg++; strb.AppendLine("TRN*1*" //TRN01: Trace Type Code. 1=Current Transaction Trace Numbers + "1*" //TRN02: Trace Number. We don't really have a good primary key yet. Keep it simple. Use 1. + "1" + billProv.SSN + "~"); //TRN03: Entity Identifier. First digit is 1=EIN. Next 9 digits are EIN. Length validated. //2100C NM1: Subscriber Name seg++; strb.AppendLine("NM1*IL*" //NM101: IL=Insured or Subscriber + "1*" //NM102: 1=Person + Sout(subscriber.LName, 35) + "*" //NM103: LName + Sout(subscriber.FName, 25) + "*" //NM104: FName + Sout(subscriber.MiddleI, 25) + "*" //NM105: MiddleName + "*" //NM106: not used + "*" //NM107: suffix. Not present in Open Dental yet. + "MI*" //NM108: MI=MemberID + Sout(insSub.SubscriberID.Replace("-", ""), 80) + "~"); //NM109: Subscriber ID. Validated to be L>2. //2100C REF: Subscriber Additional Information. Without this, old plans seem to be frequently returned. seg++; strb.AppendLine("REF*6P*" //REF01: 6P=GroupNumber + Sout(insPlan.GroupNum, 30) + "~"); //REF02: Supplemental ID. Validated. //2100C DMG: Subscriber Demographic Information seg++; strb.AppendLine("DMG*D8*" //DMG01: Date Time Period Qualifier. D8=CCYYMMDD + subscriber.Birthdate.ToString("yyyyMMdd") + "~"); //DMG02: Subscriber birthdate. Validated //DMG03: Gender code. Situational. F or M. Since this was left out in the example, //and since we don't want to send the wrong gender, we will not send this element. //2100C DTP: Subscriber Date. Deduced through trial and error that this is required by EHG even though not by X12 specs. seg++; strb.AppendLine("DTP*307*" //DTP01: Qualifier. 307=Eligibility + "D8*" //DTP02: Format Qualifier. + DateTime.Today.ToString("yyyyMMdd") + "~"); //DTP03: Date //2000D HL: Dependent Level Hierarchical Level if (isSubscriberRequest) { //2110C EQ: Subscriber Eligibility or Benefit Enquiry Information //X12 documentation seems to say that we can loop this 99 times to request very specific benefits. //ClaimConnect wants to see either an EQ*30 for "an eligibility request", or an EQ*35 for "a general benefits request". //The director of vendor implementation at ClaimConnect has informed us that we should send an EQ*35 to get the full set of benefits. seg++; strb.AppendLine("EQ*35~"); //Dental Care } else //Dependent based request. { HLcount++; seg++; strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID. + (HLcount - 1).ToString() + "*" //HL02: Heirarchical parent id number. + "23*" //HL03: Heirarchical level code. 23=Dependent + "0~"); //HL04: Heirarchical child code. 0=no child HL present (no dependent) //2000D TRN: Dependent Trace Number seg++; strb.AppendLine("TRN*1*" //TRN01: Trace Type Code. 1=Current Transaction Trace Numbers + "1*" //TRN02: Trace Number. We don't really have a good primary key yet. Keep it simple. Use 1. + "1" + billProv.SSN + "~"); //TRN03: Entity Identifier. First digit is 1=EIN. Next 9 digits are EIN. Length validated. //2100D NM1: Dependent Name seg++; strb.AppendLine("NM1*03*" //NM101: 03=Dependent + "1*" //NM102: 1=Person + Sout(patForRequest.LName, 35) + "*" //NM103: Name Last or Organization Name + Sout(patForRequest.FName, 25) + "*" //NM104: Name First + Sout(patForRequest.MiddleI, 25) + "~"); //NM105: Name Middle //2100D REF: Dependent Additional Identification seg++; strb.AppendLine("REF*6P*" //REF01: 6P=GroupNumber + Sout(insPlan.GroupNum, 30) + "~"); //REF02: Supplemental ID. Validated. //2100D DMG: Dependent Demographic Information seg++; strb.AppendLine("DMG*D8*" //DMG01: Date Time Period Qualifier. D8=CCYYMMDD + patForRequest.Birthdate.ToString("yyyyMMdd") + "~"); //DMG02: Dependent birthdate. Validated //DMG03: Gender code. Situational. F or M. Since this was left out in the example, //and since we don't want to send the wrong gender, we will not send this element. //2100D DTP: DEPENDENT Date. Deduced through trial and error that this is required by EHG even though not by X12 specs. seg++; strb.AppendLine("DTP*307*" //DTP01: Qualifier. 307=Eligibility + "D8*" //DTP02: Format Qualifier. + DateTime.Today.ToString("yyyyMMdd") + "~"); //DTP03: Date seg++; strb.AppendLine("EQ*35~"); //Dental Care } //Transaction Trailer seg++; strb.AppendLine("SE*" + seg.ToString() + "*" //SE01: Total segments, including ST & SE + transactionNum.ToString().PadLeft(4, '0') + "~"); //End of transaction-------------------------------------------------------------------------------------- //Functional Group Trailer strb.AppendLine("GE*" + transactionNum.ToString() + "*" //GE01: Number of transaction sets included + groupControlNumber + "~"); //GE02: Group Control number. Must be identical to GS06 //Interchange Control Trailer strb.AppendLine("IEA*1*" //IEA01: number of functional groups + batchNum.ToString().PadLeft(9, '0') + "~"); //IEA02: Interchange control number return(strb.ToString()); /* * return @" * ISA*00* *00* *30*AA0989922 *30*330989922 *030519*1608*U*00401*000012145*1*T*:~ * GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~ * ST*270*0001~ * BHT*0022*13*ASX012145WEB*20030519*1608~ * HL*1**20*1~ * NM1*PR*2*Metlife*****PI*65978~ * HL*2*1*21*1~ * NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~ * REF*TJ*200384584~ * N3*JUNIT ROAD~ * N4*CHICAGO*IL*60602~ * PRV*PE*ZZ*1223G0001X~ * HL*3*2*22*0~ * TRN*1*12145*1AA0989922~ * NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~ * DMG*D8*19750323~ * DTP*307*D8*20030519~ * EQ*30~ * SE*17*0001~ * GE*1*12145~ * IEA*1*000012145~"; */ //return "ISA*00* *00* *30*AA0989922 *30*330989922 *030519*1608*U*00401*000012145*1*T*:~GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~ST*270*0001~BHT*0022*13*ASX012145WEB*20030519*1608~HL*1**20*1~NM1*PR*2*Metlife*****PI*65978~HL*2*1*21*1~NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~REF*TJ*200384584~N3*JUNIT ROAD~N4*CHICAGO*IL*60602~PRV*PE*ZZ*1223G0001X~HL*3*2*22*0~TRN*1*12145*1AA0989922~NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~DMG*D8*19750323~DTP*307*D8*20030519~EQ*30~SE*17*0001~GE*1*12145~IEA*1*000012145~"; }
public static List <List <int> > GetProdInc(DateTime dateFrom, DateTime dateTo) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <List <int> > >(MethodBase.GetCurrentMethod(), dateFrom, dateTo)); } #if DEBUG _elapsedTimeProdInc = ""; System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); System.Diagnostics.Stopwatch stopWatchTotal = new System.Diagnostics.Stopwatch(); _elapsedTimeProdInc = "Elapsed time for GetProdInc:\r\n"; stopWatch.Restart(); stopWatchTotal.Restart(); #endif string command; command = @"SELECT procedurelog.ProcDate, SUM(procedurelog.ProcFee*(procedurelog.UnitQty+procedurelog.BaseUnits))-IFNULL(SUM(claimproc.WriteOff),0) FROM procedurelog LEFT JOIN claimproc ON procedurelog.ProcNum=claimproc.ProcNum AND claimproc.Status='7' /*only CapComplete writeoffs are subtracted here*/ WHERE procedurelog.ProcStatus = '2' AND procedurelog.ProcDate >= " + POut.Date(dateFrom) + @" AND procedurelog.ProcDate <= " + POut.Date(dateTo) + @" GROUP BY MONTH(procedurelog.ProcDate)" ; DataTable tableProduction = Db.GetTable(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProdInc += "tableProduction: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif command = @"SELECT AdjDate, SUM(AdjAmt) FROM adjustment WHERE AdjDate >= " + POut.Date(dateFrom) + @" AND AdjDate <= " + POut.Date(dateTo) + @" GROUP BY MONTH(AdjDate)" ; DataTable tableAdj = Db.GetTable(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProdInc += "tableAdj: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif if (PrefC.GetBool(PrefName.ReportsPPOwriteoffDefaultToProcDate)) //use procdate { command = "SELECT " + "claimproc.ProcDate," + "SUM(claimproc.WriteOff) " + "FROM claimproc " + "WHERE claimproc.ProcDate >= " + POut.Date(dateFrom) + " " + "AND claimproc.ProcDate <= " + POut.Date(dateTo) + " " + "AND (claimproc.Status=1 OR claimproc.Status=4 OR claimproc.Status=0) " //received or supplemental or notreceived + "GROUP BY MONTH(claimproc.ProcDate)"; } else { command = "SELECT " + "claimproc.DateCP," + "SUM(claimproc.WriteOff) " + "FROM claimproc " + "WHERE claimproc.DateCP >= " + POut.Date(dateFrom) + " " + "AND claimproc.DateCP <= " + POut.Date(dateTo) + " " + "AND (claimproc.Status=1 OR claimproc.Status=4) " //Received or supplemental + "GROUP BY MONTH(claimproc.DateCP)"; } DataTable tableWriteoff = Db.GetTable(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProdInc += "tableWriteoff: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif command = "SELECT " + "paysplit.DatePay," + "SUM(paysplit.SplitAmt) " + "FROM paysplit " + "WHERE paysplit.IsDiscount=0 " + "AND paysplit.DatePay >= " + POut.Date(dateFrom) + " " + "AND paysplit.DatePay <= " + POut.Date(dateTo) + " " + "GROUP BY MONTH(paysplit.DatePay)"; DataTable tablePay = Db.GetTable(command); #if DEBUG stopWatch.Stop(); _elapsedTimeProdInc += "tablePay: " + stopWatch.Elapsed.ToString() + "\r\n"; stopWatch.Restart(); #endif command = "SELECT claimpayment.CheckDate,SUM(claimproc.InsPayamt) " + "FROM claimpayment,claimproc WHERE " + "claimproc.ClaimPaymentNum = claimpayment.ClaimPaymentNum " + "AND claimpayment.CheckDate >= " + POut.Date(dateFrom) + " " + "AND claimpayment.CheckDate <= " + POut.Date(dateTo) + " " + " GROUP BY claimpayment.CheckDate ORDER BY checkdate"; DataTable tableIns = Db.GetTable(command); #if DEBUG stopWatch.Stop(); stopWatchTotal.Stop(); _elapsedTimeProdInc += "tableIns: " + stopWatch.Elapsed.ToString() + "\r\n"; _elapsedTimeProdInc += "Total: " + stopWatchTotal.Elapsed.ToString(); if (_showElapsedTimesForDebug) { System.Windows.Forms.MessageBox.Show(_elapsedTimeProdInc); } #endif //production-------------------------------------------------------------------- List <int> listInt; listInt = new List <int>(); for (int i = 0; i < 12; i++) { decimal prod = 0; decimal adjust = 0; decimal inswriteoff = 0; DateTime datePeriod = dateFrom.AddMonths(i); //only the month and year are important for (int j = 0; j < tableProduction.Rows.Count; j++) { if (datePeriod.Year == PIn.Date(tableProduction.Rows[j][0].ToString()).Year && datePeriod.Month == PIn.Date(tableProduction.Rows[j][0].ToString()).Month) { prod += PIn.Decimal(tableProduction.Rows[j][1].ToString()); } } for (int j = 0; j < tableAdj.Rows.Count; j++) { if (datePeriod.Year == PIn.Date(tableAdj.Rows[j][0].ToString()).Year && datePeriod.Month == PIn.Date(tableAdj.Rows[j][0].ToString()).Month) { adjust += PIn.Decimal(tableAdj.Rows[j][1].ToString()); } } for (int j = 0; j < tableWriteoff.Rows.Count; j++) { if (datePeriod.Year == PIn.Date(tableWriteoff.Rows[j][0].ToString()).Year && datePeriod.Month == PIn.Date(tableWriteoff.Rows[j][0].ToString()).Month) { inswriteoff += PIn.Decimal(tableWriteoff.Rows[j][1].ToString()); } } listInt.Add((int)(prod + adjust - inswriteoff)); } List <List <int> > retVal = new List <List <int> >(); retVal.Add(listInt); //income---------------------------------------------------------------------- listInt = new List <int>(); for (int i = 0; i < 12; i++) { decimal ptincome = 0; decimal insincome = 0; DateTime datePeriod = dateFrom.AddMonths(i); //only the month and year are important for (int j = 0; j < tablePay.Rows.Count; j++) { if (datePeriod.Year == PIn.Date(tablePay.Rows[j][0].ToString()).Year && datePeriod.Month == PIn.Date(tablePay.Rows[j][0].ToString()).Month) { ptincome += PIn.Decimal(tablePay.Rows[j][1].ToString()); } } for (int j = 0; j < tableIns.Rows.Count; j++) // { if (datePeriod.Year == PIn.Date(tableIns.Rows[j][0].ToString()).Year && datePeriod.Month == PIn.Date(tableIns.Rows[j][0].ToString()).Month) { insincome += PIn.Decimal(tableIns.Rows[j][1].ToString()); } } listInt.Add((int)(ptincome + insincome)); } retVal.Add(listInt); return(retVal); }
public static string Validate(Clearinghouse clearinghouseClin, Carrier carrier, Provider billProv, Clinic clinic, InsPlan insPlan, Patient subscriber, InsSub insSub, Patient patForRequest) { StringBuilder strb = new StringBuilder(); X12Validate.ISA(clearinghouseClin, strb); X12Validate.Carrier(carrier, strb); if (carrier.ElectID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Electronic ID"); } if (billProv.SSN.Length != 9) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Prov TIN 9 digits"); } X12Validate.BillProv(billProv, strb); if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims)) { X12Validate.BillingAddress(strb); } else if (clinic == null) { X12Validate.PracticeAddress(strb); } else { X12Validate.Clinic(clinic, strb); } if (insSub.SubscriberID.Length < 2) { if (strb.Length != 0) { strb.Append(","); } strb.Append("SubscriberID"); } if (subscriber.Birthdate.Year < 1880) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Subscriber Birthdate"); } if (patForRequest.PatNum != subscriber.PatNum) //Dependent validation. { if (patForRequest.Birthdate.Year < 1880) //Dependent level validation. { if (strb.Length != 0) { strb.Append(","); } strb.Append("Dependent Birthdate"); } } ElectID eID = ElectIDs.GetID(carrier.ElectID); //Medicaid uses the patient First/Last/DOB to get benefits, not group number, so skip this validation if this is medicaid bool isMedicaid = (eID != null && eID.IsMedicaid) || carrier.CarrierName.ToLower().Contains("medicaid"); if (!isMedicaid) { if (insPlan.GroupNum == "") { if (strb.Length != 0) { strb.Append(","); } strb.Append("Group Number"); } } //Darien at Dentalxchange helped us resolve one issue where the Group Number included a dash and was failing. //The fix suggested by Darien was to only include the numbers before the dash... See task #705773 if (IsClaimConnect(clearinghouseClin) && insPlan.GroupNum.Contains("-")) { if (strb.Length != 0) { strb.Append(","); } strb.Append("Group Number: Only include the group number prior to the '-'"); } return(strb.ToString()); }
private static void MakeCommlog(Patient pat, string phoneNumber, int statusCode) { string commText = ""; //Status code meanings: // -100: Patient had no phone number // -200: Patient can't text and had no email // 2XX: Successfully sent message // 422: Message has already been sent for patient // Anything else: Failure of some sort. switch (statusCode / 100) //Get general http status codes e.g. -100=-1, 203=2 { case -1: //Failure, no phone number commText = Lans.g("Podium", "Podium review invitation request failed because there was no phone number. Error code:") + " " + statusCode; break; case -2: //Failure, no email commText = Lans.g("Podium", "Podium review invitation request failed because the patient doesn't accept texts " + "and there was no email address. Error code:") + " " + statusCode; break; case 2: //Success https://httpstatusdogs.com/200-ok commText = Lans.g("Podium", "Podium review invitation request successfully sent."); break; case 4: //Client side communication failure https://httpstatusdogs.com/400-bad-request if (statusCode == 422) //422 is Unprocessable Entity, which is sent in this case when a phone number has received an invite already. { commText = Lans.g("Podium", "The request failed because an identical request was previously sent."); } else { commText = Lans.g("Podium", "The request failed to reach Podium with error code:") + " " + statusCode; } break; case 5: //Server side internal failure. https://httpstatusdogs.com/500-internal-server-error commText = Lans.g("Podium", "The request was rejected by the Podium server with error code:") + " " + statusCode; break; default: //General Failure commText = Lans.g("Podium", "The request failed to send with error code:") + " " + statusCode; break; } if (!string.IsNullOrEmpty(commText)) { commText += "\r\n"; } commText += Lans.g("Podium", "The information sent in the request was") + ": \r\n" + Lans.g("Podium", "First name") + ": \"" + pat.FName + "\", " + Lans.g("Podium", "Last name") + ": \"" + pat.LName + "\", " + Lans.g("Podium", "Email") + ": \"" + pat.Email + "\""; if (phoneNumber != "") //If "successful". { commText += ", " + Lans.g("Podium", "Phone number") + ": \"" + phoneNumber + "\""; } else { string wirelessPhone = new string(pat.WirelessPhone.Where(x => char.IsDigit(x)).ToArray()); string homePhone = new string(pat.HmPhone.Where(x => char.IsDigit(x)).ToArray()); List <string> phonesTried = new List <string> { wirelessPhone, homePhone }.FindAll(x => x != ""); string phoneNumbersTried = ", " + Lans.g("Podium", "No valid phone number found."); if (pat.TxtMsgOk == YN.No || (pat.TxtMsgOk == YN.Unknown && PrefC.GetBool(PrefName.TextMsgOkStatusTreatAsNo))) //Used email { phoneNumbersTried = ""; } else if (phonesTried.Count > 0) { phoneNumbersTried = ", " + Lans.g("Podium", "Phone numbers tried") + ": " + string.Join(", ", phonesTried); } commText += phoneNumbersTried; } long programNum = Programs.GetProgramNum(ProgramName.Podium); Commlog commlogCur = new Commlog(); commlogCur.CommDateTime = DateTime.Now; commlogCur.DateTimeEnd = DateTime.Now; commlogCur.PatNum = pat.PatNum; commlogCur.UserNum = 0; //run from server, no valid CurUser commlogCur.CommSource = CommItemSource.ProgramLink; commlogCur.ProgramNum = programNum; commlogCur.CommType = Commlogs.GetTypeAuto(CommItemTypeAuto.MISC); commlogCur.Note = commText; commlogCur.Mode_ = CommItemMode.Text; commlogCur.SentOrReceived = CommSentOrReceived.Sent; Commlogs.Insert(commlogCur); }
///<summary>For orderBy, use 0 for BillingType and 1 for PatientName.</summary> public static DataTable GetBilling(bool isSent, int orderBy, DateTime dateFrom, DateTime dateTo, List <long> clinicNums) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), isSent, orderBy, dateFrom, dateTo, clinicNums)); } DataTable table = new DataTable(); DataRow row; //columns that start with lowercase are altered for display rather than being raw data. table.Columns.Add("amountDue"); table.Columns.Add("balTotal"); table.Columns.Add("billingType"); table.Columns.Add("insEst"); table.Columns.Add("IsSent"); table.Columns.Add("lastStatement"); table.Columns.Add("mode"); table.Columns.Add("name"); table.Columns.Add("PatNum"); table.Columns.Add("payPlanDue"); table.Columns.Add("StatementNum"); table.Columns.Add("SuperFamily"); string command = "SELECT patient.BalTotal,BillingType,FName,patient.InsEst,statement.IsSent," + "IFNULL(MAX(s2.DateSent)," + POut.Date(DateTime.MinValue) + ") LastStatement," + "LName,MiddleI,statement.Mode_,PayPlanDue,Preferred," + "statement.PatNum,statement.StatementNum,statement.SuperFamily " + "FROM statement " + "LEFT JOIN patient ON statement.PatNum=patient.PatNum " + "LEFT JOIN statement s2 ON s2.PatNum=patient.PatNum " + "AND s2.IsSent=1 "; if (PrefC.GetBool(PrefName.BillingIgnoreInPerson)) { command += "AND s2.Mode_ !=1 "; } if (orderBy == 0) //BillingType { command += "LEFT JOIN definition ON patient.BillingType=definition.DefNum "; } command += "WHERE statement.IsSent=" + POut.Bool(isSent) + " "; //if(dateFrom.Year>1800){ command += "AND statement.DateSent>=" + POut.Date(dateFrom) + " "; //greater than midnight this morning //} //if(dateFrom.Year>1800){ command += "AND statement.DateSent<" + POut.Date(dateTo.AddDays(1)) + " "; //less than midnight tonight //} if (clinicNums.Count > 0) { command += "AND patient.ClinicNum IN (" + string.Join(",", clinicNums) + ") "; } command += "GROUP BY patient.BalTotal,BillingType,FName,patient.InsEst,statement.IsSent," + "LName,MiddleI,statement.Mode_,PayPlanDue,Preferred," + "statement.PatNum,statement.StatementNum,statement.SuperFamily "; if (orderBy == 0) //BillingType { command += "ORDER BY definition.ItemOrder,LName,FName,MiddleI,PayPlanDue"; } else { command += "ORDER BY LName,FName"; } DataTable rawTable = Db.GetTable(command); double balTotal; double insEst; double payPlanDue; DateTime lastStatement; List <Patient> listFamilyGuarantors; foreach (DataRow rawRow in rawTable.Rows) { row = table.NewRow(); if (rawRow["SuperFamily"].ToString() == "0") //not a super statement, just get bal info from guarantor { balTotal = PIn.Double(rawRow["BalTotal"].ToString()); insEst = PIn.Double(rawRow["InsEst"].ToString()); payPlanDue = PIn.Double(rawRow["PayPlanDue"].ToString()); } else //super statement, add all guar positive balances to get bal total for super family { listFamilyGuarantors = Patients.GetSuperFamilyGuarantors(PIn.Long(rawRow["SuperFamily"].ToString())).FindAll(x => x.HasSuperBilling); //exclude fams with neg balances in the total for super family stmts (per Nathan 5/25/2016) if (PrefC.GetBool(PrefName.BalancesDontSubtractIns)) { listFamilyGuarantors = listFamilyGuarantors.FindAll(x => x.BalTotal > 0); insEst = 0; } else { listFamilyGuarantors = listFamilyGuarantors.FindAll(x => (x.BalTotal - x.InsEst) > 0); insEst = listFamilyGuarantors.Sum(x => x.InsEst); } balTotal = listFamilyGuarantors.Sum(x => x.BalTotal); payPlanDue = listFamilyGuarantors.Sum(x => x.PayPlanDue); } row["amountDue"] = (balTotal - insEst).ToString("F"); row["balTotal"] = balTotal.ToString("F");; row["billingType"] = Defs.GetName(DefCat.BillingTypes, PIn.Long(rawRow["BillingType"].ToString())); if (insEst == 0) { row["insEst"] = ""; } else { row["insEst"] = insEst.ToString("F"); } row["IsSent"] = rawRow["IsSent"].ToString(); lastStatement = PIn.Date(rawRow["LastStatement"].ToString()); if (lastStatement.Year < 1880) { row["lastStatement"] = ""; } else { row["lastStatement"] = lastStatement.ToShortDateString(); } row["mode"] = Lans.g("enumStatementMode", ((StatementMode)PIn.Int(rawRow["Mode_"].ToString())).ToString()); row["name"] = Patients.GetNameLF(rawRow["LName"].ToString(), rawRow["FName"].ToString(), rawRow["Preferred"].ToString(), rawRow["MiddleI"].ToString()); row["PatNum"] = rawRow["PatNum"].ToString(); if (payPlanDue == 0) { row["payPlanDue"] = ""; } else { row["payPlanDue"] = payPlanDue.ToString("F"); } row["StatementNum"] = rawRow["StatementNum"].ToString(); row["SuperFamily"] = rawRow["SuperFamily"].ToString(); table.Rows.Add(row); } return(table); }