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

562 lines
22 KiB
Plaintext

maintenance:
title: Rules for Duplicate Task Checking;;
mlmname: STD_FUNC_TASK_RULES;;
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: Process the OrderTaskOccurrences according to the rules
stated in the std_duplicate_task.mlm.
Returns information on the duplicate task occurrences to the calling MLM.
;;
explanation: See the explanation in std_duplicate_task.mlm
;;
keywords: Duplicate Task;
;;
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;
/********************************************************************************/
/* Do Not Changes these Internal MLM Variables */
exact_msg:= "exact";
performed_msg:= "performed";
scheduled_msg:= "scheduled";
same_item_type:= "same item";
same_therapeutic_class_type:= "same therapeutic class";
similar_task_type:= "similar task";
conflict_type:= "conflict";
possible_conflict_type:= "possible conflict";
no_std_message_type:= "no std message";
/*==============================================================================*/
(task_name,
task_occurrence_guid,
task_status_code,
task_summary_line,
is_primary_task,
originating_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 ):= ARGUMENT;
/* Declares MLMs which can be called */
func_task_duration:= MLM {{{SINGLE-QUOTE}}}std_func_task_duration{{{SINGLE-QUOTE}}};
func_task_retrieval:= MLM {{{SINGLE-QUOTE}}}std_func_task_retrieval{{{SINGLE-QUOTE}}};
/* Gets the Client GUID */
client_guid := read last {ClientInfo: GUID};
/* Gets the evoking task occurrence{{{SINGLE-QUOTE}}}s Duplicate Policy */
(catalog_name,
duplicate_policy_guid ):= read last
{"SELECT Name, DuplicatePolicyGUID "
|| " FROM CV3CatalogItemTask "
|| " WHERE GUID = " || SQL(task_catalog_item_guid)
|| " AND Active = 1 "};
/* Continue if "check for duplicates" is marked in the Item-Catalog */
If exist duplicate_policy_guid
then
/* Gets evoking OrderTaskOccurrence{{{SINGLE-QUOTE}}}s duplicate policy information */
(task_loc_group_guid_list,
task_scope_list,
task_performed_time_list,
task_performed_unit_list,
task_exact_time_list,
task_exact_unit_list,
task_scheduled_time_list,
task_scheduled_unit_list,
loc_is_excluded_list) := read
{"SELECT LocationGroupGUID, SearchScope, PastTime, PastTimeUnits,"
|| " ExactTime, ExactTimeUnits, FutureTime, FutureTimeUnits, IsExcluded"
|| " FROM CV3OrderDuplicatePolicyDtl "
|| " WHERE OrderDuplicatePolicyGUID = " || SQL(duplicate_policy_guid)
|| " AND LocationGroupGUID IN (0, " || SQL(patient_loc_group)|| " )"
|| " AND 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 task_scope_list
then
If any (patient_loc_group = task_loc_group_guid_list)
then
loc_group_found := patient_loc_group = task_loc_group_guid_list;
else
loc_group_found := task_loc_group_guid_list is null;
endif;
loc_is_excluded := last (loc_is_excluded_list where loc_group_found);
endif; /* if exist task_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 */
/*--------------------------------------------------*/
task_loc_grp:= last (task_loc_group_guid_list
where loc_group_found);
task_scope:= last (task_scope_list
where loc_group_found);
task_performed_time:= last (task_performed_time_list
where loc_group_found);
task_performed_unit:= last (task_performed_unit_list
where loc_group_found);
task_exact_time:= last (task_exact_time_list
where loc_group_found);
task_exact_unit:= last (task_exact_unit_list
where loc_group_found);
task_scheduled_time:= last (task_scheduled_time_list
where loc_group_found);
task_scheduled_unit:= last (task_scheduled_unit_list
where loc_group_found);
/*-------------------------------------*/
/* Converts EXACT TIME into Arden Time */
/*-------------------------------------*/
If task_exact_time >= 0
and task_exact_unit is string
then
exact_duration := call func_task_duration with
(task_exact_time, task_exact_unit, frequency_unit);
If task_exact_unit = "days"
then exact_low_time:= (day floor of task_significant_date)
- exact_duration ;
exact_high_time:= (day floor of task_significant_date)
+ exact_duration + (1 day) - (1 second);
else exact_low_time:= task_significant_date - exact_duration;
exact_high_time:= task_significant_date + exact_duration;
endif; /* if task_exact_unit = */
endif; /* If task_exact_time >= 0 */
if exact_duration is NOT Duration
then
xxx_debug1:= "made EXACT time substitution";
/* Substitute times */
exact_low_time:= task_significant_date;
exact_high_time:= task_significant_date;
endif; /* if exact_duration is NOT Duration */
/*-----------------------------------------*/
/* Converts PERFORMED TIME into Arden Time */
/*-----------------------------------------*/
If task_performed_time >= 0 and task_performed_unit is string
then
performed_duration := call func_task_duration with
(task_performed_time, task_performed_unit, frequency_unit);
If task_performed_unit = "days"
then past_time:= (day floor of task_significant_date)
- performed_duration;
else past_time:= task_significant_date - performed_duration;
endif; /* if task_performed_unit = */
endif; /* if task_performed_time >= 0 ...*/
if performed_duration is NOT Duration
then
xxx_debug2:= "made PAST time substitution";
/* Substitute times */
if task_exact_unit = "Task %"
then
past_time:= task_significant_date - 12 hours;
substituted_past_frequency_date := true;
else
past_time:= task_significant_date;
endif; /* if task_exact_unit = "Task %" */
endif; /* if performed_duration is NOT Duration */
/*-----------------------------------------*/
/* Converts SCHEDULED TIME into Arden Time */
/*-----------------------------------------*/
If task_scheduled_time >= 0 and task_scheduled_unit is string
then
scheduled_duration := call func_task_duration with
(task_scheduled_time, task_scheduled_unit, frequency_unit);
If task_scheduled_unit = "days"
then future_time:= (day floor of task_significant_date)
+ scheduled_duration + (1 day) - (1 second);
else future_time:= task_significant_date + scheduled_duration;
endif; /* if task_scheduled_unit = */
endif; /* if task_scheduled_time >= 0 ...*/
if scheduled_duration is NOT Duration
then
xxx_debug3:= "made FUTURE time substitution";
/* Substitute times */
if task_exact_unit = "Task %"
then
future_time:= task_significant_date + 12 hours;
substituted_future_frequency_date := true;
else
future_time:= task_significant_date;
endif; /* if task_exact_unit = "Task %" */
endif; /* if scheduled_duration is NOT Duration */
/*---------------------------------------------------------*/
/* Determine if the Time Intervals are GOOD. */
/* Also determine if there was a frequency substitutition */
/* so the user can be warned that a complete check */
/* was not done */
/*---------------------------------------------------------*/
/* Check if the past and future are valid times */
has_time_interval := all ((past_time, future_time)are time);
/* Check if the past or future dates used a frequency substitution */
If substituted_past_frequency_date
OR substituted_future_frequency_date
then has_unknown_frequency := true;
else has_unknown_frequency := false;
endif; /* If substituted_past_frequency_date */
/* Only continue duplicate check if there are good dates for the */
/* time-interval for duplicates */
if has_time_interval
then
/*---------------------------------------------------------------------*/
/* Get evoking task{{{SINGLE-QUOTE}}}s Duplicate Item information from the Item-Catalog */
/*---------------------------------------------------------------------*/
/* Get the evoking task occurrence{{{SINGLE-QUOTE}}}s list of Duplicate ITEMS/CLASSES */
(cat_dup_item_name_list,
cat_dup_item_guid_list,
cat_class_name_list,
cat_class_value_list,
cat_message_type_list,
cat_message_list) := read
{"SELECT DuplicateItemName, DuplicateItemGUID, ClassTypeCode, "
|| " ClassValue, MessageType, MessageText "
|| " FROM CV3CatalogTaskDuplicate "
|| " WHERE CatalogItemTaskGUID = "||SQL(task_catalog_item_guid)
|| " AND Active = 1 "};
/*----------------------------------------------------------------------*/
/* Get the items from Item-Catalog that have a matching Duplicate CLASS */
/*----------------------------------------------------------------------*/
/* If there are any classes associated with the evoking task occurrence, */
/* then get the GUIDs of the items */
// Select same kind of task (primary or follow-up)
if is_primary_task
then
AND_match_task_sequence_number := " AND t.TaskSeqNum = 0";
else
AND_match_task_sequence_number := " AND t.TaskSeqNum <> 0";
endif;
If exist cat_class_value_list
then
other_class_guid_list:= ();
other_class_type_list:= ();
other_class_value_list:= ();
other_class_msg_type_list:= ();
other_class_msg_text_list:= ();
index1_list := 1 seqto (count cat_class_value_list);
for I in index1_list do
single_class_value := last(first I from cat_class_value_list);
single_class_type:= last(first I from cat_class_name_list);
single_class_msg_type:= last(first I from cat_message_type_list);
single_class_message:= last(first I from cat_message_list);
If exist single_class_value
and exist single_class_type
and exist task_catalog_item_guid
then
(temp_catalog_GUID_db,
temp_class_type_db,
temp_class_value_db):= read
{"SELECT t.OrderCatalogMasterItemGUID, "
|| " d.ClassTypeCode, d.ClassValue "
|| " FROM CV3CatalogTaskDuplicate as d"
|| " JOIN CV3CatalogItemTask as t"
|| " ON d.CatalogItemTaskGUID = t.GUID"
|| " WHERE "
|| " d.ClassTypeCode = " || SQL(single_class_type)
|| " AND d.ClassValue = " || SQL(single_class_value)
|| AND_match_task_sequence_number
|| " AND d.CatalogItemTaskGUID <> "
|| SQL(task_catalog_item_guid)} ;
If exist temp_catalog_GUID_db
then
other_class_guid_list:= other_class_guid_list,
temp_catalog_GUID_db;
other_class_type_list:= other_class_type_list,
temp_class_type_db;
other_class_value_list:= other_class_value_list,
temp_class_value_db;
/* Add the MessageType and MessageText */
/* Create the same number of instances as */
/* the temp_catalog_GUID_db list */
for each_catalog_guid in temp_catalog_GUID_db do
other_class_msg_type_list:=
other_class_msg_type_list,
single_class_msg_type;
other_class_msg_text_list:=
other_class_msg_text_list,
single_class_message;
enddo; /* for each_catalog_guid */
endif; /* if exist temp_catalog_GUID_db */
endif; /* if exist single_class_value */
enddo; /* for I */
endif; /* if exist cat_class_value_list */
/*-------------------------------------------------*/
/* Retrieve the task occurrences from the DATABASE */
/*-------------------------------------------------*/
(latest_scheduled_dtm_list,
master_GUID_list,
order_name_list,
order_type_code_list,
performed_to_dtm_list,
process_type_list,
schedule_type_code_list,
significant_date_list,
task_name_list,
task_status_code_list ):= call func_task_retrieval with
(client_guid,
chart_guid,
client_visit_guid,
task_occurrence_guid,
task_name,
task_scope,
is_primary_task,
originating_order_guid,
past_time,
future_time,
tasks_to_be_canceled_string,
schedule_type_code,
order_task_guid );
endif; /* if has_time_interval */
endif; /* if any loc_group_found and not loc_is_excluded */
endif; /* if exist duplicate_policy_guid */
;;
evoke:
;;
logic:
/*-----------------------*/
/* Initializes Variables */
/*-----------------------*/
matching_guid_list:= ();
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:= ();
/*--------------------------------------------------------*/
/* Create the DUP_ITEM_GUID_LIST and its associated lists */
/*--------------------------------------------------------*/
/* These lists are created from the item-catalog information associated */
/* with the Evoking OrderTaskOccurrence object. */
/* The DUP_ITEM_GUID_LIST contains the OrderCatalogMasterItemGUIDs */
/* that are potential duplicates of the EvokingObject */
/* The other lists contain information about the MessageType, MessageText, */
/* etc. which are used to construct the alert message */
/* Step 1: Initialize the lists with the individual ITEMs */
/* The individual ITEMs will have OrderCatalogMasterItemGUIDs in */
/* the cat_dup_item_guid_list */
cat_data_found := cat_dup_item_guid_list is not null;
dup_item_guid_list:= cat_dup_item_guid_list where cat_data_found;
class_name_list:= cat_class_name_list where cat_data_found;
class_value_list:= cat_class_value_list where cat_data_found;
message_type_list:= cat_message_type_list where cat_data_found;
message_list:= cat_message_list where cat_data_found;
/* Step 2: A task is always a duplicate of itself. */
/* Add the evoking object{{{SINGLE-QUOTE}}}s OrderCatalogMasterItemGUID */
/* to the front of the following lists, if the information from the */
/* item-catalog--duplicate checking panel does not include it. */
If item_catalog_guid is not in dup_item_guid_list
then
dup_item_guid_list:= item_catalog_guid, dup_item_guid_list;
class_name_list:= null, class_name_list;
class_value_list:= null, class_value_list;
message_type_list:= same_item_type, message_type_list;
message_list:= null, message_list;
endif; /* if item_catalog_guid is not in... */
/* Step 3: Add the OrderCatalogMasterItemGUIDs for the CLASSES */
/* and the other associated data to the lists */
If exist other_class_guid_list
then
dup_item_guid_list:= dup_item_guid_list, other_class_guid_list;
class_name_list:= class_name_list, other_class_type_list;
class_value_list:= class_value_list, other_class_value_list;
message_type_list:= message_type_list, other_class_msg_type_list;
message_list:= message_list, other_class_msg_text_list;
endif; /* if exist other_class_guid_list */
/*---------------------------------------------------------------*/
/* Finds all possible duplicates among the ITEMS and the CLASSES */
/*---------------------------------------------------------------*/
If any(dup_item_guid_list is in master_guid_list)
then
/* The matching is done on the OrderCatalogMasterItemGUIDs */
/* Process each GUID one-at-a-time to find a match between the following */
/* Dup_item_guid_list, which are item-catalogs{{{SINGLE-QUOTE}}} OrderCatalogMasterItemGUIDs. */
/* Master_guid_list, which are task occurrences{{{SINGLE-QUOTE}}} OrderCatalogMasterItemGUIDs. */
index2_list := 1 seqto (count dup_item_guid_list);
for J in index2_list do
item_master_guid := last(first J from dup_item_guid_list);
if item_master_guid is in master_guid_list
then
master_guid_found:= item_master_guid = master_guid_list;
temp_guid:= master_guid_list where master_guid_found;
temp_task_name:= task_name_list where master_guid_found;
temp_signif:= significant_date_list where master_guid_found;
temp_latest_scheduled_dtm:= latest_scheduled_dtm_list
where master_guid_found;
temp_order_name:= order_name_list where master_guid_found;
temp_order_type:= order_type_code_list where master_guid_found;
temp_performed_to_dtm:= performed_to_dtm_list where master_guid_found;
temp_process_type:= process_type_list where master_guid_found;
temp_schedule_type:= schedule_type_code_list where master_guid_found;
temp_status:= task_status_code_list where master_guid_found;
matching_guid_list:=
matching_guid_list, temp_guid;
matching_task_name_list:=
matching_task_name_list, temp_task_name;
matching_significant_date_list:=
matching_significant_date_list, temp_signif;
matching_latest_scheduled_dtm_list:=
matching_latest_scheduled_dtm_list, temp_latest_scheduled_dtm;
matching_order_name_list:=
matching_order_name_list, temp_order_name;
matching_order_type_code_list:=
matching_order_type_code_list, temp_order_type;
matching_performed_to_dtm_list:=
matching_performed_to_dtm_list, temp_performed_to_dtm;
matching_process_type_list:=
matching_process_type_list, temp_process_type;
matching_schedule_type_code_list:=
matching_schedule_type_code_list, temp_schedule_type;
matching_task_status_code_list:=
matching_task_status_code_list, temp_status;
/* Find the associated MessageType and MessageText */
For each_guid in temp_guid do
temp_class_value := last(first J from class_value_list);
temp_msg_type := last(first J from message_type_list);
temp_msg_text := last(first J from message_list);
matching_msg_type_list:= matching_msg_type_list, temp_msg_type;
matching_msg_text_list:= matching_msg_text_list, temp_msg_text;
matching_class_list:= matching_class_list, temp_class_value;
/* Set the time messages */
task_time:= time of each_guid;
relative_date:= now;
If task_time >= exact_low_time AND task_time <= exact_high_time
then correct_msg:= exact_msg;
elseif task_time < relative_date
then correct_msg:= performed_msg;
elseif task_time > relative_date
then correct_msg:= scheduled_msg;
else correct_msg:= null;
endif; /* if task_time */
matching_time_msg_list:= matching_time_msg_list, correct_msg;
enddo; /* for each_guid */
endif; /* if item_master_guid is in master_guid_list */
enddo; /* for J */
endif; /* if any(dup_item_guid_list...*/
/* All remaining, matched task occurrences are considered duplicates */
/* Concludes true to return data to the calling MLM */
conclude true;
;;
action:
return( 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 );
;;
end: