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

628 lines
22 KiB
Plaintext

maintenance:
title: Duplicate Task Occurrence Checking;;
mlmname: STD_DUPLICATE_TASK;;
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: Provide Duplicate Task Occurrence Checking. The checking will include:
1. Tasks of the same name or type within a pre-defined date range,
which will be varied by patient location.
2. Active task of the same type/class.
;;
explanation:
Evoking-Occurrence: This is the Order Task Occurrence that causes the MLM
to be triggered (evoked).
DB-Occurrence: This is an existing Order Task Occurrence from the database
or from the cached memory.
An Evoking-Occurrence is considered a duplicate of a DB-Occurrence when
all of the criteria listed below are true:
1. The Evoking-Occurrence is created by the Order Generation Server,
and by a user when marking a task as done at order entry, or adding a completed
task, or adding a scheduled task to the worklist, or rescheduling a single
instance of a task.
2. The Evoking-Occurrence is a New occurrence, a Modified occurrence,
or a Rescheduled occurrence.
3. If the Evoking-Occurrence is a Modified occurrence, only an occurrence
with changes to ScheduledDtm, EarliestScheduledDtm, or LatestScheduledDtm
will be checked for duplicates.
4. The Evoking-Occurrence must have a CV3OrderTaskOccurrence.CDSOccurrenceType
of {10, 11, 20, 30, 31, 40, 41, 90, 91, 110, 111, 120, 130, 131, 140, 141}
or is a task that was rescheduled from Clinical Manager to be checked for
duplicates. See the Duplicate Task Checking chapter of the CDS Configuration
Guide for a detailed definition of each number.
5. The Evoking-Occurrence must have a CV3OrderTaskOccurrence.TaskStatusCode
of {Pending, Rescheduled, Overdue}.
6. The Evoking-Occurrence must have a CV3OrderTask.ScheduleTypeCode of
{Scheduled, Unscheduled, PRN, To Schedule (when 1st given), Continuous}.
The Evoking-Occurrence with a ScheduleTypeCode of
{To Schedule (manual), Conditional } will be excluded.
7. The Evoking-Occurrence is not excluded from duplicate checking
(over-all or by patient location) in its Duplicate Policy.
8. The DB-Occurrence must have a CV3OrderTaskOccurrence.TaskStatusCode
of { Overdue, Pending, Performed, Rescheduled }. DB-Occurrences that
have TaskStatusCodes of Canceled or Not Done will be excluded.
9. The DB-Occurrence must have a CV3OrderTask.ScheduleTypeCode of
{Scheduled, Unscheduled, PRN, To Schedule (manual),
To Schedule (when 1st given), Continuous} or a
CV3OrderTaskOccurrence.TaskStatusCode of Performed, except in the case of
{{{SINGLE-QUOTE}}}Adding a Completed Task{{{SINGLE-QUOTE}}} on the worklist.
DB-Occurrences with a ScheduleTypeCode of Conditional will be excluded.
10. When the Evoking-Occurrence has a ScheduleTypeCode of Continuous,
it cannot be a duplicate of DB-Occurrences that are from the
same order task (OrderTaskGUID).
11. The Evoking-Occurrence and the DB-Occurrence have identical Item-Catalog
names, or the DB-Occurrence match the Item or Class-Name & Value listed
in the Evoking-Occurrence{{{SINGLE-QUOTE}}}s item-catalog-tasks panel.
12. The DB-Occurrences are within the scoping rules for the patient location
listed in the Evoking-Occurrence{{{SINGLE-QUOTE}}}s Duplicate Policy.
13. The Evoking-Occurrence and the DB-Occurrence have overlapping start
and stop dates within the time interval specified in the
Evoking-Occurrence{{{SINGLE-QUOTE}}}s Duplicate Policy. See the CDS Configuration and
Standard MLM Set up Guide, for a detailed definition of overlapping
start and stop dates in the "Setting up Duplicate Task Checking" chapter.
14. If the Duplicate Policy uses Task % and the MLM is unable to determine
a time interval for the Evoking-Occurrence, a default time interval
of 24 hours (12 hours before and after the date/time of when the
Evoking-Occurrence should be done) will be used to screen for potential
duplicate tasks. If a potential duplicate exists, an error alert would
be generated, unless the facility has turned off the error flag. The
error alert would state that the user should review the task because
all the required information is not present to identify duplicate
task occurrences.
15. The combination of a Scheduled Evoking-Occurrence and a
Performed DB-Occurrence is considered a HIGH priority alert.
All other combinations are considered a MEDIUM priority alert.
16. To prevent over alerting, an alert will NOT be generated for the
same Order Task, if there is a higher priority or equivalent
priority alert for one of the Order Task{{{SINGLE-QUOTE}}}s earlier DB-Occurrences.
;;
keywords: Duplicate Task Occurrence;
;;
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;
/* Change the message within the quotes if a different short-message is needed.*/
high_dup_task_alert:= destination { Alert: warning,
"Duplicate Task", high, chart,
"HVC Duplicate Task", 2005 };
medium_dup_task_alert:= destination { Alert: warning,
"Duplicate Task", medium, chart,
"HVC Duplicate Task", 2005 };
/* Change the spelling within the quotes to match the order item-catalog.*/
any_new_task:= event {OrderTaskOccurrenceEnter
Any OrderTaskOccurrence:
WHERE TaskStatusCode is in
("Pending", "Rescheduled", "Overdue" )
AND CDSOccurrenceType is in
(10,11,20,30,31,40,41,90,91,110,111,120,130,131,140,141)
OR
(TaskStatusCode is in ("Performed" )
AND CDSOccurrenceType = 91)};
any_modified_task:= event {OrderTaskOccurrenceModify
Any OrderTaskOccurrence:
WHERE TaskStatusCode is in
("Pending", "Rescheduled", "Overdue" )
AND CDSOccurrenceType is in
(10,11,20,30,31,40,41,90,91,110,111,120,130,131,140,141)};
any_rescheduled_task_instance:= event {OrderTaskOccurrenceReschedule
User OrderTaskOccurrence:
WHERE TaskStatusCode is in
("Rescheduled")};
/* A flag to determine if the clinical user should be alerted when */
/* duplicate task occurrences cannot be checked due to an unknown frequency */
/* that is associated with the order task. A time-interval (past-present) */
/* for duplicates cannot be calculated. This only affects Duplicate Policies */
/* that use the "Task %" unit of measure. */
/* True = alert user; False = do not alert user. */
alert_if_unknown_frequency := true;
/********************************************************************************/
/* Execute only when this MLM is called by the editor */
if called_by_editor then
task_obj:= read last
{OrderTaskOccurrence: This
WHERE TaskName = "Ampicillin 500 mg"
//AND SignificantDtm = 2000-09-13T06:00:00
//AND CDSOCCURRENCETYPE = 10
//and TaskStatusCode = "Rescheduled"
//and ScheduleTypeCode = "ToSchedule"
};
EvokingObject:= task_obj;
endif;
/* Declare MLMs which can be called */
func_task_messages:= MLM {{{SINGLE-QUOTE}}}std_func_task_messages{{{SINGLE-QUOTE}}};
func_task_rules:= MLM {{{SINGLE-QUOTE}}}std_func_task_rules{{{SINGLE-QUOTE}}};
/* Get the Client GUID */
client_guid := read last {ClientInfo: GUID};
/* Get information from the evoking OrderTaskOccurrence */
(task_occurrence_name,
task_occurrence_guid,
task_summary_line,
task_status_code,
task_cds_occurrence_type,
task_catalog_item_guid,
task_significant_date,
task_scheduled_date,
task_earliest_date,
task_latest_date,
tasks_to_be_canceled_string,
order_obj,
order_task_obj,
back_up_obj ) := read last
{OrderTaskOccurrence: TaskName, GUID, SummaryLine,
TaskStatusCode, CDSOccurrenceType,
CatalogItemTaskGUID, SignificantDtm,
ScheduledDtm, EarliestScheduledDtm, LatestScheduledDtm,
GUIDList, Order, OrderTask, Backup
REFERENCING EvokingObject};
/* Get data from the OrderTask associated with the OrderTaskOccurrence */
(schedule_type_code,
process_type,
order_task_frequency,
item_catalog_guid,
order_task_guid,
order_guid,
task_seq_num,
application_source ) := read last
{OrderTask: ScheduleTypeCode, ProcessType,
OrderFrequency, OrderCatalogMasterItemGUID, GUID, OrderGUID, TaskSeqNum, ApplicSource
REFERENCING order_task_obj };
primary_task_sequence_num := 0;
if (task_seq_num = primary_task_sequence_num)
then
is_primary_task := true;
else
is_primary_task := false;
endif;
/* Determine if the MLM should continue checking for duplicates */
/* The evoking-object{{{SINGLE-QUOTE}}}s OrderTask must be Continuous, PRN, Scheduled or Unscheduled */
/* OR be ToSchedule (when 1st given). Exclude everything else */
if (schedule_type_code is in ("Continuous","PRN","Scheduled","Unscheduled" )
OR (schedule_type_code = "ToSchedule"
AND process_type = 4 )) AND application_source IS NULL
then
continue_checking_task := true;
else
continue_checking_task := false;
endif;
/* Determine if a modified OrderTaskOccurrence should be checked for duplicates */
If EvokingEventType = any_modified_task.type and continue_checking_task
then
if exist back_up_obj
then
(backup_scheduled_date,
backup_earliest_date,
backup_latest_date ) := read last
{OrderTaskOccurrence: ScheduledDtm,
EarliestScheduledDtm, LatestScheduledDtm
REFERENCING back_up_obj };
/* Continue checking if the ScheduledDtm, EarliestScheduledDtm, */
/* or LatestScheduledDtm have been modified */
if (backup_scheduled_date <> task_scheduled_date )
OR
(backup_scheduled_date is null and task_scheduled_date is time)
OR
(backup_scheduled_date is time and task_scheduled_date is null)
OR
(backup_earliest_date <> task_earliest_date )
OR
(backup_earliest_date is null and task_earliest_date is time)
OR
(backup_earliest_date is time and task_earliest_date is null)
OR
(backup_latest_date <> task_latest_date )
OR
(backup_latest_date is null and task_latest_date is time)
OR
(backup_latest_date is time and task_latest_date is null)
then continue_checking_task:= true;
endif; /* backup_scheduled_date... */
else
continue_checking_task:= false;
endif; /* if exist back_up_obj */
endif; /* If EvokingEvent = any_modified_task */
if continue_checking_task
then
/* Get data from the order associated with the OrderTaskOccurrence */
(task_name,
chart_guid,
client_visit_guid,
order_type_code ) := read last
{Order: Name, ChartGUID, ClientVisitGUID, TypeCode
REFERENCING order_obj };
/* 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;
/* Get all the alerts in the CACHED MEMORY for the Std_duplicate_task MLM */
(unsub_mlm_name_list,
unsub_alert_priority_code_list ):= read
{UnsubmittedAlerts: MLMName, PriorityCode
where MLMName = "STD_DUPLICATE_TASK" };
/* Stop duplicate checking if a high priority alert exists */
/* in the CACHED MEMORY for a the same OrderTask parent in the set */
if task_cds_occurrence_type is in (11,31,41,111,131,141)
AND "HIGH" is in unsub_alert_priority_code_list
then continue_checking_task := false;
else
/* Get all alerts in the DATABASE for the same OrderTask GUID */
(task_name_list,
mlm_name_list,
alert_priority_code_list,
mlm_pobject_name_list,
mlm_rule_group_list,
mlm_rule_number_list,
mlm_alert_create_when_list ) := read
{"SELECT t.TaskName, a.MLMName, a.PriorityCode, a.PObjectName,"
||" a.RuleGroup, a.RuleNumber, a.CreatedWhen"
||" FROM CV3AlertDeclaration AS a JOIN CV3OrderTaskOccurrence AS t"
||" ON a.ClientGUID = t.ClientGUID"
||" AND t.GUID = a.PObjectGUID "
||" WHERE a.ClientGUID = " || SQL(client_guid)
||" AND t.ClientGUID = " || SQL(client_guid)
||" AND t.OrderTaskGUID = " || SQL(order_task_guid)
||" AND a.PObjectName = {{{SINGLE-QUOTE}}}COrderTaskOccurrence{{{SINGLE-QUOTE}}} "
||" AND a.MLMName = {{{SINGLE-QUOTE}}}STD_DUPLICATE_TASK{{{SINGLE-QUOTE}}} "
||" AND a.Active = 1 "
, PrimaryTime = CreatedWhen };
/* Stop duplicate checking if a high priority alert exists */
/* in the DATABASE for a the same OrderTask parent in the set */
if task_cds_occurrence_type is in (11,31,41,111,131,141)
AND "HIGH" is in alert_priority_code_list
then continue_checking_task := false;
endif; /* if task_cds_occurrence_type */
endif; /* if task_cds_occurrence_type */
endif; /* continue_checking_task */
;;
evoke: any_new_task
OR any_modified_task
OR any_rescheduled_task_instance;
;;
logic:
If NOT continue_checking_task
then conclude false;
endif;
/* Initialize variable */
indent:= " ";
/* Determine Frequency Unit to calculate time interval for "Task %" */
/* Use the frequency code from the OrderTask object, */
if exist order_task_frequency
then frequency_unit := order_task_frequency;
else
frequency_unit := NULL;
endif;
/*---------------------------------*/
/* Find Duplicate task occurrences */
/*---------------------------------*/
(has_time_interval,
has_unknown_frequency,
exact_msg,
performed_msg,
scheduled_msg,
same_item_type,
same_therapeutic_class_type,
similar_task_type,
conflict_type,
possible_conflict_type,
no_std_message_type,
duplicate_policy_guid,
matching_task_name_list,
matching_significant_date_list,
matching_msg_type_list,
matching_msg_text_list,
matching_time_msg_list,
matching_class_list,
matching_latest_scheduled_dtm_list,
matching_order_name_list,
matching_order_type_code_list,
matching_performed_to_dtm_list,
matching_process_type_list,
matching_schedule_type_code_list,
matching_task_status_code_list )
:= call func_task_rules with
(task_name,
task_occurrence_guid,
task_status_code,
task_summary_line,
is_primary_task,
order_guid,
item_catalog_guid,
chart_guid,
client_visit_guid,
task_significant_date,
patient_loc_group,
task_catalog_item_guid,
frequency_unit,
tasks_to_be_canceled_string,
schedule_type_code,
order_task_guid );
/*-------------------------------------------------------------*/
/* Call an MLM to select the appropriate message and format it */
/*-------------------------------------------------------------*/
If exist matching_task_name_list
and (NOT has_unknown_frequency OR schedule_type_code = "continuous")
then
alert_msg:= call func_task_messages with
(task_name,
task_status_code,
is_primary_task,
order_type_code,
exact_msg,
performed_msg,
scheduled_msg,
same_item_type,
same_therapeutic_class_type,
similar_task_type,
conflict_type,
possible_conflict_type,
no_std_message_type,
matching_task_name_list,
matching_significant_date_list,
matching_msg_type_list,
matching_msg_text_list,
matching_time_msg_list,
matching_class_list,
matching_latest_scheduled_dtm_list,
matching_order_name_list,
matching_order_type_code_list,
matching_performed_to_dtm_list,
matching_process_type_list,
matching_schedule_type_code_list,
matching_task_status_code_list );
endif; /* If exist matching_task_name_list */
/*-------------------------------------*/
/* Determine if Alert Message Priority */
/*-------------------------------------*/
if schedule_type_code = "scheduled"
and "Performed" is in matching_task_status_code_list
then
alert_priority := "HIGH";
high_priority_alert := true;
else
alert_priority := "MEDIUM";
high_priority_alert := false;
endif; /* schedule_type_code */
/*-------------------------------------*/
/* Set Variables for the Alert Message */
/*-------------------------------------*/
if alert_priority = "high"
then a1_heading := "Warning";
else a1_heading := "Caution";
endif; /* if alert_priority */
// Set task string
if is_primary_task
then
task_string := "task";
else
task_string := "follow-up task";
endif;
if (is_primary_task
and order_type_code = "Medication")
then
a2_order_type := "medication administration";
else
a2_order_type := task_string;
endif; // if is_primary_task and order_type_code
if schedule_type_code = "scheduled"
then a5_task_schedule_type := "Scheduled";
elseif schedule_type_code = "unscheduled"
then a5_task_schedule_type := "Unscheduled";
elseif schedule_type_code = "PRN"
then a5_task_schedule_type := "Pending PRN";
elseif schedule_type_code = "continuous"
then a5_task_schedule_type := "Pending continuous";
elseif schedule_type_code = "ToSchedule" and process_type = 4
then a5_task_schedule_type := "To be scheduled starting when first done";
else a5_task_schedule_type := schedule_type_code;
endif; /* if schedule_type_code */
if schedule_type_code = "scheduled"
then a6_date_label := "Date" ;
else a6_date_label := "Earliest Date" ;
endif; /* if schedule_type_code */
/*------------------------*/
/* Assemble Alert Message */
/*------------------------*/
complete_alert_msg := "{{+B}}{{+R}}" || a1_heading || "{{-R}}{{-B}}\n"
||"This " || a2_order_type || "\n"
|| indent ||"{{+B}}{{+C}}"|| task_occurrence_name || "{{-C}}{{-B}}\n"
|| indent || "( " || a5_task_schedule_type ||" )\n"
|| indent || a6_date_label || ": " || task_significant_date formatted with "%.4t"|| "\n\n";
if exist matching_task_name_list
and exist alert_msg
and (NOT has_unknown_frequency OR schedule_type_code = "continuous")
then
/* Display Regular Alert Message */
complete_alert_msg := complete_alert_msg
||"{{+B}}May be too close to, or conflict with:{{-B}}\n\n"
|| alert_msg;
elseif exist matching_task_name_list
and has_unknown_frequency
and alert_if_unknown_frequency
then
/* Display Error Message */
alert_msg:= true;
complete_alert_msg := complete_alert_msg
||"Unable to check for duplicate task occurrences"
||" because all the required information to do a check, is not available. "
||" Please review the tasks at the above time for potential duplicates.";
endif; /* exist matching_task_name_list */
/*------------------*/
/* Debug Statements */
/*------------------*/
xxx1_alert_msg:= exist alert_msg;
xxx2_dup_policy_guid:= exist duplicate_policy_guid;
xxx3_has_time_interval:= has_time_interval;
xxx4_alert_priority:= alert_priority;
xxx5_occur_first:= (task_cds_occurrence_type is in (10,20,30,40,110,120,130,140) );
xxx6_occur_subsequent:= (task_cds_occurrence_type is in (11,31,41,111,131,141)
AND alert_priority is NOT in (alert_priority_code_list,
unsub_alert_priority_code_list));
xxx7_occur_all:= (
/* First task occurrence of the set */
(task_cds_occurrence_type is in (10,20,30,40,110,120,130,140) )
OR
/* Second task occurrence of the set */
(task_cds_occurrence_type is in (11,31,41,111,131,141)
AND alert_priority is NOT in (alert_priority_code_list,
unsub_alert_priority_code_list)));
xxx8_previous_alert_priorities:= alert_priority_code_list,
unsub_alert_priority_code_list;
xxx9_task_cds_occurrence_type:= task_cds_occurrence_type;
/*---------------*/
/* Clinical Rule */
/*---------------*/
If exist alert_msg
AND exist duplicate_policy_guid
AND
(
// First task occurrence of the set
(task_cds_occurrence_type is in (10,20,30,40,110,120,130,140) )
OR
// Second task occurrence of the set
(task_cds_occurrence_type is in (11,31,41,111,131,141)
AND alert_priority is NOT in (alert_priority_code_list,
unsub_alert_priority_code_list))
OR
// Added scheduled occurrence to the set
(task_cds_occurrence_type = 90)
OR
// Added performed occurrence to the set
(task_cds_occurrence_type = 91)
OR
// Rescheduled an instance in the set
(EVOKINGEVENTTYPE = any_rescheduled_task_instance.type)
)
then conclude true;
endif;
;;
action:
/* Select the Destination for the Alert{{{SINGLE-QUOTE}}}s Priority */
if high_priority_alert
then
write complete_alert_msg
at high_dup_task_alert;
else
write complete_alert_msg
at medium_dup_task_alert;
endif; /* if high_priority_alert */
;;
Urgency: 50;;
end: