maintenance: title: Advanced Therapeutic Duplication Checking;; mlmname: STD_Duplicate_Medication_Therapy_UnsubOnly;; arden: version 2.5;; version: 18.4;; institution: Allscripts, Standard MLM;; author: Allscripts Healthcare Solutions, Inc.;; specialist: ;; date: 2018-10-26;; validation: testing;; /* P r o p r i e t a r y N o t i c e */ /* Unpublished (c) 2014 - 2018 Allscripts Healthcare, LLC. and/or its affiliates. All Rights Reserved. P r o p r i e t a r y N o t i c e: This software has been provided pursuant to a License Agreement, with Allscripts Healthcare, LLC. and/or its affiliates, containing restrictions on its use. This software contains valuable trade secrets and proprietary information of Allscripts Healthcare, LLC. and/or its affiliates and is protected by trade secret and copyright law. This software may not be copied or distributed in any form or medium, disclosed to any third parties, or used in any manner not provided for in said License Agreement except with prior written authorization from Allscripts Healthcare, LLC. and/or its affiliates. Notice to U.S. Government Users: This software is {{{SINGLE-QUOTE}}}Commercial Computer Software{{{SINGLE-QUOTE}}}. All product names are the trademarks or registered trademarks of Allscripts Healthcare, LLC. and/or its affiliates. */ /* P r o p r i e t a r y N o t i c e */ library: purpose: Provide Therapeutic Duplicate Checking using information from Multum. ;; explanation: An Evoking-Order is considered for therapeutic medication duplication when all of the criteria listed below are met: a. The evoking-order is one of the following events: new order or outpatient order, released from hold, activated from a conditional order, unsuspended, verified, or an order or outpatient order that has been modified. And in SMM when an order is entered or modified during {{{SINGLE-QUOTE}}}Perfect{{{SINGLE-QUOTE}}} b. If the evoking object is a modified order or outpatient order, it will only be checked for duplicates if there have been changes to: SignificantDtm, the StopDtm or the additives/components c. The evoking-order has an order status level number between 0-50 excluding 15 = HOLD. d. For Complex Orders only the Master order is checked An Evoking-Prescription is considered for therapeutic medication duplication when all of the criteria listed below are met: a. The evoking-prescription is one of the following events: new prescription or a renewed prescription of any of these types: a regular prescription("Rx"), a historical prescription("HX"). b. The evoking-prescription has StatusType = 1(Active) or StatusType = 5(Unapproved). Medications retrieved for duplicate checking include: a. Database/Unsubmitted medications that are active or unapproved. b. Database/Unsubmitted medications that are completed, and the evoking order{{{SINGLE-QUOTE}}}s SignificantDTM, evoking prescriptions StartDTM or RenwalDTM, or start of Today for Alert Checking, is before the completed medication{{{SINGLE-QUOTE}}}s StopDTM plus 3 times the completed medication{{{SINGLE-QUOTE}}}s half-life (e.g. if medication completed Aug 3 at 1800 and has a half-life of 12 hours, then the StopDTM plus 3 times its half life would be Aug 5 at 06:00. So if the medication being entered starts before Aug 5 at 06:00 the completed medication is included) c. If the medication being entered has no StopDTM then all medications in the database or on the unsubmitted list with a future StartDTM are included d. If the medication being placed has a StopDTM then future medications are only included if they have a StartDTM prior to the entered order{{{SINGLE-QUOTE}}}s StopDTM plus 3 x the entered orders half life. e. Database/Unsubmitted medications belonging to the session types as defined in the following list variables (e.g. at_discharge_session_list, at_in_house_session_list, at_historical_session_list, at_prescription_session_list, at_prescription_historical_session_list, or at_outpatient_session_list). The list variable corresponding to the session type of the order being entered is used. f. Orders that are part of linked order sets are checked for duplicates, unless the following occurs: - Item Catalog{{{SINGLE-QUOTE}}}s SUPPRESS DUPLICATE CHECKING FOR ORDERS IN THIS SET is CHECKED. - MLM flag USE_CATALOG_SETTING_TO_SUPPRESS_DUPLICATE_CHECKING_IN_SETS is reset to TRUE. This MLM works with Duplicate Medication information configured by the site using the Multum Data Configuration Tool. This allows the site to override the Multum data with: a. the level of category to check b. which drugs to exclude from checking c. which categories to exclude from checking d. site defined threshold levels for categories and drugs e. site defined interaction text f. site defined Duplicate Medication Override rights for categories and drugs STD_FUNC_COMMUNITY_DATA_RETRIEVAL_RULES- Checks for a user{{{SINGLE-QUOTE}}}s right to ignore a patient{{{SINGLE-QUOTE}}}s community medication allergy data when allergy check performed. This is a required MLM. Change History 3/13/2009 RS added flag to make the process account level based schaccbased = True will only fire on the current account schaccbased = False will fire on MRN 08/10/2011 TMS changed alert to fire on occupation (RN, US, RPh, and IT) instead of select user names. 02/29/2012 TMS Added Physician and physician extenders to users receiving alerts. 03/14/2012 TMS Changed order status level to 40 to only check pending and above orders for duplicates. 02/26/2013 TMS Added line to not fire duplicate for unsubmitted now order to eliminate duplicates for now and then orders. CSR 26926 10.25.2013 TMS Updated with St. clair customization for 5.5. CSR 31299 07.15.2015 TMS Updated with St. clair customization for 15.1. CSR 33555 02.16.2016 TMS Copy of STD_Duplicate_Medication_Therapy MLM to fire silent alerts for unsubmitted orders only. This version of the MLM is for statistical purposes only. CSR 33465 04.27.2016 TMS Logic added to not fire duplicate alert for stat or now orders ordered as part of the Stat and Then or Now and Then functionality. CSR 34032 04.27.2016 TMS Version of the STD_Duplicate_Medication_Therapy MLM to fire active alerts for unsubmitted orders only. CSR 33465 09.14.2016 TMS Updated logic for Stat/Now and Then orders to cycle through user defined data items to check for Now/then dosing data items on the unsubmitted and the evoking order. Alerts were generating for "quick pick" orders or orders reopened to select Now/then checkboxes. HD 2244191 05.09.2017 TMS Modified to supress duplicate alerts from between Vancomycin PO and Vancomycin IV. CSR 34904 03.21.2019 TMS Updated with St. Clair customization for 18.4 CSR 37676 ;; keywords: Therapeutic Duplication; ;; citations: {{+B}}Development{{-B}}: Drug information provided by Cerner Multum, Inc. Drug information can be customized and configured by local facility. {{+B}}Funding{{-B}}: Cerner Multum, Inc. {{+B}}Citations{{-B}}: None supplied by Cerner Multum, Inc. {{+B}}Release{{-B}}: VantageRx Multum Database ;; knowledge: type: data-driven;; data: //******************Make Changes To Spelling And Flags In This Section******************* // Set to true if logging is needed. log_execution_info := false; /* Set to only fire on specific users SCH Custom Coding*/ /* 8.10.11 (tms) changed from firing on select user names to firing on User occupation */ continue_checking_meds := TRUE; fire_on_User := ("RN","US","IT","RPh","MD","DO","DDS","DPM","PA","PA-C","CRNP"); /* Get the current user{{{SINGLE-QUOTE}}}s occupation*/ userguid :=read last {UserInfo: guid}; UserCode := read last {"Select occupationcode " ||" From cv3user with (nolock) " ||" Where Guid = " || SQL(userguid) }; continue_checking_meds := usercode in fire_on_User; /* Set the account level processing = true or false */ schaccbased := TRUE; // Set a flag indicating whether or not Actions on Alerts should be generated // NOTE - Actions on Alerts are only available in Clinical Manager Order Entry. generate_actions_on_alerts := TRUE; // The LOWEST_STATUS_LEVEL_FOR_MEDS determines the lowest order statuses // retrieved from the database and the unsubmitted orders. // A facility may wish to increase/decrease the order status number to // retrieve more/less order statuses that should be checked for duplicates. // Examples of setting are: // * 0 includes all order statuses // * 40 includes orders from Pending up (excludes Pending Verification) // // Set to a different Order Status Level // if fewer order statuses should be included lowest_status_level_for_meds:= 40; // Normally orders with a StopDTM will have 3 times their half-life added to // their stopDTM when figuring what drugs are still active in the patient{{{SINGLE-QUOTE}}}s system. // This value indicates that if a completed drug has a half // life less than this then not to bother adding on the 3 x the half-life Past_HalfLife_Grace_Period := 10000; // value in hours // Normally if the drug being ordered has a StopDTM then we add 3 times the // half-life to the StopDTM when figuring what drugs in the database with // start times in the future to include in the checking. // This value indicates that if the drug being ordered has a half // life less than this then not to bother adding on the 3 x the half-life Future_HalfLife_Grace_Period := 10000; //value in hours // Set the variable to indicate timeframe in minutes between the stopdtm // and startdtm of identical orders that would make them be considered // a reorder and thus not included in the duplicate checking. Reorder_Grace_Period := 0; // value in minutes // Set the flag to TRUE to indicate that discontinued prescriptions // should not be checked. ignore_discontinued_prescriptons := TRUE; // To display the threshold numbers in parenthesis after the category // that has been exceeded change this flag to TRUE display_threshold_numbers := FALSE; // To display all category threshold levels that have been exceeded // change this flag to FALSE display_lowest_category_exceeded := TRUE; // Set this flag to TRUE to include community data in drug interaction checking enable_community_data_medication_alerts := false; // Set flag to exclude pending Community Medications that are older that // the days specified by the flag value // Set the value to null to turn off the exclusion filter and include all // pending community medications: // exclude_pending_community_meds_older_than_days := null; exclude_pending_community_meds_older_than_days := 366; // Enter the list of triggers that you want to exclude from community medication interaction checking. // The trigger names must be strings. Use double-quotes around the trigger name. // // The following are triggers that can be placed in the list: // ("PrescriptionEnter", "PrescriptionRenew") // ("OrderInitNoIVAdditives", "OrderEnterNoIVAdditives", "OrderEnterWithIVAdditives") // ("OrderModify") // ("OutpatientOrderInitNoIVAdditive", "OutpatientOrderModify", "OutpatientOrderEnterNoIVAdditive") // ("OrderEnterPharmacyPerfect", "OrderModifyPharmacyPerfect", "OrderModifyPharmacy") // ("AlertCheckingOrder", "AlertCheckingClientPrescription") // ("OrderAlternateEnterWithIVAdditive", "OrderAlternateInitNoIVAdditive", "OrderAlternateModify") // // The default is an empty list (). It means that no triggers are excluded. community_data_excluded_triggers_list:= (); //Enter the text to differentiate community data in drug interaction checking //Sites can change the default " (Pending)" pending Community Medication identifier string // by changing the MLM flag. pending_community_medication_alert_text :=" (Pending)" ; // Set the list variables with the session types of existing orders against which // the current order will be checked. The possible values for these variables are // one or more types from the following list ("Discharge", "Inhouse", Outpatient Rx, // Outpatient Hx,"Historical", "Prescriptions", "Historical Prescriptions", //"Community Medication"). // // Set the list variables with the session types of existing prescriptions against which // the current prescription will be checked. The possible values for these variables are // one or more types from the following list ("Discharge", "Inhouse", Outpatient Rx, // Outpatient Hx,"Historical", "Prescriptions", "Historical Prescriptions", // "Community Medication"). // // The default setting is to check for Duplicate Medication checking between // - current order entered during a discharge session type and existing discharge orders, // - current order entered during an in-house session type and existing in-house orders // - current order entered during historical session type and existing historical orders. // - current prescription entered and existing and historical prescriptions. // - current historical prescriptions entered and existing and historical prescriptions // and community medication // - current outpatient orders entered and existing outpatient orders // - current pending community medications entered and existing outpatient orders // at_discharge_session_list:= ("Discharge", "Community Medication"); at_in_house_session_list:= ("Inhouse", "Community Medication"); // at_in_house_session_list:= ("Inhouse", "Community Medication", "Prescriptions"); // at_historical_session_list:= ("Historical", "Community Medication"); // at_outpatient_session_list:= ("Outpatient Rx", "Outpatient Hx", "Community Medication"); // at_prescription_session_list:= ("Prescriptions", "Historical Prescriptions", // "Community Medication", "Inhouse"); // at_prescription_historical_session_list:= ("Prescriptions", "Historical Prescriptions", // "Community Medication"); // Change this setting to TRUE to use the Item Catalog // setting for "Suppress Duplicate Checking for Items in This Set" use_catalog_setting_to_suppress_duplicate_checking_in_sets:= TRUE; // Set the variable below to indicate whether to send alert with order. // The valid values are: // "", or blank = use the {{{SINGLE-QUOTE}}}Send with order{{{SINGLE-QUOTE}}} flag set in the // Alert Types dictionary // (NOTE that default setting of flag is unchecked. If the // flag is checked and this variable is left blank or "" all // of the alerts for this MLM will be sent with the order.) // "DoNotSend" = do not send the alert regardless of the Alert Types // dictionary setting for the {{{SINGLE-QUOTE}}}Send with order{{{SINGLE-QUOTE}}} flag // "Send" = send the alert regardless of the Alert Types dictionary // setting for the {{{SINGLE-QUOTE}}}Send with order{{{SINGLE-QUOTE}}} flag send_alert := "DoNotSend"; // Set a flag indicating whether un-mapped drugs are to be reported // in the alert message or should be ignored. alert_if_unmapped := FALSE; // The SYNC_ALERT_DIALOG flag controls the alert override, acknowledgement, comment, // and document requirements in the Synchronous Alert Detail dialog. // The variable is used to set the ALERT_DIALOG_SETTINGS for the synchronous alert. // The following phrases must be placed in a single string: // "No Override Allowed", "Must Acknowledge", "If Acknowledged", // "Must Comment", "Must Document", "Conditionally Document", "Default", "" // Example: "Must Acknowledge, Must Document" sync_alert_dialog := ""; // The ASYNC_ALERT_DIALOG flag controls the comment and document requirements when // the alert is acknowledged in the Asynchronous Alert Detail dialog. The variable // is used to set the ASYNC_ALERT_DIALOG_SETTINGS for the asynchronous alert. The // following phrases must be placed in a single string: "If Acknowledged", "Must // Comment", "Must Document", "Conditionally Document", "Default", "" // Example: "If Acknowledged, Conditionally Document" async_alert_dialog := ""; // If a document can be attached to the alert, specify its name within the quotes. // Example: "Alert Override Document" alert_override_document_name := ""; // If you are using "Conditionally Document" for one of the alert dialog settings, // specify the phrases that can make the document mandatory. // Put quotes around each phrase. Put them in a list using parentheses and commas. // Example: ("Using different protocol", "Other Reason") document_conditional_text_list := (); // If you are using a User Defined Data Dictionary (UDDD), specify its name within // the quotes. // Example: "My Restricted Dictionary" UDDD_dictionary_name := ""; // If you are using UDDD, specify if is restricted dictionary or not. // Selections are: TRUE, FALSE UDDD_is_restricted := FALSE; // Change the message within the quotes if a different short-message is needed. duplicate_order_alert:= DESTINATION {Alert} WITH [ alert_type:= warning, short_message:= "Duplicate Medication Therapy", priority:= low, scope:= chart, rule_group:= "Therapeutic Med Duplicate", rule_number:= 2015, send_with_order := send_alert, alert_dialog_settings := sync_alert_dialog, async_alert_dialog_settings := async_alert_dialog, document_name := alert_override_document_name, document_conditional_text:= document_conditional_text_list, ack_comment_UDDD := UDDD_dictionary_name, ack_comment_UDDD_is_restricted := UDDD_is_restricted ]; //--------------------- // Order Trigger Events //--------------------- any_new_order:= event {OrderEnter User Order: WHERE TypeCode = "Medication" AND OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 // AND IsHeld = FALSE AND IsSuspended = FALSE }; any_new_patient_group_order:= event {OrderEnter Batch Order: WHERE TypeCode = "Medication" AND OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND IsCreatedFromPatientGroupOrderTemplate = TRUE AND IsHeld = FALSE AND IsSuspended = FALSE }; any_modified_order:= event {OrderModify User Order: WHERE TypeCode = "Medication" AND OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND IsHeld = FALSE AND ComplexOrderType not in (2, 4, 6) AND IsSuspended = FALSE }; any_released_order:= event {OrderRelease User Order: WHERE TypeCode = "Medication" AND OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND IsHeld = FALSE AND IsSuspended = FALSE }; // Other order triggers are set as "User", whereas // OrderUnsuspend trigger is set as "Any" to support "Future Unsuspend" // When the user sets an order for "Future Unsuspend", // the Order Generation services perform the unsuspend any_unsuspended_order:= event {OrderUnsuspend Any Order: WHERE TypeCode = "Medication" AND OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND IsHeld = FALSE AND ComplexOrderType not in (2, 4, 6) AND IsSuspended = FALSE }; any_verified_order:= event {OrderVerify User Order: WHERE TypeCode = "Medication" AND OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND IsHeld = FALSE AND IsSuspended = FALSE }; // -------------------------------------------------- // Outpatient Prescription and Home Medication Orders //--------------------------------------------------- // Comment out below triggers to exclude checking all Outpatient Orders // To include Home Medications remove the code {{{SINGLE-QUOTE}}}AND OrderAddtionalInfo.IsScript <> FALSE{{{SINGLE-QUOTE}}} outpatient_order_entry_trigger := event {OutpatientOrderEnterNoIVAdditive User Order: WHERE TypeCode = "Medication" AND OrderAdditionalInfo.IsScript <> FALSE}; outpatient_order_modify_trigger := event {OutpatientOrderModify User Order: WHERE TypeCode = "Medication" AND OrderAdditionalInfo.IsScript <> FALSE}; //------------------------ // Pharmacy Trigger Events //------------------------ any_pharmacy_enter_order:= event {OrderEnterPharmacyPerfect Any Order: WHERE TypeCode = "Medication" AND OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND IsHeld = FALSE AND IsSuspended = FALSE }; any_pharmacy_modify_perfect:= event {OrderModifyPharmacyPerfect Any Order: WHERE TypeCode = "Medication" AND OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND IsHeld = FALSE AND ComplexOrderType not in (2, 4, 6) AND IsSuspended = FALSE }; any_pharmacy_modify_order:= event {OrderModifyPharmacy Any Order: WHERE OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND IsHeld = FALSE AND ComplexOrderType not in (2, 4, 6) AND IsSuspended = FALSE }; // --------------------------- // Prescription Trigger Events // --------------------------- // Remove prescription types "Rx", "Hx" from the list // to exclude that type from checking // Uncomment the line with {{{SINGLE-QUOTE}}}and SourceApplicationType NOT in (10, 15){{{SINGLE-QUOTE}}} if the alerts // from this MLM should not occur in the {{{SINGLE-QUOTE}}}Meds from Other Sources{{{SINGLE-QUOTE}}} dialog when the user // accepts a Surescripts or Community Medication as a Sunrise Home Medication. // * 10 = SureScripts Medication // * 15 = Community Medication (from dbMotion) // // Depending on the required behavior, edit the {{{SINGLE-QUOTE}}}(10, 15){{{SINGLE-QUOTE}}} as follows: // * Exclude (10) to suppress the alert for SureScripts Medications // * Exclude (15) to suppress alerts for Community Medications // * Exclude (10, 15) to suppress alerts for both SureScripts and Community Medications // * Don{{{SINGLE-QUOTE}}}t exclude any of 10 or 15 to show alerts for both (default) any_new_prescription := EVENT { PrescriptionEnter Any ClientPrescription :WHERE PrescriptionTypeDescription in ("Rx", "Hx") //AND SourceApplicationType NOT in (10, 15) AND BackUp is NULL // First time PrescriptionEnter is called }; any_modify_prescription := EVENT { PrescriptionEnter Any ClientPrescription :WHERE PrescriptionTypeDescription in ("Rx", "Hx") And BackUp is NOT NULL // Unapproved/Historial Prescription is edited }; any_renew_prescription := EVENT { PrescriptionRenew Any ClientPrescription :WHERE PrescriptionTypeDescription in ("Rx") }; // ------------------------------ // Alert On Demand Trigger Events // ------------------------------ order_alert_check := event {AlertCheckingOrder User Order : WHERE ComplexOrderType not in (2, 4, 6) AND IsHeld = FALSE AND IsSuspended = FALSE }; prescription_alert_check := event {AlertCheckingClientPrescription User ClientPrescription }; // Uncomment this section if you would like historical session type orders to be // evoke this MLM, otherwise keep it commented out and this MLM will ignore // historical session type orders.If you uncomment this section make sure to // also uncomment the equivalent in the evoke clause. /* order_alternate_enter_IV:= event{OrderAlternateEnterWithIVAdditive User Order: WHERE TypeCode = "Medication" AND AlternateOrderType = 1}; order_alternate_enter_NOIV:= event{OrderAlternateEnterNoIVAdditive User Order: WHERE TypeCode = "Medication" AND AlternateOrderType = 1}; order_alternate_modify:= event{OrderAlternateModify User Order: WHERE TypeCode = "Medication" AND AlternateOrderType = 1}; */ /********************************************************************************/ // Executes only when this MLM is called by the editor if called_by_editor then // Define object choice "Order", or "ClientPrescription" object_choice := //"ClientPrescription"; "Order"; if (object_choice = "Order") then EvokingObject:= read last {Order: This WHERE TypeCode = "Medication" }; else EvokingObject:= read last {ClientPrescription: This WHERE PrescriptionTypeDescription in ("Rx", "Hx") }; endif; endif; // other MLMs being called create_alert_action_object := MLM {{{SINGLE-QUOTE}}}STD_FUNC_CREATE_ALERT_ACTION_OBJECT{{{SINGLE-QUOTE}}}; func_dup_suppress_checking := MLM {{{SINGLE-QUOTE}}}STD_FUNC_Dup_Suppress_Checking{{{SINGLE-QUOTE}}}; func_session_type_filter := MLM {{{SINGLE-QUOTE}}}STD_FUNC_SESSION_TYPE_FILTER{{{SINGLE-QUOTE}}}; func_Alert_On_Demand_Filter := MLM {{{SINGLE-QUOTE}}}STD_Func_Alert_On_Demand_Filter{{{SINGLE-QUOTE}}}; func_community_data_retrieval_rules:= MLM {{{SINGLE-QUOTE}}}STD_FUNC_COMMUNITY_DATA_RETRIEVAL_RULES{{{SINGLE-QUOTE}}}; // Retrieve user guid from State object (user_guid) := read last { StateInfo: UserGUID}; // Retrieve clientvisit guid from State object (visit_guid) := read last { StateInfo: visitGuid}; // This flag is set when there is initial error alert_if_initial_error:= FALSE; //Initialize variable to Community Data string community_medication_abstract_text := " (Community Data)"; // Enum values for Community Medication defined enum_rx_type_Community_Med := 5; // Initialize input XML parameter evoking_order_parameter_xml := ""; evoking_rx_parameter_xml := ""; unsubmitted_order_parameter_xml := ""; unsub_rx_parameter_xml := ""; filter_rx_parameter_xml := ""; renewed_as_me_rx_parameter_xml := ""; check_if_rx_is_from_orm := false; check_if_rx_is_from_orm_str := read last { "SELECT Value FROM HVCEnvProfile WHERE HierarchyCode = {{{SINGLE-QUOTE}}}Orders|Order Reconciliation Types|Discharge Reconciliation{{{SINGLE-QUOTE}}} and Code = {{{SINGLE-QUOTE}}}DuplicateMedicationTherapyChecking{{{SINGLE-QUOTE}}}"}; if ( check_if_rx_is_from_orm_str = "False" OR check_if_rx_is_from_orm_str = "F" ) then // value is reversed by design - if the EP setting is FALSE, we WANT to check the {{{SINGLE-QUOTE}}}isFromORM{{{SINGLE-QUOTE}}} flag check_if_rx_is_from_orm := true; endif; evoking_rx_is_from_orm := false; //added to eliminate duplicate alert firing when medication ordered as Now and Then dosing /* Get the OrderUserData object pointer */ OrderUserDataObj := read last { Order: OrderUserData REFERENCING EvokingObject }; for r in (1 seqto(count(OrderUserDataObj))) do CurOrder_UserDataFields := OrderUserDataObj[r]; (userdatacodelist, valuelist ) := read { OrderUserData: UserDataCode, Value REFERENCING CurOrder_UserDataFields } ; for s in (1 seqto(count(userdatacodelist))) do if ((userdatacodelist [s] = "PRX_Dosing Start Now" or userdatacodelist [s] = "PRX_Dosing Stat and Then" or userdatacodelist [s] = "PRX_Dosing Addl Dose" ) and valuelist [s] = "1" ) and (EVOKINGOBJECT.FrequencyCode = "Stat" or EVOKINGOBJECT.FrequencyCode = "Now") then continue_checking_meds := false; endif; enddo; enddo; //end of added Now and then dosing logic if (EvokingObject is Order) then // Gets information from the evoking Order (main_order_name, evoking_order_object_guid, order_status_code, order_level_num, order_summary_line, main_item_catalog_guid, chart_guid, client_guid, client_visit_guid, significant_date, requested_date, entered_date, stop_date, order_is_conditional, order_exists, parent_conditional_order_guid, order_component_obj, complex_order, order_is_for_discharge, order_alternate_order_type, evoking_med_source, back_up_obj, evoking_order_additional_info) := read last {Order: Name, GUID, OrderStatusCode, OrderStatusLevelNum, SummaryLine, OrderCatalogMasterItemGUID, ChartGUID, ClientGUID, ClientVisitGUID, SignificantDtm, RequestedDtm, Entered, StopDtm, IsConditional, OrderExists, ParentConditionalOrderGUID, OrderComponent, ComplexOrderType, IsForDischarge, AlternateOrderType, AlertOnDemandSource, Backup, OrderAdditionalInfo REFERENCING EvokingObject }; (evoking_order_isScript) := read last {OrderAdditionalInfo: IsScript REFERENCING evoking_order_additional_info}; if exists EvokingObject and (significant_date is null) then alert_if_initial_error:= TRUE; endif; // Only retrieves data if the Order has IV additives If exist order_component_obj then // Gets the catalog item from the order component object (evoking_additive_cat_item_guid_list, evoking_additive_name_list) := read { OrderComponent: OrderCatalogMasterItemGUID, Name REFERENCING order_component_obj where (Dosage AS Number) > 0 }; endif; /* Initialize variable to empty string */ avoid_parent_orderset_guid := ""; avoid_child_orderset_guid := ""; cont1 := continue_checking_meds; //marker RS mainorder := main_order_name; //marker RS //if exists main_order_name if (exists main_order_name and continue_checking_meds = true) then continue_checking_meds := TRUE; If use_catalog_setting_to_suppress_duplicate_checking_in_sets then (avoid_parent_orderset_guid, avoid_child_orderset_guid) := call func_dup_suppress_checking with main_order_name, evoking_order_object_guid; if not exist avoid_parent_orderset_guid then avoid_parent_orderset_guid := ""; endif; if not exist avoid_child_orderset_guid then avoid_child_orderset_guid := ""; endif; endif; else continue_checking_meds := FALSE; endif; evoking_item_name := main_order_name; elseif (EvokingObject is ClientPrescription) then (evoking_rx_name, evoking_rx_start_date, evoking_rx_stop_date, evoking_rx_renewal_date, evoking_rx_cds_unique_guid, evoking_rx_generic_name_id, evoking_rx_status_type, evoking_rx_prescription_type, client_guid, evoking_med_source, evoking_rx_back_up, evoking_rx_is_from_orm, evoking_dispensed_detail_id ) := read last {ClientPrescription: DrugName, StartDate, EndDate, RenewalDate, CDSUniqueIDGUID, GenericNameID, StatusType, PrescriptionType, ClientGUID, AlertOnDemandSource, BackUp, IsFromORM, DispensedDetailID REFERENCING EvokingObject WHERE PrescriptionTypeDescription in ("Rx", "Hx") }; continue_checking_meds := TRUE; if (evoking_rx_renewal_date is NULL) then significant_date := evoking_rx_start_date; else significant_date := evoking_rx_renewal_date; endif; stop_date := evoking_rx_stop_date; evoking_item_name := evoking_rx_name; // When the prescription is renewed with "renew as me", or when it is being modified, // the CDSUniqueIDGUID value changes if ((EvokingEventType = any_renew_prescription.type OR EvokingEventType = any_modify_prescription.type) AND evoking_rx_cds_unique_guid <> evoking_rx_back_up.CDSUniqueIDGUID AND evoking_rx_back_up.CDSUniqueIDGUID is not null) then renewed_as_me_orig_rx_cds_unique_guid := evoking_rx_back_up.CDSUniqueIDGUID; endif; endif; // When the flag is set to TRUE, the alert generated for all users does include dbMotion medication data // that conflicts with current medication that triggered the call to the Interaction MLM. if(enable_community_data_medication_alerts = true) then // mlm name is passed to STD_FUNC_COMMUNITY_DATA_RETRIEVAL_RULES which is responsible for user right{{{SINGLE-QUOTE}}}s mlm_Name := "STD_DUPLICATE_MEDICATION_THERAPY_UNSUBONLY"; //To make sure that the below SUB MLM is called only when the flag is true. (can_perform,can_retrieve_data_obj) := call func_community_data_retrieval_rules with ( EvokingObject, EvokingEventType, mlm_Name, community_data_excluded_triggers_list ); else can_perform := true; endif; if (can_perform) then is_alert_on_demand := false; if (EvokingEventType = order_alert_check.type OR EvokingEventType = prescription_alert_check.type) then alert_on_demand_obj := read last {StateInfo: AlertOnDemand}; aod_check_against_flag := alert_on_demand_obj.AlertCheckAgainstSelection; // Get the session type bit flags and prescription type filter // from the AlertCheckAgainstSelection flag (order_table_name, include_in_house_session_type_orders, include_historical_session_type_orders, include_discharge_session_type_orders, include_outpatient_rx_session_type_orders, include_outpatient_hx_session_type_orders, unsubmitted_session_type_bit_flags, unsubmitted_prescriptions_filter_list, filter_prescriptions_query, prescriptions_type_filter_list, include_community_medication):= call func_Alert_On_Demand_Filter with (aod_check_against_flag, can_retrieve_data_obj.PendingImportedMedications); is_alert_on_demand := true; // For alert checking, evoking medication is checked from start of today start_date := (day floor of now); else // Get the session type bit flags to filter the unsubmitted orders // that will be checked against the entered order. (order_table_name, filter_orders_query, order_session_type_bit_flags, filter_prescriptions_query, prescriptions_type_filter_list, include_in_house_session_type_orders, include_historical_session_type_orders, include_discharge_session_type_orders, include_outpatient_rx_session_type_orders, include_outpatient_hx_session_type_orders, include_community_medication ) := call func_session_type_filter with (at_in_house_session_list, at_historical_session_list, at_discharge_session_list, at_outpatient_session_list, at_prescription_session_list, at_prescription_historical_session_list, can_retrieve_data_obj.PendingImportedMedications, order_is_for_discharge, order_alternate_order_type, evoking_rx_prescription_type); db_session_type_bit_flags := order_session_type_bit_flags; unsubmitted_session_type_bit_flags := order_session_type_bit_flags; unsubmitted_prescriptions_filter_list := prescriptions_type_filter_list; // Check medications from significant date for non-alert checking triggers start_date := significant_date; if (start_date is NULL) then // Prescriptions can have empty start dates. Set it to Today. start_date := (day floor of now); endif; endif; // if evoking event is from SMM or Prescription Writer // then do not want Actions on Alerts If EvokingEventType = any_pharmacy_enter_order.type OR EvokingEventType = any_pharmacy_modify_order.type OR EvokingEventType = any_pharmacy_modify_perfect.type OR EvokingEventType = any_new_prescription.type OR EvokingEventType = any_renew_prescription.type then generate_actions_on_alerts := FALSE; endif; If EvokingEventType = any_modified_order.type OR EvokingEventType = any_pharmacy_modify_order.type OR EvokingEventType = order_alternate_modify.type OR EvokingEventType = outpatient_order_modify_trigger.type then continue_checking_meds:= false; if exist back_up_obj then (back_up_obj_signif_date, back_up_obj_stop_date, back_up_obj_component_obj):= read last {Order: SignificantDtm, StopDtm, OrderComponent REFERENCING back_up_obj WHERE OrderSetGUID not in avoid_parent_orderset_guid AND OrderSubSetGUID not in avoid_child_orderset_guid}; if (back_up_obj_signif_date <> significant_date) OR (back_up_obj_stop_date <> stop_date) OR (back_up_obj_stop_date is null and stop_date is time) OR (back_up_obj_stop_date is time and stop_date is null) then continue_checking_meds:= true; endif; if exist order_component_obj then // Gets the catalog item from the order component object (temp_additive_cat_item_guid_list) := read { OrderComponent: OrderCatalogMasterItemGUID REFERENCING order_component_obj where (Dosage AS Number) > 0 }; if not exist back_up_obj_component_obj then continue_checking_meds:= true; endif; endif; if exist back_up_obj_component_obj then (back_up_add_cat_item_guid_list) := read { OrderComponent: OrderCatalogMasterItemGUID REFERENCING back_up_obj_component_obj where (Dosage AS Number) > 0 }; if not exist order_component_obj then continue_checking_meds:= true; else // Check if the additive list is different additive_removed := not all (back_up_add_cat_item_guid_list in temp_additive_cat_item_guid_list); additive_added := not all (temp_additive_cat_item_guid_list in back_up_add_cat_item_guid_list); if (additive_removed or additive_added) then continue_checking_meds:= true; endif; endif; endif; //if exist back_up_obj_component_obj endif; // if exist back_up_obj elseif (EvokingEventType = any_modify_prescription.type AND evoking_rx_back_up is not NULL) then backup_rx_start_date := evoking_rx_back_up.StartDate; backup_rx_stop_date := evoking_rx_back_up.EndDate; backup_rx_renewal_date := evoking_rx_back_up.RenewalDate; if ( evoking_rx_start_date <> backup_rx_start_date ) OR ( evoking_rx_stop_date <> backup_rx_stop_date ) OR ( evoking_rx_renewal_date <> backup_rx_renewal_date ) OR ( backup_rx_start_date is NULL and evoking_rx_start_date is NOT NULL ) OR ( backup_rx_start_date is NOT NULL and evoking_rx_start_date is NULL ) OR ( backup_rx_stop_date is NULL and evoking_rx_stop_date is NOT NULL ) OR ( backup_rx_stop_date is NOT NULL and evoking_rx_stop_date is NULL ) then continue_checking_meds:= true; else continue_checking_meds:= false; endif; endif; // if modify if continue_checking_meds then if (evoking_med_source = "EvokingCatalog") then evoking_is_selected := 1; else evoking_is_selected := 0; endif; // Add evoking object information in the input XML parameter if (EvokingObject is Order) then evoking_order_parameter_xml := " \n"; additive_index_list := 1 seqto count (evoking_additive_name_list); for additive_ind in additive_index_list do evoking_additive_cat_GUID := evoking_additive_cat_item_guid_list[additive_ind]; evoking_additive_name := evoking_additive_name_list[additive_ind]; if (evoking_additive_cat_GUID is not null) then evoking_additive_xml := " \n"; evoking_order_parameter_xml := evoking_order_parameter_xml || evoking_additive_xml; endif; enddo; evoking_item_guid := evoking_order_object_guid; evoking_item_name := main_order_name; else evoking_rx_parameter_xml := " \n"; evoking_item_guid := evoking_rx_cds_unique_guid; evoking_item_name := evoking_rx_name; endif; // END if EvokingObject - for adding evoking object info unsubmitted_session_flag_override := false; if (is_alert_on_demand AND not include_in_house_session_type_orders) then include_in_house_session_type_orders := true; unsubmitted_session_flag_override := true; endif; // Get the unsubmitted orders // that should be checked for therapeutic duplication. // These are New or Modified orders (unsub_intended_action_list, unsub_order_name_list, unsub_order_guid_list, unsub_start_time_list, unsub_requested_date_list, unsub_entered_time_list, unsub_stop_time_list, unsub_summary_line_list, unsub_catalog_item_guid_list, unsub_order_additiveobj_list, unsub_freq_code_list, unsub_order_user_data_Obj, unsub_order_med_source_list, unsub_order_status_num_list, unsub_alternate_order_type_list, unsub_order_additional_info_list) := read {Unsubmitted Order: IntendedAction, Name, GUID, SignificantDtm, RequestedDtm, Entered, StopDtm, SummaryLine, OrderCatalogMasterItemGUID, OrderComponent, FrequencyCode, OrderUserData, AlertOnDemandSource, OrderStatusLevelNum, AlternateOrderType, OrderAdditionalInfo WHERE TypeCode = "Medication" AND ComplexOrderType not in (2,4,6) AND IsHeld = FALSE AND IsSuspended = FALSE AND OrderStatusLevelNum >= lowest_status_level_for_meds // AND OrderStatusLevelNum <= 50 AND ( OrderSetGUID not in avoid_parent_orderset_guid OR OrderSetGUID is NULL) AND ( OrderSubSetGUID not in avoid_child_orderset_guid OR OrderSubSetGUID is NULL) AND not( (not include_in_house_session_type_orders AND (AlternateOrderType = 0 AND IsForDischarge = false)) OR (not include_historical_session_type_orders AND AlternateOrderType = 1) OR (not include_discharge_session_type_orders AND IsForDischarge) OR (not include_outpatient_rx_session_type_orders AND (AlternateOrderType = 2 AND OrderAdditionalInfo.IsScript = true)) OR (not include_outpatient_hx_session_type_orders AND (AlternateOrderType = 2 AND OrderAdditionalInfo.IsScript = false))) }; if (unsubmitted_session_flag_override) then include_in_house_session_type_orders := false; endif; // For each unsubmitted order, add the order-name and additive info (if any), // to the list of unsubmitted order names to be processed. unsubmitted_order_parameter_xml := ""; index_list := 1 seqto count (unsub_order_name_list); for JJ in index_list do unsub_order_guid := unsub_order_guid_list[JJ]; unsub_cat_guid := unsub_catalog_item_guid_list[JJ]; unsub_additiveObj := unsub_order_additiveobj_list[JJ]; unsub_order_name := unsub_order_name_list[JJ]; unsub_order_significant_dtm := unsub_start_time_list[JJ]; unsub_order_requested_dtm := unsub_requested_date_list[JJ]; unsub_order_entered_dtm := unsub_entered_time_list[JJ]; unsub_order_stop_dtm := unsub_stop_time_list[JJ]; unsub_order_summary_line := unsub_summary_line_list[JJ]; unsub_order_med_source := unsub_order_med_source_list[JJ]; unsub_freq_code := unsub_freq_code_list[JJ]; unsub_order_status_num := unsub_order_status_num_list[JJ]; unsub_alternate_order_type := unsub_alternate_order_type_list[JJ]; unsub_order_additional_info := unsub_order_additional_info_list[JJ]; unsub_is_script := read last {OrderAdditionalInfo: IsScript REFERENCING unsub_order_additional_info}; unsub_freq_code := unsub_freq_code_list[JJ]; unsub_UserData := unsub_order_user_data_Obj [JJ]; ( UnsubUserDataCode, UnsubValue ) := read last { OrderUserData: UserDataCode, Value REFERENCING unsub_UserData where UserDataCode = "PRX_Dosing Addl Dose" }; if (unsub_order_med_source = "EvokingCatalog" OR unsub_order_med_source = "SelectedCatalog" ) then unsub_is_selected := 1; else unsub_is_selected := 0; endif; if UnsubUserDataCode = "PRX_Dosing Addl Dose" and UnsubValue = "1" and (unsub_freq_code = "STAT" or unsub_freq_code = "Now") and EVOKINGOBJECT.Name = unsub_order_name then processthisorder := "No"; else unsubmitted_order_parameter_xml := unsubmitted_order_parameter_xml|| " \n"; // If there is are additives obtain the info // If there is are additives obtain the info if exist unsub_additiveObj then (temp_additive_name_list, temp_item_guid_list):= read { OrderComponent: Name, OrderCatalogMasterItemGUID REFERENCING unsub_additiveObj where (Dosage AS Number) > 0 }; // Equalize the length of the lists additive_index_list := 1 seqto count(temp_additive_name_list); for additive_ind in additive_index_list do unsubmitted_additive_cat_GUID := temp_item_guid_list[additive_ind]; unsubmitted_additive_name := temp_additive_name_list[additive_ind]; if (unsubmitted_additive_cat_GUID is not null) then unsubmitted_additive_xml := " \n"; unsubmitted_order_parameter_xml := unsubmitted_order_parameter_xml || unsubmitted_additive_xml; endif; enddo; //for additive_index_list endif; //if exist unsub_additiveObj endif; enddo; //for for JJ // ----------- unsubmited rx processing -------------------- // Get the unsubmitted prescriptions // that should be checked for therapeutic duplication. // These are New or Modified prescriptions (unsub_rx_name_list, unsub_rx_start_time_list, unsub_rx_stop_time_list, unsub_rx_renewal_time_list, unsub_rx_cds_unique_guid_list, unsub_rx_generic_name_id_list, unsub_rx_status_type_list, unsub_rx_prescription_type_list, unsub_rx_med_source_list ) := read {Unsubmitted ClientPrescription: DrugName, StartDate, EndDate, RenewalDate, CDSUniqueIDGUID, GenericNameID, StatusType, PrescriptionType, AlertOnDemandSource WHERE PrescriptionType in unsubmitted_prescriptions_filter_list AND ( StatusType in (0,1,5) OR (ignore_discontinued_prescriptons=FALSE AND StatusType=3) ) }; unsub_rx_parameter_xml := ""; unsub_rx_index_list := 1 seqto count(unsub_rx_name_list); unsub_rx_significant_dtm_list:= (); for unsub_rx_ind in unsub_rx_index_list do unsub_rx_cds_unique_guid := unsub_rx_cds_unique_guid_list[unsub_rx_ind]; unsub_rx_name := unsub_rx_name_list[unsub_rx_ind]; unsub_rx_generic_name_id := unsub_rx_generic_name_id_list[unsub_rx_ind]; unsub_rx_med_source := unsub_rx_med_source_list[unsub_rx_ind]; unsub_rx_prescription_type:= unsub_rx_prescription_type_list[unsub_rx_ind]; if (unsub_rx_med_source = "EvokingCatalog" OR unsub_rx_med_source = "SelectedCatalog" ) then unsub_is_selected := 1; else unsub_is_selected := 0; endif; if (unsub_rx_renewal_time_list[unsub_rx_ind] is not null) then unsub_rx_significant_dtm := unsub_rx_renewal_time_list[unsub_rx_ind]; else unsub_rx_significant_dtm := unsub_rx_start_time_list[unsub_rx_ind]; endif; unsub_rx_significant_dtm_list := unsub_rx_significant_dtm_list, (unsub_rx_significant_dtm as time); if (unsub_rx_significant_dtm is NULL) then unsub_rx_significant_dtm := (day floor of now); endif; unsub_rx_stop_dtm := unsub_rx_stop_time_list[unsub_rx_ind]; unsub_rx_parameter_xml := unsub_rx_parameter_xml || " \n"; enddo; // END for unsub_rx_ind for rx_type in prescriptions_type_filter_list do filter_rx_parameter_xml := filter_rx_parameter_xml || " \n"; enddo; if exists renewed_as_me_orig_rx_cds_unique_guid then renewed_as_me_rx_parameter_xml := " \n"; endif; // Community medication parameter orig_pending_community_med_str := ""; if (evoking_dispensed_detail_id is not null) then orig_pending_community_med_str := " OriginalCommunityMedicationId={{{SINGLE-QUOTE}}}" || XMLEX(evoking_dispensed_detail_id) || "{{{SINGLE-QUOTE}}}"; endif; // exclude pending community medication parameter exclude_older_than_days_str := ""; if (exclude_pending_community_meds_older_than_days is not null) then exclude_older_than_days_str := " ExcludeOlderThanDays={{{SINGLE-QUOTE}}}" || XMLEX(exclude_pending_community_meds_older_than_days) || "{{{SINGLE-QUOTE}}}"; endif; community_medication_parameter_xml := ""; community_medication_parameter_xml := community_medication_parameter_xml || " \n"; input_parameter_xml := "\n\n" || evoking_order_parameter_xml || evoking_rx_parameter_xml || unsubmitted_order_parameter_xml || unsub_rx_parameter_xml || filter_rx_parameter_xml || renewed_as_me_rx_parameter_xml || community_medication_parameter_xml || "\n"; // Convert the boolean values to binary flag ignore_discontinued_prescriptons_flag := ignore_discontinued_prescriptons as number; display_lowest_category_exceeded_flag := display_lowest_category_exceeded as number; //prepare new parameter for conditional order check_parent_conditional_order := 0; if (EvokingObject is Order AND order_is_conditional = false AND order_exists = true ) then check_parent_conditional_order := 1; endif; include_existing_db_orders := true; if (check_if_rx_is_from_orm AND evoking_rx_is_from_orm) then include_existing_db_orders := false; endif; // Call stored proc to check duplicate medication therapy (ComponentDrugKey_list, ParentDrugKey_list, EnteredDrugComponent_list, EnteredDrugName_list, EnteredIsAdditive_list, DuplicateOrderName_list, DuplicateAdditiveName_list, DupIngredientName_list, DupIsAdditive_list, DupOrderGUID_list, OrderCatlogMasterItem_list, DupCategoryName_list, MaxDupThreshold_list, DupSummaryLine_list, DupStartDTM_list, DupRequestedDTM_list, DupEnteredDTM_list, DupStopDTM_list, DupOrderStatusNum_list, DupOrderStatus_list, CategoryLevel_list, IsMapped_list, DupIsOrder_list, DupAlternateOrderType_list, DupIsScript_list, DupPrescriptionType_list):= read{" SCMTherapeuticDuplicateMedsCheckingPR " || SQL(input_parameter_xml) || ", " || client_guid || ", " || user_guid || ", " || SQL(Past_HalfLife_Grace_Period) || ", " || SQL(Future_HalfLife_Grace_Period) || ", " || SQL(Reorder_Grace_Period) || ", " || SQL(lowest_status_level_for_meds) || ", " || SQL(include_in_house_session_type_orders) || ", " || SQL(include_discharge_session_type_orders) || ", " || SQL(include_historical_session_type_orders) || ", " || SQL(include_outpatient_rx_session_type_orders) || ", " || SQL(include_outpatient_hx_session_type_orders) || ", " || SQL(avoid_parent_orderset_guid) || ", " || SQL(avoid_child_orderset_guid) || ", " || SQL(ignore_discontinued_prescriptons_flag) || ", " || SQL(display_lowest_category_exceeded_flag) || ", " || SQL(check_parent_conditional_order) || ", " || SQL(parent_conditional_order_guid) || ", " || SQL(include_existing_db_orders) }; //added from RS custom coding //marker RS added flag to make the process account level based sqlextract := ""; countnosub := 0; if exist EnteredDrugName_list then // if main_order_name = "Vancomycin:" then noalertname := "Vancomycin Soln"; elseif main_order_name = "Vancomycin Soln" then noalertname := "Vancomycin:"; else noalertname := "x"; endif; spool_list := 1 seqto count (EnteredDrugName_list); for countorder in spool_list do singorder := DupOrderGUID_list[countorder]; singsum := DupSummaryLine_list[countorder]; singstat := DupOrderStatus_list[countorder]; singname:= DuplicateOrderName_list[countorder]; if (singsum <>"Unsubmitted" and (singsum is not null) and (singname <> noalertname)) // no need to check different accoutn if = unsubmitted then // countnosub := countnosub + 1; if countnosub = 1 then sqlextract := "{{{SINGLE-QUOTE}}}" || singorder || "{{{SINGLE-QUOTE}}}"; else sqlextract := sqlextract || ",{{{SINGLE-QUOTE}}}" || singorder || "{{{SINGLE-QUOTE}}}"; endif; endif; enddo; endif; // if (schaccbased = true) and (countnosub > 0) // use account based, must have dup orders not submitted. // then // (NoAccOrderList,NoAccClientvisit) := read{ " Select guid,clientvisitguid " // || " from Cv3order as o " // || " where o.guid in ( " || sqlextract || ") " // || " and o.clientvisitguid <> " || SQL(client_visit_guid) // }; if (exist DupOrderStatus_list)// and (exist NoAccOrderList) then spool_list := 1 seqto count (DupOrderStatus_list); // if (exist EnteredDrugName_List) and (exist NoAccOrderList) // then // spool_list := 1 seqto count (EnteredDrugName_list); // set temp lists RSCPDK := (); RSPDK := (); RSEDC := (); RSEDN := (); RSEIA:= (); RSDON :=(); RSDAN := (); RSDIN := (); RSDIA := (); RSDOG :=(); RSOCMI := (); RSDCN := (); RSMDT := (); RSDSL:=(); RSDStaD:= (); RSDReqD := (); RSDEntD := (); RSDStoD := (); RSDOSN := (); RSDOSL:= (); RSCL:=(); RSIM := (); RSDIO := (); RSDAOT := (); RSDIS := (); RSDPT := (); addhappened:=false; for countorder in spool_list do singstat := DupOrderStatus_list[countorder]; singname := DuplicateOrderName_list[countorder]; // if (singstat = "Unsubmitted Order") if (singstat = "Unapproved") and (singname <> noalertname) then // // for countorder in spool_list do // singorder := DupOrderGUID_list[countorder]; // if (singorder not in NoAccOrderList) // then RSCPDK := RSCPDK ,ComponentDrugKey_list[countorder] ; RSPDK := RSPDK , ParentDrugKey_list[countorder] ; RSEDC := RSEDC , EnteredDrugComponent_list[countorder] ; RSEDN := RSEDN , EnteredDrugName_list[countorder] ; RSEIA := RSEIA, EnteredIsAdditive_list[countorder] ; RSDON := RSDON , DuplicateOrderName_list[countorder] ; RSDAN := RSDAN, DuplicateAdditiveName_list[countorder] ; RSDIN := RSDIN, DupIngredientName_list[countorder] ; RSDIA := RSDIA, DupIsAdditive_list[countorder] ; RSDOG := RSDOG, DupOrderGUID_list[countorder] ; RSOCMI := RSOCMI, OrderCatlogMasterItem_list[countorder] ; RSDCN := RSDCN , DupCategoryName_list[countorder] ; RSMDT := RSMDT , MaxDupThreshold_list[countorder] ; RSDSL := RSDSL, DupSummaryLine_list[countorder] ; RSDStaD := RSDStaD, DupStartDTM_list[countorder] ; RSDReqD := RSDReqD, DupRequestedDTM_list[countorder] ; RSDEntD := RSDEntD,DupEnteredDTM_list[countorder] ; RSDStoD := RSDStoD , DupStopDTM_list[countorder] ; RSDOSN := RSDOSN , DupOrderStatusNum_list[countorder] ; RSDOSL := RSDOSL, DupOrderStatus_list[countorder] ; RSCL := RSCL, CategoryLevel_list[countorder] ; RSIM := RSIM, IsMapped_list[countorder] ; RSDIO := RSDIO, DupIsOrder_list[countorder] ; RSDAOT := RSDAOT,DupAlternateOrderType_list[countorder] ; RSDIS := RSDIS,DupIsScript_list[countorder] ; RSDPT := RSDPT,DupPrescriptionType_list[countorder] ; addhappened := true; endif; enddo; if (addhappened = true) then ComponentDrugKey_list:= RSCPDK ; ParentDrugKey_list:= RSPDK ; EnteredDrugComponent_list:= RSEDC ; EnteredDrugName_list:= RSEDN ; EnteredIsAdditive_list := RSEIA ; DuplicateOrderName_list := RSDON ; DuplicateAdditiveName_list := RSDAN ; DupIngredientName_list := RSDIN ; DupIngredientName_list:= RSDIA ; DupOrderGUID_list := RSDOG ; OrderCatlogMasterItem_list:= RSOCMI ; DupCategoryName_list := RSDCN ; MaxDupThreshold_list := RSMDT ; DupSummaryLine_list := RSDSL ; DupStartDTM_list := RSDStaD ; DupRequestedDTM_list := RSDReqD; DupEnteredDTM_list := RSDEntD; DupStopDTM_list := RSDStoD ; DupOrderStatusNum_list := RSDOSN ; DupOrderStatus_list := RSDOSL ; CategoryLevel_list := RSCL ; IsMapped_list := RSIM ; DupIsOrder_list := RSDIO ; DupAlternateOrderType_list := RSDAOT; DupIsScript_list := RSDIS; DupPrescriptionType_list := RSDPT; else ComponentDrugKey_list := () ; ParentDrugKey_list := () ; EnteredDrugComponent_list := () ; EnteredDrugName_list:= () ; EnteredIsAdditive_list := () ; DuplicateOrderName_list := () ; DuplicateAdditiveName_list := () ; DupIngredientName_list := () ; DupIngredientName_list:= () ; DupOrderGUID_list := () ; OrderCatlogMasterItem_list:= () ; DupCategoryName_list := () ; MaxDupThreshold_list := () ; DupSummaryLine_list := () ; DupStartDTM_list := () ; DupRequestedDTM_list := (); DupEnteredDTM_list := (); DupStopDTM_list := () ; DupOrderStatusNum_list := () ; DupOrderStatus_list := () ; CategoryLevel_list := () ; IsMapped_list := () ; DupIsOrder_list := () ; DupAlternateOrderType_list := (); DupIsScript_list := (); DupPrescriptionType_list := (); endif; endif; // endif; // find clientvisit guids //end of RS custom coding endif; // continue_checking_meds // Get the last revision date of the Multum database, strip out time portion revision_date := read last { "select change_date from SXAMTdatabase_infoSYN" }; revision_date := revision_date formatted with "%.2t"; revision_date_string := "\n{{+B}}Revision Date{{-B}}: " || revision_date; endif;// ;; evoke: // Uncomment this section if you would like historical session type orders to // evoke this MLM,otherwise keep it commented out. // If you uncomment this section please make sure to also uncomment // the equivalent event clauses /* order_alternate_enter_IV; order_alternate_enter_NOIV; order_alternate_modify; */ any_new_order; // any_new_patient_group_order; // any_modified_order; // any_released_order; // any_unsuspended_order; // any_verified_order; // outpatient_order_entry_trigger; // outpatient_order_modify_trigger; // any_pharmacy_enter_order; // any_pharmacy_modify_perfect; // any_pharmacy_modify_order; // any_new_prescription; // any_modify_prescription; // any_renew_prescription; order_alert_check; // prescription_alert_check; ;; logic: if alert_if_initial_error then conclude true; endif; If NOT continue_checking_meds then conclude false; endif; If NOT can_perform then conclude false; endif; // Initialize variables indent:= " "; new_line := "\n"; dash_line:= "-----"; printable_alert_msg:= ""; summary_header_msg := "\nMay be a Therapeutic Duplicate " || "with the following medication(s): \n"; summary_header_component_with_msg := " with" || new_line; dup_med_found := false; details_header_msg := "\n{{+B}}Details for {{-B}}"; details_header_warning := "The maximum number of medications within a therapeutic category has been exceeded.\n" || "Note this warning may apply to past or future medications as a drug{{{SINGLE-QUOTE}}}s half life is taken in " || "to consideration when comparing a medication{{{SINGLE-QUOTE}}}s start and stop dates.\n"; msg_to_display := ""; details_to_display := ""; details_msg := ""; dup_drug_msg := ""; dup_generic_list := ""; current_dup_drug := ""; dup_ingredient_name := ""; current_drug_msg := ""; current_drug_name := ""; current_drug_component_name := ""; current_drug_display_name := ""; current_order_guid := ""; current_generic_name := ""; alert_to_display:= FALSE; evoking_unmapped_display_names := (); other_unmapped_display_names := (); alert_abstract_ingredient_names := (); alert_abstract_str := ""; unmapped_alert_abstract_str := ""; current_order_header_msg := "The current "; if (order_alternate_order_type = 2) then if (evoking_order_isScript) then current_order_header_msg := current_order_header_msg || "prescription: \n" || indent; else current_order_header_msg := current_order_header_msg || "home medication: \n" || indent; endif; else current_order_header_msg := current_order_header_msg || "medication: \n" || indent; endif; //rs/tms marker := true; // Create a printable list of additives if exist IsMapped_list then index_list := 1 seqto count (EnteredDrugName_list); for JJ in index_list do component_key := ComponentDrugKey_list[JJ]; parent_key := ParentDrugKey_list[JJ]; next_drug_component_name := EnteredDrugComponent_list[JJ]; next_drug_name := EnteredDrugName_list[JJ]; next_drug_is_additive := EnteredIsAdditive_List[JJ]; dup_order_name := DuplicateOrderName_list[JJ]; dup_drug_name := DuplicateAdditiveName_list[JJ]; dup_is_additive := DupIsAdditive_list[JJ]; dup_ingredient_name := DupIngredientName_list[JJ]; dup_order_guid := DupOrderGUID_list[JJ]; dup_category_name := DupCategoryName_list[JJ]; dup_category_level := CategoryLevel_list[JJ]; dup_summary_line := DupSummaryLine_list[JJ]; dup_start_time := DupStartDTM_list[JJ]; dup_requested_date := DupRequestedDTM_list[JJ]; dup_entered_time := DupEnteredDTM_list[JJ]; dup_stop_time := DupStopDTM_list[JJ]; dup_order_status := DupOrderStatus_list[JJ]; dup_status_num := DupOrderStatusNum_list[JJ]; dup_is_order := DupIsOrder_list[JJ]; is_mapped := IsMapped_list[JJ]; dup_alternate_order_type := DupAlternateOrderType_list[JJ]; dup_is_script := DupIsScript_list[JJ]; dup_prescription_type := DupPrescriptionType_list[JJ]; // If part of the evoking item is counted as duplicate medication // make sure the start time is set correctly // For alert on demand, the DupStartDTM_list value for the evoking // medication is set to NOW. We should display the actual value if (dup_order_guid = evoking_item_guid) then dup_start_time := significant_date as time; endif; //-----------------------------------------------// // Format current drug display name //-----------------------------------------------// // Single ingredient medication - order_name // Codeine // Combo drug - order_name (COMPONENT: ingredient_name) // Aspirin-Codeine (COMPONENT: CODEINE) // Additive - in order_name // Aspirin-Codeine (COMPONENT: CODEINE) additive in Lidocaine 5% Soln if component_key <> parent_key then current_drug_display_name := next_drug_name || " (COMPONENT:" || next_drug_component_name || ")"; is_curr_drug_component := true; else current_drug_display_name := next_drug_name; is_curr_drug_component := false; endif; current_drug_display_name := "{{+B}}{{+R}}" || current_drug_display_name || "{{-R}}{{-B}}"; // Current drug header name does not contain the Component section // Codeine // Aspirin-Codeine // Aspirin-Codeine additive in Lidocaine 5% Soln current_drug_header_name := "{{+B}}{{+R}}" || next_drug_name || "{{-R}}{{-B}}"; if ( next_drug_is_additive ) then current_drug_display_name := current_drug_display_name || " additive in " || evoking_item_name; current_drug_header_name := current_drug_header_name || " additive in " || evoking_item_name; endif; //-----------------------------------------------// // Format other drug display name //-----------------------------------------------// // Single ingredient medication - order_name // Codeine // Combo drug - drug_name // Aspirin-Codeine // Additive - drug_name in order_name // Aspirin-Codeine additive in Lidocaine 5% Soln dup_display_name := "{{+B}}{{+C}}" || dup_drug_name || "{{-C}}{{-B}}"; if (dup_is_additive) then dup_display_name := dup_display_name || " additive in " || dup_order_name; endif; if is_mapped then dup_med_found := true; // add the dup med ingredient to alert abstract if (dup_ingredient_name not in alert_abstract_ingredient_names) then alert_abstract_ingredient_names := alert_abstract_ingredient_names, dup_ingredient_name; if (alert_abstract_str <> "") then alert_abstract_str := alert_abstract_str || ", " ; endif; alert_abstract_str := alert_abstract_str || dup_ingredient_name; // Add the phrase community_medication_abstract_text next to the Medication, when it is a Community Medication if(enable_community_data_medication_alerts = true AND dup_prescription_type = enum_rx_type_Community_Med) then alert_abstract_str := alert_abstract_str || community_medication_abstract_text; endif; endif; // new drug that is being ordered If (next_drug_component_name <> current_drug_component_name) or (next_drug_name <> current_drug_name) then dup_drug_msg:= dup_drug_msg || dup_generic_list; details_msg:= details_msg || dup_drug_msg; msg_to_display:= msg_to_display || current_drug_msg; details_to_display := details_to_display || details_msg; If JJ > 1 then msg_to_display := msg_to_display || new_line; details_to_display := details_to_display || new_line; endif; If (current_drug_name <> next_drug_name) then drug_changed_print_header := true; else drug_changed_print_header := false; endif; current_drug_msg := ""; details_msg := ""; dup_drug_msg := ""; dup_generic_list := ""; current_order_guid := ""; current_generic_name := ""; current_drug_component_name := next_drug_component_name; current_drug_name := next_drug_name; // If the drug changed, print header if (drug_changed_print_header) then current_drug_msg:= current_order_header_msg || "{{+B}}{{+R}}" || current_drug_header_name || "{{-R}}{{-B}}" || summary_header_msg; endif; if is_curr_drug_component then current_drug_msg := current_drug_msg || indent || current_drug_display_name || summary_header_component_with_msg; endif; details_msg := details_msg || details_header_msg || current_drug_display_name || new_line; endif; If current_order_guid <> dup_order_guid then current_order_guid := dup_order_guid; details_msg := details_msg || dup_drug_msg || dup_generic_list; dup_drug_msg := ""; dup_generic_list := ""; current_generic_name := ""; // Generate duplicate info message current_drug_msg := current_drug_msg || indent || dup_display_name; if(enable_community_data_medication_alerts = true AND dup_prescription_type = enum_rx_type_Community_Med) then current_drug_msg := current_drug_msg||"{{+B}}"||pending_community_medication_alert_text||"{{-B}}"; endif; current_drug_msg := current_drug_msg || new_line; dupDatePrefix := "Start Date: "; dup_status_suffix := "Order"; // Format the start date string if (dup_is_order) then if (dup_alternate_order_type = 2) then if (dup_requested_date is NULL or dup_requested_date = "") then dupDatePrefix := "Entered Date: "; endif; if (dup_is_script) then dup_status_suffix := "Prescription"; else dup_status_suffix := "Home Medication"; endif; elseif (dup_alternate_order_type = 1) then dup_status_suffix := ""; endif; // Order Start time is formatted as MON-DD HH:MM dup_date_time_str := dup_start_time formatted with "%.4t"; else // Use the significant dtm set in // The unsubmitted rx start time can be NULL, but overriden to NOW // - Search through the unsub_rx_significant_dtm_list // to get the original value unsub_rx_found := unsub_rx_cds_unique_guid_list = dup_order_guid; if any unsub_rx_found then dup_start_time := last(unsub_rx_significant_dtm_list where unsub_rx_found); endif; if (dup_start_time is NULL) then dup_date_time_str := ""; else // Prescription Start time is formatted as MON-DD dup_date_time_str := dup_start_time formatted with "%.2t"; endif; //Status string of the Details header line should display as "Pending Community Medication" in blue for pending Community Medication if(dup_prescription_type = 1) then dup_status_suffix := "Prescription"; elseif(dup_prescription_type = 3) then dup_status_suffix := "Home Medication"; elseif(enable_community_data_medication_alerts = true AND dup_prescription_type = enum_rx_type_Community_Med) then dup_status_suffix := "Community Medication"; endif; endif; dup_drug_msg := dup_drug_msg || new_line || indent ||dup_display_name || indent || dupDatePrefix || dup_date_time_str || indent || "Status: " ||"{{+C}}"|| dup_order_status || " " || dup_status_suffix||"{{-C}}"; endif; if dup_ingredient_name <> current_generic_name then current_generic_name := dup_ingredient_name; dup_drug_msg := dup_drug_msg || dup_generic_list; dup_generic_list := ""; dup_generic_list := dup_generic_list || new_line || indent || indent || "{{+C}}" || dup_ingredient_name || "{{-C}}"|| ": "; if (dup_category_level = 0) then dup_generic_list := dup_generic_list || "Ingredient: " || dup_category_name; else dup_generic_list := dup_generic_list || "Category: " || dup_category_name; endif; current_category_level := dup_category_level; else if (current_category_level = 0) then dup_generic_list := dup_generic_list || ", Category: " || dup_category_name; else dup_generic_list := dup_generic_list || ", " || dup_category_name; endif; current_category_level := dup_category_level; endif; // display the duplicate medication therapy threshold numbers if (display_threshold_numbers) then dup_generic_list := dup_generic_list || "(" || MaxDupThreshold_list[JJ] || ")"; endif; else evoking_drug_is_unmapped := next_drug_component_name = "Unmapped Evoking"; dup_drug_is_unmapped := dup_ingredient_name = "Unmapped other item"; if (evoking_drug_is_unmapped) then evoking_unmapped_display_names := evoking_unmapped_display_names, current_drug_display_name; unmappedDrugName := next_drug_name; else other_unmapped_display_names := other_unmapped_display_names, dup_display_name; alert_abstract_ingredient_names := alert_abstract_ingredient_names, unmappedDrugName; unmappedDrugName := dup_drug_name; endif; if (unmappedDrugName not in alert_abstract_ingredient_names) then alert_abstract_ingredient_names := alert_abstract_ingredient_names, unmappedDrugName; if (unmapped_alert_abstract_str <> "") then unmapped_alert_abstract_str := unmapped_alert_abstract_str || ", " ; endif; unmapped_alert_abstract_str := unmapped_alert_abstract_str || "Unmapped - " || unmappedDrugName; endif; endif; // is_mapped enddo; dup_drug_msg := dup_drug_msg || dup_generic_list; details_msg := details_msg || dup_drug_msg; msg_to_display := msg_to_display || current_drug_msg; details_to_display := details_to_display || details_msg; endif; // if exist additive_name_list // Initialize to empty string alert_unmapped_evoking_msg := ""; alert_unmapped_other_msg := ""; If alert_if_unmapped then // Now process any unmapped drugs that were being ordered nUnmappedEvoking := count (evoking_unmapped_display_names); unmapped_evoking_found := false; if nUnmappedEvoking > 0 then alert_to_display:= TRUE; unmappedEvokingFound := true; index_list := 1 seqto nUnmappedEvoking; for evoking_ind in index_list do unmapped_evoking_display_name := evoking_unmapped_display_names[evoking_ind]; alert_unmapped_evoking_msg := alert_unmapped_evoking_msg || "Your medication for " || unmapped_evoking_display_name || " was {{+B}}not checked for possible" || " therapeutic duplicate{{-B}} with other patient medications." || " Please use an alternate plan to do the check." || " \n\n This drug was not checked because it is unmapped." || "\n\n"; enddo; endif; // unmapped evoking found // Now process any unmapped unsubmitted or existing drugs nUnmappedOther := count(other_unmapped_display_names); If nUnmappedOther > 0 then alert_to_display:= TRUE; if (combined_alert_msg <> "") then combined_alert_msg := combined_alert_msg || draw_line; endif; if ((not unmapped_evoking_found) AND (not dup_med_found)) then alert_unmapped_other_msg := "{{+B}}{{+R}}" || evoking_item_name || "{{-R}}{{-B}}" || " was not checked for therapeutic duplicate" || " with the following medication(s):\n" || indent || "{{+B}}Unmapped Medications{{-B}}\n"; indent := indent || " "; else if (nUnmappedother = 1) then med_str := "is an {{+B}}Unmapped Medication{{-B}}"; else med_str := "are {{+B}}" || nUnmappedother || " Unmapped Medications{{-B}}"; endif; alert_unmapped_other_msg := alert_unmapped_other_msg || "There " || med_str || " not checked for therapeutic duplicate\n"; endif; index_list := 1 seqto nUnmappedother; for other_ind in index_list do unmappedDrugName := other_unmapped_display_names[other_ind]; alert_unmapped_other_msg := alert_unmapped_other_msg || indent || unmappedDrugName || "\n"; enddo; alert_unmapped_other_msg := alert_unmapped_other_msg || "\n"; endif; // Add the unmapped drugs at the end of the alert abstract if nUnmappedEvoking > 0 OR nUnmappedOther > 0 then if (alert_abstract_str <> "") then alert_abstract_str := alert_abstract_str || ", " ; endif; alert_abstract_str := alert_abstract_str || unmapped_alert_abstract_str; endif; endif; // alert_if_unmapped alert_details_msg := ""; if (dup_med_found) then alert_to_display:= TRUE; alert_details_msg := new_line || details_header_warning || details_to_display; endif; combined_alert_msg := ""; if (alert_to_display) then combined_alert_msg := msg_to_display || new_line || alert_unmapped_evoking_msg || alert_unmapped_other_msg || alert_details_msg; // Set the alert abstract duplicate_order_alert.alert_abstract := alert_abstract_str; endif; //------------------------------- // Create the Actions On Alerts //------------------------------- // Only create actions for alerts when the flag, // generate_actions_on_alerts, is TRUE // and the evoking object is a new order. // Since the MLM Editor does NOT have an evoking trigger, // Check that the EvokingEventType is a new order // or the MLM is running the the MLM Editor found_actions:= FALSE; if generate_actions_on_alerts AND alert_to_display AND ( EvokingEventType = any_new_order.type OR EvokingEventType = any_new_patient_group_order.type OR EvokingEventType = "OrderEnterNoIVAdditives" OR EvokingEventType = "OrderEnterWithIVAdditives" OR Called_By_Editor) then existing_order_actions := "DC-Cancel", "Modify"; unsubmitted_order_actions := "Delete", "Modify"; evoking_order_GUID:= evoking_order_object_guid; evoking_order_Name:= main_order_name; evoking_OCMI_GUID := main_item_catalog_guid; alert_action_object_list := (); index_list := 1 seqto count(DupOrderGUID_list); for AA in index_list do dup_order_name := DuplicateOrderName_list[AA]; dup_name := DuplicateAdditiveName_list[AA]; dup_GUID := DupOrderGUID_list[AA]; dup_StatusNum := DupOrderStatusNum_list[AA]; dup_summLine := DupSummaryLine_list[AA]; dup_OCMI := OrderCatlogMasterItem_list[AA]; dup_IsOrder := DupIsOrder_list[AA]; // can only take actions on not completed orders if ( ((dup_StatusNum as number) <= 50) and (dup_GUID <> evoking_order_GUID) and dup_IsOrder ) then found_actions:= TRUE; // check if the duplicate order is in the unsubmitted order list found_unsubmitted_drugs := unsub_order_guid_list = dup_GUID; if any found_unsubmitted_drugs then action_item_status := "Unsubmitted"; action_event_list := unsubmitted_order_actions; else action_item_status := "Existing"; action_event_list := existing_order_actions; endif; for action_event in action_event_list do // Call MLM to create one instance of the alert object aoa_object := CALL create_alert_action_object with "CV3Order", "CV3Order"; // Populate the object fields aoa_object.EvokingEnterpriseItemID := (evoking_OCMI_GUID as string); aoa_object.EvokingObjectID := (evoking_order_GUID as string); aoa_object.EvokingObjectName := evoking_order_Name; aoa_object.ActionItemStatus := action_item_status; aoa_object.ActionEvent := action_event; aoa_object.ActionItemID := (dup_GUID as string); aoa_object.ActionItemName := dup_order_name; aoa_object.ActionEnterpriseItemID := (dup_OCMI as string); aoa_object.MLMName := "STD_Duplicate_Medication_Therapy"; aoa_object.ShortMessage := "An order for " || dup_order_name || " may conflict with your current order for " || evoking_order_Name || ". Please review. " ; alert_action_object_list := alert_action_object_list, aoa_object; enddo; endif; enddo; endif; // generate actions //--------------- // Clinical Rule //--------------- If alert_to_display then conclude true; endif; ;; action: if alert_if_initial_error then if (EvokingObject is Order) then main_medication_name := main_order_name; else main_medication_name := evoking_rx_name; endif; write "Your medication for {{+B}}{{+C}}" || main_medication_name || "{{-B}}{{-C}} was{{+B}}{{+R}} not checked for possible duplicates {{-B}}{{-R}}" || "with other patient medications." || " Please use an alternate plan to do the check." || " \n\nThis drug was not checked " || "because it does not have a start date or a stop date." at duplicate_order_alert; else If alert_to_display then write combined_alert_msg at duplicate_order_alert; if found_actions then attach alert_action_object_list to duplicate_order_alert; endif; endif; endif; duplicate_order_alert.references := duplicate_order_alert.references || revision_date_string; ;; Urgency: 50;; end: