289 lines
12 KiB
Plaintext
289 lines
12 KiB
Plaintext
maintenance:
|
|
|
|
title: First Alert Escalation via Pager;;
|
|
mlmname: STD_ESCALATION_PAGER;;
|
|
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: Notifies the patient{{{SINGLE-QUOTE}}}s Care-Provider that an urgent alert has occurred.
|
|
;;
|
|
explanation:
|
|
This time-based MLM handles the first phase of Alert Escalation through a pager or email.
|
|
It is triggered zero minutes after the alert is stored into the database.
|
|
A facility designates which Care-Provider-Role will be paged when an Escalation alert
|
|
occurs. This designation is set using the "provider_role_string" variable in this MLM.
|
|
When the care-provider cannot be paged, an email message is sent to the
|
|
designated Alert Center, where the appropriate care-provider can be contacted
|
|
by the people at the Alert Center. The three rules are as follows:
|
|
|
|
1. If an "Escalation" alert-type is stored into the database in an UNACKNOWLEDGED state,
|
|
then the patient{{{SINGLE-QUOTE}}}s care-provider is contacted through an alpha-numeric pager.
|
|
|
|
2. When the patient{{{SINGLE-QUOTE}}}s care-provider does not have an alpha-numeric pager,
|
|
then an email message is sent to the Alert Center.
|
|
|
|
3. When the patient does not have a care-provider with a role that can receive the page,
|
|
then an email message is sent to the Alert Center.
|
|
;;
|
|
keywords: Time-based; Escalation; Alert Escalation;;
|
|
|
|
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;
|
|
|
|
/* The Destination statment is located at the end of the data slot */
|
|
/* This is due to the use of a variable in the statement, that is set dynamically */
|
|
|
|
/* Escalation is a core-loaded Alert Type. */
|
|
/* Recommend that the spelling within the quotes not be modified */
|
|
unack_escalated_alert:= event {AlertEnter Any Alert:
|
|
where TypeCode= "Escalation" and Status= "Unack"};
|
|
|
|
/* Change the spelling within the quotes to match a specific dictionary */
|
|
phone_type_string:= "Pager-AlphaNum"; /* Phone Type (alpha-numeric pager)*/
|
|
|
|
/* Which Care-Provider should be contacted when there is an escalated-alert? */
|
|
/* Change the provider-role in quotes to match a role in the Provider Role dictionary */
|
|
provider_role_string:= "Attending";
|
|
|
|
/* Where should the alert be sent if there is no pager? */
|
|
/* Change the email address in quotes */
|
|
/* Recommend that this message be sent to your facility{{{SINGLE-QUOTE}}}s designated Alert Center */
|
|
email_address:= "AlertCenter";
|
|
|
|
/* What is the long-distance country-code for your facility? */
|
|
/* In the USA and Canada, the code is 1 */
|
|
country_code:= 1;
|
|
|
|
/****************************************************************************************/
|
|
|
|
/* This block executes only when this MLM is called by the editor */
|
|
if called_by_editor then
|
|
obj := read last
|
|
{ Alert: THIS
|
|
WHERE TypeCode= "Escalation"
|
|
AND Status = "Unack" };
|
|
EvokingObject := obj;
|
|
endif;
|
|
|
|
/* Get the patient{{{SINGLE-QUOTE}}}s ID and Name */
|
|
(client_guid,
|
|
client_name) := read last {ClientInfo: GUID, Name};
|
|
|
|
/* Get information about the evoking alert */
|
|
(alert_type,
|
|
alert_status,
|
|
client_visit_guid,
|
|
short_alert_msg,
|
|
alert_guid,
|
|
alert_text,
|
|
alert_has_long_text ):= read last
|
|
{Alert: TypeCode, Status, ClientVisitGUID, Description, GUID,
|
|
PlainMessageText, HasLongText
|
|
REFERENCING EvokingObject };
|
|
|
|
/* Continue processing when there is an Unacknowledged alert. */
|
|
/* It is possible that someone may have acknowledged the alert */
|
|
/* before the time-based MLM could run */
|
|
if alert_status = "Unack"
|
|
then
|
|
/* Get the patient{{{SINGLE-QUOTE}}}s location group (unit) */
|
|
(current_loc_name,
|
|
patient_loc_group_name ):= read last
|
|
{"SELECT cv.CurrentLocation, loc.Name "
|
|
|| " FROM CV3ClientVisit AS cv JOIN CV3Location AS loc"
|
|
|| " ON cv.CurrentLocationGUID = loc.GUID "
|
|
|| " WHERE cv.GUID = " || SQL(client_visit_guid)
|
|
|| " AND cv.Active = 1 "
|
|
|| " AND loc.Active = 1 " };
|
|
|
|
/* Retrieve the current (unexpired) Care Provider for the patient */
|
|
/* and the provider{{{SINGLE-QUOTE}}}s current (unexpired) Pager and Pin number combination */
|
|
/* Only one pager and pin number combination is used. */
|
|
/* If there are two or more in the database, then the older ones will be ignored */
|
|
(provider_role_code_list,
|
|
provider_status_list,
|
|
from_date_list,
|
|
to_date_list,
|
|
active_phone_list,
|
|
phone_type_list,
|
|
area_code_list,
|
|
phone_and_pin_list,
|
|
touched_when_list,
|
|
provider_name_list ):= read
|
|
{"SELECT cpvr.RoleCode, cpvr.Status, fromDtm.TimeValue AS FromDtm, toDtm.TimeValue AS ToDtm, "
|
|
||" p.Active, p.PhoneType, p.AreaCode, p.PhoneNumber, "
|
|
||" touchedWhen.TimeValue AS TouchedWhen, cp.DisplayName"
|
|
||" FROM CV3CareProviderVisitRole AS cpvr JOIN CV3CareProvider AS cp "
|
|
||" ON cpvr.ProviderGUID = cp.GUID "
|
|
||" INNER JOIN CV3ClientVisit cv ON cpvr.ClientVisitGUID = cv.GUID "
|
|
||" LEFT OUTER JOIN CV3Phone AS p "
|
|
||" ON cpvr.ProviderGUID = p.PersonGUID"
|
|
||" CROSS APPLY dbo.SXADBConvertLocalToOffsetForVisitTblFn(cpvr.ClientVisitGUID, cpvr.FromDtm) as fromDtm "
|
|
||" CROSS APPLY dbo.SXADBConvertLocalToOffsetForVisitTblFn(cpvr.ClientVisitGUID, cpvr.ToDtm) as toDtm "
|
|
||" CROSS APPLY dbo.SXADBConvertEnterpriseToLocalTblFn(cv.TimeZone, cpvr.TouchedWhen) touchedWhenLocal "
|
|
||" CROSS APPLY dbo.SXADBConvertLocalToOffsetForVisitTblFn(cv.GUID, touchedWhenLocal.LocalDate) touchedWhen "
|
|
||" WHERE cpvr.ClientVisitGUID = " || SQL(client_visit_guid)
|
|
||" AND cpvr.Status = {{{SINGLE-QUOTE}}}Active{{{SINGLE-QUOTE}}} "
|
|
||" AND cpvr.RoleCode = " || SQL(provider_role_string)
|
|
||" AND cpvr.FromDtm <= (SELECT TOP 1 LocalDate FROM dbo.SXADBConvertEnterpriseToLocalTblFn(cv.TimeZone, (SELECT CurDate FROM dbo.SXADBGetEnterpriseNowTblFn()))) "
|
|
||" AND (ISNULL (cpvr.ToDtm, (SELECT TOP 1 LocalDate FROM dbo.SXADBConvertEnterpriseToLocalTblFn(cv.TimeZone, (SELECT CurDate FROM dbo.SXADBGetEnterpriseNowTblFn())))) >= "
|
|
||" (SELECT TOP 1 LocalDate FROM dbo.SXADBConvertEnterpriseToLocalTblFn(cv.TimeZone, (SELECT CurDate FROM dbo.SXADBGetEnterpriseNowTblFn()))))"
|
|
, PrimaryTime = TouchedWhen };
|
|
|
|
/*-------------------------------------------------------*/
|
|
/* Find the AlphaNumeric Pager Number and Associated Info */
|
|
/*-------------------------------------------------------*/
|
|
|
|
/* Find the location of the phone_type in the phone type list */
|
|
found_phone_type := (phone_type_list = phone_type_string) AND (active_phone_list);
|
|
|
|
/* Get the most recent instance of the data if there is a pager */
|
|
/* using the location of the phone type in found_phone_type */
|
|
provider_role_code := last (provider_role_code_list where found_phone_type);
|
|
provider_status := last (provider_status_list where found_phone_type);
|
|
from_date := last (from_date_list where found_phone_type);
|
|
to_date := last (to_date_list where found_phone_type);
|
|
phone_type := last (phone_type_list where found_phone_type);
|
|
area_code := last (area_code_list where found_phone_type);
|
|
phone_and_pin := last (phone_and_pin_list where found_phone_type);
|
|
touched_when := last (touched_when_list where found_phone_type);
|
|
|
|
/* Get the provider name */
|
|
if exist provider_role_code
|
|
then /* The provider has an alpha-numeric pager */
|
|
/* Get the provider name associated with the PHONE_TYPE_STRING */
|
|
provider_name := last (provider_name_list where found_phone_type);
|
|
else /* The provider does not have an alpha-numeric pager */
|
|
/* So get the provider name and phone at the end of the lists, */
|
|
/* sorted by PrimaryTime (CV3Phone.TouchedWhen) */
|
|
provider_name := last (provider_name_list);
|
|
if last (active_phone_list) then
|
|
provider_phone := last (phone_and_pin_list);
|
|
else
|
|
provider_phone := "NOT ACTIVE";
|
|
endif; // last phone is active
|
|
endif; /* if exist provider_role_code */
|
|
endif; /* if alert_status = "Unack" */
|
|
|
|
/*-----------------------*/
|
|
/* Assemble Pager Number */
|
|
/*-----------------------*/
|
|
If exist country_code
|
|
and exist area_code
|
|
and exist phone_and_pin
|
|
then
|
|
pager_num_and_pin:= country_code || "-" || area_code || "-" || phone_and_pin;
|
|
endif; /* If exist country_code */
|
|
|
|
/*------------------------*/
|
|
/* DESTINATION STATEMENTS */
|
|
/*------------------------*/
|
|
/* Change the message within the quotes if a different short-message as needed.*/
|
|
/* Do not change the Alert Type to Escalation. This will cause an infinite loop */
|
|
intermediate_alert:= destination { IntermediateMessage: warning,
|
|
"Escalation Alert", high, chart,
|
|
"HVC Saved Escalation Message", 1005 };
|
|
|
|
/* There must be a Care Provider and a Pager with a pin number to send a page */
|
|
/* Otherwise, Email is sent to a facility{{{SINGLE-QUOTE}}}s designated Alert Center */
|
|
if exist provider_name and exist pager_num_and_pin
|
|
then
|
|
primary_alert:= destination { Pager: warning,
|
|
"Escalation Alert", high, chart, pager_num_and_pin };
|
|
else
|
|
primary_alert:= destination { Email: warning,
|
|
"Escalation Alert", high, chart, email_address };
|
|
endif;
|
|
|
|
;;
|
|
evoke: 0 minutes after time of unack_escalated_alert
|
|
|
|
;;
|
|
|
|
logic:
|
|
/* Exit the MLM when the alert has already been acknowledged */
|
|
If alert_status <> "Unack"
|
|
then conclude false;
|
|
endif;
|
|
|
|
/* Determine the content of the message */
|
|
If exist provider_name and exist pager_num_and_pin
|
|
then
|
|
alert_message:= client_name
|
|
|| " ("|| patient_loc_group_name || ") " || short_alert_msg;
|
|
phone_string := "\nPAGER number and pin: " ||pager_num_and_pin;
|
|
else
|
|
/* Create the top part of the message */
|
|
if exist provider_name
|
|
then
|
|
alert_message:= "A pager message could not be sent to the "
|
|
|| provider_role_string || " (" || provider_name || " )"
|
|
|| " because he or she does not have an alpha-numeric pager. "
|
|
|| " Please notify him or her that there is an escalated alert"
|
|
|| " regarding the following patient: " ;
|
|
phone_string := "\nPHONE number: " || provider_phone;
|
|
else
|
|
alert_message:= "A pager message could not be sent because the patient"
|
|
|| " does not have a care-provider assigned as "
|
|
|| provider_role_string
|
|
|| ". Please notify the appropriate person that there is an"
|
|
|| " escalated alert regarding the following patient: " ;
|
|
provider_name := "NO CARE PROVIDER ASSIGNED";
|
|
phone_string := "\nPHONE number: N/A";
|
|
endif; /* if exist provider_name */
|
|
|
|
/* Create the bottom part of the message */
|
|
alert_message:= alert_message
|
|
||"\n\nPatient: " || client_name
|
|
||"\nLocation: " || patient_loc_group_name
|
|
|| "\nAlert Title: " || short_alert_msg || " (full text below)"
|
|
||"\n\n"
|
|
|| alert_text;
|
|
endif; /* If exist provider_name... */
|
|
|
|
/*---------------*/
|
|
/* Clinical Rule */
|
|
/*---------------*/
|
|
If alert_status = "Unack"
|
|
then conclude true;
|
|
endif;
|
|
;;
|
|
action:
|
|
/* Send message to pager or email */
|
|
write alert_message
|
|
at primary_alert;
|
|
|
|
/* Keep a copy of the message and the care-provider{{{SINGLE-QUOTE}}}s ID */
|
|
/* Store it in the database as an intermediate message */
|
|
write provider_role_string || ": " ||provider_name
|
|
|| phone_string
|
|
|| "\n\n" || alert_message
|
|
at intermediate_alert;
|
|
;;
|
|
end:
|