///<summary>Throws Exception. ///Helper method that calls TryInsertPDF(...) for treatment plan PDFs.</summary> public static bool TryInsertTreatPlanPDF(PdfDocument doc, TreatPlan treatPlan, bool hasPracticeSig, string unlockCode , out string errorMsg, out MobileDataByte mobileDataByte) { mobileDataByte = null; if (!MobileAppDevices.IsClinicSignedUpForEClipboard(Clinics.ClinicNum)) { throw new Exception($"This practice or clinic is not signed up for eClipboard.\r\nGo to eServices | Signup Portal to sign up."); } try{ List <string> listTagValues = new List <string>() { treatPlan.Heading, treatPlan.TreatPlanNum.ToString(), hasPracticeSig.ToString(), treatPlan.DateTP.Ticks.ToString() }; TryInsertPDF(doc, treatPlan.PatNum, unlockCode, eActionType.TreatmentPlan , out long mobileDataByteNum, out errorMsg, listTagValues ); if (mobileDataByteNum != -1) { mobileDataByte = GetOne(mobileDataByteNum); } } catch (Exception ex) { errorMsg = ex.Message; } return(errorMsg.IsNullOrEmpty() && mobileDataByte != null); }
///<summary>Dependencies checked first and throws an exception if any found. So surround by try catch</summary> public static void Delete(TreatPlan tp) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), tp); return; } //check proctp for dependencies string command = "SELECT * FROM proctp WHERE TreatPlanNum =" + POut.Long(tp.TreatPlanNum); DataTable table = Db.GetTable(command); if (table.Rows.Count > 0) { //this should never happen throw new ApplicationException(Lans.g("TreatPlans", "Cannot delete treatment plan because it has ProcTP's attached")); } command = "DELETE from treatplan WHERE TreatPlanNum = '" + POut.Long(tp.TreatPlanNum) + "'"; Db.NonQ(command); if (!tp.TPStatus.In(TreatPlanStatus.Saved)) { return; } List <MobileAppDevice> listPatDevices = MobileAppDevices.GetAll(tp.PatNum); if (listPatDevices.Count > 0) { PushNotificationUtils.CI_RemoveTreatmentPlan(listPatDevices.First().MobileAppDeviceNum, tp); } }
///<summary></summary> public static long Insert(TreatPlan tp) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { tp.TreatPlanNum=Meth.GetLong(MethodBase.GetCurrentMethod(),tp); return tp.TreatPlanNum; } return Crud.TreatPlanCrud.Insert(tp); }
///<summary></summary> public TreatPlan Copy() { TreatPlan newTP = (TreatPlan)MemberwiseClone(); newTP.ListProcTPs = this.ListProcTPs.Select(x => x.Copy()).ToList(); return(newTP); }
///<summary></summary> public static void Update(TreatPlan tp){ if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),tp); return; } Crud.TreatPlanCrud.Update(tp); }
///<summary>Called after setting the status to treatPlanCur to Active. ///Updates the status of any other plan with Active status to Inactive. ///If the original heading of the other plan is "Active Treatment Plan" it will be updated to "Inactive Treatment Plan".</summary> public static void SetOtherActiveTPsToInactive(TreatPlan treatPlanCur) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), treatPlanCur); return; } string command = "SELECT * FROM treatplan " + "WHERE PatNum=" + POut.Long(treatPlanCur.PatNum) + " " + "AND TPStatus=" + POut.Int((int)TreatPlanStatus.Active) + " " + "AND TreatPlanNum!=" + POut.Long(treatPlanCur.TreatPlanNum); //Make Active TP's inactive. Rename if TP's still have default name. List <TreatPlan> listActivePlans = Crud.TreatPlanCrud.SelectMany(command); foreach (TreatPlan tp in listActivePlans) //should only ever be one, but just in case there are multiple this will rectify the problem. { if (tp.Heading == Lans.g("TreatPlans", "Active Treatment Plan")) { tp.Heading = Lans.g("TreatPlans", "Inactive Treatment Plan"); } tp.TPStatus = TreatPlanStatus.Inactive; TreatPlans.Update(tp); } //Heading is changed from within the form, if they have changed it back to Inactive Treatment Plan it was deliberate. //if(treatPlanCur.Heading==Lans.g("TreatPlans","Inactive Treatment Plan")) { // treatPlanCur.Heading=Lans.g("TreatPlans","Active Treatment Plan"); //} //Not necessary, treatPlanCur should be set to Active prior to calling this function. //treatPlanCur.TPStatus=TreatPlanStatus.Active; //TreatPlans.Update(treatPlanCur); }
public static string GetHashString(TreatPlan tp, List <ProcTP> proclist) { //No need to check RemotingRole; no call to db. //the key data is a concatenation of the following: //tp: Note, DateTP //each proctp: Descript,PatAmt //The procedures MUST be in the correct order, and we'll use ItemOrder to order them. StringBuilder strb = new StringBuilder(); strb.Append(tp.Note); strb.Append(tp.DateTP.ToString("yyyyMMdd")); for (int i = 0; i < proclist.Count; i++) { strb.Append(proclist[i].Descript); strb.Append(proclist[i].PatAmt.ToString("F2")); } byte[] textbytes = Encoding.UTF8.GetBytes(strb.ToString()); //byte[] filebytes = GetBytes(doc); //int fileLength = filebytes.Length; //byte[] buffer = new byte[textbytes.Length + filebytes.Length]; //Array.Clone(filebytes,0,buffer,0,fileLength); //Array.Clone(textbytes,0,buffer,fileLength,textbytes.Length); HashAlgorithm algorithm = MD5.Create(); byte[] hash = algorithm.ComputeHash(textbytes); //always results in length of 16. return(Encoding.ASCII.GetString(hash)); }
///<summary></summary> public static void Update(TreatPlan tp) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), tp); return; } Crud.TreatPlanCrud.Update(tp); }
///<summary></summary> public static long Insert(TreatPlan tp) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { tp.TreatPlanNum = Meth.GetLong(MethodBase.GetCurrentMethod(), tp); return(tp.TreatPlanNum); } return(Crud.TreatPlanCrud.Insert(tp)); }
///<summary></summary> public FormTreatPlanEdit(TreatPlan planCur) { // // Required for Windows Form Designer support // InitializeComponent(); Lan.F(this); PlanCur=planCur.Copy(); }
///<summary></summary> public TreatPlan Copy() { TreatPlan t = new TreatPlan(); t.TreatPlanNum = TreatPlanNum; t.PatNum = PatNum; t.DateTP = DateTP; t.Heading = Heading; t.Note = Note; return(t); }
///<summary></summary> public static long Insert(TreatPlan tp) { if (RemotingClient.RemotingRole != RemotingRole.ServerWeb) { tp.SecUserNumEntry = Security.CurUser.UserNum; //must be before normal remoting role check to get user at workstation } if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { tp.TreatPlanNum = Meth.GetLong(MethodBase.GetCurrentMethod(), tp); return(tp.TreatPlanNum); } return(Crud.TreatPlanCrud.Insert(tp)); }
///<summary>Dependencies checked first and throws an exception if any found. So surround by try catch</summary> public static void Delete(TreatPlan tp){ if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),tp); return; } //check proctp for dependencies string command="SELECT * FROM proctp WHERE TreatPlanNum ="+POut.Long(tp.TreatPlanNum); DataTable table=Db.GetTable(command); if(table.Rows.Count>0){ //this should never happen throw new InvalidProgramException(Lans.g("TreatPlans","Cannot delete treatment plan because it has ProcTP's attached")); } command= "DELETE from treatplan WHERE TreatPlanNum = '"+POut.Long(tp.TreatPlanNum)+"'"; Db.NonQ(command); }
///<summary>Gets the key data string needed to create a hashstring to be used later when filling the signature. ///This is done seperate of the hashing so that new line replacements can be done when validating signatures before hashing.</summary> public static string GetKeyDataForSignatureHash(TreatPlan tp, List <ProcTP> proclist) { //No need to check RemotingRole; no call to db. //the key data is a concatenation of the following: //tp: Note, DateTP //each proctp: Descript,PatAmt //The procedures MUST be in the correct order, and we'll use ItemOrder to order them. StringBuilder strb = new StringBuilder(); strb.Append(tp.Note); strb.Append(tp.DateTP.ToString("yyyyMMdd")); for (int i = 0; i < proclist.Count; i++) { strb.Append(proclist[i].Descript); strb.Append(proclist[i].PatAmt.ToString("F2")); } return(strb.ToString()); }
///<summary>Dependencies checked first and throws an exception if any found. So surround by try catch</summary> public static void Delete(TreatPlan tp) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), tp); return; } //check proctp for dependencies string command = "SELECT * FROM proctp WHERE TreatPlanNum =" + POut.Long(tp.TreatPlanNum); DataTable table = Db.GetTable(command); if (table.Rows.Count > 0) { //this should never happen throw new InvalidProgramException(Lans.g("TreatPlans", "Cannot delete treatment plan because it has ProcTP's attached")); } command = "DELETE from treatplan WHERE TreatPlanNum = '" + POut.Long(tp.TreatPlanNum) + "'"; Db.NonQ(command); }
public static string GetHashString(TreatPlan tp,List<ProcTP> proclist) { //No need to check RemotingRole; no call to db. //the key data is a concatenation of the following: //tp: Note, DateTP //each proctp: Descript,PatAmt //The procedures MUST be in the correct order, and we'll use ItemOrder to order them. StringBuilder strb=new StringBuilder(); strb.Append(tp.Note); strb.Append(tp.DateTP.ToString("yyyyMMdd")); for(int i=0;i<proclist.Count;i++){ strb.Append(proclist[i].Descript); strb.Append(proclist[i].PatAmt.ToString("F2")); } byte[] textbytes=Encoding.UTF8.GetBytes(strb.ToString()); //byte[] filebytes = GetBytes(doc); //int fileLength = filebytes.Length; //byte[] buffer = new byte[textbytes.Length + filebytes.Length]; //Array.Clone(filebytes,0,buffer,0,fileLength); //Array.Clone(textbytes,0,buffer,fileLength,textbytes.Length); HashAlgorithm algorithm = MD5.Create(); byte[] hash = algorithm.ComputeHash(textbytes);//always results in length of 16. return Encoding.ASCII.GetString(hash); }
///<summary>Returns only 5 columns for all saved treatment plans.</summary> public static List <TreatPlan> GetAllSavedLim() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <TreatPlan> >(MethodBase.GetCurrentMethod())); } string command = "SELECT TreatPlanNum, PatNum, DateTP, SecUserNumEntry, UserNumPresenter " + " FROM treatplan WHERE treatplan.TPStatus=" + POut.Int((int)TreatPlanStatus.Saved); DataTable table = Db.GetTable(command); List <TreatPlan> listSavedTreatPlanLim = new List <TreatPlan>(); foreach (DataRow row in table.Rows) { TreatPlan treatPlanCur = new TreatPlan(); treatPlanCur.TreatPlanNum = PIn.Long(row["TreatPlanNum"].ToString()); treatPlanCur.PatNum = PIn.Long(row["PatNum"].ToString()); treatPlanCur.DateTP = PIn.Date(row["DateTP"].ToString()); treatPlanCur.SecUserNumEntry = PIn.Long(row["SecUserNumEntry"].ToString()); treatPlanCur.UserNumPresenter = PIn.Long(row["UserNumPresenter"].ToString()); listSavedTreatPlanLim.Add(treatPlanCur); } return(listSavedTreatPlanLim); }
private void OnCreate_Click() { if(gridPlans.SelectedIndices[0]!=0){ MsgBox.Show(this,"The default TP must be selected before saving a TP. You can highlight some procedures in the default TP to save a TP with only those procedures in it."); return; } if(gridMain.SelectedIndices.Length==0){ gridMain.SetSelected(true); } TreatPlan tp=new TreatPlan(); tp.Heading=Lan.g(this,"Proposed Treatment Plan"); tp.DateTP=DateTime.Today; tp.PatNum=PatCur.PatNum; tp.Note=PrefC.GetString(PrefName.TreatmentPlanNote); tp.ResponsParty=PatCur.ResponsParty; TreatPlans.Insert(tp); ProcTP procTP; Procedure proc; int itemNo=0; for(int i=0;i<gridMain.SelectedIndices.Length;i++){ if(gridMain.Rows[gridMain.SelectedIndices[i]].Tag==null){ //user must have highlighted a subtotal row. continue; } proc=(Procedure)gridMain.Rows[gridMain.SelectedIndices[i]].Tag; procTP=new ProcTP(); procTP.TreatPlanNum=tp.TreatPlanNum; procTP.PatNum=PatCur.PatNum; procTP.ProcNumOrig=proc.ProcNum; procTP.ItemOrder=itemNo; procTP.Priority=proc.Priority; procTP.ToothNumTP=Tooth.ToInternat(proc.ToothNum); if(ProcedureCodes.GetProcCode(proc.CodeNum).TreatArea==TreatmentArea.Surf){ procTP.Surf=Tooth.SurfTidyFromDbToDisplay(proc.Surf,proc.ToothNum); } else{ procTP.Surf=proc.Surf;//for UR, L, etc. } procTP.ProcCode=ProcedureCodes.GetStringProcCode(proc.CodeNum); procTP.Descript=RowsMain[gridMain.SelectedIndices[i]].Description; if(checkShowFees.Checked){ procTP.FeeAmt=PIn.Double(RowsMain[gridMain.SelectedIndices[i]].Fee.ToString()); } if(checkShowIns.Checked){ procTP.PriInsAmt=PIn.Double(RowsMain[gridMain.SelectedIndices[i]].PriIns.ToString()); procTP.SecInsAmt=PIn.Double(RowsMain[gridMain.SelectedIndices[i]].SecIns.ToString()); } if(checkShowDiscount.Checked){ procTP.Discount=PIn.Double(RowsMain[gridMain.SelectedIndices[i]].Discount.ToString()); } if(checkShowIns.Checked){ procTP.PatAmt=PIn.Double(RowsMain[gridMain.SelectedIndices[i]].Pat.ToString()); } procTP.Prognosis=RowsMain[gridMain.SelectedIndices[i]].Prognosis; procTP.Dx=RowsMain[gridMain.SelectedIndices[i]].Dx; ProcTPs.InsertOrUpdate(procTP,true); itemNo++; #region Canadian Lab Fees /* proc=(Procedure)gridMain.Rows[gridMain.SelectedIndices[i]].Tag; procTP=new ProcTP(); procTP.TreatPlanNum=tp.TreatPlanNum; procTP.PatNum=PatCur.PatNum; procTP.ProcNumOrig=proc.ProcNum; procTP.ItemOrder=itemNo; procTP.Priority=proc.Priority; procTP.ToothNumTP=""; procTP.Surf=""; procTP.Code=proc.LabProcCode; procTP.Descript=gridMain.Rows[gridMain.SelectedIndices[i]] .Cells[gridMain.Columns.GetIndex(Lan.g("TableTP","Description"))].Text; if(checkShowFees.Checked) { procTP.FeeAmt=PIn.PDouble(gridMain.Rows[gridMain.SelectedIndices[i]] .Cells[gridMain.Columns.GetIndex(Lan.g("TableTP","Fee"))].Text); } if(checkShowIns.Checked) { procTP.PriInsAmt=PIn.PDouble(gridMain.Rows[gridMain.SelectedIndices[i]] .Cells[gridMain.Columns.GetIndex(Lan.g("TableTP","Pri Ins"))].Text); procTP.SecInsAmt=PIn.PDouble(gridMain.Rows[gridMain.SelectedIndices[i]] .Cells[gridMain.Columns.GetIndex(Lan.g("TableTP","Sec Ins"))].Text); procTP.PatAmt=PIn.PDouble(gridMain.Rows[gridMain.SelectedIndices[i]] .Cells[gridMain.Columns.GetIndex(Lan.g("TableTP","Pat"))].Text); } ProcTPs.InsertOrUpdate(procTP,true); itemNo++;*/ #endregion Canadian Lab Fees } //Send TP DFT HL7 message to ECW with embedded PDF when using tight integration only. if(Programs.UsingEcwTight()){ PrepImageForPrinting(); MigraDoc.Rendering.PdfDocumentRenderer pdfRenderer=new MigraDoc.Rendering.PdfDocumentRenderer(true,PdfFontEmbedding.Always); pdfRenderer.Document=CreateDocument(); pdfRenderer.RenderDocument(); MemoryStream ms=new MemoryStream(); pdfRenderer.PdfDocument.Save(ms); byte[] pdfBytes=ms.GetBuffer(); //#region Remove when testing is complete. //string tempFilePath=Path.GetTempFileName(); //File.WriteAllBytes(tempFilePath,pdfBytes); //#endregion string pdfDataStr=Convert.ToBase64String(pdfBytes); Bridges.ECW.SendHL7(Bridges.ECW.AptNum,PatCur.PriProv,PatCur,pdfDataStr,"treatment",true); } ModuleSelected(PatCur.PatNum); for(int i=0;i<PlanList.Length;i++){ if(PlanList[i].TreatPlanNum==tp.TreatPlanNum){ gridPlans.SetSelected(i+1,true); FillMain(); } } }
///<summary>If not using clinics then supply an empty list of clinicNums.</summary> public static DataTable GetTreatPlanPresentationStatistics(DateTime dateStart, DateTime dateEnd, bool isFirstPresented, bool hasAllClinics , bool hasClinicsEnabled, bool isPresenter, bool isGross, bool hasAllUsers, List <long> listUserNums, List <long> listClinicNums) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetTable(MethodBase.GetCurrentMethod(), dateStart, dateEnd, isFirstPresented, hasAllClinics, hasClinicsEnabled, isPresenter, isGross , hasAllUsers, listUserNums, listClinicNums)); } List <ProcTP> listProcTPsAll = ReportsComplex.RunFuncOnReportServer(() => ProcTPs.GetAllLim()); List <TreatPlan> listSavedTreatPlans = ReportsComplex.RunFuncOnReportServer(() => TreatPlans.GetAllSavedLim()); List <ProcTpTreatPlan> listProcTPTreatPlans = new List <ProcTpTreatPlan>(); listProcTPsAll.ForEach(x => { listProcTPTreatPlans.Add(new ProcTpTreatPlan() { TreatPlanCur = listSavedTreatPlans.First(y => y.TreatPlanNum == x.TreatPlanNum), ProcTPCur = x }); }); //get one entry per procedure with their first/last date of presentation based on radio buttons. if (isFirstPresented) { listProcTPTreatPlans = listProcTPTreatPlans .OrderBy(x => x.ProcTPCur.ProcNumOrig) .ThenBy(x => x.TreatPlanCur.DateTP) .ThenBy(x => x.TreatPlanCur.TreatPlanNum) .GroupBy(x => x.ProcTPCur.ProcNumOrig) .Select(x => x.First()) .ToList(); } else { listProcTPTreatPlans = listProcTPTreatPlans .OrderBy(x => x.ProcTPCur.ProcNumOrig) .ThenByDescending(x => x.TreatPlanCur.DateTP) .ThenBy(x => x.TreatPlanCur.TreatPlanNum) .GroupBy(x => x.ProcTPCur.ProcNumOrig) .Select(x => x.First()) .ToList(); } //get rid of any entries that are outside the range selected. listProcTPTreatPlans = listProcTPTreatPlans.Where(x => x.TreatPlanCur.DateTP.Date >= dateStart && x.TreatPlanCur.DateTP.Date <= dateEnd).ToList(); //Get the associated procedures, claimprocs, adjustments, users, appointments. List <Procedure> listProcsForTreatPlans = ReportsComplex.RunFuncOnReportServer(() => Procedures.GetForProcTPs(listProcTPTreatPlans.Select(x => x.ProcTPCur).ToList(), ProcStat.C, ProcStat.TP)); if (hasClinicsEnabled && !hasAllClinics) { listProcsForTreatPlans = listProcsForTreatPlans.FindAll(x => listClinicNums.Contains(x.ClinicNum)); } List <ClaimProc> listClaimProcs = ReportsComplex.RunFuncOnReportServer(() => ClaimProcs.GetForProcsLimited(listProcsForTreatPlans.Select(x => x.ProcNum).ToList(), ClaimProcStatus.CapComplete, ClaimProcStatus.NotReceived, ClaimProcStatus.Received, ClaimProcStatus.Supplemental, ClaimProcStatus.Estimate)); List <Adjustment> listAdjustments = ReportsComplex.RunFuncOnReportServer(() => Adjustments.GetForProcs(listProcsForTreatPlans.Select(x => x.ProcNum).ToList())); List <Userod> listUserods = ReportsComplex.RunFuncOnReportServer(() => Userods.GetAll()); List <TreatPlanPresenterEntry> listTreatPlanPresenterEntries = new List <TreatPlanPresenterEntry>(); List <ProcedureCode> listProcCodes = ReportsComplex.RunFuncOnReportServer(() => ProcedureCodes.GetCodesForCodeNums(listProcsForTreatPlans.Select(x => x.CodeNum).ToList())); List <Appointment> listApts = ReportsComplex.RunFuncOnReportServer(() => Appointments.GetMultApts(listProcsForTreatPlans.Select(x => x.AptNum).ToList())); double amt = listProcsForTreatPlans.Sum(x => x.ProcFee); foreach (Procedure procCur in listProcsForTreatPlans) { double grossProd = procCur.ProcFeeTotal; double writeOffs = listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum) .Where(x => x.Status == ClaimProcStatus.CapComplete) .Sum(x => x.WriteOff); grossProd -= writeOffs; if (procCur.ProcStatus == ProcStat.C) { writeOffs += listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum) .Where(x => x.Status.In(ClaimProcStatus.NotReceived, ClaimProcStatus.Received, ClaimProcStatus.Supplemental)) .Sum(x => x.WriteOff); } else { foreach (ClaimProc claimProcCur in listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum).Where(x => x.Status == ClaimProcStatus.Estimate)) { if (claimProcCur.WriteOffEstOverride == -1) { if (claimProcCur.WriteOffEst != -1) { writeOffs += claimProcCur.WriteOffEst; } } else { writeOffs += claimProcCur.WriteOffEstOverride; } } //writeOffs += listClaimProcs.Where(x => x.ProcNum == procCur.ProcNum) // .Where(x => x.Status == ClaimProcStatus.Estimate) // .Sum(x => x.WriteOffEstOverride == -1 ? (x.WriteOffEst == -1 ? 0 : x.WriteOffEst) : x.WriteOffEstOverride); //Allen won't let me commit this nested ternary :( } double adjustments = listAdjustments.Where(x => x.ProcNum == procCur.ProcNum).Sum(x => x.AdjAmt); double netProd = grossProd - writeOffs + adjustments; TreatPlan treatPlanCur = listProcTPTreatPlans.Where(x => x.ProcTPCur.ProcNumOrig == procCur.ProcNum).First().TreatPlanCur; Userod userPresenter; if (isPresenter) { userPresenter = listUserods.FirstOrDefault(x => x.UserNum == treatPlanCur.UserNumPresenter); } else //radioEntryUser { userPresenter = listUserods.FirstOrDefault(x => x.UserNum == treatPlanCur.SecUserNumEntry); } ProcedureCode procCode = listProcCodes.First(x => x.CodeNum == procCur.CodeNum); Appointment aptCur = listApts.FirstOrDefault(x => x.AptNum == procCur.AptNum); listTreatPlanPresenterEntries.Add(new TreatPlanPresenterEntry() { Presenter = userPresenter == null ? "" : userPresenter.UserName, DatePresented = treatPlanCur.DateTP, DateCompleted = procCur.ProcDate, ProcDescript = procCode.Descript, GrossProd = grossProd, Adjustments = adjustments, WriteOffs = writeOffs, NetProd = netProd, UserNumPresenter = userPresenter == null?0:userPresenter.UserNum, PresentedClinic = procCur.ClinicNum, ProcStatus = procCur.ProcStatus, TreatPlanNum = treatPlanCur.TreatPlanNum, AptNum = procCur.AptNum, AptStatus = aptCur == null?ApptStatus.None:aptCur.AptStatus }); } DataTable table = new DataTable(); table.Columns.Add("Presenter"); table.Columns.Add("# of Plans"); table.Columns.Add("# of Procs"); table.Columns.Add("# of ProcsSched"); table.Columns.Add("# of ProcsComp"); if (isGross) { table.Columns.Add("GrossTPAmt"); table.Columns.Add("GrossSchedAmt"); table.Columns.Add("GrossCompAmt"); } else { table.Columns.Add("NetTpAmt"); table.Columns.Add("NetSchedAmt"); table.Columns.Add("NetCompAmt"); } if (!hasAllUsers) { listTreatPlanPresenterEntries = listTreatPlanPresenterEntries.Where(x => listUserNums.Contains(x.UserNumPresenter)).ToList(); } listTreatPlanPresenterEntries = listTreatPlanPresenterEntries.OrderBy(x => x.Presenter).ToList(); listTreatPlanPresenterEntries .GroupBy(x => x.Presenter).ToList().ForEach(x => { DataRow row = table.NewRow(); row["Presenter"] = x.First().Presenter == "" ? "None" : x.First().Presenter; row["# of Plans"] = x.GroupBy(y => y.TreatPlanNum).Count(); row["# of Procs"] = x.Count(); row["# of ProcsSched"] = x.Count(y => y.ProcStatus == ProcStat.TP && y.AptNum != 0 && y.AptStatus == ApptStatus.Scheduled); row["# of ProcsComp"] = x.Count(y => y.ProcStatus == ProcStat.C); if (isGross) { row["GrossTpAmt"] = x.Sum(y => y.GrossProd); row["GrossSchedAmt"] = x.Where(y => y.ProcStatus == ProcStat.TP && y.AptNum != 0 && y.AptStatus == ApptStatus.Scheduled).Sum(y => y.GrossProd); row["GrossCompAmt"] = x.Where(y => y.ProcStatus == ProcStat.C).Sum(y => y.GrossProd); } else { row["NetTpAmt"] = x.Sum(y => y.NetProd); row["NetSchedAmt"] = x.Where(y => y.ProcStatus == ProcStat.TP && y.AptNum != 0 && y.AptStatus == ApptStatus.Scheduled).Sum(y => y.NetProd); row["NetCompAmt"] = x.Where(y => y.ProcStatus == ProcStat.C).Sum(y => y.NetProd); } table.Rows.Add(row); }); //DataTable table=ReportsComplex.RunFuncOnReportServer(() => ReportsComplex.GetTable(query)); return(table); }
///<summary>No need to pass in userNum, it's set before remoting role check and passed to the server if necessary. ///<para>This is the automation behind keeping treatplans correct. Many calls to DB, consider optimizing or calling sparingly.</para> ///<para>Ensures patients only have one active treatplan, marks extras inactive and creates an active if necessary.</para> ///<para>Attaches procedures to the active plan if the proc status is TP or status is TPi and the procs is attached to a sched/planned appt.</para> ///<para>Creates an unassigned treatplan if necessary and attaches any unassigned procedures to it.</para> ///<para>Also maintains priorities of treatplanattaches and procedures and updates the procstatus of TP and TPi procs if necessary.</para></summary> public static void AuditPlans(long patNum, TreatPlanType tpType, long userNum = 0) { if (RemotingClient.RemotingRole != RemotingRole.ServerWeb) { userNum = Security.CurUser.UserNum; //must be before normal remoting role check to get user at workstation } if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), patNum, tpType, userNum); return; } #region Pseudo Code //Get all treatplans for the patient //Find active TP if it already exists //If more than one active TP, update all but the first to Inactive //Find unassigned TP if it already exists //Get all treatplanattaches for the treatplans //Get all TP and TPi procs for the patient //Get list of procs for the active plan, i.e. TPA exists linking to active plan or ProcStatus is TP or attached to sched/planned appt //Get list of inactive procs, i.e. ProcStatus is TPi and AptNum is 0 and PlannedAptNum is 0 and no TPA exists linking it to the active plan //Create an active plan if one doesn't exist and there are procs that need to be attached to it //Create an unassigned plan if one doesn't exist and there are unassigned TPi procs //For each proc that should be attached to the active plan // update status from TPi to TP // if TPA exists linking to active plan, update priority to TPA priority // delete any TPA that links the proc to the unassigned plan // if TPA linking the proc to the active plan does not exist, insert one with TPA priority set to the proc priority //For each proc that is not attached to the active plan (ProcStatus is TPi) // set proc priority to 0 // if TPA does not exist, insert one linking the proc to the unassigned plan with TPA priority 0 // if multiple TPAs exist with one linking the proc to the unassigned plan, delete the TPA linking to the unassigned plan //Foreach TPA // if TPA links proc to the unassigned plan and TPA exists linking the proc to any other plan, delete the link to the unassigned plan //If an unassigned plan exists and there are no TPAs pointing to it, delete the unassigned plan #endregion Pseudo Code #region Variables List <TreatPlan> listTreatPlans = TreatPlans.GetAllForPat(patNum); //All treatplans for the pat. [([Includes Saved Plans]}}; TreatPlan activePlan = listTreatPlans.FirstOrDefault(x => x.TPStatus == TreatPlanStatus.Active); //can be null TreatPlan unassignedPlan = listTreatPlans.FirstOrDefault(x => x.TPStatus == TreatPlanStatus.Inactive && x.Heading == Lans.g("TreatPlans", "Unassigned")); //can be null List <TreatPlanAttach> listTPAs = TreatPlanAttaches.GetAllForTPs(listTreatPlans.Select(x => x.TreatPlanNum).ToList()); List <Procedure> listProcsTpTpi = Procedures.GetProcsByStatusForPat(patNum, new[] { ProcStat.TP, ProcStat.TPi }); //All TP and TPi procs for the pat. List <Procedure> listProcsForActive = new List <Procedure>(); //All procs that should be linked to the active plan (can be linked to inactive plans as well) List <Procedure> listProcsForInactive = new List <Procedure>(); //All procs that should not be linked to the active plan (linked to inactive or unnasigned) long[] arrayTpaProcNums = listTPAs.Select(x => x.ProcNum).ToArray(); //All procnums from listTPAs, makes it easier to see if a TPA exists for a proc #endregion Variables #region Fill Proc Lists and Create Active and Unassigned Plans foreach (Procedure procCur in listProcsTpTpi) //puts each procedure in listProcsForActive or listProcsForInactive { if (procCur.ProcStatus == ProcStat.TP || //all TP procs should be linked to active plan procCur.AptNum > 0 || //all procs attached to an appt should be linked to active plan procCur.PlannedAptNum > 0 || //all procs attached to a planned appt should be linked to active plan (activePlan != null && //if active plan exists and proc is linked to it, add to list listTPAs.Any(x => x.ProcNum == procCur.ProcNum && x.TreatPlanNum == activePlan.TreatPlanNum))) { listProcsForActive.Add(procCur); } else //TPi status, AptNum=0, PlannedAptNum=0, and not attached to active plan { listProcsForInactive.Add(procCur); } } //Create active plan if needed if (activePlan == null && listProcsForActive.Count > 0) { activePlan = new TreatPlan() { Heading = Lans.g("TreatPlans", "Active Treatment Plan"), Note = PrefC.GetString(PrefName.TreatmentPlanNote), TPStatus = TreatPlanStatus.Active, PatNum = patNum, //UserNumPresenter=userNum, SecUserNumEntry = userNum, TPType = tpType }; TreatPlans.Insert(activePlan); listTreatPlans.Add(activePlan); } //Update extra active plans to Inactive status, should only ever be one Active status plan //All TP procs are linked to the active plan, so proc statuses won't have to change to TPi for procs attached to an "extra" active plan foreach (TreatPlan tp in listTreatPlans.FindAll(x => x.TPStatus == TreatPlanStatus.Active && activePlan != null && x.TreatPlanNum != activePlan.TreatPlanNum)) { tp.TPStatus = TreatPlanStatus.Inactive; TreatPlans.Update(tp); } //Create unassigned plan if needed if (unassignedPlan == null && listProcsForInactive.Any(x => !arrayTpaProcNums.Contains(x.ProcNum))) { unassignedPlan = new TreatPlan() { Heading = Lans.g("TreatPlans", "Unassigned"), Note = PrefC.GetString(PrefName.TreatmentPlanNote), TPStatus = TreatPlanStatus.Inactive, PatNum = patNum, //UserNumPresenter=userNum, SecUserNumEntry = userNum, TPType = tpType }; TreatPlans.Insert(unassignedPlan); listTreatPlans.Add(unassignedPlan); } #endregion Fill Proc Lists and Create Active and Unassigned Plans #region Procs for Active Plan //Update proc status to TP for all procs that should be linked to the active plan. //For procs with an existing TPA linking it to the active plan, update proc priority to the TPA priority. //Remove any TPAs linking the proc to the unassigned plan. //Create TPAs linking the proc to the active plan if needed with TPA priority set to the proc priority. foreach (Procedure procActive in listProcsForActive) { Procedure procOld = procActive.Copy(); procActive.ProcStatus = ProcStat.TP; //checking the array of ProcNums for an existing TPA is fast, so check the list first if (arrayTpaProcNums.Contains(procActive.ProcNum)) { if (unassignedPlan != null) //remove any TPAs linking the proc to the unassigned plan { listTPAs.RemoveAll(x => x.ProcNum == procActive.ProcNum && x.TreatPlanNum == unassignedPlan.TreatPlanNum); } TreatPlanAttach tpaActivePlan = listTPAs.FirstOrDefault(x => x.ProcNum == procActive.ProcNum && x.TreatPlanNum == activePlan.TreatPlanNum); if (tpaActivePlan == null) //no TPA linking the proc to the active plan, create one with priority equal to the proc priority { listTPAs.Add(new TreatPlanAttach() { ProcNum = procActive.ProcNum, TreatPlanNum = activePlan.TreatPlanNum, Priority = procActive.Priority }); } else //TPA linking this proc to the active plan exists, update proc priority to equal TPA priority { procActive.Priority = tpaActivePlan.Priority; } } else //no TPAs exist for this proc, add one linking the proc to the active plan and set the TPA priority equal to the proc priority { listTPAs.Add(new TreatPlanAttach() { ProcNum = procActive.ProcNum, TreatPlanNum = activePlan.TreatPlanNum, Priority = procActive.Priority }); } Procedures.Update(procActive, procOld); } #endregion Procs for Active Plan #region Procs for Inactive and Unassigned Plans //Update proc priority to 0 for all inactive procs. //If no TPA exists for the proc, create a TPA with priority 0 linking the proc to the unassigned plan. foreach (Procedure procInactive in listProcsForInactive) { Procedure procOld = procInactive.Copy(); procInactive.Priority = 0; Procedures.Update(procInactive, procOld); if (unassignedPlan != null && !arrayTpaProcNums.Contains(procInactive.ProcNum)) { //no TPAs for this proc, add a new one to the list linking proc to the unassigned plan listTPAs.Add(new TreatPlanAttach { TreatPlanNum = unassignedPlan.TreatPlanNum, ProcNum = procInactive.ProcNum, Priority = 0 }); } } #endregion Procs for Inactive and Unassigned Plans #region Sync and Clean-Up TreatPlanAttach List //Remove any TPAs if the proc isn't in listProcsTpTpi, status could've changed or possibly proc is for a different pat. listTPAs.RemoveAll(x => !listProcsTpTpi.Select(y => y.ProcNum).Contains(x.ProcNum)); if (unassignedPlan != null) //if an unassigned plan exists //Remove any TPAs from the list that link a proc to the unassigned plan if there is a TPA that links the proc to any other plan { listTPAs.RemoveAll(x => x.TreatPlanNum == unassignedPlan.TreatPlanNum && listTPAs.Any(y => y.ProcNum == x.ProcNum && y.TreatPlanNum != unassignedPlan.TreatPlanNum)); } listTreatPlans.ForEach(x => TreatPlanAttaches.Sync(listTPAs.FindAll(y => y.TreatPlanNum == x.TreatPlanNum), x.TreatPlanNum)); if (unassignedPlan != null) //Must happen after Sync. Delete the unassigned plan if it exists and there are no TPAs pointing to it. { listTPAs = TreatPlanAttaches.GetAllForTreatPlan(unassignedPlan.TreatPlanNum); //from DB. if (listTPAs.Count == 0) //nothing attached to unassigned anymore { Crud.TreatPlanCrud.Delete(unassignedPlan.TreatPlanNum); } } #endregion Sync and Clean-Up TreatPlanAttach List }
private void ToolBarMainCreate_Click(){//Save TP if(gridPlans.SelectedIndices[0]!=0){ MsgBox.Show(this,"The default TP must be selected before saving a TP. You can highlight some procedures in the default TP to save a TP with only those procedures in it."); return; } //Check for duplicate procedures on the appointment before sending the DFT to eCW. if(Programs.UsingEcwTightOrFullMode() && Bridges.ECW.AptNum!=0) { List<Procedure> procs=Procedures.GetProcsForSingle(Bridges.ECW.AptNum,false); string duplicateProcs=ProcedureL.ProcsContainDuplicates(procs); if(duplicateProcs!="") { MessageBox.Show(duplicateProcs); return; } } if(gridMain.SelectedIndices.Length==0){ gridMain.SetSelected(true); } TreatPlan tp=new TreatPlan(); tp.Heading=Lan.g(this,"Proposed Treatment Plan"); tp.DateTP=DateTimeOD.Today; tp.PatNum=PatCur.PatNum; tp.Note=PrefC.GetString(PrefName.TreatmentPlanNote); tp.ResponsParty=PatCur.ResponsParty; TreatPlans.Insert(tp); ProcTP procTP; Procedure proc; int itemNo=0; List<Procedure> procList=new List<Procedure>(); for(int i=0;i<gridMain.SelectedIndices.Length;i++){ if(gridMain.Rows[gridMain.SelectedIndices[i]].Tag==null){ //user must have highlighted a subtotal row. continue; } proc=(Procedure)gridMain.Rows[gridMain.SelectedIndices[i]].Tag; procList.Add(proc); procTP=new ProcTP(); procTP.TreatPlanNum=tp.TreatPlanNum; procTP.PatNum=PatCur.PatNum; procTP.ProcNumOrig=proc.ProcNum; procTP.ItemOrder=itemNo; procTP.Priority=proc.Priority; procTP.ToothNumTP=Tooth.ToInternat(proc.ToothNum); if(ProcedureCodes.GetProcCode(proc.CodeNum).TreatArea==TreatmentArea.Surf){ procTP.Surf=Tooth.SurfTidyFromDbToDisplay(proc.Surf,proc.ToothNum); } else{ procTP.Surf=proc.Surf;//for UR, L, etc. } procTP.ProcCode=ProcedureCodes.GetStringProcCode(proc.CodeNum); procTP.Descript=RowsMain[gridMain.SelectedIndices[i]].Description; if(checkShowFees.Checked){ procTP.FeeAmt=PIn.Double(RowsMain[gridMain.SelectedIndices[i]].Fee.ToString()); } if(checkShowIns.Checked){ procTP.PriInsAmt=PIn.Double(RowsMain[gridMain.SelectedIndices[i]].PriIns.ToString()); procTP.SecInsAmt=PIn.Double(RowsMain[gridMain.SelectedIndices[i]].SecIns.ToString()); } if(checkShowDiscount.Checked){ procTP.Discount=PIn.Double(RowsMain[gridMain.SelectedIndices[i]].Discount.ToString()); } if(checkShowIns.Checked){ procTP.PatAmt=PIn.Double(RowsMain[gridMain.SelectedIndices[i]].Pat.ToString()); } procTP.Prognosis=RowsMain[gridMain.SelectedIndices[i]].Prognosis; procTP.Dx=RowsMain[gridMain.SelectedIndices[i]].Dx; ProcTPs.InsertOrUpdate(procTP,true); itemNo++; #region Canadian Lab Fees /* proc=(Procedure)gridMain.Rows[gridMain.SelectedIndices[i]].Tag; procTP=new ProcTP(); procTP.TreatPlanNum=tp.TreatPlanNum; procTP.PatNum=PatCur.PatNum; procTP.ProcNumOrig=proc.ProcNum; procTP.ItemOrder=itemNo; procTP.Priority=proc.Priority; procTP.ToothNumTP=""; procTP.Surf=""; procTP.Code=proc.LabProcCode; procTP.Descript=gridMain.Rows[gridMain.SelectedIndices[i]] .Cells[gridMain.Columns.GetIndex(Lan.g("TableTP","Description"))].Text; if(checkShowFees.Checked) { procTP.FeeAmt=PIn.PDouble(gridMain.Rows[gridMain.SelectedIndices[i]] .Cells[gridMain.Columns.GetIndex(Lan.g("TableTP","Fee"))].Text); } if(checkShowIns.Checked) { procTP.PriInsAmt=PIn.PDouble(gridMain.Rows[gridMain.SelectedIndices[i]] .Cells[gridMain.Columns.GetIndex(Lan.g("TableTP","Pri Ins"))].Text); procTP.SecInsAmt=PIn.PDouble(gridMain.Rows[gridMain.SelectedIndices[i]] .Cells[gridMain.Columns.GetIndex(Lan.g("TableTP","Sec Ins"))].Text); procTP.PatAmt=PIn.PDouble(gridMain.Rows[gridMain.SelectedIndices[i]] .Cells[gridMain.Columns.GetIndex(Lan.g("TableTP","Pat"))].Text); } ProcTPs.InsertOrUpdate(procTP,true); itemNo++;*/ #endregion Canadian Lab Fees } //Send TP DFT HL7 message to ECW with embedded PDF when using tight or full integration only. if(Programs.UsingEcwTightOrFullMode() && Bridges.ECW.AptNum!=0){ PrepImageForPrinting(); MigraDoc.Rendering.PdfDocumentRenderer pdfRenderer=new MigraDoc.Rendering.PdfDocumentRenderer(true,PdfFontEmbedding.Always); pdfRenderer.Document=CreateDocument(); pdfRenderer.RenderDocument(); MemoryStream ms=new MemoryStream(); pdfRenderer.PdfDocument.Save(ms); byte[] pdfBytes=ms.GetBuffer(); //#region Remove when testing is complete. //string tempFilePath=Path.GetTempFileName(); //File.WriteAllBytes(tempFilePath,pdfBytes); //#endregion string pdfDataStr=Convert.ToBase64String(pdfBytes); if(HL7Defs.IsExistingHL7Enabled()) { //DFT messages that are PDF's only and do not include FT1 segments, so proc list can be empty //MessageConstructor.GenerateDFT(procList,EventTypeHL7.P03,PatCur,Patients.GetPat(PatCur.Guarantor),Bridges.ECW.AptNum,"treatment",pdfDataStr); MessageHL7 messageHL7=MessageConstructor.GenerateDFT(new List<Procedure>(),EventTypeHL7.P03,PatCur,Patients.GetPat(PatCur.Guarantor),Bridges.ECW.AptNum,"treatment",pdfDataStr); if(messageHL7==null) { MsgBox.Show(this,"There is no DFT message type defined for the enabled HL7 definition."); return; } HL7Msg hl7Msg=new HL7Msg(); hl7Msg.AptNum=0;//Prevents the appt complete button from changing to the "Revise" button prematurely. hl7Msg.HL7Status=HL7MessageStatus.OutPending;//it will be marked outSent by the HL7 service. hl7Msg.MsgText=messageHL7.ToString(); hl7Msg.PatNum=PatCur.PatNum; HL7Msgs.Insert(hl7Msg); } else { Bridges.ECW.SendHL7(Bridges.ECW.AptNum,PatCur.PriProv,PatCur,pdfDataStr,"treatment",true); } } ModuleSelected(PatCur.PatNum); for(int i=0;i<PlanList.Length;i++){ if(PlanList[i].TreatPlanNum==tp.TreatPlanNum){ gridPlans.SetSelected(i+1,true); FillMain(); } } }
///<summary>Gets the hashstring for generating signatures. ///Should only be used when saving signatures, for validating see GetKeyDataForSignatureHash() and GetHashStringForSignature()</summary> public static string GetKeyDataForSignatureSaving(TreatPlan tp, List <ProcTP> proclist) { string keyData = GetKeyDataForSignatureHash(tp, proclist); return(GetHashStringForSignature(keyData)); }