maintenance: title: Dosing recommendations based on age, weight, or total dose;; mlmname: SCH_Misc_Dosing_Recommendations;; arden: version 2;; version: 5.50;; institution: St Clair;; author: Teresa Spicuzza, Allscripts Corp;; specialist: Teresa Spicuzza;; date: 2012-08-20;; validation: testing;; library: purpose: Dosing Recommendations and Warnings based on age or weight ;; explanation: MLM will read table and suggest dosing based upon medication, dose and patient age or weight. Change history 08.20.2012 TMS Created CSR 30865 09.05.2012 TMS Added drug ordered information to dialog of alert CSR 30865 06.05.2013 TMS Updated with additional rules to accommodate additional drugs. CSR 31334 05.31.2017 TMS Updated with rule J for additional drugs. CSR 35636 05.16.2018 TMS Add "With Dialysis Treatment" to Frequency retrievals that contain As Ordered. CSR 33940 06.25.2018 TMS Add New Rule type "K" to present same drug/age alert as Rule D, except to suppress it for users with an OrderRoleType of "Anesthesia Physician". CSR 36984 09.30.2019 TMS Updated alert to require reason when alert presented to user not in physician/physician extender group. CSR 37977 ;; keywords: Dosing ;; knowledge: type: data-driven;; data: // Specify which .NET assemblies need to be loaded for ObjectsPlus standard_libs := MLM {{{SINGLE-QUOTE}}}std_include_libs{{{SINGLE-QUOTE}}}; include standard_libs; error_occurred := false; error_message := ""; str_parse := mlm {{{SINGLE-QUOTE}}}UTIL_STRING_PARSE{{{SINGLE-QUOTE}}}; log_execution_info := false; //Set the text for this variable to indicate whether to send the message or not send_alert := "DoNotSend"; //alert_settings := ""; //-------------------------------------------------------------------- if called_by_editor then EvokingObject := read last {Order: THIS where Name="Ketorolac Inj" }; endif; doalert := false; SupressAlertFlag := false; order_enter_event := event { OrderEnter User Order: where TypeCode = "Medication"}; (CatalogItemObj, FrequencyValue, UOMValue, DoseValue, OrderName, AdminIns, UserSchedType ,UserSchedDays, UserSchedDoses, OrderingProviderGuid, StopDtm) := read last {Order: OrderCatalogMasterItem, FrequencyCode, UOM, DosageLow, Name, AdminInstructions, Interval, DaysInInterval, DoseMultiplier, CareProviderGuid, StopDtm REFERENCING EvokingObject}; CatalogClassTypeValueObj := read last {OrderCatalogMasterItem: CatalogClassTypeValue, REFERENCING CatalogItemObj}; ClassTypeValue_code_list, ClassTypeValue_value_list := read {CatalogClassTypeValue: Code, Value REFERENCING CatalogClassTypeValueObj where code = "PRX_MiscDosing"}; /* Get the OrderAdditionalInfo object pointer */ OrderAdditionalInfoObj := read last { Order: OrderAdditionalInfo REFERENCING EvokingObject }; /* Get information from the OrderAdditionalInfo object */ (SummaryLine, FreqfromTime,FreqUOM, StopAfterValue, StopAfterOption) := read last { OrderAdditionalInfo: FreqSummaryLine, FreqFromTime, FreqUOM, StopAfterValue, StopAfterOption REFERENCING OrderAdditionalInfoObj }; // (Defintiontype, freqfromtime2, freqtimetovalue, frequom2) := read // { " select Definitiontype,timefromvalue, timetovalue, timeuom from CV3Frequency " // || " where Code = " || SQL(summaryline) }; /* Get the OrderUserData object pointer */ OrderUserDataObj := read last { Order: OrderUserData REFERENCING EvokingObject }; for r in (1 seqto(count(OrderUserDataObj))) do CurOrder_UserDataFields := OrderUserDataObj[r]; (userdatacodelist, valuelist ) := read { OrderUserData: UserDataCode, Value REFERENCING CurOrder_UserDataFields } ; for s in (1 seqto(count(userdatacodelist))) do if ((userdatacodelist [s] = "PRX_Suppress_Alert_Flag") and valuelist [s] = "1" ) then SupressAlertFlag := True; endif; enddo; enddo; PainMgtDoc := read { " select Guid from CV3CareProvider " || " where DisplayName = {{{SINGLE-QUOTE}}}Spicuzza, Teresa{{{SINGLE-QUOTE}}}" || " or DisplayName = {{{SINGLE-QUOTE}}}Rivero-Becerra, Jorge N{{{SINGLE-QUOTE}}}" }; If OrderingProviderGuid in PainMgtDoc then PainMgtOverride := True; else PainMgtOverride := False; endif; // fire_on_User := ("IT","MD","DO","DDS","DPM","PA","PA-C","CRNP","RPh"); fire_on_UserCPOE := ("MD","DO","DDS","DPM","PA","PA-C","CRNP","IT"); fire_on_User := ("RN","RPh"); // fire_on_User := ("tspicuzza","deiler","shead","gfino","ccorbettit", "dwarnick", // "dmiklavichis","ageorgulis","dbellissimo","kbaumgarte"); /* Get the current user{{{SINGLE-QUOTE}}}s occupation*/ (user_id,userguid) :=read last {UserInfo: idcode, guid}; UserCode, OrderRole := read last {"Select occupationcode, orderroletype " ||" From cv3user with (nolock) " ||" Where Guid = " || SQL(userguid) }; // continue_processing:= user_id in fire_on_User; // continue_processing:= usercode in fire_on_User; If usercode in fire_on_UserCPOE then alert_settings := ""; UDDD_dictionary_name := ""; UDDD_is_restricted := FALSE; continue_processing := true; elseif usercode in fire_on_User then alert_settings := "Must Comment"; UDDD_dictionary_name := "AlertAckComment"; UDDD_is_restricted := TRUE; continue_processing := true; else continue_processing := false; endif; dose_alert_dest := destination {alert} with [alert_type := "Warning", short_message := "Dosing Recommendation", priority := "High", scope := "Chart", rule_group := "Dosing Recommendations", rule_number := 4080, send_with_order := send_alert, alert_dialog_settings := alert_settings, ack_comment_UDDD := UDDD_dictionary_name, ack_comment_UDDD_is_restricted := UDDD_is_restricted, display_alert := true]; for r in (1 seqto 1) do classvaluelist := call str_parse with ClassTypeValue_value_list [r],","; classvalue := classvaluelist[1]; enddo; if EvokingEvent = order_enter_event and continue_processing = true and SupressAlertFlag = False then if "PRX_MiscDosing" in ClassTypeValue_code_list then continue := "yes"; else continue := "no"; endif; endif; If continue = "yes" then (schedtime, freqcode, timefrom, timeuom) := read last {" select fsd.ScheduledTime, cft.FrequencyCode, cft.TimeFromValue, cft.TimeUom from CV3CodedFreqTranslation cft" || " join CV3FixedScheduleDefinition fsd on fsd.ParentGUID = cft.guid " || " where cft.FrequencyCode = " || sql(frequencyvalue) || " and FrequencyClass = {{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}} and cft.Active = 1" || " order by fsd.ScheduledTime " }; (TimesPerDay) := read last {" select count (fsd.ScheduledTime) from CV3CodedFreqTranslation cft" || " join CV3FixedScheduleDefinition fsd on fsd.ParentGUID = cft.guid " || " where cft.FrequencyCode = " || sql(frequencyvalue) || " and FrequencyClass = {{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}} and cft.Active = 1" }; Oncegroup := ("Now", "STAT", "Once", "One Time", "Today,", "Load", "Pre-procedure", "Post-procedure","Pre-Transfusion", "Post-Transfusion","Between Blood", "PRE OP,", "POST OP", "As Ordered", "As Directed", "Given in Infusion Center", "Given in Delivery Room", "With Dialysis Treatment"); If frequencyvalue in Oncegroup then frequencygroup := "OneTime"; else frequencygroup := "Other"; endif; If frequencyvalue <> "" and frequencygroup <> "OneTime" then If timefrom = 1 and timeuom = "day" then If TimesPerDay = 1 then frequencygroup := "Q24H"; Freqfactor := 24; endif; If TimesPerDay = 2 then frequencygroup := "Q12H"; Freqfactor := 12; endif; If TimesPerDay = 3 then frequencygroup := "Q8H"; Freqfactor := 8; endif; If TimesPerDay = 4 then frequencygroup := "Q6H"; Freqfactor := 6; endif; If TimesPerDay = 6 then frequencygroup := "Q4H"; Freqfactor := 4; endif; If TimesPerDay = 8 then frequencygroup := "Q3H"; Freqfactor := 3; endif; If TimesPerDay = 12 then frequencygroup := "Q2H"; Freqfactor := 2; endif; If TimesPerDay = 24 then frequencygroup := "Q1H"; Freqfactor := 1; endif; elseif timefrom = 2 and timeuom = "day" then If TimesPerDay = 1 then frequencygroup := "Q48H"; endif; endif; endif; If frequencyvalue = "" then If UserSchedType = "Weekly" then If UserSchedDays <= 2 and UserSchedDoses = 1 then frequencygroup := "Q7D"; endif; elseif UserSchedType = "Daily" and UserSchedDays = 1 and FreqFromTime = 1 and FreqUom = "day" then If UserSchedDoses = 1 then frequencygroup := "Q24H"; Freqfactor := 24; endif; If UserSchedDoses = 2 then frequencygroup := "Q12H"; Freqfactor := 12; endif; If UserSchedDoses = 3 then frequencygroup := "Q8H"; Freqfactor := 8; endif; If UserSchedDoses = 4 then frequencygroup := "Q6H"; Freqfactor := 6; endif; If UserSchedDoses = 6 then frequencygroup := "Q4H"; Freqfactor := 4; endif; If UserSchedDoses = 8 then frequencygroup := "Q3H"; Freqfactor := 3; endif; If UserSchedDoses = 12 then frequencygroup := "Q2H"; Freqfactor := 2; endif; If UserSchedDoses = 24 then frequencygroup := "Q1H"; Freqfactor := 1; endif; elseif UserSchedType = "Daily" and UserSchedDays = 1 and FreqFromTime = 2 and FreqUom = "day" then If UserSchedDoses = 1 then frequencygroup := "Q48H"; endif; endif; endif; //If frequencyvalue = "" DurationFactor := StopAfterValue; If StopAfterOption = 2 then DurationType := "Hours"; endif; If StopAfterOption = 3 then DurationType := "Mins"; endif; If StopAfterOption = 4 then DurationType := "Times"; endif; If StopAfterOption = 1 then DurationType := "Days"; endif; If StopAfterOption = 0 then DurationFactor := 1; DurationType := "Days"; endif; // Calculate the Total Daily Dose // If (DoseValue as number) > 0 then If (UserSchedDoses as number) > 0 and UserSchedType = "Daily" and UserSchedDays = 1 then If DurationType = "Days" then TotalDailyDose := ((UserSchedDoses as number) * (DoseValue as number)); elseif DurationType = "Times" and (DurationFactor as number) < (UserSchedDoses as number) then TotalDailyDose := ((DurationFactor as number) * (DoseValue as number)); elseif DurationType = "Hours" and (DurationFactor as number) <= 24 then TotalDailyDose := (Int((DurationFactor as number)/(FreqFactor as number))) * (DoseValue as number); elseif DurationType = "Mins" and (DurationFactor as number) <= 999 then TotalDailyDose := (Int((DurationFactor as number) / 60)/(FreqFactor as number)) * (DoseValue as number); endif; elseif (TimesPerDay as number) > 0 then TotalDailyDose := ((TimesPerDay as number) * (DoseValue as number)); If DurationType = "Days" then TotalDailyDose := ((TimesPerDay as number) * (DoseValue as number)); elseif DurationType = "Times" and (DurationFactor as number) < (TimesPerDay as number) then TotalDailyDose := ((DurationFactor as number) * (DoseValue as number)); elseif DurationType = "Hours" and (DurationFactor as number) <= 24 then TotalDailyDose := (Int((DurationFactor as number)/(FreqFactor as number))) * (DoseValue as number); elseif DurationType = "Mins" and (DurationFactor as number) <= 999 then TotalDailyDose := (Int((DurationFactor as number) / 60)/(FreqFactor as number)) * (DoseValue as number); endif; else TotalDailyDose := "Unknown"; endif; endif; (ClientVisitGuid, ChartGuid, ClientGuid, CurrentLocation, LocationGuid, VisitStatus) := read last {ClientVisit: GUID, ChartGUID, ClientGUID, CurrentLocation, CurrentLocationGUID, VisitStatus }; (UserGUID ) := read last { UserInfo: GUID }; // Get the patient age (birthdate,dobM,dobD,birth_year, patientgender ) := read last { ClientInfo: BirthDate, BirthMonthNum, BirthDayNum, BirthYearNum, gendercode }; patientAge := (NOW - birthdate) / (1 year); patientage:= (int (patientage)); // Get the patient weight wtgm := read last { " Select Text from CV3PhysicalNoteDeclaration " || " where ClientGUID = " || SQL(ClientGuid) || " and ClientVisitGUID = " || SQL(ClientVisitGuid) || " and TypeCode = {{{SINGLE-QUOTE}}}weight{{{SINGLE-QUOTE}}} " || " order by Entered asc " }; patientwt := (wtgm as number) / 1000; // Loop through dictionary to parse fields needed to see if rule exists for ordered drug. if continue = "yes" then medlist := (); medlist := read { "select value from cv3userdictionaryvalue v with (nolock)" || " where userdictionarycode = {{{SINGLE-QUOTE}}}PRX_Misc_Dosing_Rules{{{SINGLE-QUOTE}}} " || " and active = {{{SINGLE-QUOTE}}}1{{{SINGLE-QUOTE}}} " }; NumRules:= count medlist; for k in (1 seqto (NumRules)) do rules := call str_parse with medlist[k],"|"; RuleClass := rules[1]; RuleType := rules[2]; RuleMsgType := rules[3]; RuleOrder := rules[4]; RuleDose := rules[5]; RuleDoseTD := rules[6]; RuleUOM := rules[7]; RuleRoute := rules[8]; RuleFreqQual := rules[9]; RuleFreq := rules[10]; RuleAge := rules[11]; RuleWtLow := rules[12]; RuleWtHi := rules[13]; RuleMsg := rules[14]; // Compare ordering info with rule info and process when match found. If RuleClass = classvalue and ruletype = "A" then If ((DoseValue as number)> (RuleDose as number)) and UOMValue = RuleUom then If RuleFreqQual = "Is" and Frequencygroup = RuleFreq then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n\n {{+R}}" || Rulemsg || "{{-R}} {{-B}}"; doalert := true; elseif RuleFreqQual = "IsNot" and Frequencygroup <> RuleFreq then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || " \n\n {{+R}}" || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; endif; elseif RuleClass = classvalue and ruletype = "B" then If ((DoseValue as number)> (RuleDoseHi as number)) and UOMValue = RuleUom then If RuleFreqQual = "Is" and Frequencygroup = RuleFreq then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n This patient is " || patientage || " years old." || "\n\n {{+R}} " || Rulemsg || "{{-R}} {{-B}}"; doalert := true; elseif RuleFreqQual = "IsNot" and Frequencygroup <> RuleFreq then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n\n {{+R}}" || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; endif; elseif RuleClass = classvalue and ruletype = "C" then If ((PatientWt as number) < (RuleWtLow as number)) and ((DoseValue as number)>= (RuleDose as number)) and UOMValue = RuleUom then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n\n {{+R}}" || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; elseif RuleClass = classvalue and ruletype = "D" then If ((PatientAge as number) > (RuleAge as number)) then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n This patient is " || patientage || " years old." || "\n\n {{+R}} " || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; elseif RuleClass = classvalue and ruletype = "E" then If ((PatientAge as number) > (RuleAge as number)) and ((TotalDailyDose as number) > (RuleDoseTD as number)) then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n The total daily dose for this order is " || TotalDailyDose || UOMValue || "\n\n {{+R}} " || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; elseif RuleClass = classvalue and ruletype = "F" then If RuleMsgType = "PMO" and PainMgtOverride = false then If ((DoseValue as number) > (RuleDose as number)) then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n\n {{+R}}" || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; endif; elseif RuleClass = classvalue and ruletype = "G" then If RuleMsgType = "PMO" and PainMgtOverride = false then If ((TotalDailyDose as number) > (RuleDoseTD as number)) then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n The total daily dose for this order is " || TotalDailyDose || UOMValue || "\n\n {{+R}} " || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; endif; elseif RuleClass = classvalue and ruletype = "H" then If RuleUOM = "mg/kg/day" and UomValue = "mg" then TotalDosePerWgt := (RuleDose as number) * (patientwt as number); If ((TotalDailyDose as number) > (TotalDosePerWgt as number)) then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " " || UomValue|| ", " || SummaryLine || "\n The total daily dose for this order is " || TotalDailyDose || UOMValue || "\n\n {{+R}} " || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; endif; elseif RuleClass = classvalue and ruletype = "J" then If ((PatientAge as number) > (RuleAge as number)) and ((DoseValue as number) > (RuleDose as number)) then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n This patient is " || patientage || " years old." || "\n\n {{+R}} " || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; elseif RuleClass = classvalue and ruletype = "K" and OrderRole <> "Anesthesia Physician" then If ((PatientAge as number) > (RuleAge as number)) then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n This patient is " || patientage || " years old." || "\n\n {{+R}} " || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; elseif RuleClass = classvalue and ruletype = "L" and (StopAfterOption = 0 and StopDtm is null) then If RuleFreqQual = "Is" and Frequencygroup = RuleFreq then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n\n {{+R}} " || Rulemsg || "{{-R}} {{-B}}"; doalert := true; elseif RuleFreqQual = "IsNot" and Frequencygroup <> RuleFreq then alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n\n {{+R}} " || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; elseif RuleClass = classvalue and ruletype = "M" and (StopAfterOption = 0 and StopDtm is null) then //Digoxin alert only If RuleFreqQual = "IsNot" and Frequencygroup not in ("Q24H","Q48H","OneTime") then If UserCode = "RPh" then alert_settings := "Must Comment"; else alert_settings := "No Override Allowed"; endif; alert_message := "{{+B}} Ordered: "||OrderName || " " || DoseValue || " "|| UomValue|| ", " || SummaryLine || "\n\n {{+R}} " || Rulemsg || "{{-R}} {{-B}}"; doalert := true; endif; else nomessage := ""; endif; enddo; endif; endif; ;; priority: 50 ;; evoke: order_enter_event; ;; logic: if called_by_editor then conclude false; endif; //---------------------------------------------------------------- // If there is no evoking object then do nothing, this can // only be true for the MLM Editor //---------------------------------------------------------------- if EvokingObject is null then conclude false; endif; if continue = "no" then conclude false; endif; conclude doalert; ;; action: write alert_message at dose_alert_dest ;; Urgency: 50;; end: