Files
St.Clair/MLMStripper/bin/Debug/STD/STD_VENIPUNCTURE.mlm

948 lines
38 KiB
Plaintext

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: