maintenance:
title: Advanced Therapeutic Duplication Checking;;
mlmname: STD_Duplicate_Medication_Therapy;;
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
04.27.2016 TMS Updated to fire only for medication released from hold session. Unsubmitted orders will use
STD_Duplicate_Medication_Therapy_UnsubOnly MLM for unsubmited orders. All other duplicate
orders will be alerted using custom Orders management application. CSR 33465
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:= 0;
// 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:= 1015,
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;
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";
//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_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,
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_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};
if (unsub_order_med_source = "EvokingCatalog" OR
unsub_order_med_source = "SelectedCatalog" )
then
unsub_is_selected := 1;
else
unsub_is_selected := 0;
endif;
unsubmitted_order_parameter_xml := unsubmitted_order_parameter_xml||
" \n";
// 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
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
spool_list := 1 seqto count (EnteredDrugName_list);
for countorder in spool_list do
singorder := DupOrderGUID_list[countorder];
singsum := DupSummaryLine_list[countorder];
if (singsum <>"Unapproved" and (singsum is not null)) // 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 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
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: