maintenance: title: Home Medication Summary upon Discharge;; mlmname: DOC_STD_HOME_MED_SUMMARY;; arden: version 2.5;; version: 5.50;; //FP1 institution: Allscripts, Standard Document Called MLM ;; author: Allscripts Healthcare Solutions, Inc. ;; specialist: ;; date: 2011-09-07;; validation: testing ;; library: purpose: This MLM demonstrates the ability to generate a list of home medication for patient upon discharge. ;; explanation: As part of discharge workflow, hospitals are obliged to provide the patient with a document/report that list all of the home medications patient will be sent home with. Currently, there is no easy way to enable users to create such document/report. To resolve that MLMs is created to get patient’s home medication records from Outpatient Medication Profile tables. Once the medication records are retrieved into the Structured Note, the hospital can save the note as patient’s documentation ;; keywords: Discharge; home medication; Document Called MLM ;; knowledge: type: data-driven;; data: (this_documentCommunication) := argument; /***********Make Changes To Spelling And Flags In This Section**********/ /* Set to true if a decision.log is needed.*/ log_execution_info := false; /************************************************************************/ //*** Variable and Constant Declaration ***// // this is the Part III MLM that updates the document object. WriteToNote_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_DOC_WRITE_TO_DOCUMENT{{{SINGLE-QUOTE}}} ; REPLACECHAR_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_DOC_REPLACE_CHAR{{{SINGLE-QUOTE}}}; // this is the parameter in the structure note, charting on it triggers this MLM. target_parameter_name := "med_rec_summary_text";//"Out_Patient_Rx_Reconciliation" ; TAB := 9 formatted with "%c" ; (this_structuredNoteDoc) := this_documentCommunication.DocumentConfigurationObj; (this_parameters) := this_structuredNoteDoc.ParametersList; (this_event) := this_documentCommunication.EventType ; (client_guid) := this_documentCommunication.ClientGUID; (client_chart_guid) := this_documentCommunication.ChartGUID; (client_visit_guid) := this_documentCommunication.ClientVisitGUID; (this_document_name) := this_documentCommunication.DocumentName ; (this_parameters_display_name) := this_parameters.DisplayName ; (this_currentObj) := this_documentCommunication.CurrentObservationObj ; return_string:=""; target_parameter := first of (this_Parameters WHERE this_Parameters.Name = target_parameter_name); if called_by_editor then (client_visit_guid, client_guid, client_chart_guid) := READ LAST{ClientVisit:GUID,ClientGUID, ChartGUID}; endif; ReviewStatus :=READ FIRST {"SELECT ReviewStatusType FROM SXAAMBOrderMedRecReview " || "WHERE ClientGUID= " || sql(client_guid) || " and VisitGUID= " || sql(client_visit_guid) }; DischargeReconcileStatus :=READ FIRST {"SELECT ReconcileStatusType from CV3OrderReconcile " || "WHERE ClientGUID = " || sql(client_guid) || " AND ClientVisitGUID = " || sql(client_visit_guid) }; if (not exists DischargeReconcileStatus) then DischargeReconcileStatus:=1; endif; if (not exists ReviewStatus) then ReviewStatus:=0; endif; Med_Obj := OBJECT [ PrescriptionID,Name, GenericNameID,GenericItemID,Instructions, Comments,IsFreeText,ChangeDesc ] ; HomeMeds:= READ AS Med_Obj{" exec SXASvcHomeMedsSELPR " || sql(client_guid) || "," || sql(client_visit_guid) }; DischargeMeds:= READ AS Med_Obj{" exec SXASvcDischargeMedsSELPR " || sql(client_guid) || "," || sql(client_visit_guid) }; IF EXIST HomeMeds AND Exist DischargeMeds THEN tmpHomeMed2 := new med_Obj;tmpHomeMed2 := (); FOR ictr IN 1 SEQTO COUNT OF DischargeMeds DO // loop through DischargeMeds tmpHomeMed := (HomeMeds WHERE HomeMeds.GenericNameID = DischargeMeds[ictr].GenericNameID OR (HomeMeds.IsFreeText = 1 AND DischargeMeds[ictr].IsFreeText = 1 AND HomeMeds.Name = DischargeMeds[ictr].Name)); if not exists tmpHomeMed then DischargeMeds[ictr].ChangeDesc := "NEW"; else tmpHomeMed2 := (tmpHomeMed WHERE ( ( (tmpHomeMed.GenericItemID is null AND DischargeMeds[ictr].GenericItemID is null OR tmpHomeMed.GenericItemID = DischargeMeds[ictr].GenericItemID) AND (tmpHomeMed.Instructions is null AND DischargeMeds[ictr].Instruction is null OR tmpHomeMed.Instructions = DischargeMeds[ictr].Instructions) ) OR (tmpHomeMed.IsFreeText = 1 AND DischargeMeds[ictr].IsFreeText = 1 AND tmpHomeMed.Name = DischargeMeds[ictr].Name AND tmpHomeMed.Instructions = DischargeMeds[ictr].Instructions ) ) ); if exists tmpHomeMed2 then DischargeMeds[ictr].ChangeDesc := "NO CHANGE" ; else DischargeMeds[ictr].ChangeDesc := "CHANGED" ; Endif; // Reset tmpHomeMed:=""; tmpHomeMed2:=""; endif; ENDDO; FOR ictr IN 1 SEQTO COUNT OF HomeMeds DO tmpDCMed := new med_Obj; tmpDCMed := (DischargeMeds WHERE DischargeMeds.GenericNameID = HomeMeds[ictr].GenericNameID OR (DischargeMeds.IsFreeText = 1 AND HomeMeds[ictr].IsFreeText = 1 AND DischargeMeds.Name = HomeMeds[ictr].Name )); if not exist tmpDCMed then HomeMeds[ictr].ChangeDesc := "STOP"; endif; //if not exist tmpDCMed then ENDDO; // FOR ictr IN 1 SEQTO COUNT OF HomeMeds DO ELSEIF NOT EXIST HomeMeds AND EXIST DischargeMeds THEN FOR ictr IN 1 SEQTO COUNT OF DischargeMeds DO DischargeMeds[ictr].ChangeDesc := "NEW"; ENDDO; ELSEIF EXIST HomeMeds AND NOT EXIST DischargeMeds THEN FOR ictr IN 1 SEQTO COUNT OF HomeMeds DO HomeMeds[ictr].ChangeDesc := "STOP"; ENDDO; ENDIF; // IF EXIST HomeMeds AND Exist DischargeMeds THEN HEADER1_ON:="\f1\fs28 \b1"; HEADER1_OFF:="\b0 \fs0"; HEADER2_ON:="\f1\fs24 \b1"; HEADER2_OFF:="\b0 \fs0"; HEADER3_ON:="\f1\fs22 \b1"; HEADER3_OFF:="\b0 \fs0"; BODY_TAG:="\fs20"; BOLD_ON:="\b1"; BOLD_OFF:="\b0"; ITALIC_ON:="\i"; ITALIC_OFF:="\i0"; BULLETPREFIX:= "{\*\pn\pnlvlblt\pnf1\pnindent0{\pntxtb\{{{SINGLE-QUOTE}}}B7}}\fi-360\li720\sa200\sl276\slmult1 "; BULLETPREFIX_L2:= "{\*\pn\pnlvlblt\pnf1\pnindent0{\pntxtb\{{{SINGLE-QUOTE}}}B7}}\fi-360\li1080\sa200\sl276\slmult1 "; BULLETPREFIX_L3:= "{\*\pn\pnlvlblt\pnf1\pnindent0{\pntxtb\{{{SINGLE-QUOTE}}}B7}}\fi-360\li1440\sa200\sl276\slmult1 "; BULLETPOSTFIX:="\pard"; BULLET_ON:="{\pntext\f1\{{{SINGLE-QUOTE}}}B7\tab}";//"\bullet"; BULLET_OFF:="\par"; NOTDONE_STRING:="Home Medication Collection/Verification was NOT DONE for the visit in context," || "unable to determine Patient{{{SINGLE-QUOTE}}}s Home Medications on Admission."; NOTDONE_DISCHARGE_STRING:="Home Medication Collection/Verification was NOT DONE for the " || "visit in context, unable to determine Patient{{{SINGLE-QUOTE}}}s Home Medications on Discharge."; HOME_MED_STRING :="Patient{{{SINGLE-QUOTE}}}s Home Medications On Admission\n"; if (ReviewStatus = 2) then // Complete H_return_string:= HEADER1_ON|| HOME_MED_STRING|| HEADER1_OFF; elseif (ReviewStatus=1) then // InComplete H_return_string:= HEADER2_ON||"Home Medication Collection/Verification was " || "INCOMPLETE for the visit in context.\n" || "\n" || HEADER1_ON || HOME_MED_STRING || HEADER1_OFF || "\n" || HEADER2_ON || "The following Patient’s Home Medications on Admission" || " have been verified:\n"||HEADER2_OFF; else // Not Done H_return_string:= HEADER1_ON|| HOME_MED_STRING|| HEADER1_OFF; H_return_string:= H_return_string || "\n"; H_return_string:= H_return_string || HEADER2_ON || NOTDONE_STRING || HEADER2_OFF; endif; if (not exists HomeMeds) then if (ReviewStatus=2) then H_return_string:=H_return_string || BOLD_ON ||"Verified patient not taking any medication on Admission"||BOLD_OFF; elseif (ReviewStatus=1) then H_return_string:=H_return_string || BOLD_ON ||"No Patient Home Medications on Admission were verified."||BOLD_OFF; endif; else H_return_string:= H_return_string || "\n"; H_return_string:= H_return_string || BULLETPREFIX; endif; if exists HomeMeds then for ictr IN 1 SEQTO COUNT OF HomeMeds do //H_return_string:= H_return_string || TAB || BULLET; H_return_string:= H_return_string || BODY_TAG; H_return_string:= H_return_string || BULLET_ON; H_return_string:= H_return_string || BOLD_ON || LOWERCASE HomeMeds[ictr].Name || BOLD_OFF ; if (exists HomeMeds[ictr].Instructions and LENGTH(TRIM(HomeMeds[ictr].Instructions))>0 ) then tmpInst := Trim HomeMeds[ictr].Instructions; H_return_string:= H_return_string || " : " || tmpInst; endif; if (exists HomeMeds[ictr].Comments and LENGTH(TRIM(HomeMeds[ictr].Comments))>0) then tmpComments := Trim HomeMeds[ictr].Comments; tmpComments2:=CALL REPLACECHAR_MLM WITH tmpComments, "\n"; H_return_string:=H_return_string || ITALIC_ON || " . Comments: " || tmpComments2 || ITALIC_OFF; endif; H_return_string:= H_return_string || BULLET_OFF; enddo; H_return_string:=H_return_string || BULLETPOSTFIX; endif; DISCHARGE_MED_STRING :="\n\nPatient{{{SINGLE-QUOTE}}}s Home Medications on Discharge"; DISCHARGE_WARNING_STRING:="The category for the medication below is based on " || "an incomplete review of medication on Discharge:"; RECONCILIATION_WARNING_STRING:="\nThe category for the medication below is based " || "on an incomplete Discharge Reconciliation process on Discharge:"; RECONCILIATION_DISCHARGE_WARNING_STRING:="\nThe category for the medication below " || "is based on an incomplete review of medication on Admission and " || "an incomplete Discharge Reconciliation process on Discharge:\n"; if (ReviewStatus = 2) then // complete if (DischargeReconcileStatus = 2) then // complete DC_return_string:= HEADER1_ON || DISCHARGE_MED_STRING || HEADER1_OFF || BULLET_OFF || BULLETPOSTFIX; else // incomplete or something else DC_return_string:= HEADER1_ON || DISCHARGE_MED_STRING || HEADER1_OFF || BULLET_OFF || BULLETPOSTFIX; DC_return_string:= DC_return_string || HEADER2_ON || RECONCILIATION_WARNING_STRING || HEADER2_OFF; DC_return_string:= DC_return_string || "\n"; endif; DC_return_string:= DC_return_string || "\n"; elseif (ReviewStatus = 1) then // incomplete if (DischargeReconcileStatus = 2) then // complete DC_return_string:= HEADER1_ON || DISCHARGE_MED_STRING || HEADER1_OFF; DC_return_string:= DC_return_string || "\n"; DC_return_string:= DC_return_string || HEADER2_ON || DISCHARGE_WARNING_STRING || HEADER2_OFF; DC_return_string:= DC_return_string || "\n"; else // incomplete or some other status DC_return_string:= HEADER1_ON || DISCHARGE_MED_STRING || HEADER1_OFF || BULLET_OFF || BULLETPOSTFIX; DC_return_string:= DC_return_string || HEADER2_ON ||RECONCILIATION_DISCHARGE_WARNING_STRING || HEADER2_OFF; DC_return_string:= DC_return_string || "\n"; endif; else // not done DC_return_string:= HEADER1_ON || DISCHARGE_MED_STRING || HEADER1_OFF; DC_return_string:= DC_return_string || "\n\n"; DC_return_string:= DC_return_string || HEADER2_ON || NOTDONE_DISCHARGE_STRING || HEADER2_OFF; DC_return_string:= DC_return_string || "\n"; endif; if (not exists HomeMeds AND not exists DischargeMeds) then if (ReviewStatus=2) then DC_return_string:=DC_return_string || BOLD_ON || "No medication is required on Discharge"||BOLD_OFF; elseif (ReviewStatus=1) then DC_return_string:=DC_return_string || BOLD_ON || "No medication is required on Discharge."||BOLD_OFF; endif; endif; IF ReviewStatus = 1 OR ReviewStatus = 2 THEN // Stop IF exists HomeMeds Then //AND exists DischargeMeds THEN STOPMeds := new Med_Obj ; STOPMeds := (HomeMeds WHERE HomeMeds.ChangeDesc = "STOP"); STOP_MED_STRING :=" Stop taking the following Medication"; if (exists STOPMeds) then DC_return_string:= DC_return_string || "\n"; DC_return_string:= DC_return_string || BULLETPREFIX; DC_return_string:= DC_return_string || BULLET_ON; DC_return_string:= DC_return_string || HEADER2_ON || STOP_MED_STRING || HEADER2_OFF; DC_return_string:= DC_return_string || BULLET_OFF; DC_return_string:= DC_return_string || BULLETPOSTFIX; DC_return_string:= DC_return_string || BULLETPREFIX_L2; for ictr IN 1 SEQTO COUNT OF STOPMeds do DC_return_string:= DC_return_string || BODY_TAG; DC_return_string:= DC_return_string || BULLET_ON; DC_return_string:= DC_return_string || BOLD_ON || LOWERCASE STOPMeds[ictr].Name || BOLD_OFF; if (exists STOPMeds[ictr].Instructions and LENGTH(TRIM(STOPMeds[ictr].Instructions))>0) then DC_return_string:= DC_return_string || " : " || STOPMeds[ictr].Instructions; endif; if (exists HomeMeds[ictr].Comments and LENGTH(TRIM(HomeMeds[ictr].Comments))>0) then tmpComments := Trim STOPMeds[ictr].Comments; tmpComments2:=CALL REPLACECHAR_MLM WITH tmpComments, "\n"; DC_return_string:=DC_return_string || ITALIC_ON ||" . Comments: "; DC_return_string:=DC_return_string || tmpComments2 || ITALIC_OFF ; endif; DC_return_string:=DC_return_string || BULLET_OFF; enddo; DC_return_string:= DC_return_string || BULLETPOSTFIX; endif; endif; if (exists DischargeMeds) then // Continue taking the following medication if (ReviewStatus <> 0) then CONTINUE_MED_STRING:=" Continue taking the following medication:"; DC_return_string:=DC_return_string || BULLET_ON; DC_return_string:=DC_return_string || BULLETPREFIX; DC_return_string:=DC_return_string || HEADER2_ON || CONTINUE_MED_STRING || HEADER2_OFF; DC_return_string:=DC_return_string || BULLET_OFF; DC_return_string:=DC_return_string || BULLETPOSTFIX; endif; // No Change SameMeds := new med_Obj ; SameMeds := (DischargeMeds WHERE DischargeMeds.ChangeDesc = "NO CHANGE"); if exists SameMeds then DC_return_string:=DC_return_string || BULLET_ON; DC_return_string:=DC_return_string || BULLETPREFIX_L2; DC_return_string:=DC_return_string || HEADER3_ON || " These medications are NOT CHANGED:" || HEADER3_OFF; DC_return_string:=DC_return_string || BULLET_OFF; DC_return_string:=DC_return_string || BULLETPOSTFIX; DC_return_string:=DC_return_string || BODY_TAG; DC_return_string:= DC_return_string || BULLETPREFIX_L3; for ictr IN 1 SEQTO COUNT OF SameMeds do DC_return_string:= DC_return_string || BULLET_ON; DC_return_string:= DC_return_string || BOLD_ON || LOWERCASE SameMeds[ictr].Name || BOLD_OFF; if (exists SameMeds[ictr].Instructions and LENGTH(TRIM(SameMeds[ictr].Instructions))>0) then DC_return_string:= DC_return_string || " : " || SameMeds[ictr].Instructions; endif; if (exists SameMeds[ictr].Comments and LENGTH(TRIM(SameMeds[ictr].Comments))>0) then tmpComments := Trim SameMeds[ictr].Comments; tmpComments2:=CALL REPLACECHAR_MLM WITH tmpComments, "\n"; DC_return_string:=DC_return_string || ITALIC_ON || " . Comments: "; DC_return_string:=DC_return_string || tmpComments2 || ITALIC_OFF ; endif; DC_return_string:= DC_return_string || BULLET_OFF; enddo; //for ictr IN 1 SEQTO COUNT OF SameMeds do DC_return_string:=DC_return_string || BULLETPOSTFIX; endif; //if exist SameMeds then // Change ChangedMeds := new med_Obj ; ChangedMeds := (DischargeMeds WHERE DischargeMeds.ChangeDesc = "CHANGED"); if exists ChangedMeds then DC_return_string:= DC_return_string || "\n"; DC_return_string:= DC_return_string || BULLETPREFIX_L2; DC_return_string:= DC_return_string || BULLET_ON; // level 2 bullets DC_return_string:= DC_return_string || HEADER3_ON || " These medications are CHANGED: " || HEADER3_OFF; DC_return_string:= DC_return_string || BULLET_OFF; DC_return_string:= DC_return_string || BULLETPOSTFIX; DC_return_string:= DC_return_string || BODY_TAG; DC_return_string:= DC_return_string || BULLETPREFIX_L3; for ictr IN 1 SEQTO COUNT OF ChangedMeds do DC_return_string:= DC_return_string || BULLETPREFIX_L3; // level 3 bullets DC_return_string:= DC_return_string || BULLET_ON; DC_return_string:= DC_return_string || BOLD_ON || LOWERCASE ChangedMeds[ictr].Name || BOLD_OFF; if (exists ChangedMeds[ictr].Instructions and LENGTH(TRIM(ChangedMeds[ictr].Instructions))>0) then DC_return_string:= DC_return_string || " : " || ChangedMeds[ictr].Instructions; endif; if (exists ChangedMeds[ictr].Comments and LENGTH(TRIM(ChangedMeds[ictr].Comments))>0) then tmpComments:=Trim ChangedMeds[ictr].Comments; tmpComments2:=CALL REPLACECHAR_MLM WITH tmpComments, "\n"; DC_return_string:=DC_return_string || ITALIC_ON || ". Comments: "; DC_return_string:=DC_return_string || tmpComments2 || "\n" || ITALIC_OFF; endif; DC_return_string:= DC_return_string || BULLET_OFF; enddo; //for ictr IN 1 SEQTO COUNT OF ChangedMeds do DC_return_string:= DC_return_string || BULLETPOSTFIX; endif; //if exist ChangedMeds then // New NewMeds := new med_Obj ; NewMeds := (DischargeMeds WHERE DischargeMeds.ChangeDesc = "NEW"); if exists NewMeds then NEW_MED_STRING := " Start taking the following NEW medication:"; DC_return_string:= DC_return_string || BULLET_ON; DC_return_string:= DC_return_string || BULLETPREFIX; DC_return_string:= DC_return_string || HEADER2_ON || NEW_MED_STRING || HEADER2_OFF; DC_return_string:= DC_return_string || BULLET_OFF; DC_return_string:= DC_return_string || BULLETPOSTFIX; DC_return_string:= DC_return_string || BULLETPREFIX_L2; for ictr IN 1 SEQTO COUNT OF NewMeds do DC_return_string:= DC_return_string || BODY_TAG; DC_return_string:= DC_return_string || BULLET_ON; DC_return_string:= DC_return_string || BOLD_ON || LOWERCASE NewMeds[ictr].Name || BOLD_OFF; HasInstruction := exists NewMeds[ictr].Instructions and LENGTH(TRIM(NewMeds[ictr].Instructions)) <> 0; if (HasInstruction) then tmpI:=call REPLACECHAR_MLM WITH NewMeds[ictr].Instructions,"\n", "."; DC_return_string:= DC_return_string || " : " || tmpI; endif; if (exists NewMeds[ictr].Comments and LENGTH(TRIM(NewMeds[ictr].Comments)) <> 0 ) then tmpComments:=Trim NewMeds[ictr].Comments; tmpComments2:=CALL REPLACECHAR_MLM WITH tmpComments, "\n"; if (not HasInstruction) then DC_return_string:=DC_return_string || " : "; endif; DC_return_string:=DC_return_string || ITALIC_ON; DC_return_string:=DC_return_string || " Comments: "; DC_return_string:=DC_return_string || tmpComments2 || ITALIC_OFF; endif; DC_return_string:= DC_return_string || BULLET_OFF; enddo; //for ictr IN 1 SEQTO COUNT OF ChangedMeds do DC_return_string:= DC_return_string || BULLETPOSTFIX; endif; //if exist NewMeds then endif; // if exists DischargeMeds ENDIF; // IF ReviewStatus < 1 THEN if (exists H_return_string) then return_string := return_string || H_return_string; endif; if( exists S_return_string) then return_string:= return_string || S_return_string; endif; return_string:=return_string || DC_return_string; IF exists return_string THEN newValue := return_string; sugg_txt_value:= "" ; // REPLACE_APPEND "Replace" or "Append" will affect FreeTextValue Data Types REPLACE_APPEND := "Replace" ; this_documentCommunication := CALL WriteToNote_MLM WITH (this_documentCommunication, target_parameter_name,newValue,sugg_txt_value,REPLACE_APPEND); ENDIF; ////////////////////////////////////////////////////////////////////////////////////////////// ;; evoke: ;; logic: conclude true; ;; action: return this_documentCommunication; ;; Urgency: 50;; end: