maintenance: title: DOC_ACS_Reciprocal_Multi_Select ;; mlmname: DOC_ACS_Reciprocal_Multi_Select ;; arden: version 2.5;; version: 5.50;; institution: RPM, Sample Document Called MLM;; author: Rick Mansour and Allscripts Custom Services;; specialist: ;; date: 2011-07-16;; validation: testing;; library: purpose: Demonstrate the ability to select a list if the first item "all" is selected Deselect the list if all items are selected and "all" is selected Reciprocating relationship between two lists with a name relationship ;; explanation: It is common for sites to create two lists with the same list values- one to chart the patient has that symptom (+) and one to document the patient does not have that symptom (-). Charting the same item in both lists would result in the document saying the patient both has and doesn’t have the symptom. This MLM will be used across two lists to ensure that contradicting values do not get charted. If a contradicting value is individually selected, then the first item will be unselected. HOWEVER if the entire list is selected with a select all type function then the list member will be skipped if the reciprocal already checked on the reciprocal list. "all" is the first member of each list. If all is checked the the entire list is checked except "all" and any members of the opposite list that are checked. If "all" is checked when all other members of the list are already checked then the mlm sets the list to all unchecked. this mlm assumes a naming convention: 1. "ros_gi_pos"/"ros_gi_neg" are reciprical pairs" 2. "ros_gi_" is the root of both parameter names 3. "neg" and "pos" are the variable parts of the paired opposites list. 4. the list members are the same in "list value" 5. for readability of the note the "cell value" in the pos list is in UPPERCASE This assumption makes this a generic mlm. An alternative if to use an if then else statement to finds named pairs. ;; keywords: RTF, Document Called MLM , list, multi-select ;; knowledge: type: data-driven;; data: (this_documentCommunication) := argument; // CALLED MLMS used by this mlm WriteToNote := MLM {{{SINGLE-QUOTE}}}STD_DOC_FUNC_CHART_OBSERVATION_HELPER_JAB{{{SINGLE-QUOTE}}}; // {{{SINGLE-QUOTE}}}CALLED_RPM_DOM_MLM{{{SINGLE-QUOTE}}}; // get_Object := MLM{{{SINGLE-QUOTE}}}CALLED_RETURN_OBJECT{{{SINGLE-QUOTE}}}; /* Set to true if a decision.log is needed.*/ log_execution_info := false; /***************************************************************************************/ //*** Variable and Constant Declaration ***// //The following variables are references to various points in the //DocumentCommunication object model. // (this_structuredNoteDoc) := this_documentCommunication.DocumentConfigurationObj; (this_chartedObservationsList) := this_structuredNoteDoc.ChartedObservationsList; (this_parameters) := this_structuredNoteDoc.ParametersList; // this_documentCommunication.CurrentObservationObj is the observation that changed // and trigered the mlm. It shares a parameterguid with its Parameter (a member of // the observation catalog) this_currentObj := this_documentCommunication.CurrentObservationObj; parameter := FIRST OF (this_Parameters WHERE this_parameters.ParameterGUID = this_CurrentObj.ParameterGUID); parameter_name := parameter.name ; parameter_guid := parameter.ParameterGuid ; // Object needed to declare in the calling the above MLM (for listitems only) SelectedList := OBJECT[ ListGUID, SelectedValues, SuggestiveText]; if called_by_editor then parameter_name := "ros_rpm_gi_pos" ; endif; // This code determines the recirpocal paramter name IF UPPERCASE parameter_name MATCHES PATTERN "%POS%" THEN reciprocal_parameter_name := (SUBSTRING (FIND "POS" IN STRING UPPERCASE parameter_name)-1 CHARACTERS FROM STRING parameter_name) || "neg"; ELSEIF UPPERCASE parameter_name MATCHES PATTERN "%NEG%" THEN reciprocal_parameter_name := (SUBSTRING (FIND "NEG" IN STRING UPPERCASE parameter_name)-1 CHARACTERS FROM STRING parameter_name) || "pos"; ENDIF; //Get the parameter(s) and observations curr_param := first of (this_parameters where this_parameters.name = parameter_name ); recip_param := first of (this_parameters where this_parameters.name = reciprocal_parameter_name ); reciprocal_obs := FIRST OF (this_ChartedObservationsList WHERE this_ChartedObservationsList.parameterGUID = recip_param.parameterGUID); curr_obs:= FIRST OF (this_ChartedObservationsList WHERE this_ChartedObservationsList.parameterGUID = curr_param.parameterGUID); //Get the ListConfiguration object of the parameter currentObj_parameterObj := curr_param.configurationobj; // currentObj_parameterObj := CALL get_Object WITH (this_documentCommunication,parameter_name); //get the selected items currentObj_selected_items := (this_currentObj.valueobj.listitemslist.value where this_currentObj.valueobj.listitemslist.isselected = true); // currentObj_selected_items := currentObj_parameterObj.Obs_SelectedListValues; reciprocal_selected_items := (reciprocal_obs.valueobj.listitemslist.value where reciprocal_obs.valueobj.listitemslist.isselected = true); // reciprocal_parameterObj := CALL get_Object // WITH (this_documentCommunication,reciprocal_parameter_name) ; // reciprocal_selected_items := reciprocal_parameterObj.Obs_SelectedListValues; ///////////////////////////////////////////////////////////////////////////////////////////////////// count_current_config_items := (count of currentObj_parameterObj.listitemslist.value) // count_current_config_items := (count of currentObj_parameterObj.ConfigurationObjValues) AS NUMBER ; count_current_selected_items := (count of currentObj_selected_items) AS NUMBER ; newValue :=(); // initialize list of items for selection PN_sel_list := NEW SelectedList; //instantiate NewValue for ListItems IF "all" IN currentObj_selected_items THEN if count_current_selected_items = count_current_config_items then newValue := ""; //no need to select any more list items else for item IN currentObj_parameterObj.listitemslist.value do // for item IN currentObj_parameterObj.ConfigurationObjValues do if item <> "all" and item NOT IN reciprocal_selected_items then newValue := newValue, item ; endif; // if item <> "all" and item NOT IN reciprocal_selected_items enddo; // for item IN currentObj_parameterObj.listitemslist.value endif; // if count_current_selected_items = count_current_config_items // create the selection list for helper MLM PN_sel_list.ListGUID := currentObj_parameterObj.listguid; //guid for list list_name := parameter_name; ELSE // IF "all" NOT IN currentObj_selected_items THEN for item IN reciprocal_selected_items do if item <> "all" and item NOT IN currentObj_selected_items then newValue := newValue, item ; endif; // if item <> "all" and item NOT IN reciprocal_selected_items enddo; // for item IN reciprocal_selected_items // create the selection list for helper MLM PN_sel_list.ListGUID := recip_param.configurationobj.listguid; list_name := reciprocal_parameter_name; ENDIF; //if "all" IN currentObj_selected_items then PN_sel_list.SelectedValues := newvalue; //value to select PN_sel_list.SuggestiveText := null; //optional text if exists newvalue then //limit updates, otherwise copyforward will not work properly! this_documentCommunication := CALL WriteToNote WITH (this_documentCommunication, list_name , PN_sel_list); // newValue,"",""); endif; // uncomment for debugging /* sMessage := parameter_name || "\nnewvalue = " || newvalue || "\ncurrentObj_selected_items = " || currentObj_selected_items.records__ ||"\nPN_sel_list = " || PN_sel_list || "\nreciprocal_selected_items = " || reciprocal_selected_items.records__ ; //Tell DocumentCommunication to Display the Message this_documentCommunication.DisplayMessage := TRUE; this_documentCommunication.Message := sMessage ; */ //////////////////////////////////////////////////////////////////////////////////////////////////// ;; evoke: ;; logic: conclude true; ;; action: return this_documentCommunication; ;; Urgency: 50;; end: