maintenance: title: Check Allergy Already Alerted;; mlmname: FUNC_ACS_ALLERGY_SUPPRESS_ALERT;; arden: version 2.5;; version: 16.3;; institution: Allscripts, Standard MLM;; author: Allscripts Healthcare Solutions, Inc.;; specialist: ;; date: 2016-12-20;; validation: testing;; /* P r o p r i e t a r y N o t i c e */ /* Unpublished (c) 2013 - 2015 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: In keeping with alert reduction efforts, work out a way in SCM that when an allergy override has been addressed once, SCM retains that information and no alert is fired again. ;; explanation: If an allergy alert exists in the CV3AlertDeclaration table for this patient, this visit, and the ingredients of the triggering order are the same and the allergen is the same and the ordering provider has an OrderRoleType like {{{SINGLE-QUOTE}}}%physician%{{{SINGLE-QUOTE}}} or OrderRoleType = {{{SINGLE-QUOTE}}}CRNP{{{SINGLE-QUOTE}}} or OrderRoleType = {{{SINGLE-QUOTE}}}PA-C{{{SINGLE-QUOTE}}} the allergy alert should be supressed. Code changes such that if the physician’s decide to only alert once per visit, regardless of who receives the first alert (%physician%, CRNP, or PA-C) the change can be made by changing a parameter in the MLM. All other providers (non-physician, non-physician extenders) will continue to receive allergy alerts as they are currently presented to the end user. Change History: 12.14.2017 JBickley Created CSR 35068 05.21.2018 TSpicuzza Add logic to only suppress alerts for appropriate users when they are members of the Emergency Department which is being used as the pilot unit beginning on 5/21/2018. CSR 35068 ;; keywords: allergy; ;; citations: ;; knowledge: type: data-driven;; data: (EvokingObject) := argument; // Specify which .NET assemblies need to be loaded for ObjectsPlus standard_libs := MLM {{{SINGLE-QUOTE}}}std_include_libs{{{SINGLE-QUOTE}}}; include standard_libs; // Set to true if logging is needed. log_execution_info := false; //***************Make Changes To Spelling And Flags In This Section************* SuppressAlertOnlyIfCurrentUserHasSeen := true; SuppressAlertOnlyIfCurrentUserHasAcknowledged := true; SuppressAlertOnlyIfAlertProceeded := true; SuppressAlertOnlyIfAlertAcknowledged := true; SuppressCrossDrugKey := true; SuppressCrossDrugComponents := true; PilotDepartment := read last { "select GUID from CV3OrganizationalUnit where name = {{{SINGLE-QUOTE}}}Emergency Department{{{SINGLE-QUOTE}}}"}; // OrderRoleTypesToSuppressSecondaryAlert := read {"select Code from CV3OrderRoleType where Active = 1 and (Code like {{{SINGLE-QUOTE}}}%physician%{{{SINGLE-QUOTE}}} or Code = {{{SINGLE-QUOTE}}}CRNP{{{SINGLE-QUOTE}}} or Code = {{{SINGLE-QUOTE}}}PA-C{{{SINGLE-QUOTE}}})"}; OrderRoleTypesToSuppressSecondaryAlert := read {"select Code from CV3OrderRoleType where Active = 1 and (Code like {{{SINGLE-QUOTE}}}%ed physician%{{{SINGLE-QUOTE}}} or Code = {{{SINGLE-QUOTE}}}CRNP{{{SINGLE-QUOTE}}} or Code = {{{SINGLE-QUOTE}}}PA-C{{{SINGLE-QUOTE}}})"}; //assume the default is to alert the user SuppressAlert := false; SuppressAlertReason := ""; /* Get the current user info*/ (user_id,userguid) := read last {UserInfo: idcode, guid}; (ClientGUID, ChartGUID, ClientVisitGUID) := read last {StateInfo: ClientGUID, ChartGUID, VisitGUID}; OrderRoleType := read last {"Select OrderRoleType " ||" From cv3user with (nolock) " ||" Where Guid = " || SQL(userguid) ||" and OrgUnitGUID = " || PilotDepartment }; /* OrderRoleType := read last {"Select OrderRoleType " ||" From cv3user with (nolock) " ||" Where Guid = " || SQL(userguid) }; */ if(called_by_editor)then //ClientGUID := 3400200; //ChartGUID := 3400170; //ClientVisitGUID := 3400270; // Define object choice "Order", or "ClientPrescription" Object_Choice := //"ClientPrescription"; //"Allergy"; "Order"; if (object_choice = "Order") then EvokingObject:= read last {Order: This WHERE TypeCode = "Medication" //AND Name = "Acetaminophen 650 mg suppository" //AND Name = "Tylenol Caplet 500 mg - Oral" //AND Name = "Acetaminophen-Codeine #3" //AND Name = "ibuprofen"//"Acetaminophen" AND Name = "acetaminophen + oxyCODONE 325 mg-5 mg" }; //EvokingEventType := entered_order.type; elseif (object_choice = "Allergy") then EvokingObject:= read last {Allergy: This}; //EvokingEventType := entered_allergy.type; else EvokingObject:= read last {ClientPrescription: This WHERE PrescriptionTypeDescription in ("Rx", "Hx") }; //EvokingEventType := prescription_enter.Type; endif; endif; AlertObj := OBJECT [UserGUID ,Status ,AcknowledgedUserName ,AcknowledgedUserGUID ,PObjectName ,PObjectGUID ,AlertRepositoryGUID ,PrimaryProviderGUID ,Abstract ,TriggeringInfo ,OrderName ]; query := "select alert.UserGUID ,alert.Status ,alert.AcknowledgedUserName ,alert.AcknowledgedUserGUID ,alert.PObjectName ,alert.PObjectGUID ,alert.GUID ,alert.PrimaryProviderGUID ,alert.Abstract ,alert.TriggeringInfo ,o.Name from CV3AlertRepository alert left outer join CV3Order o on o.ClientGUID = alert.ClientGUID and o.ChartGUID = alert.ChartGUID and o.GUID = alert.PObjectGUID left outer join SXAAMBClientPrescription cp on cp.ClientGUID = alert.ClientGUID and cp.ClientVisitGUID = alert.ClientVisitGUID and cp.CDSUniqueIDGUID = alert.PObjectGUID where alert.MLMName = {{{SINGLE-QUOTE}}}STD_ALLERGY{{{SINGLE-QUOTE}}} and alert.ClientGUID = " || ClientGUID //|| " and alert.ChartGUID = " || ChartGUID || " and alert.ClientVisitGUID = " || ClientVisitGUID; Alerts := read as AlertObj {""||query}; if(SuppressAlertOnlyIfCurrentUserHasSeen)then Alerts := Alerts Where Alerts.UserGUID = userguid; endif; if(SuppressAlertOnlyIfCurrentUserHasAcknowledged)then Alerts := Alerts Where Alerts.AcknowledgedUserGUID = userguid; endif; if(SuppressAlertOnlyIfAlertProceeded)then Alerts := Alerts Where Alerts.OrderName is not null; endif; if(SuppressAlertOnlyIfAlertAcknowledged)then Alerts := Alerts Where Alerts.Status = "Ack"; endif; if(count(Alerts) > 0)then if (EvokingObject IS ClientPrescription) then evoked_from_prescriptions := true; display_alert_types := display_prescription_alert_other_types, allergen_type_string; (evoking_prescription_description, evoking_prescription_name, evoking_prescription_NameID, alert_on_demand_source, client_guid ) := read last { ClientPrescription: PrescriptionTypeDescription, DrugName, GenericNameID, AlertOnDemandSource, ClientGUID REFERENCING EvokingObject }; elseif (EvokingObject IS Order) then evoked_from_prescriptions := false; display_alert_types:= display_order_alert_other_types, allergen_type_string; // Get the order component object associated with the evoking order (evoking_order_name, evoking_cat_item_guid, order_type, OrdComponentObj, PharmOrderObj, evoking_complex_order_type, OrderVariableComponentObj, alert_on_demand_source, client_guid, alternate_order_type, AdditionalInfoObj, BackupObj ) := read last { Order: Name, OrderCatalogMasterItemGUID, TypeCode, OrderComponent, PharmacyOrder, ComplexOrderType, OrderVariableComponent, AlertOnDemandSource, ClientGUID, AlternateOrderType, OrderAdditionalInfo, Backup REFERENCING EvokingObject }; endif; DrugMappingObj := OBJECT [ocmi_GUID,ocmi_Name,ocmi_TherapeuticCategoryID,TherapeuticCategory,DBStatus,DrugKey,DrugName,DrugSynonymID,function_id,OriginalTouchedWhen,DrugMappingTouchedWhen,GenericName,MMDC,AlternateMappingName,DrugMappingXrefTouchedWhen,IsObsolete]; DrugMappingComponentObj := OBJECT [ocmi_GUID, ocmi_Name, Multum_drug_id, Multum_drug_name ]; ThisOrderDrugMappingDataSQL := "DECLARE @OrderName varchar(200) = " || SQL(evoking_order_name) || " SELECT ocmi.GUID, ocmi.Name, ocmi.TherapeuticCategoryID, TherapeuticCategory = CASE WHEN ocmi.TherapeuticCategoryID > 0 THEN (SELECT category_name FROM SXAMTDrugCategoriesVW WHERE multum_category_id = ocmi.TherapeuticCategoryID) ELSE {{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}} END, DBStatus = CASE WHEN DrugKey IS NOT NULL THEN {{{SINGLE-QUOTE}}}M{{{SINGLE-QUOTE}}} WHEN DrugKey IS NULL AND ISNULL(IsIgnored,0) = 1 THEN {{{SINGLE-QUOTE}}}I{{{SINGLE-QUOTE}}} ELSE {{{SINGLE-QUOTE}}}U{{{SINGLE-QUOTE}}} END, DrugKey = ISNULL(dm.DrugKey,{{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}}), DrugName = ISNULL(dnv.drug_name,{{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}}), xref.DrugSynonymID, function_id = (SELECT MIN(function_id) FROM SXAMTDrugNameMapVw AS dnm WHERE dnv.drug_synonym_id = dnm.drug_synonym_id AND function_id <> 29 ), OriginalTouchedWhen = ocmi.TouchedWhen, DrugMappingTouchedWhen = dm.TouchedWhen, GenericName = CASE WHEN DrugKey IS NOT NULL THEN (SELECT drug_name FROM SXAMTDrugNameVW vw INNER JOIN SXAMTDrugNameMapVW map ON (vw.drug_synonym_id = map.drug_synonym_id) WHERE function_id = 16 AND drug_id = DrugKey) ELSE {{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}} END, MMDC = CASE WHEN xref.DrugSynonymID IS NOT NULL THEN (SELECT top 1 mmdcXRef.MainMultumDrugCode FROM SXAMTDrugNameVW AS mtDN INNER JOIN SXAAMBDrugName AS dn ON dn.DrugCatalogKey = mtDN.drug_synonym_id INNER JOIN SXAAMBDrugNameMMDCXRef AS mmdcXRef ON mmdcXRef.DrugNameID = dn.DrugNameID INNER JOIN SXAMTNdcMainMultumDrugCodeVW AS mtMMDC ON mtMMDC.main_multum_drug_code = mmdcXRef.MainMultumDrugCode INNER JOIN SXAAMBClinicalDataFunctionType AS ft ON ft.FunctionTypeID = mmdcXRef.FunctionTypeID WHERE mtDN.drug_synonym_id = DrugSynonymID AND ft.DrugCatalogKey IN (59,60) ) ELSE NULL END, AlternateMappingName = ISNULL(ocmi.AlternateMappingName, {{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}}), DrugMappingXrefTouchedWhen = xref.TouchedWhen, IsObsolete = dnv.is_obsolete from Cv3OrderCatalogMasterItem AS ocmi INNER JOIN CV3OrderEntryForm oef ON (ocmi.EntryFormGUID = oef.GUID AND OrderTypeCode = {{{SINGLE-QUOTE}}}Medication{{{SINGLE-QUOTE}}}) LEFT OUTER JOIN CV3DrugMapping AS dm ON (ocmi.GUID = dm.CatalogItemGUID) LEFT OUTER JOIN CV3DrugMappingXref AS xref ON (ocmi.GUID = xref.CatalogItemGUID AND xref.IsDefaultSynonym = 1) LEFT OUTER JOIN SXAMTDrugNameVw AS dnv ON (xref.DrugSynonymID = dnv.drug_synonym_id) AND dnv.is_obsolete = {{{SINGLE-QUOTE}}}F{{{SINGLE-QUOTE}}} WHERE ocmi.Name = @OrderName"; ThisOrderDrugMapping := read AS DrugMappingObj last {"" || ThisOrderDrugMappingDataSQL}; if(SuppressCrossDrugKey)then OtherOrderDrugMappingDataByDrugKeySQL := "SELECT ocmi.GUID, ocmi.Name, ocmi.TherapeuticCategoryID, TherapeuticCategory = CASE WHEN ocmi.TherapeuticCategoryID > 0 THEN (SELECT category_name FROM SXAMTDrugCategoriesVW WHERE multum_category_id = ocmi.TherapeuticCategoryID) ELSE {{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}} END, DBStatus = CASE WHEN DrugKey IS NOT NULL THEN {{{SINGLE-QUOTE}}}M{{{SINGLE-QUOTE}}} WHEN DrugKey IS NULL AND ISNULL(IsIgnored,0) = 1 THEN {{{SINGLE-QUOTE}}}I{{{SINGLE-QUOTE}}} ELSE {{{SINGLE-QUOTE}}}U{{{SINGLE-QUOTE}}} END, DrugKey = ISNULL(dm.DrugKey,{{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}}), DrugName = ISNULL(dnv.drug_name,{{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}}), xref.DrugSynonymID, function_id = (SELECT MIN(function_id) FROM SXAMTDrugNameMapVw AS dnm WHERE dnv.drug_synonym_id = dnm.drug_synonym_id AND function_id <> 29 ), OriginalTouchedWhen = ocmi.TouchedWhen, DrugMappingTouchedWhen = dm.TouchedWhen, GenericName = CASE WHEN DrugKey IS NOT NULL THEN (SELECT drug_name FROM SXAMTDrugNameVW vw INNER JOIN SXAMTDrugNameMapVW map ON (vw.drug_synonym_id = map.drug_synonym_id) WHERE function_id = 16 AND drug_id = DrugKey) ELSE {{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}} END, MMDC = CASE WHEN xref.DrugSynonymID IS NOT NULL THEN (SELECT top 1 mmdcXRef.MainMultumDrugCode FROM SXAMTDrugNameVW AS mtDN INNER JOIN SXAAMBDrugName AS dn ON dn.DrugCatalogKey = mtDN.drug_synonym_id INNER JOIN SXAAMBDrugNameMMDCXRef AS mmdcXRef ON mmdcXRef.DrugNameID = dn.DrugNameID INNER JOIN SXAMTNdcMainMultumDrugCodeVW AS mtMMDC ON mtMMDC.main_multum_drug_code = mmdcXRef.MainMultumDrugCode INNER JOIN SXAAMBClinicalDataFunctionType AS ft ON ft.FunctionTypeID = mmdcXRef.FunctionTypeID WHERE mtDN.drug_synonym_id = DrugSynonymID AND ft.DrugCatalogKey IN (59,60) ) ELSE NULL END, AlternateMappingName = ISNULL(ocmi.AlternateMappingName, {{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}}), DrugMappingXrefTouchedWhen = xref.TouchedWhen, IsObsolete = dnv.is_obsolete FROM CV3DrugMapping AS dm INNER JOIN Cv3OrderCatalogMasterItem AS ocmi ON (ocmi.GUID = dm.CatalogItemGUID) INNER JOIN CV3OrderEntryForm oef ON (ocmi.EntryFormGUID = oef.GUID AND OrderTypeCode = {{{SINGLE-QUOTE}}}Medication{{{SINGLE-QUOTE}}}) LEFT OUTER JOIN CV3DrugMappingXref AS xref ON (ocmi.GUID = xref.CatalogItemGUID AND xref.IsDefaultSynonym = 1) LEFT OUTER JOIN SXAMTDrugNameVw AS dnv ON (xref.DrugSynonymID = dnv.drug_synonym_id) AND dnv.is_obsolete = {{{SINGLE-QUOTE}}}F{{{SINGLE-QUOTE}}} WHERE dm.DrugKey = " || SQL(ThisOrderDrugMapping.DrugKey); OtherOrdersDrugMappingsByDrugKey := read AS DrugMappingObj {"" || OtherOrderDrugMappingDataByDrugKeySQL}; endif; if(SuppressCrossDrugComponents)then SVR,DB := read last {"SELECT @@SERVERNAME,DB_NAME()"}; OtherOrderDrugMappingDataByComponentSQL := "select " || " ocmi.GUID, ocmi.Name, mdi.drug_id, mdn.drug_name " || " from [" || DB || "_MT].[dbo].multum_drug_id mdi " || " join [" || DB || "_MT].[dbo].multum_drug_name mdn " || " on mdn.drug_synonym_id = mdi.drug_synonym_id " || " join CV3DrugMapping AS dm on dm.DrugKey = mdi.drug_id" || " JOIN Cv3OrderCatalogMasterItem AS ocmi ON (ocmi.GUID = dm.CatalogItemGUID) " || " where mdi.drug_id in " || " (select member_drug_id from [" || DB || "_MT].[dbo].multum_combination_drug mcd " || " where mcd.drug_id = " || SQL(ThisOrderDrugMapping.DrugKey) || ")"; OtherOrdersDrugMappingsByComponent := read AS DrugMappingComponentObj {"" || OtherOrderDrugMappingDataByComponentSQL}; OtherOrderDrugMappingDataContainingThisComponentSQL := "select " || " ocmi.GUID, ocmi.Name, mdi.drug_id, mdn.drug_name " || " from [" || DB || "_MT].[dbo].multum_drug_id mdi " || " join [" || DB || "_MT].[dbo].multum_drug_name mdn " || " on mdn.drug_synonym_id = mdi.drug_synonym_id " || " join CV3DrugMapping AS dm on dm.DrugKey = mdi.drug_id" || " JOIN Cv3OrderCatalogMasterItem AS ocmi ON (ocmi.GUID = dm.CatalogItemGUID) " || " where mdi.drug_id in " || " (select mcd.drug_id from [" || DB || "_MT].[dbo].multum_combination_drug mcd " || " where member_drug_id = " || SQL(ThisOrderDrugMapping.DrugKey) || ")"; OtherOrderDrugMappingDataContainingThisComponent := read AS DrugMappingComponentObj {"" || OtherOrderDrugMappingDataContainingThisComponentSQL}; endif; endif; ;; evoke: ;; logic: if(count(Alerts) = 0)then SuppressAlert := false; conclude true; endif; If OrderRoleType not in OrderRoleTypesToSuppressSecondaryAlert then if(user_id <> "services")then SuppressAlert := false; conclude true; endif; endif; //if (count(Alerts Where Alerts.OrderName = evoking_order_name) > 0) then if (count(Alerts Where Alerts.TriggeringInfo = evoking_order_name) > 0) then SuppressAlert := true; SuppressAlertReason := "Alert Has Been Triggered For THIS Drug."; conclude true; endif; if(SuppressCrossDrugKey and (count(Alerts Where Alerts.TriggeringInfo in (OtherOrdersDrugMappingsByDrugKey.ocmi_Name)) > 0))then SuppressAlert := true; crossDrugName := (first of (Alerts Where Alerts.TriggeringInfo in (OtherOrdersDrugMappingsByDrugKey.ocmi_Name))).TriggeringInfo; SuppressAlertReason := "Alert Has Been Triggered For a Drug by CrossKey. - " || crossDrugName; conclude true; endif; if(SuppressCrossDrugComponents)then// and (count(Alerts Where Alerts.TriggeringInfo in (OtherOrdersDrugMappingsByComponent.ocmi_Name)) > 0))then //if all components have been alerted if(count(OtherOrdersDrugMappingsByComponent) > 0)then CountAlertsFoundForComponents := 0; for DrugComponent in OtherOrdersDrugMappingsByComponent do if(count(Alerts Where Alerts.TriggeringInfo in (DrugComponent.ocmi_Name)) > 0)then CountAlertsFoundForComponents := CountAlertsFoundForComponents + 1; endif; enddo; if(CountAlertsFoundForComponents = count(OtherOrdersDrugMappingsByComponent))then SuppressAlert := true; SuppressAlertReason := "Alert Has Been Triggered For all containing Drugs."; conclude true; endif; endif; //END if all components have been alerted //if this drug is a component that has been alerted if(count(Alerts Where Alerts.TriggeringInfo in (OtherOrderDrugMappingDataContainingThisComponent.ocmi_Name)) > 0)then SuppressAlert := true; containingDrugName := (first of (Alerts Where Alerts.TriggeringInfo in (OtherOrderDrugMappingDataContainingThisComponent.ocmi_Name))).TriggeringInfo; SuppressAlertReason := "Alert Has Been Triggered For a Drug containing this Drug - " || containingDrugName; conclude true; endif; //END if this drug is a component that has been alerted endif; conclude true; ;; action: return SuppressAlert; ;; Urgency: 90;; end: