maintenance: title: Venipuncture Consolidation;; mlmname: STD_VENIPUNCTURE;; 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) 2013 - 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: Recommends consolidation of blood collections to improve patient comfort by avoiding duplicate venipunctures and to avoid inefficient blood draws. Provides Actions on Alerts with each recommendation. ;; explanation: An Evoking-Order is considered a candidate for venipuncture consolidation of Other-Orders when all of the criteria listed below are met: a. The Evoking-Order is one of the following events: new order, released from hold, activated from a conditional order, unsuspended, verified, or an order that has a modified significant-date. b. The evoking-order has a Type Code of "Diagnostic." "Medication" and "Other" are excluded, unless the order name is listed in the event clause. c. A flag, check_for_unsubmitted_orders, in the MLM determines which Other-Orders are checked. FALSE=only orders stored in the database. TRUE=unsubmitted orders and orders stored in the database. The default setting is TRUE. d. The orders (Evoking-Order and the Other-Orders) have order status level numbers between 0-50 (AWPA-AUA10, inclusive), excluding 15 = HOLD. e. CONDITIONAL, PRN, and Suspended orders are excluded. f. Master Repeat Orders are excluded. g. The orders have been designated for venipuncture consolidation checking with an "HVC-Venipuncture" "Yes" in their item-catalog-Ordering Information 2 panel. h. The location of the patient is not excluded from venipuncture checking in the HVC-Venipuncture Policy. The patient{{{SINGLE-QUOTE}}}s location is based on the location-business-rules established by the facility for other parts of Sunrise Clinical Manager. i. The Other-Orders are within the scoping rules for the patient location listed in the HVC-Venipuncture Policy. j. The Other-Orders are within the consolidation period specified in HVC-Venipuncture Policy, and are NOT in the past (ie. less than NOW, adjusted by the EXACT MATCH time criteria in the HVC-Venipuncture Policy). k. STAT orders cannot be consolidated. Routine (RTN) orders can be moved to a time critical (TIMEC) collection time, but a TIMEC order cannot be moved to a RTN collection time. Two RTN orders can be moved to the others collection times. l. Exception---If another order requiring a venipuncture is already scheduled for the same time slot as the evoking order, then a venipuncture alert is not needed, since it is already consolidated. The GENERATE_ACTIONS_ON_ALERTS variable indicates whether to generate Actions on Alerts. The values are: * TRUE = Generate Actions on Alerts * FALSE = Do NOT generate Actions on Alerts Master orders (ComplexOrderType of 1,3,5) existing in the database from Complex and Multiple Frequencies Orders are not checked. The following ComplexOrderType values define the type of order: 0 or NULL - regular order 1 - Sequential Complex Dose Master 2 - Sequential Complex Dose Child Order 3 - Concurrent Complex Dose Master 4 - Concurrent Complex Dose Child Order 5 - Multiple Frequencies Master 6 - Multiple Frequencies Child Order Change history 12.27.2010 DW Added site customization to 5.5 version 02.26.2013 JML Added logic to not display venipuncture alert for AM Round orders 07.15.2015 TMS Added site customization to 15.1 version. CSR 33555 11.14.2016 TMS Added site customization to 16.3 version. CSR 35130 03.21.2019 TMS Added site customization to 18.4 version. CSR 37676 ;; keywords: Venipuncture; ;; citations: {{+B}}Development{{-B}}: Allscripts Healthcare Solutions, Inc. Clinical Information can be customized and configured by local facility. {{+B}}Funding{{-B}}: None specific to the development of this alert {{+B}}Release{{-B}}: None {{+B}}Revision Date{{-B}}: 2012-11-07 {{+B}}Citations{{-B}}: None ;; 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; /* If UNSUBMITTED orders need to be checked for venipuncture consolidation */ /* Set the flag below to TRUE */ check_for_unsubmitted_orders:= TRUE; /* Set a flag indicating whether or not Actions on Alerts should be generated */ generate_actions_on_alerts := TRUE; /* Change the message within the quotes if a different short-message is needed.*/ venipuncture_alert:= destination { Alert: warning, "Venipuncture Consolidation", low, chart, "HVC Activity Consolidations", 1005 }; /* Change the spelling within the quotes to match the order item-catalog.*/ /* If Non-diagnostic (Medication or Other) orders need to be screened, */ /* change the string "Order_Name#" to the name of the non-diagnostic order. */ /* If there are more than 3 of these, add more ORs to the where clause */ any_new_order:= event {OrderEnter User Order: WHERE OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND OrderStatusCode <> "HOLD" AND IsConditional = FALSE AND IsPRN = FALSE AND IsSuspended = FALSE AND SystemOrderPriorityCode <> "STAT" AND (TypeCode = "Diagnostic" OR Name = "Order_Name1" OR Name = "Order_Name2" OR Name = "Order_Name3" )}; any_new_patient_group_order:= event {OrderEnter Batch Order: WHERE OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND OrderStatusCode <> "HOLD" AND IsConditional = FALSE AND IsPRN = FALSE AND IsSuspended = FALSE AND SystemOrderPriorityCode <> "STAT" AND (TypeCode = "Diagnostic" OR Name = "Order_Name1" OR Name = "Order_Name2" OR Name = "Order_Name3" ) AND IsCreatedFromPatientGroupOrderTemplate = TRUE}; any_modified_order:= event {OrderModify User Order: WHERE OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND OrderStatusCode <> "HOLD" AND IsConditional = FALSE AND IsPRN = FALSE AND IsSuspended = FALSE AND SystemOrderPriorityCode <> "STAT" AND (TypeCode = "Diagnostic" OR Name = "Order_Name1" OR Name = "Order_Name2" OR Name = "Order_Name3" )}; any_released_order:= event {OrderRelease User Order: WHERE OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND OrderStatusCode <> "HOLD" AND IsConditional = FALSE AND IsPRN = FALSE AND IsSuspended = FALSE AND SystemOrderPriorityCode <> "STAT" AND (TypeCode = "Diagnostic" OR Name = "Order_Name1" OR Name = "Order_Name2" OR Name = "Order_Name3" )}; any_unsuspended_order:= event {OrderUnsuspend User Order: WHERE OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND OrderStatusCode <> "HOLD" AND IsConditional = FALSE AND IsPRN = FALSE AND IsSuspended = FALSE AND SystemOrderPriorityCode <> "STAT" AND (TypeCode = "Diagnostic" OR Name = "Order_Name1" OR Name = "Order_Name2" OR Name = "Order_Name3" )}; any_verified_order:= event {OrderVerify User Order: WHERE OrderStatusLevelNum >= 0 AND OrderStatusLevelNum <= 50 AND OrderStatusCode <> "HOLD" AND IsConditional = FALSE AND IsPRN = FALSE AND IsSuspended = FALSE AND SystemOrderPriorityCode <> "STAT" AND (TypeCode = "Diagnostic" OR Name = "Order_Name1" OR Name = "Order_Name2" OR Name = "Order_Name3" )}; /***************** Do not change these Internal Representations *****************/ hold_code:= "HOLD"; stat_code:= "STAT"; routine_code:= "RTN"; time_critical_code:= "TIMEC"; lowest_level:= 0; highest_level:= 50; /* Set the master order types */ complex_master_order_type := (1,3,5); continue_checking_order := true; /********************************************************************************/ /* Executes only when this MLM is called by the editor */ if called_by_editor then order_obj:= read last {Order: This WHERE Name = "cbc" // AND complexordertype is not in (2,4,6) // AND ORDERSTATUSLEVELNUM <=50 }; EvokingObject:= order_obj; endif; /* Declares MLMs which can be called */ calc_duration:= MLM {{{SINGLE-QUOTE}}}std_func_dup_duration{{{SINGLE-QUOTE}}}; func_venipuncture_actions := MLM {{{SINGLE-QUOTE}}}std_func_venipuncture_actions{{{SINGLE-QUOTE}}}; /* Gets the Client GUID */ client_guid := read last {ClientInfo: GUID}; /* Gets the TimeZone of current evoking order */ visit_tz := read last {ClientVisit: TimeZone}; /* Gets information from the evoking Order */ (order_name, order_guid, order_status_code, order_level_num, order_summary_line, item_catalog_guid, chart_guid, client_visit_guid, order_significant_date, order_stop_date, order_sys_priority, order_user_priority, order_is_conditional, order_complex_type, order_variable_component_obj, back_up_obj) := read last {Order: Name, GUID, OrderStatusCode, OrderStatusLevelNum, SummaryLine, OrderCatalogMasterItemGUID, ChartGUID, ClientVisitGUID, SignificantDtm, StopDtm SystemOrderPriorityCode, OrderPriorityCode, IsConditional, ComplexOrderType, OrderVariableComponent, BackUp REFERENCING EvokingObject}; /* Check to see if this is a master order and if so whether children exist */ if exists order_complex_type and order_complex_type IS IN complex_master_order_type then /* Gets information from the order variable components */ (component_child_order_guid_list) := read {OrderVariableComponent: ChildOrderGUID REFERENCING order_variable_component_obj}; /* Check to see if children exist */ if exists component_child_order_guid_list then child_orders_generated := true; /* If children exist, this MLM should not run on Master order on modify or unsuspend */ If EvokingEventType = any_modified_order.type OR EvokingEventType = any_unsuspended_order.type then continue_checking_order := false; endif; //If EvokingEventType = any_modified_order.type /* This is a master order without children*/ else continue_checking_order := true; endif; //if exists component_child_order_guid_list endif; //if exists order_complex_type /* Determines if a modified order should be checked for duplicates */ If EvokingEventType = any_modified_order.type and continue_checking_order then if exist back_up_obj then back_up_obj_date:= read last {Order: SignificantDtm REFERENCING back_up_obj}; if (back_up_obj_signif_date <> order_significant_date) OR (back_up_obj_stop_date <> order_stop_date) OR (back_up_obj_stop_date is null and order_stop_date is time) OR (back_up_obj_stop_date is time and order_stop_date is null) then continue_checking_order:= true; endif; /* back_up_obj_signif_date... */ else continue_checking_order:= false; endif; /* if exist back_up_obj */ endif; /* If EvokingEventType = any_modified_order.type */ // St.Clair Hospital Customization after this // /* Get User Info */ no_fire_on_User := ("gfino","chughes","mvennero"); user_id := read last {UserInfo: idcode}; userinlist := user_id in no_fire_on_User; if userinlist = True then continue_checking_order := False; endif; //CSR 25233: AM Rounds change if (order_user_priority = "AM Rounds") then continue_checking_order := false; endif; // St.Clair Hospital Customization before this // If continue_checking_order then /* Gets the Item-Catalog GUIDs that have HVC-Venipuncture YES associated with it */ (venipuncture_catalog_GUID_list, veni_value, veni_code):= read {"SELECT CV3CatalogClassTypeValue.CatalogMasterGUID," ||" CV3CatalogClassTypeValue.Value, CV3ClassType.Code " ||" FROM CV3ClassType JOIN CV3CatalogClassTypeValue " ||" ON CV3ClassType.GUID = CV3CatalogClassTypeValue.ClassTypeGUID " ||" WHERE CV3ClassType.Code = {{{SINGLE-QUOTE}}}HVC-Venipuncture{{{SINGLE-QUOTE}}} " ||" AND CV3CatalogClassTypeValue.Value = {{{SINGLE-QUOTE}}}Yes{{{SINGLE-QUOTE}}} " ||" AND CV3CatalogClassTypeValue.Active = 1 " }; /* Continue if the Item-Catalog is marked with a HVC-Venipuncture YES */ If item_catalog_GUID is in venipuncture_catalog_GUID_list then /* Gets the patient{{{SINGLE-QUOTE}}}s location group */ If called_by_editor Then /* Since the patient has many visits, we must get the one from the Evoking Object */ patient_loc_group:= read last { ClientVisit: BusinessRuleLocationGUID where GUID = client_visit_guid}; Else patient_loc_group:= read last { ClientVisit: BusinessRuleLocationGUID}; Endif; /* Gets the HVC-Venipuncture Policy information */ (venpuncture_policy_name, policy_loc_group_guid_list, policy_scope_list, policy_performed_time_list, policy_performed_unit_list, policy_exact_time_list, policy_exact_unit_list, policy_scheduled_time_list, policy_scheduled_unit_list, policy_loc_is_excluded_list) := read {"SELECT Name, LocationGroupGUID, SearchScope, PastTime, PastTimeUnits," || " ExactTime, ExactTimeUnits, FutureTime, FutureTimeUnits, IsExcluded" || " FROM CV3OrderDuplicatePolicy JOIN CV3OrderDuplicatePolicyDtl " || " ON CV3OrderDuplicatePolicyDtl.OrderDuplicatePolicyGUID = " || " CV3OrderDuplicatePolicy.GUID " || " WHERE CV3OrderDuplicatePolicy.Name = {{{SINGLE-QUOTE}}}HVC-Venipuncture Policy{{{SINGLE-QUOTE}}} " || " AND LocationGroupGUID IN (0, " || SQL(patient_loc_group) || " )" || " AND CV3OrderDuplicatePolicy.Active = 1 " || " AND CV3OrderDuplicatePolicyDtl.Active = 1 "}; /* Matches patient{{{SINGLE-QUOTE}}}s location group to the item-catalog{{{SINGLE-QUOTE}}}s location group and */ /* Determines if the match excludes the location from duplicate checking */ If exist policy_scope_list then If any (patient_loc_group = policy_loc_group_guid_list) then loc_group_found := patient_loc_group = policy_loc_group_guid_list; else loc_group_found := policy_loc_group_guid_list is null; endif; loc_is_excluded := last (policy_loc_is_excluded_list where loc_group_found); endif; /* if exist policy_loc_group_guid_list */ /* Continue if there is a location group match or a default location group */ /* and the location is not excluded from duplicate checking */ If any loc_group_found and not loc_is_excluded then /*--------------------------------------------------*/ /* Finds the scope and times for the location group */ /*--------------------------------------------------*/ policy_loc_grp := last (policy_loc_group_guid_list where loc_group_found); policy_scope := last (policy_scope_list where loc_group_found); policy_performed_time := last (policy_performed_time_list where loc_group_found); policy_performed_unit := last (policy_performed_unit_list where loc_group_found); policy_exact_time := last (policy_exact_time_list where loc_group_found); policy_exact_unit := last (policy_exact_unit_list where loc_group_found); policy_scheduled_time := last (policy_scheduled_time_list where loc_group_found); policy_scheduled_unit := last (policy_scheduled_unit_list where loc_group_found); /*-------------------------------------*/ /* Converts EXACT TIME into Arden Time */ /*-------------------------------------*/ If policy_exact_time > 0 and policy_exact_unit is string then exact_duration:= call calc_duration with (policy_exact_time, policy_exact_unit); If policy_exact_unit = "days" then exact_low_time:= (day floor of order_significant_date) - exact_duration ; exact_high_time:= (day floor of order_significant_date) + exact_duration + (1 day) - (1 second); else exact_low_time:= order_significant_date - exact_duration; exact_high_time:= order_significant_date + exact_duration; endif; /* if policy_exact_unit = */ else exact_low_time:= order_significant_date; exact_high_time:= order_significant_date; endif; /* if policy_exact_time > 0...*/ /*-----------------------------------------*/ /* Converts PERFORMED TIME into Arden Time */ /*-----------------------------------------*/ If policy_performed_time > 0 and policy_performed_unit is string then performed_duration:= call calc_duration with (policy_performed_time, policy_performed_unit); If policy_performed_unit = "days" then past_time:= (day floor of order_significant_date) - performed_duration; else past_time:= order_significant_date - performed_duration; endif; /* if policy_performed_unit = */ else past_time:= exact_low_time; endif; /* if policy_performed_time > 0...*/ /* Reset the time to NOW - EXACT MATCH time criteria, */ /* when past_time is less than now */ If past_time < now then visit_now := now AS Time visit_tz; If policy_exact_unit = "days" then past_time:= (day floor of visit_now ) - exact_duration ; else past_time:= visit_now - exact_duration; endif; /* If policy_exact_unit */ endif; /* If past_time < now */ /*-----------------------------------------*/ /* Converts SCHEDULED TIME into Arden Time */ /*-----------------------------------------*/ If policy_scheduled_time > 0 and policy_scheduled_unit is string then scheduled_duration:= call calc_duration with (policy_scheduled_time, policy_scheduled_unit); If policy_scheduled_unit = "days" then future_time:= (day floor of order_significant_date) + scheduled_duration + (1 day) - (1 second); else future_time:= order_significant_date + scheduled_duration; endif; /* if policy_scheduled_unit = */ else future_time:= exact_high_time; endif; /* if policy_scheduled_time > 0...*/ /* Reset the time to NOW + EXACT MATCH time criteria, */ /* when future_time is less than now */ If future_time < now then visit_now := now AS Time visit_tz; if policy_exact_unit = "days" then future_time:= (day floor of visit_now ) + exact_duration + (1 day) - (1 second); else future_time:= visit_now + exact_duration; endif; /* if policy_exact_unit ... */ endif; /* If future_time < now */ /*-----------------------------------------------------*/ /* Sets the SCOPE to retrieve orders from the database */ /*-----------------------------------------------------*/ If policy_scope = "This Chart" then ID_equals_patient_GUID := "CV3Order.ClientGUID = " || SQL(client_guid) || " AND CV3Order.ChartGUID = " || SQL(chart_guid); elseif policy_scope = "This Visit" then ID_equals_patient_GUID := "CV3Order.ClientGUID = " || SQL(client_guid) || " AND CV3Order.ChartGUID = " || SQL(chart_guid) || " AND CV3Order.ClientVisitGUID = " || SQL(client_visit_guid); else ID_equals_patient_GUID := "CV3Order.ClientGUID = " || SQL(client_guid); endif; /* policy_scope */ /*---------------------------------------------*/ /* Get the GUIDs of ALL the Unsubmitted Orders */ /*---------------------------------------------*/ /* So we do not retrieve them from the database */ (all_unsub_intended_action, all_unsub_order_name_list, all_unsub_order_guid_list) := read {UnsubmittedOrders: IntendedAction, Name, GUID WHERE GUID <> order_guid}; /*----------------------------------*/ /* Only get some UNSUBMITTED ORDERS */ /*----------------------------------*/ /* 1. They are New or Modifed unsubmitted orders */ /* 2. The check_for_unsubmitted_orders flag is true */ If check_for_unsubmitted_orders then (unsub_order_name_list, unsub_order_guid_list, unsub_significant_date_list, unsub_sys_priority_list, unsub_user_priority_list, unsub_is_conditional_list, unsub_is_suspended_list, unsub_order_status_code_list, unsub_order_status_level_list, unsub_summary_list, unsub_master_GUID_list ):= read {UnsubmittedOrders: Name, GUID, SignificantDtm, SystemOrderPriorityCode, OrderPriorityCode, IsConditional, IsSuspended, OrderStatusCode, OrderStatusLevelNum, SummaryLine, OrderCatalogMasterItemGUID WHERE SignificantDtm >= past_time AND SignificantDtm <= future_time AND IsConditional = FALSE AND IsPRN = FALSE AND IsSuspended = FALSE AND SystemOrderPriorityCode <> stat_code AND OrderStatusLevelNum >= lowest_level AND OrderStatusLevelNum <= highest_level AND OrderStatusCode <> HOLD_code AND RepeatOrder <> 1 AND GUID <> order_guid AND (IntendedAction is NULL OR IntendedAction is in ("Add New","Modify","Modified"))}; endif; /* if check_for_unsubmitted_orders */ /* Get ALL the UNSUBMITTED ORDERS */ /*------------------------------------------------------------------------------*/ /* Create a fragment of the SQL code that avoids retrieving the same orders */ /* from the database that are in the unsubmitted list. */ /* This is needed when the CDS Trigger is one of the order maintenance triggers */ /* and the user is performing a multi-order function */ /*------------------------------------------------------------------------------*/ /* Initialize variable to empty string */ AND_avoid_these_unsubmitted_order_guids := ""; /* Concatenate a fragment of the SQL code to the initalized variable */ if exist all_unsub_order_guid_list then if (count(all_unsub_order_guid_list) = 1) then //Set up to exclude this single order item single_unsub_order_guid := last of (all_unsub_order_guid_list); AND_avoid_these_unsubmitted_order_guids := AND_avoid_these_unsubmitted_order_guids || " AND (CV3Order.GUID <> " || SQL(single_unsub_order_guid)||")"; else //Set up to exclude the these order guids AND_avoid_these_unsubmitted_order_guids := AND_avoid_these_unsubmitted_order_guids || " AND (CV3Order.GUID NOT IN (" || SQL(all_unsub_order_guid_list)||"))"; endif; else AND_avoid_these_unsubmitted_order_guids :=""; endif; /* Create 2 tables temporary result sets of potential orders within the range of maximum time zone difference */ /* These results will then be filtered by the datetime range based on the Duplicate Policy */ FROM_common_columns := " Name, CV3Order.GUID, " || " ConvSignificantDtm.TimeValue as SignificantDtmOffset, " || " SystemOrderPriorityCode, " || " OrderPriorityCode, IsConditional,IsSuspended, " || " OrderStatusCode, OrderStatusLevelNum, " || " SummaryLine, OrderCatalogMasterItemGUID " || " FROM CV3Order " || " INNER JOIN CV3ClientVisit v on v.GUID = CV3Order.ClientVisitGUID" || " CROSS APPLY dbo.SXADBConvertLocalToOffsetTblFn(v.TimeZone, SignificantDtm) AS ConvSignificantDtm "; max_hours_differece_between_time_zones := 26 as number; WHERE_conditions_common := " WHERE " || ID_equals_patient_GUID || " AND CV3Order.SignificantDtm >= dateadd( hour, -" || SQLEX(max_hours_differece_between_time_zones) || ", " || SQL(past_time) || " )" // filter out potential orders based on unconverted datetime || " AND CV3Order.SignificantDtm <= dateadd( hour, " || SQLEX(max_hours_differece_between_time_zones) || ", " || SQL(future_time) || " )" // filter out potential orders based on unconverted datetime; || " AND CV3Order.OrderStatusLevelNum >= " || SQLEX(lowest_level) || " AND CV3Order.OrderStatusLevelNum <= " || SQLEX(highest_level) || " AND CV3Order.IsConditional = 0 " || " AND CV3Order.IsPRN = 0 " || " AND CV3Order.IsSuspended = 0 " || " AND CV3Order.Active = 1" || " AND CV3Order.SystemOrderPriorityCode <> " ||SQLEX(stat_code) || " AND CV3Order.RepeatOrder <> 1 " || " AND CV3Order.GUID <> " || SQLEX(order_guid) || " AND CV3Order.OrderStatusCode <> " || SQLEX(HOLD_code); FROM_result_columns := " Name, GUID, SignificantDtmOffset, SystemOrderPriorityCode, OrderPriorityCode, IsConditional,IsSuspended, " || " OrderStatusCode, OrderStatusLevelNum, " || " SummaryLine, OrderCatalogMasterItemGUID "; Filter_by_policy_datetime_range := " SignificantDtmOffset >= " || SQLEX(past_time) || " AND SignificantDtmOffset <= " || SQLEX(future_time); /*----------------------------------*/ /* Gets the list of DATABASE ORDERS */ /*----------------------------------*/ (db_order_name_list, db_order_guid_list, db_significant_date_list, db_sys_priority_list, db_user_priority_list, db_is_conditional_list, db_is_suspended_list, db_order_status_code_list, db_order_status_level_list, db_summary_list, db_master_GUID_list ):= read { ";With CteAllOrders AS ( " || "SELECT " || FROM_common_columns || WHERE_conditions_common || " AND CV3Order.ComplexOrderType NOT IN (" || complex_master_order_type|| ")" || " ), " || " CteAllOrdersComp AS ( " || "SELECT DISTINCT " || FROM_common_columns || " INNER JOIN CV3OrderVariableComponent" || " ON CV3Order.GUID = CV3OrderVariableComponent.OrderGUID " || WHERE_conditions_common || AND_avoid_these_unsubmitted_order_guids || " AND CV3Order.ComplexOrderType IN (" || complex_master_order_type|| ")" || " AND ChildOrderGUID is NULL " || " ) " || "SELECT " || FROM_result_columns || " FROM CteAllOrdersComp" || " WHERE " || Filter_by_policy_datetime_range || " UNION " || "SELECT DISTINCT " || FROM_result_columns || " FROM CteAllOrders" || " WHERE " || Filter_by_policy_datetime_range , PrimaryTime = SignificantDtmOffset}; endif; /* if any loc_group_found and not loc_is_excluded */ endif; /* if item_catalog_GUID is in venipuncture_catalog_GUID_list */ endif; /* If continue_checking_order */ ;; evoke: any_new_order OR any_new_patient_group_order OR any_modified_order OR any_released_order OR any_unsuspended_order OR any_verified_order ; ;; logic: If item_catalog_GUID is NOT in venipuncture_catalog_GUID_list OR NOT continue_checking_order OR NOT (any loc_group_found) OR loc_is_excluded then conclude false; endif; /*-----------------------------------------------------------------*/ /* Concatenates information on "unsubmitted" and "database" orders */ /* and avoids concatenating NULL lists */ /*-----------------------------------------------------------------*/ If (exist unsub_master_guid_list) and (exist db_master_guid_list) then master_guid_list:= (unsub_master_guid_list, db_master_guid_list); order_name_list:= (unsub_order_name_list, db_order_name_list); significant_date_list:= (unsub_significant_date_list, db_significant_date_list); sys_priority_list:= (unsub_sys_priority_list, db_sys_priority_list); user_priority_list:= (unsub_user_priority_list, db_user_priority_list); summary_list:= (unsub_summary_list, db_summary_list); order_status_code_list:= (unsub_order_status_code_list, db_order_status_code_list); order_guid_list := (unsub_order_guid_list,db_order_guid_list); is_suspended_list := (unsub_is_suspended_list,db_is_suspended_list); elseif (not exist unsub_master_guid_list) and (exist db_master_guid_list) then master_guid_list:= db_master_guid_list; order_name_list:= db_order_name_list; significant_date_list:= db_significant_date_list; sys_priority_list:= db_sys_priority_list; user_priority_list:= db_user_priority_list; summary_list:= db_summary_list; order_status_code_list:= db_order_status_code_list; order_guid_list := db_order_guid_list; is_suspended_list := db_is_suspended_list; elseif (exist unsub_master_guid_list) and (not exist db_master_guid_list) then master_guid_list:= unsub_master_guid_list; order_name_list:= unsub_order_name_list; significant_date_list:= unsub_significant_date_list; sys_priority_list:= unsub_sys_priority_list; user_priority_list:= unsub_user_priority_list; summary_list:= unsub_summary_list; order_status_code_list:= unsub_order_status_code_list; order_guid_list := unsub_order_guid_list; is_suspended_list := unsub_is_suspended_list; endif; /* If (exist unsub_master_guid_list)... */ /*-------------------------------------------------*/ /* Create List of Unsubmitted and Existing Strings */ /*-------------------------------------------------*/ action_item_status_list:= (); for AA in unsub_order_name_list do action_item_status_list := action_item_status_list, "Unsubmitted"; enddo; //for AA for BB in db_order_name_list do action_item_status_list := action_item_status_list, "Existing"; enddo; //for BB /*-----------------------*/ /* Initializes Variables */ /*-----------------------*/ matching_master_guid_list:= (); matching_name_list:= (); matching_significant_date_list:= (); matching_sys_priority_list:= (); matching_user_priority_list:= (); matching_summary_list:= (); matching_order_status_code:= (); matching_order_guid_list:= (); matching_is_suspended_list:= (); matching_action_item_status_list := (); already_consolidated:= false; /*------------------------------------------------*/ /* Finds all possible venipuncture consolidations */ /*------------------------------------------------*/ If any(venipuncture_catalog_GUID_list is in master_guid_list) then for item_master_guid in venipuncture_catalog_GUID_list do master_guid_found:= item_master_guid = master_guid_list; temp_sys_priority:= sys_priority_list where master_guid_found; temp_user_priority:= user_priority_list where master_guid_found; temp_guid:= master_guid_list where master_guid_found; temp_name:= order_name_list where master_guid_found; temp_signif:= significant_date_list where master_guid_found; temp_summary:= summary_list where master_guid_found; temp_status:= order_status_code_list where master_guid_found; temp_order_guid:= order_guid_list where master_guid_found; temp_is_suspended := is_suspended_list where master_guid_found; temp_action_status := action_item_status_list where master_guid_found; matching_sys_priority_list:= matching_sys_priority_list, temp_sys_priority; matching_user_priority_list:= matching_user_priority_list, temp_user_priority; matching_master_guid_list:= matching_master_guid_list, temp_guid; matching_name_list:= matching_name_list, temp_name; matching_significant_date_list:= matching_significant_date_list, temp_signif; matching_summary_list:= matching_summary_list, temp_summary; matching_order_status_code:= matching_order_status_code, temp_status; matching_order_guid_list:= matching_order_guid_list, temp_order_guid; matching_is_suspended_list:= matching_is_suspended_list, temp_is_suspended; matching_action_item_status_list:= matching_action_item_status_list, temp_action_status; enddo; /* for item_master_guid...*/ /* If there is another order within the exact-match time interval */ /* that requires a venipuncture, */ /* then the current order{{{SINGLE-QUOTE}}}s blood collection time does not have be be changed */ /* and there is no need for an venipunture consolidation alert */ if any(matching_significant_date_list>= exact_low_time AND matching_significant_date_list <= exact_high_time) then already_consolidated:= true; else /* Removes TIMEC orders, only keeps RTN orders */ If order_sys_priority = time_critical_code AND (time_critical_code is in matching_sys_priority_list) then RTN_found:= matching_sys_priority_list = routine_code; matching_sys_priority_list:= matching_sys_priority_list where RTN_found; matching_user_priority_list:= matching_user_priority_list where RTN_found; matching_master_guid_list:= matching_master_guid_list where RTN_found; matching_name_list:= matching_name_list where RTN_found; matching_significant_date_list:= matching_significant_date_list where RTN_found; matching_summary_list:= matching_summary_list where RTN_found; matching_order_status_code:= matching_order_status_code where RTN_found; matching_order_guid_list:= matching_order_guid_list where RTN_found; matching_is_suspended_list:= matching_is_suspended_list where RTN_found; matching_action_item_status_list:= matching_action_item_status_list where RTN_found; endif; /* if order_sys_priority */ endif; /* if any(matching_significant_date_list>= exact_low_time */ endif; /* if any(venipuncture_catalog_GUID_list...*/ /*----------------------*/ /* Format Alert Message */ /*----------------------*/ if NOT already_consolidated then matching_short_message_list := (); alert_message:= ""; order_index:= 1 seqto count(matching_name_list); for I in order_index do index_found:= I = order_index; temp_name:= first(matching_name_list where index_found); temp_signif:= first(matching_significant_date_list where index_found); temp_sys_priority:= first(matching_sys_priority_list where index_found); temp_user_priority:= first(matching_user_priority_list where index_found); /* Format dates, removing milliseconds */ If exist temp_signif then temp_signif_formatted := temp_signif formatted with "%.4t"; endif; If exist order_significant_date then temp_order_significant_date_formatted := order_significant_date formatted with "%.4t"; endif; first_sentence:= "A " || temp_user_priority || " blood collection for this patient is currently scheduled at " || temp_signif_formatted || " for " || temp_name ||"."; If order_sys_priority = routine_code AND temp_sys_priority = routine_code then temp_msg_list:= first_sentence || " Consider consolidating one of the collection times to" || " the other collection time"; elseif order_sys_priority = time_critical_code AND temp_sys_priority = routine_code then temp_msg_list:= first_sentence || " Consider consolidating the collection time of the " || temp_user_priority || " order " || "to the collection time of the " || order_user_priority ||" order"; elseif order_sys_priority = routine_code AND temp_sys_priority = time_critical_code then temp_msg_list:= first_sentence || " Consider consolidating the collection time of the " || order_user_priority || " order " || "to the collection time of the " || temp_user_priority ||" order."; endif; /* if order_sys_priority... */ /* Append or Concatenate alert messages */ matching_short_message_list:= matching_short_message_list, temp_msg_list; alert_message := alert_message ||temp_msg_list || "\n\n"; enddo; /* for I */ endif; /* if NOT already_consolidated */ /*------------------------------*/ /* Create the Actions on Alerts */ /*------------------------------*/ // Only create actions for alerts when the flag, generate_actions_on_alerts, is TRUE // And there are alerts // And the EvokingEventType is a new order or the MLM is running the the MLM Editor If generate_actions_on_alerts and exist matching_name_list and NOT already_consolidated 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 /* Call the MLM to create and populate actions */ alert_action_list := call func_venipuncture_actions WITH order_guid, matching_action_item_status_list, matching_order_guid_list, matching_name_list, matching_master_guid_list, matching_short_message_list, matching_is_suspended_list ; if exist alert_action_list then alert_actions_exist := true; else alert_actions_exist := false; endif; //if exist alert_action_list endif; //generate_actions_on_alerts /*---------------*/ /* Clinical Rule */ /*---------------*/ If exist matching_name_list and NOT already_consolidated then conclude true; endif; ;; action: Write "Current Order: " ||order_user_priority || " " || order_name || "---" || temp_order_significant_date_formatted || "\n\n" || alert_message at venipuncture_alert; /* Only attach actions, when they exist */ if alert_actions_exist then attach alert_action_list to venipuncture_alert; endif; //if generate_actions_on_alerts ;; Urgency: 50;; end: