maintenance: title: DOC_IANDO_FS_CRRT;; mlmname: DOC_IANDO_FS_CRRT;; arden: version 2.5;; version: 1.02;; //Release 5.5 SP1/FP1 and 6.0/6.1 SU2 and higher institution: St. Clair, Allscrtips;; author: Shawn Head;; specialist: Janet Nordin;; date: 2016-09-22;; validation: testing;; library: purpose: This MLM will automatically update an OUTPUT observation for Fluid Removal - Hemodialysis/CRRT from the "copied forward" or "shared" obsevation from the CRRT flowsheet. This MLM will also be used on the CRRT flowsheet to complete the 3 way calculation (A - B - C) that SCM cannot handle as it was throwing unhandled exception errors crashing SCM. ;; explanation: Modification history: 09.22.2016 - STH CSR#: 34876 - created 05.30.2018 - STH Ticket#: 3250761 - Issue identified where Cumulative UF was not populating on first column entry, and also the Total Net Patient Fluid removal was only calculating on first entry. Any modificatoin was not updating if a value was changed in A, B or C. {Go-Live 5/30/2018} 06.01.2018 - STH Ticket#: 3250761 - Additional issue found with initial charting not populating the Cumulative UF with the Total Net Patient Fluid on first charting {Go-Live 6-4-2018} ;; keywords: Objects Plus, CRRT, RENAL, Hemodialysis, Fluid Removal, I&O Flowsheet update. ;; knowledge: type: data-driven;; data: standard_libs := mlm {{{SINGLE-QUOTE}}}std_include_libs{{{SINGLE-QUOTE}}}; include standard_libs; using "ObjectsPlusXA.SCM.Forms"; using namespace "ObjectsPlusXA.SunriseClinicalManager.Forms"; this_DocCommObj := argument; ////////////////////////////////////////////////////////////////////////// // **** START OF USER CONFIGURED CONSTANTS ****// // Set to true if calculation should be restricted to the current hour CALC_THIS_HOUR_ONLY := TRUE; // The maximum number of hours, from the current column, to look back for // the charted rate value MAX_HRS_TO_CHK_RATE := 9; //docnames := "({{{SINGLE-QUOTE}}}2. Intake and Output{{{SINGLE-QUOTE}}},{{{SINGLE-QUOTE}}}SCH_Continuous Renal Replacement Therapy_Version{{{SINGLE-QUOTE}}})"; HOURLY_Input_A := "SCH_CRRT_Total hourly input A"; HOURLY_Output_B := "SCH_CRRT_Total hourly output B"; CRRT_Ultfilter_C := "SCH_CRRT_Ultrafiltrate Volume C"; OUTPUT_Dialysis := "SCH_IO_FluidRemoval_Dialysis"; TOTAL_Net_Fluid_Removal := "SCH_CRRT_Net Patient Fluid Removal_NU"; CRRT_CU := "SCH_CRRT_Cumulative Ultrafiltration"; // **** END OF USER CONFIGURED CONSTANTS ****// ////////////////////////////////////////////////////////////////////////// /************************************************************************/ //*** Variable and Constant Declaration ***// // log_execution_info := FALSE; stop_at_break := FALSE; // Document Types FLOWSHEET := "Flowsheet"; STRUCTUREDNOTE := "StructuredNote"; // Event Types DOCUMENTOPENING := "DocumentOpening"; CHARTOBSERVATION := "ChartObservation"; DOCUMENTCLOSING := "DocumentClosing"; // Parameter Types NUMERICVALUE := "NumericValue"; FREETEXTVALUE := "FreeTextValue"; LISTVALUE := "ListValue"; LISTSETVALUE := "ListSetValue"; DATEVALUE := "DateValue"; IOVALUE := "IOValue" ; GENERICDRIPVALUE := "GenericDripValue" ; DRIPVALUE := "DripValue" ; // set cancelProcessing to TRUE to discard the charted observation cancelProcessing := FALSE; // set debugFlag to TRUE to display a popup dialog with debug information debugFlag := FALSE; //*** Data Structures ***// // Definitions for subset of data structures that can be used to create // new objects within the MLM. ObservationType := OBJECT [ObservationGUID, ClientDocumentGUID, ParameterGUID, DataType, ValueObj]; DateValueType := OBJECT [Value]; FreeTextValueType := OBJECT [Value]; ListValueType := OBJECT [ListGUID, ListItemsList, SuggestedTextValue]; ListValueListItemType := OBJECT [ListItemGUID, Value, IsSelected]; NumericValueType := OBJECT [Value]; IOValueType := OBJECT [InValue, OutValue, DayRunningValue, BagNumber, BagInitialVolume]; GenericDripValueType := OBJECT [DoseValue, RateValue]; DripValueType := OBJECT [Value, BagNumber, BagInitialVolume]; ListSetValueType := OBJECT [ListValuesList]; CumulativeUF_value := (); CumulativeUF_colDTTM := (); // The following variables capture DocumentCommunication object model // references at the time the mlm is called. this_ClientGUID := this_DocCommObj.ClientGUID; this_ChartGUID := this_DocCommObj.ChartGUID; this_ClientVisitGUID := this_DocCommObj.ClientVisitGUID; this_ConfigurationGUID := this_DocCommObj.ConfigurationGUID; this_currentObs := this_DocCommObj.CurrentObservationObj; this_Doc := this_DocCommObj.DocumentConfigurationObj; this_DocumentType := this_DocCommObj.DocumentType; this_EventType := this_DocCommObj.EventType; IF this_DocumentType = FLOWSHEET THEN this_fs_colsList := this_Doc.ColumnsList; this_currentColumn := this_Doc.CurrentColumn; this_chartedObsList := this_currentColumn.ChartedObservationsList; ELSEIF this_DocumentType = STRUCTUREDNOTE THEN this_chartedObsList := this_Doc.ChartedObservationsList; ENDIF; this_paramList := this_Doc.ParametersList; IF NOT EXISTS this_Doc OR NOT this_Doc.IsIOFlowsheet THEN errorMessage := errorMessageHeader || "This MLM can only be used by an I&O Flowsheet."; ENDIF; FirstColDTTM := first(this_fs_colsList.DateTime where this_fs_colsList.Type = "Observation"); lastColDTTM := last(this_fs_colsList.DateTime where this_fs_colsList.Type = "Observation"); OUT_Drainage_Hemo_param := LAST (this_paramList WHERE this_paramList.Name = OUTPUT_Dialysis);//"SCH_IO_FluidRemoval_Dialysis"); //BEGIN WORKING SECTION TO ADD OUTPUT AUTOMATICALLY Input_A_Param := last (this_paramList WHERE this_paramList.Name = HOURLY_Input_A); Output_B_Param := last (this_paramList WHERE this_paramList.Name = HOURLY_Output_B); OTHER_CRRT_Param := last (this_paramList WHERE this_paramList.Name = CRRT_Ultfilter_C);//"SCH_CRRT_Cumulative Ultrafiltration"); Total_NFR_Param := last (this_paramList WHERE this_paramList.Name = TOTAL_Net_Fluid_Removal); Cumulative_UF_Param := last (this_paramList WHERE this_paramList.Name = CRRT_CU); if(((this_DocCommObj.EventType = "ChartObservation") and (true)) or (this_DocCommObj.EventType = "AutoEnter")) then for j in 1 seqto (count this_fs_colsList) do (this_obs) := this_fs_colsList[j].chartedobservationslist; valobj := null; Colobj := null; if(Cumulative_UF_Param.ParameterGUID in (this_obs.ParameterGUID)) then valobj := last of (this_obs.ValueObj where this_obs.ParameterGUID = Cumulative_UF_Param.ParameterGUID); Colobj := this_fs_colsList[j]; if(count(CumulativeUF_value) = 0) then CumulativeUF_value := (valobj.Value); else CumulativeUF_value := (CumulativeUF_value, valobj.Value); endif; if(count(CumulativeUF_colDTTM) = 0) then CumulativeUF_colDTTM := (Colobj.DateTime); else CumulativeUF_colDTTM := (CumulativeUF_colDTTM,Colobj.DateTime ); endif; endif; enddo; (group,Charted_Value, Charted_Column_DTTM) := read { " select guid ,name into #tmp_obsitems from CV3ObsCatalogMasterItem with (nolock) where name = " || sql(CRRT_Ultfilter_C) || " or name = " || sql(OUTPUT_Dialysis) || " or name = " || sql(CRRT_CU) || " select * INTO #TMP_CD FROM CV3ClientDocument CD WITH (NOLOCK) WHERE CLIENTGUID = " || SQL(this_ClientGUID) || " AND CHARTGUID = " || SQL(this_ChartGUID) || " AND CLIENTVISITGUID = " || SQL(this_ClientVisitGUID) || " AND DOCUMENTNAME = " || SQL(this_DocCommObj.DocumentName) || " and AuthoredDtm >= " || SQL(FirstColDTTM) || " and AuthoredDtm <= " || SQL(lastColDTTM) || " select case when obsx.OutValue is not null then obsx.OutValue else o.ValueText end as {{{SINGLE-QUOTE}}}value{{{SINGLE-QUOTE}}} ,cd.AuthoredDtm ,cd.guid as {{{SINGLE-QUOTE}}}cd_guid{{{SINGLE-QUOTE}}} ,ocmi2.guid as {{{SINGLE-QUOTE}}}ocmi_guid{{{SINGLE-QUOTE}}} ,ocmi2.Name into #tmp_results from #TMP_CD cd with (nolock) inner join CV3ClientDocDetail cdd with (nolock) ON (cdd.ClientDocumentGUID = cd.GUID AND cdd.ClientGUID = cd.clientguid and cdd.active = 1) inner join CV3ObservationDocument od with (nolock) ON cdd.CLientDocumentGUID = od.OwnerGUID and od.active = 1 inner join CV3Observation o with (nolock) ON o.GUID = od.ObservationGUID inner join #tmp_obsitems ocmi2 with (nolock) on od.ObsMasterItemGUID = ocmi2.GUID and ocmi2.name in({{{SINGLE-QUOTE}}}" || OUTPUT_Dialysis || "{{{SINGLE-QUOTE}}},{{{SINGLE-QUOTE}}}" || CRRT_Ultfilter_C || "{{{SINGLE-QUOTE}}},{{{SINGLE-QUOTE}}}" || CRRT_CU || "{{{SINGLE-QUOTE}}}) left Join CV3ObservationXInfo AS obsx ON (obsx.ObservationXInfoGUID = o.GUID AND obsx.ArcType = o.ArcType And obsx.BagVolumeUnit is Not Null ) select {{{SINGLE-QUOTE}}}CRRT_UFV_C{{{SINGLE-QUOTE}}}, r1.value, r1.AuthoredDtm from #tmp_results r1 with (nolock) left join #tmp_results r2 with (nolock) on r1.cd_guid = r2.cd_guid and r1.ocmi_guid <> r2.ocmi_guid and r2.name = " || sql(OUTPUT_Dialysis) || " where r1.name = " || sql(CRRT_Ultfilter_C) || " and ((r2.ocmi_guid is null) or cast(r1.AuthoredDtm as varchar) <> cast(r2.AuthoredDtm as varchar) or (r1.value <> r2.value)) or (r2.Name = {{{SINGLE-QUOTE}}}SCH_IO_FluidRemoval_Dialysis{{{SINGLE-QUOTE}}} and r2.value is not null and r1.value is null) UNION SELECT distinct {{{SINGLE-QUOTE}}}Cummulative_CRRT{{{SINGLE-QUOTE}}}, value, authoredDtm from #tmp_results where name = " || sql(CRRT_CU) || " DROP TABLE #TMP_CD, #tmp_obsitems, #tmp_results "}; Charted_CRRT_Value := (); Charted_CRRT_Column_DTTM := (); for s in (1 seqto(count(group))) do if group[s] = "Cummulative_CRRT" then if(count(CumulativeUF_value) = 0) then CumulativeUF_value := Charted_Value[s]; CumulativeUF_colDTTM := Charted_Column_DTTM[s]; else CumulativeUF_value := (CumulativeUF_value, Charted_Value[s]); CumulativeUF_colDTTM := (CumulativeUF_colDTTM, Charted_Column_DTTM[s]); endif; elseif group[s] = "CRRT_UFV_C" then if(count(Charted_CRRT_Value) = 0) then Charted_CRRT_Value := Charted_Value[s]; Charted_CRRT_Column_DTTM := Charted_Column_DTTM[s]; else Charted_CRRT_Value := (Charted_CRRT_Value, Charted_Value[s]); Charted_CRRT_Column_DTTM := (Charted_CRRT_Column_DTTM, Charted_Column_DTTM[s]); endif; endif; enddo; endif; if(this_DocCommObj.EventType = "ChartObservation") then Input_A_Obs := last of (this_chartedObsList WHERE this_chartedObsList.ParameterGUID = Input_A_Param.ParameterGUID); Output_B_Obs := last of (this_chartedObsList WHERE this_chartedObsList.ParameterGUID = Output_B_Param.ParameterGUID); CRRT_Vol_C_Obs := last of (this_chartedObsList WHERE this_chartedObsList.ParameterGUID = OTHER_CRRT_Param.ParameterGUID); OUT_Drain_Hemo_Obs := last of (this_chartedObsList WHERE this_chartedObsList.ParameterGUID = OUT_Drainage_Hemo_param.ParameterGUID); Total_NFR_Obs := last of (this_chartedObsList WHERE this_chartedObsList.ParameterGUID = Total_NFR_Param.ParameterGUID); Cumulative_UF_Obs := last of (this_chartedObsList WHERE this_chartedObsList.ParameterGUID = Cumulative_UF_Param.ParameterGUID); crrt_Value := CRRT_Vol_C_Obs.ValueObj.Value; Hemo_Value := OUT_Drain_Hemo_Obs.ValueObj.OutValue; Total_NFR_Value := Total_NFR_Obs.ValueObj.Value; Input_A_Value := Input_A_Obs.ValueObj.Value; Output_B_Value := Output_B_Obs.ValueObj.Value; if(Input_A_Value is not null and Output_B_Value is not null and crrt_Value is not null) then IF NOT EXISTS Total_NFR_Obs THEN Total_NFR_Obs := NEW ObservationType; Total_NFR_Obs.ClientDocumentGUID := this_currentColumn.ClientDocumentGUID; Total_NFR_Obs.ParameterGUID := Total_NFR_Param.ParameterGUID; Total_NFR_Obs.DataType := Total_NFR_Param.DataType; Total_NFR_Obs.ValueObj := NEW NumericValueType; ENDIF; Total_NFR_Calc_Val := ((Input_A_Value as number) - (Output_B_Value as number) - (crrt_Value as number)); IF Total_NFR_Calc_Val is not null THEN Total_NFR_Obs.ValueObj.Value := Total_NFR_Calc_Val; else Total_NFR_Obs.ValueObj := null; void := Total_NFR_Obs.ValueObj.dispose; Total_NFR_Obs := null; void := Total_NFR_Obs.dispose; ENDIF; endif; if(count(CumulativeUF_value) = 0) then AutoChart_CumulativeUF := Total_NFR_Calc_Val;//0; else tempDTTM := ""; finalDTTM := FirstColDTTM; finalValue := ""; for r in (1 seqto(count(CumulativeUF_value))) do tempDTTM := CumulativeUF_colDTTM[r]; if(tempDTTM < This_currentColumn.DateTime and tempDTTM >= FinalDTTM) then finalDTTM := tempDTTM; finalValue := CumulativeUF_value[r]; endif; enddo; if((finalValue = 0) or (finalValue = "") or (finalValue is null)) then AutoChart_CumulativeUF := Total_NFR_Calc_Val; else AutoChart_CumulativeUF := finalValue + Total_NFR_Calc_Val; endif; endif; IF NOT EXISTS Cumulative_UF_Obs THEN Cumulative_UF_Obs := NEW ObservationType; Cumulative_UF_Obs.ClientDocumentGUID := this_currentColumn.ClientDocumentGUID; Cumulative_UF_Obs.ParameterGUID := Cumulative_UF_Param.ParameterGUID; Cumulative_UF_Obs.DataType := Cumulative_UF_Param.DataType; Cumulative_UF_Obs.ValueObj := NEW NumericValueType; ENDIF; IF AutoChart_CumulativeUF is not null THEN Cumulative_UF_Obs.ValueObj.Value := AutoChart_CumulativeUF; else Cumulative_UF_Obs.ValueObj := null; void := Cumulative_UF_Obs.ValueObj.dispose; Cumulative_UF_Obs := null; void := Cumulative_UF_Obs.dispose; ENDIF; this_currentColumn.ChartedObservationsList := (this_currentColumn.ChartedObservationsList, Total_NFR_Obs, Cumulative_UF_Obs); if(this_DocCommObj.DocumentName matches pattern "%Intake and Output%") then volumeFormat := "%" || 4 || "." || 0 || "f"; abc123 := ((crrt_Value as number) <> (Hemo_Value as number)); if((Hemo_Value is null) or ((crrt_Value as number) <> (Hemo_Value as number))) then addoutput := true; else addoutput := false; endif; if((((crrt_Value as number) >= 0) or ((crrt_Value as number) <= 0)) and (addoutput)) then IF NOT EXISTS OUT_Drain_Hemo_Obs THEN OUT_Drain_Hemo_Obs := NEW ObservationType; OUT_Drain_Hemo_Obs.ClientDocumentGUID := this_currentColumn.ClientDocumentGUID; OUT_Drain_Hemo_Obs.ParameterGUID := OUT_Drainage_Hemo_param.ParameterGUID; OUT_Drain_Hemo_Obs.DataType := OUT_Drainage_Hemo_param.DataType; OUT_Drain_Hemo_Obs.ValueObj := NEW IOValueType; ENDIF; new_calcdVol := (crrt_Value as number); IF ((new_calcdVol >= 0) or (new_calcdVol <= 0)) THEN OUT_Drain_Hemo_Obs.ValueObj.OutValue := new_calcdVol FORMATTED WITH volumeFormat; else OUT_Drain_Hemo_Obs.ValueObj := null; void := OUT_Drain_Hemo_Obs.ValueObj.dispose; OUT_Drain_Hemo_Obs := null; void := OUT_Drain_Hemo_Obs.dispose; ENDIF; this_currentColumn.ChartedObservationsList := (this_currentColumn.ChartedObservationsList, OUT_Drain_Hemo_Obs); endif; endif; endif; if(this_DocCommObj.EventType = "AutoEnter") then if(count(Charted_CRRT_Value)>0) then num_cols := COUNT this_fs_colsList; FOR c IN (1 SEQTO num_cols) DO this_col := this_fs_colsList[c]; prev_col := this_fs_colsList[c-1]; if(this_col.DateTime in Charted_CRRT_Column_DTTM) then for x in (1 seqto(count(Charted_CRRT_Column_DTTM))) do if(Charted_CRRT_Column_DTTM[x] = this_col.DateTime) then volumeObservation := first of (this_col.ChartedObservationsList WHERE this_col.ChartedObservationsList.ParameterGUID = OTHER_CRRT_Param.ParameterGUID); volumeFormat := "%" || 4 || "." || 0 || "f"; IF NOT EXISTS volumeObservation THEN volumeObservation := NEW ObservationType; volumeObservation.ClientDocumentGUID := this_col.ClientDocumentGUID; volumeObservation.ParameterGUID := OUT_Drainage_Hemo_param.ParameterGUID; volumeObservation.DataType := OUT_Drainage_Hemo_param.DataType; volumeObservation.ValueObj := NEW IOValueType; ENDIF; new_calcdVol := (Charted_CRRT_Value[x] as number); testcalcval := (new_calcdVol as number); IF ((new_calcdVol >= 0) or (new_calcVol <= 0)) THEN volumeObservation.ValueObj.OutValue := new_calcdVol FORMATTED WITH volumeFormat; else volumeObservation.ValueObj := null; void := volumeObservation.ValueObj.dispose; volumeObservation := null; void := volumeObservation.dispose; ENDIF; this_col.ChartedObservationsList := (this_fs_colsList[c].ChartedObservationsList, volumeObservation); endif; enddo; endif; enddo; ENDIF; endif; ;; priority: 50 ;; evoke: ;; logic: conclude true; ;; action: return this_DocCommObj; ;; Urgency: 50;; end: