maintenance:
title: Alert Messages for the Dosage-Range Checking MLM;;
mlmname: STD_FUNC_DOSAGE_MESSAGES;;
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: Creates the alert message for the Dosage-Range checking MLM.
;;
explanation: This MLM encapsultes the dosage-range alert messages,
so that all the changes to the message can be done in one MLM.
;;
keywords: single dose; average daily dose; total daily dose; dosage range
Change History:
01.08.2014 JML Added alert for dose of 0.0001 - used when medication not appropriate for age.
Previously part of STD_DOSAGE on 07.30.2012. Moved with 6.1 upgrade to this MLM
07.15.2015 TMS Updated with St. clair customization for 15.1. CSR 33555
03.22.2019 TMS Updated with St. Clair customization for 18.4 CSR 37676
;;
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;
// include common data structures
std_dosage_includes := MLM {{{SINGLE-QUOTE}}}std_func_dosage_includes{{{SINGLE-QUOTE}}};
include std_dosage_includes;
(
ht_cm,
wt_kg,
patient_info,
med_data_list,
average_tracker_list,
total_tracker_list,
dosage_range_list,
med_dosage_map_list,
alert_if_missing_flags,
use_multum_dosage_data,
show_irregular_message,
show_under_24_hour_message,
show_has_shift_frequency_message,
show_user_scheduled_weekly_message,
show_Debug_statements,
column_catalog_name,
column_Multum_name,
patient_birthday_info_on_order
) := ARGUMENT;
// Set to true if logging is needed.
log_execution_info := false;
//Declare function for adding commas into numbers
add_commas := MLM {{{SINGLE-QUOTE}}}SYS_FORMAT_NUMBER{{{SINGLE-QUOTE}}};
format_dose_range := MLM {{{SINGLE-QUOTE}}}STD_FUNC_DOSAGE_MSG_FORMAT_DOSE_RANGE{{{SINGLE-QUOTE}}};
// CSS style formatting
CCS_MLM := MLM {{{SINGLE-QUOTE}}}STD_FUNC_DOSAGE_CSS{{{SINGLE-QUOTE}}};
//Declare the Missing_Data_Object
Missing_Data_Object := OBJECT [
criteria,
missing_data_error,
details,
msg, // message to be shown underneath the header
unchecked_dose_range_type_list, // list of dosage types that could not be checked.
med_name, // list of medication names affected by missing data issues
alert_abstract // holds string appended to the alert abstract
];
//Declare the Cannot_Check_Object
Cannot_Check_Object := OBJECT [
med_order_type,
med_name_list,
route,
uom,
processed_for_printing,
alert_msg_for_cannot_check,
alert_abstract // holds string appended to the alert abstract
];
// Warning_Count_Object - counts number of warnings for each medication
Warning_Count_Object := OBJECT [
med_name,
warning_count
];
// Case Info Object - arrange data by case
Case_Info_Object := OBJECT [
case_id,
case_type,
dosage_range_sort_number,
map_sort_number,
based_on_text,
msg,
medication_count,
med_name,
is_default,
is_multum,
has_notes,
has_date,
conditions_text,
processed_for_printing,
based_on_header_text, // holds "based on" sub-string used text beneath headers
route, // we also differentiate cases on the route being displayed
creatinine_criteria,
patient_age_at_order
];
// Arrange missing data by default/additional condition
// and sort by medication name
Supplemental_Table_Object := OBJECT [
med_name,
is_multum,
is_contraindication,
route, // contains the route being displayed
dosage_range_sort_number,
map_sort_number,
med_case_count, // remembers the number of medications associated with a case
// Used during printing
msg,
patient_age_at_order
];
// Used to map an order medication unit of measure to the dose range
// unit of measures that it could not be converted to.
Conversion_Issue_Map_Object := OBJECT [
medication_val, // value specified in the medications
unconvertible_val_list, // list of values in dose range that
// order value could not be converted to
med_name // name of the medication
];
// Initalize Variables
average_criteria_type_list := (catalog_drc_type_const.age_average_daily_dose_string, catalog_drc_type_const.BSA_average_daily_dose_string,
catalog_drc_type_const.weight_average_daily_dose_string);
total_criteria_type_list := (catalog_drc_type_const.age_total_daily_dose_string, catalog_drc_type_const.BSA_total_daily_dose_string,
catalog_drc_type_const.weight_total_daily_dose_string);
BSA_criteria_type_list := (catalog_drc_type_const.BSA_average_daily_dose_string, catalog_drc_type_const.BSA_total_daily_dose_string,
catalog_drc_type_const.Body_Surface_Area_string);
AGE_criteria_type_list := (catalog_drc_type_const.age_average_daily_dose_string, catalog_drc_type_const.age_total_daily_dose_string,
catalog_drc_type_const.age_string);
WEIGHT_criteria_type_list := (catalog_drc_type_const.weight_average_daily_dose_string,
catalog_drc_type_const.weight_total_daily_dose_string, catalog_drc_type_const.weight_string);
// based_on_criteria_headings and patient_info_criteria_list
// These two lists must be in sync to build the "Based On string"
// Some criteria have no heading, so, null is used to indicate this.
based_on_criteria_headings := (
"age",
"gender",
"height",
"weight",
"BSA",
"liver",
"renal",
"creatinine clearance",
"route"
);
// contraindication_criteria_headings and contraindication_criteria_list
// These two lists must be in sync to display contraindication messages
contraindication_criteria_headings :=(
"Age ",
"Route = ",
"Weight ",
"Gender = ",
"Renal = ",
"Creatinine Clearance = ",
"Liver Disease = ");
// get the stop after option strings from CV3EnumReference
// sorted by enum value for display in the alert
stop_after_type_list := read
{ "Select ReferenceString "
|| " FROM CV3EnumReference"
|| " WHERE ColumnName in ({{{SINGLE-QUOTE}}}StopAfterOption{{{SINGLE-QUOTE}}}) "
|| " AND EnumValue > 0 "
|| " ORDER BY EnumValue ASC" };
// Retrieve facility-defined date and time formats
(composite_date_format,
partial_composite_date_format,
time_format) := read last
{ "select isNull((SELECT e.value FROM HVCEnvProfile e "
|| "WHERE e.HierarchyCode={{{SINGLE-QUOTE}}}Connect{{{SINGLE-QUOTE}}} AND e.Code={{{SINGLE-QUOTE}}}CompositeDateFormat{{{SINGLE-QUOTE}}}),{{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}}) "
|| "as CompositeDateFormat, "
|| " isNull((SELECT e.value FROM HVCEnvProfile e "
|| "WHERE e.HierarchyCode={{{SINGLE-QUOTE}}}Connect{{{SINGLE-QUOTE}}} AND e.Code={{{SINGLE-QUOTE}}}PartialCompositeDateFormat{{{SINGLE-QUOTE}}}),{{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}}) "
|| "as PartialCompositeDateFormat, "
|| " isNull((SELECT e.value FROM HVCEnvProfile e "
|| "WHERE e.HierarchyCode={{{SINGLE-QUOTE}}}Connect{{{SINGLE-QUOTE}}} AND e.Code={{{SINGLE-QUOTE}}}TimeFormat{{{SINGLE-QUOTE}}}),{{{SINGLE-QUOTE}}}{{{SINGLE-QUOTE}}}) "
|| "as TimeFormat " };
// Get the patient{{{SINGLE-QUOTE}}}s birth day and birth time
(birthday, birth_month_num, birth_day_num, birthtime ) := read last
{ ClientInfo: BirthDate, BirthMonthNum, BirthDayNum, BirthTime };
// Get the evoking object{{{SINGLE-QUOTE}}}s visit TimeZone
(visit_time_zone) := read last { ClientVisit: TimeZone };
// declare string constants used for string comparisons
dose_too_frequent := "too frequent";
dose_frequency_unmapped := "unmapped";
;;
evoke:
;;
logic:
////////////////////////////////////////////////////
// Populate the display_route property in the dosage_range objects
////////////////////////////////////////////////////
has_alert_on_estimated_birthtime := false;
for dosage_range in dosage_range_list
do
//[New born birth-time missing]: check if any alert using estimated birthday
if patient_birthday_info_on_order.is_estimated_birthday = true then
if ( dosage_range.estimated_age_used = 1 )
then
dosage_range.patient_age_at_order := patient_birthday_info_on_order.age_min_inhour_str;
has_alert_on_estimated_birthtime := true;
elseif ( dosage_range.estimated_age_used = 2 )
then
dosage_range.patient_age_at_order := patient_birthday_info_on_order.age_max_inhour_str;
has_alert_on_estimated_birthtime := true;
endif;
endif;
// convert to string first because the route_id or the med_route_id
// could be either an integer or a string. MLMs don{{{SINGLE-QUOTE}}}t compare strings
// and integers implicitly. "123" won{{{SINGLE-QUOTE}}}t be equal to the integer {{{SINGLE-QUOTE}}}123{{{SINGLE-QUOTE}}}
dosage_range_med_route_id_str := dosage_range.med_route_id as string;
dosage_range_route_id_str := dosage_range.route_id as string;
if (dosage_range_med_route_id_str = dosage_range_route_id_str)
or (dosage_range_route_id_str = "null")
then
dosage_range.display_route := dosage_range.med_route;
else
dosage_range.display_route := dosage_range.route;
endif;
enddo;
//[New born birth-time missing]: estimated hours
if has_alert_on_estimated_birthtime = true
then
estimated_age_hours := int(patient_birthday_info_on_order.age_hour_value);
estimated_age_min_hours := int(patient_birthday_info_on_order.age_hour_min_value);
endif;
////////////////////////////////////////////////////
// Construct the Dose Range tables shown to the user
////////////////////////////////////////////////////
if med_data_list[1].is_order
then
if med_data_list[1].is_outpatient_order
then
if med_data_list[1].is_script
then
order_rx := "This Prescription";
else
order_rx := "This Home Medication";
endif;
else
order_rx := "This Order";
endif;
else
order_rx := "This Prescription";
endif;
dose_type_sort_list := ("single", "total", "average");
is_multum_sort_list := (true, false);
is_iv_additive := last (med_data_list.is_iv_additive);
show_creatinine_clearance_note := exists (dosage_range_list
where dosage_range_list.match_found = false
AND dosage_range_list.creatinine_criteria is not null);
divisor_row := "
| ----- |
";
dosage_details_tables := "";
// This list contains all the dosage ranges
map_dose_range_list := med_dosage_map_list
where med_dosage_map_list.dosage_type <> "contraindication";
// This list contains just the contraindications
map_contraindication_list := med_dosage_map_list
where med_dosage_map_list.dosage_type = "contraindication";
Case_Info_list := (); // list of processed case IDs.
Supplemental_Table_List := (); // list of supplemental tables
medication_name_list := (); // distinct list of medication names
if not exists (dosage_range_list)
then
// insert medication name into medication_name_list
// so that the alert will still be printed
medication_name_list := medication_name_list, med_data_list[1].order_med_name;
endif;
for dosage_range in dosage_range_list
do
case_id := dosage_range.case_id;
med_name := dosage_range.med_name;
// populate medication_name_list
if med_name not in medication_name_list
then
medication_name_list := medication_name_list, med_name;
endif;
if (dosage_range.match_found) then
case_type := "dose range";
else
if (dosage_range.dosage_type <> "contraindication")
then
case_type := "missing data for dose";
else
case_type := "missing data for contraindication";
endif;
endif;
// we now group dose ranges by the route being displayed, not by the
// route stored in the dosage range
dosage_range_for_case := dosage_range_list where
( ( (dosage_range.match_found = true AND dosage_range_list.dosage_type <> "contraindication") // case_type "dose range"
OR dosage_range.match_found = false // case_type "missing data for dose", "missing data for contraindication"
)
AND dosage_range_list.case_id = dosage_range.case_id
AND dosage_range_list.match_found = dosage_range.match_found
AND dosage_range_list.med_name = med_name
AND dosage_range_list.display_route = dosage_range.display_route
AND dosage_range_list.patient_age_at_order = dosage_range.patient_age_at_order
);
map_for_case := med_dosage_map_list where
( med_dosage_map_list.dosage_range_sort_number in dosage_range_for_case.sort_number
AND
( (case_type = "dose range"
AND ( med_dosage_map_list.above_range
OR med_dosage_map_list.below_range
OR med_dosage_map_list.frequency_issue is not null )
)
OR
(case_type = "missing data for dose")
OR
(case_type = "missing data for contraindication")
)
);
dosage_range_for_missing_data := dosage_range_list where
( dosage_range_list.match_found = dosage_range.match_found
AND
dosage_range.match_found = false
AND
dosage_range_list.is_multum = dosage_range.is_multum
AND
dosage_range_list.display_route = dosage_range.display_route
AND
( (case_type = "missing data for dose" AND dosage_range_list.dosage_type in ("single", "average", "total"))
OR
(case_type = "missing data for contraindication" AND dosage_range_list.dosage_type = "contraindication")
)
AND dosage_range_list.med_name = med_name
AND dosage_range_list.patient_age_at_order = dosage_range.patient_age_at_order
AND ( ( dosage_range_list.is_multum = false // item catalog - all match not found
OR patient_info.DNum_Grouper is null // DNum_Grouper is NULL if medication mapped to a dose range group
OR not patient_info.DNum_Grouper.is_unmapped ) // multum - only match not found with grouper found
)
);
map_for_missing_data := med_dosage_map_list WHERE
( med_dosage_map_list.dosage_range_sort_number in dosage_range_for_missing_data.sort_number );
has_notes := any (dosage_range_for_case.recommendation_msg is not null AND
dosage_range_for_case.recommendation_msg <> "");
has_date := any (med_data_list.med_order_type = "Complex Order");
// execute following logic if case ID hasn{{{SINGLE-QUOTE}}}t been processed yet and
// med_dose_range map objects exist for this particular case
matching_case_info := last case_info_list where
(
case_info_list.case_type = case_type
AND
case_Info_list.case_id = case_id
AND
case_info_list.med_name = med_name
AND
case_info_list.route = dosage_range.display_route
AND
case_info_list.patient_age_at_order = dosage_range.patient_age_at_order
);
if ( (not exists matching_case_info)
AND (count map_for_case > 0)
)
then
// We want all dose ranges for this case, even if it is within the range
map_for_dosage_range_for_case := med_dosage_map_list where
( med_dosage_map_list.dosage_range_sort_number in dosage_range_for_case.sort_number
and ( (med_dosage_map_list.dosage_type = "contraindication")
OR ( case_type <> "dose range" )
OR ( case_type = "dose range"
AND med_dosage_map_list.dosage_type <> "contraindication"
AND med_dosage_map_list.adjusted_dose_low >= 0 // check that the value exists -
// when frequency is not configured,
// the total and average value can be null
)
)
);
case_info_instance := new Case_Info_Object;
case_info_instance.case_id := case_id;
case_info_instance.case_type := case_type;
case_info_instance.med_name := med_name;
case_info_instance.map_sort_number := map_for_dosage_range_for_case.sort_number;
case_info_instance.dosage_range_sort_number := dosage_range_for_case.sort_number;
case_info_instance.is_default := dosage_range.is_default;
case_info_instance.is_multum := dosage_range.is_multum;
case_info_instance.medication_count := 0;
case_info_instance.has_notes := has_notes;
case_info_instance.has_date := has_date;
case_info_instance.conditions_text := "";
case_info_instance.route := dosage_range.display_route;
case_info_instance.creatinine_criteria := dosage_range.creatinine_criteria;
case_info_instance.patient_age_at_order := dosage_range.patient_age_at_order;
Case_Info_list := Case_Info_list, case_info_instance;
endif; // if (not exists matching_case_info) AND (count map_for_case > 0)
if (dosage_range.match_found = false)
then
matching_supplemental_table := last supplemental_table_list where
(
supplemental_table_list.is_multum = dosage_range.is_multum
AND
supplemental_table_list.route = dosage_range.display_route
AND
supplemental_table_list.is_contraindication = (dosage_range.dosage_type = "contraindication")
AND
supplemental_table_list.med_name = med_name
AND
supplemental_table_list.patient_age_at_order = dosage_range.patient_age_at_order
);
if ((not exists matching_supplemental_table)
AND (count map_for_missing_data > 0)
)
then
for_drug_str := "";
if is_iv_additive
then
for_drug_str := "For " || med_name || ": ";
endif;
if (dosage_range.is_multum)
then
missing_data_based_on := ""
|| for_drug_str
|| "Applicable dosage ranges based on patient "
|| "age of
" || patient_info.Age.value || ""
|| ", route of
" || dosage_range.display_route || "";
else
missing_data_based_on := "
"
|| for_drug_str
|| "Applicable dosage ranges based on route of
"
|| dosage_range.display_route || "";
endif;
// construct the table
// print out the header row
table_heading := "
\n";
if (dosage_range.is_multum)
then
cat_multum := column_Multum_name;
col_span := "3";
else
cat_multum := column_catalog_name;
col_span := "2";
endif;
if (dosage_range.dosage_type = "contraindication")
then
dose_contra := "Contraindication ";
dose_column_header := "| ";
else
dose_contra := "Usual Dose Range ";
dose_column_header := " | ";
endif;
// first column heading
table_heading := table_heading
|| " | "
|| dose_column_header
|| ""
|| dose_contra
|| cat_multum
|| "";
missing_data_based_on := missing_data_based_on
|| " and the following additional conditions:\n";
table_heading := table_heading
|| "| Additional Conditions |
\n";
supplemental_table_instance := new Supplemental_Table_Object;
supplemental_table_instance.med_name := med_name;
supplemental_table_instance.is_contraindication := dosage_range.dosage_type = "contraindication";
supplemental_table_instance.is_multum := dosage_range.is_multum;
supplemental_table_instance.route := dosage_range.display_route;
supplemental_table_instance.msg := missing_data_based_on
|| table_heading;
supplemental_table_instance.dosage_range_sort_number := dosage_range_for_missing_data.sort_number;
supplemental_table_instance.map_sort_number := map_for_missing_data.sort_number;
supplemental_table_instance.med_case_count := 0;
supplemental_table_instance.patient_age_at_order := dosage_range.patient_age_at_order;
supplemental_table_list := supplemental_table_list, supplemental_table_instance;
endif; //if (not exists matching_supplemental_table)
endif; // if (dosage_range.match_found = false)
enddo; // for dosage_range in dosage_range_list
// sort the medication_name_list
medication_name_list := sort(medication_name_list);
// create the Based On strings
for case_item in case_info_list
do
dosage_range := dosage_range_list[case_item.dosage_range_sort_number[1]];
if dosage_range.BSA_criteria is not null then
show_height_criteria := "show height criteria";
show_weight_criteria := "show weight criteria";
else
show_height_criteria := null;
show_weight_criteria := null;
endif;
if dosage_range.weight_criteria is not null then
show_weight_criteria := dosage_range.weight_criteria;
endif;
for_iv_drug := "";
if is_iv_additive
then
for_iv_drug := "For " || case_item.med_name || ": ";
endif;
patient_BSA_str := null;
if patient_info.BSA.value is not null
then
patient_BSA_str := patient_info.BSA.value || " m2";
endif;
// if patient{{{SINGLE-QUOTE}}}s creatinine clearance is null, then, we don{{{SINGLE-QUOTE}}}t display it in the based-on
// string even if there is a creatinine clearance criteria in
// the dose ranges.
patient_creatinine_str := null;
if patient_info.Creatinine.value is not null
then
patient_creatinine_str := patient_info.Creatinine.value || " mL/min";
endif;
// we display the string "Liver Disease" in the based-on string
// if the patient has liver disease. Otherwise, the string is
// suppressed.
patient_liver_disease_str := null;
if (patient_info.Liver.value = "Yes")
then
patient_liver_disease_str := "liver disease";
endif;
// get the criteria from current dosage being processed at
// top-most loop. Should be okay, since we won{{{SINGLE-QUOTE}}}t be
// processing case ids more than once.
dosage_range_criteria_list := (
dosage_range.age_criteria,
dosage_range.gender_criteria,
show_height_criteria, // show height value for BSA criteria
show_weight_criteria, // show weight value for weight criteria, or BSA criteria
dosage_range.BSA_criteria,
dosage_range.liver_criteria,
dosage_range.renal_criteria,
dosage_range.creatinine_criteria,
true
);
patient_info_criteria_list := (
dosage_range.patient_age_at_order,
patient_info.Gender.value,
ht_cm || " cm",
wt_kg || " kg",
patient_BSA_str,
patient_liver_disease_str,
patient_info.Renal.value,
patient_creatinine_str,
case_item.route
);
// these two lists should have the same number of items
printable_based_on_criteria_headers := based_on_criteria_headings
where dosage_range_criteria_list is not null;
printable_based_on_criteria_list:= patient_info_criteria_list
where dosage_range_criteria_list is not null;
based_on_case := "";
based_on_case_header := "";
printable_based_on_criteria_count := count(printable_based_on_criteria_list);
for printable_based_on_index in (1 seqto printable_based_on_criteria_count)
do
if (printable_based_on_index > 1)
then
if (printable_based_on_index < printable_based_on_criteria_count)
and ((case_item.case_type = "dose range") or case_item.is_default)
then
based_on_case := based_on_case || ", ";
based_on_case_header := based_on_case_header || ", ";
else
based_on_case := based_on_case || " and ";
based_on_case_header := based_on_case_header || " and ";
endif;
endif;
if (printable_based_on_criteria_headers[printable_based_on_index] is not null)
then
if (printable_based_on_criteria_headers[printable_based_on_index]
not in ("renal", "liver") )
then
based_on_case := based_on_case
|| printable_based_on_criteria_headers[printable_based_on_index]
|| " of ";
endif;
based_on_case_header := based_on_case_header
|| printable_based_on_criteria_headers[printable_based_on_index];
endif;
based_on_case := based_on_case
|| ""
|| printable_based_on_criteria_list[printable_based_on_index]
|| "";
enddo;
// There is some dosage range that is outside
// Start creating the table
dose_range_based_on_case := ""
|| for_iv_drug
|| "Based on patient "
|| based_on_case
|| ":
\n";
// specify if Catalog or not
if (not dosage_range.is_multum)
then
based_on_case_header := based_on_case_header
|| " " || column_catalog_name;
endif;
dose_range_based_on_case_header := "based on patient "
|| based_on_case_header;
// Conditions text
if case_item.is_default and case_item.is_multum then
case_item.conditions_text := "No Additional Conditions";
else
age_criteria := null;
if not dosage_range.is_multum
then
age_criteria := dosage_range.age_criteria;
endif;
dose_range_criteria_list := (
age_criteria,
dosage_range.weight_criteria,
dosage_range.BSA_criteria,
dosage_range.gender_criteria,
dosage_range.liver_criteria,
dosage_range.renal_criteria,
dosage_range.creatinine_criteria
);
if (exists dosage_range.liver_criteria)
then
liver_disease_str := "Liver Disease";
else
liver_disease_str := null;
endif;
additional_conditions_list := (
"Age " || dosage_range.age_criteria,
"Weight " || dosage_range.weight_criteria,
"BSA " || dosage_range.BSA_criteria,
"Gender " || dosage_range.gender_criteria,
liver_disease_str,
dosage_range.renal_criteria,
"Creatinine Clearance " || dosage_range.creatinine_criteria
);
additional_conditions_text := "";
case_condition_count := 0;
for cond_ind in (1 seqto count additional_conditions_list)
do
cond_val := additional_conditions_list[cond_ind];
if exists dose_range_criteria_list[cond_ind]
then
if (case_condition_count > 0)
then
additional_conditions_text := additional_conditions_text || ", ";
endif;
additional_conditions_text := additional_conditions_text || cond_val;
case_condition_count := case_condition_count + 1;
endif;
enddo;
case_item.conditions_text := additional_conditions_text;
endif;
case_item.based_on_text := dose_range_based_on_case;
case_item.based_on_header_text := dose_range_based_on_case_header;
case_item.msg := "";
enddo; // for case_item in case_info_list
// Loop through all the Med_Data_Objects
for med_data in med_data_list do
if (med_data.processed_for_printing is null)
then
// Find the matching objects for the SINGLE DOSE
found_med_data := med_data_list where
(med_data_list.med_order_type = med_data.med_order_type
AND med_data_list.order_med_name = med_data.order_med_name
AND ( med_data_list.order_med_units = med_data.order_med_units
OR ( med_data_list.order_med_units is NULL
AND med_data.order_med_units is NULL
)
)
AND ( med_data_list.order_med_route = med_data.order_med_route
OR ( med_data_list.order_med_route is NULL
AND med_data.order_med_route is NULL
)
)
);
// Find the matching objects for the AVERAGE DAILY DOSE
found_average := average_tracker_list where
(average_tracker_list.med_order_type = med_data.med_order_type
AND average_tracker_list.med_name = med_data.order_med_name
AND ( average_tracker_list.uom = med_data.order_med_units
OR ( average_tracker_list.uom is NULL
AND med_data.order_med_units is NULL
)
)
AND ( average_tracker_list.route = med_data.order_med_route
OR ( average_tracker_list.route is NULL
AND med_data.order_med_route is NULL
)
)
);
// Find the matching objects for the TOTAL DAILY DOSE
found_total := total_tracker_list where
(total_tracker_list.med_order_type = med_data.med_order_type
AND total_tracker_list.med_name = med_data.order_med_name
AND ( total_tracker_list.uom = med_data.order_med_units
OR ( total_tracker_list.uom is NULL
AND med_data.order_med_units is NULL
)
)
AND ( total_tracker_list.route = med_data.order_med_route
OR ( total_tracker_list.route is NULL
AND med_data.order_med_route is NULL
)
)
);
// This is all the maps for the current medication
found_dose_map := med_dosage_map_list WHERE
( ( med_dosage_map_list.dosage_type = "single"
AND med_dosage_map_list.med_sort_number in found_med_data.sort_number )
OR ( med_dosage_map_list.dosage_type = "average"
AND med_dosage_map_list.med_sort_number in found_average.sort_number )
OR ( med_dosage_map_list.dosage_type = "total"
AND med_dosage_map_list.med_sort_number in found_total.sort_number)
);
// Process the list in reverse order for "supplemental info" section
// The out of range section does not matter as the data is stored in the case_info object
// TBD: add where condition on med_name
reverse_case_indices := reverse (1 seqto (count case_info_list));
for ind in reverse_case_indices
do
case_info_item := case_info_list[ind];
// Find all the maps for the current case for the current medication
found_dose_map_for_case := found_dose_map WHERE
(found_dose_map.sort_number in Case_Info_item.map_sort_number);
matching_case_found := count found_dose_map_for_case > 0;
// for each case, we find all the med-dose maps associated with it
// if we encounter this case more than once in this for-loop, then
// we need to add a divisor row.
if matching_case_found then
// When medication changes (medication name, route, or UOM) add a divisor
// - for child complex orders, if the uom or route changes the divisor will be added
// - if there are multiple IV additives for the same drug and route, but different UOM, the divisor will be added
case_info_item.medication_count := case_info_item.medication_count + 1;
if case_info_item.medication_count > 1 then
case_info_item.msg := case_info_item.msg || divisor_row;
endif;
dose_supplemental_table_list := supplemental_table_list WHERE (supplemental_table_list.is_contraindication = false);
for missing_table in dose_supplemental_table_list
do
// if this case is associated with unmatched dose ranges
// and there exists an "additional conditions" table
// associated with map objects that are a associated
// with this case, then add a divisor row and increment the numbery
// of medications associated with this "additional conditions" table
if case_info_item.case_type = "missing data for dose"
AND
any (missing_table.map_sort_number in found_dose_map_for_case.sort_number)
then
missing_table.med_case_count := missing_table.med_case_count + 1;
if missing_table.med_case_count > 1 // how many cases have been printed for this pair
then
missing_table.msg := missing_table.msg || divisor_row;
endif;
endif;
enddo;
for map_item in found_dose_map_for_case
do
out_of_range_row := "";
dose_range_item := dosage_range_list[map_item.dosage_range_sort_number];
if (map_item.dosage_type = "single")
then
med_object := med_data_list[map_item.med_sort_number];
row_type := "Single:";
elseif (map_item.dosage_type = "total")
then
med_object := total_tracker_list[map_item.med_sort_number];
if ( med_data.med_order_type = "Complex Order"
or med_object.dose_range_check_method = "Summed Doses")
then
row_type := "24-Hr Total:";
else
row_type := "Total Daily:";
endif;
elseif map_item.dosage_type = "average"
then
med_object := average_tracker_list[map_item.med_sort_number];
if ( med_data.med_order_type = "Complex Order"
or med_object.dose_range_check_method = "Summed Doses")
then
row_type := "24-Hr Average:";
else
row_type := "Total Average:";
endif;
endif;
// use med_data and each_dose_range objects here to populate
// this row
if case_info_item.case_type = "dose range"
then
if map_item.below_range or map_item.above_range
then
row_name := "outside_dose_";
else
row_name := "within_dose_";
endif;
else
row_name := "missing_dose_";
endif;
if case_info_item.is_multum
then
row_name := row_name || "multum";
else
row_name := row_name || "catalog";
endif;
out_of_range_row := out_of_range_row
|| ""
|| "| " || row_type || " | ";
// dosage range column
dosage_range_col := call format_dose_range with
(dose_range_item.lower_dose, dose_range_item.upper_dose);
// dosage_range_col := dosage_range_col || " " || dose_range_item.corrected_uom;
//JML - Modification to standard MLM to include patients aged 0 to 3yrs
// if (dosage_range_col = "0-0.0001 mg") or (dosage_range_col = "0.0001") then
if "0.0001" in dosage_range_col then
dosage_range_col := "Medication ordered is not recommended for a patient fitting this profile.";
else
dosage_range_col := dosage_range_col || " " || dose_range_item.corrected_uom;
endif;
//End JML Change
// Frequency Column - only shown for Multum single dose ranges
frequency_col := "";
if case_info_item.is_multum
then
if (map_item.dosage_type = "single")
and dose_range_item.dose_frequency is not null
then
frequency_col := dose_range_item.dose_frequency;
endif;
out_of_range_row := out_of_range_row
|| "" || dosage_range_col || " | "
|| "" || frequency_col || " | ";
else
out_of_range_row := out_of_range_row
|| "" || dosage_range_col || " | ";
endif;
is_duplicate_single_iv := false;
if case_info_item.case_type = "dose range"
then
// SET SINGLE ORDERED DOSE
ordered_dosage_col := call format_dose_range with
(map_item.adjusted_dose_low, map_item.adjusted_dose_high);
ordered_dosage_col := "" || ordered_dosage_col || " " || dose_range_item.corrected_uom || "";
if (map_item.above_range or map_item.below_range)
then
ordered_dosage_col := "" || ordered_dosage_col || "";
elseif (map_item.match_found
and map_item.above_range = false
and map_item.below_range = false)
then
ordered_dosage_col := "" || ordered_dosage_col || "";
endif;
if (map_item.adjusted_dose_uom <> map_item.med_dose_uom)
then
orig_dose := call format_dose_range with
(map_item.med_dose_low, map_item.med_dose_high);
ordered_dosage_col := ordered_dosage_col
|| " ("
|| orig_dose || " " || map_item.med_dose_uom
|| ")";
endif;
ordered_dosage_col := ordered_dosage_col
|| "";
if (case_info_item.is_multum
or ( med_data.med_order_type = "Complex Order"
and ( med_data.is_iv_additive is null
or not med_data.is_iv_additive )))
and map_item.dosage_type = "single"
then
freq := med_object.order_med_frequency;
if med_object.order_med_frequency is null
then
freq := "once";
endif;
if dose_range_item.frequency_issue is not null
and case_info_item.is_multum
then
ordered_dosage_col := ordered_dosage_col
|| " "
|| freq
|| "";
else
ordered_dosage_col := ordered_dosage_col
|| " " || freq;
endif;
if med_object.stop_after_value is not null
and med_object.stop_after_value > 0
and med_object.stop_after_option_type > 0
then
ordered_dosage_col := ordered_dosage_col
|| " x " || med_object.stop_after_value
|| " " || stop_after_type_list[med_object.stop_after_option_type];
endif;
endif;
ordered_dosage_col := ordered_dosage_col
|| "";
// Order/Prescription dose col
out_of_range_row := out_of_range_row
|| "" || ordered_dosage_col || " | ";
if case_info_item.has_date then
if map_item.dosage_type = "single"
then
if med_data.is_iv_additive
then
starting_on_col := "";
else
starting_on_date := med_object.admin_dtm_list[1];
if starting_on_date is null
then
starting_on_date := med_object.calcStart_dtm;
endif;
if show_debug_statements
then
starting_on_col := starting_on_date formatted with "%.4t";
else
starting_on_col := starting_on_date formatted with "%.2t";
endif;
endif;
elseif map_item.dosage_type in ("average", "total")
then
if show_debug_statements
then
starting_on_col := med_object.interval_begin_dtm_list[1] formatted with "%.4t";
else
starting_on_col := med_object.interval_begin_dtm_list[1] formatted with "%.2t";
endif;
endif;
out_of_range_row := out_of_range_row
|| "" || starting_on_col || " | ";
endif;
if case_info_item.has_notes then
// recommendation message column
if dose_range_item.recommendation_msg is not null
then
note_col := dose_range_item.recommendation_msg;
else
note_col := "";
endif;
out_of_range_row := out_of_range_row
|| "" || note_col || " | ";
endif;
if show_debug_statements
then
route_val := "";
if med_data.order_med_route <> dose_range_item.route
then
route_val := ", Route: " || dose_range_item.route;
endif;
out_of_range_row := out_of_range_row
|| ""
|| "Case ID: " || case_info_item.case_id
|| route_val
|| " | ";
endif;
out_of_range_row := out_of_range_row
|| "
\n";
if ( map_item.dosage_type = "single"
AND med_data.is_iv_additive
AND med_data.sort_number <> med_object.sort_number
AND med_data.order_med_route <> med_object.order_med_route
)
then
// change case_type to skip processing duplicate single iv additive
is_duplicate_single_iv := true;
endif;
else
// missing data
out_of_range_row := out_of_range_row
|| "" || case_info_item.conditions_text || " | \n";
supplemental_table := last (supplemental_table_list WHERE
(supplemental_table_list.is_multum = dose_range_item.is_multum
AND
supplemental_table_list.route = case_info_item.route
AND
supplemental_table_list.is_contraindication = false
AND
supplemental_table_list.med_name = dose_range_item.med_name
AND
supplemental_table_list.patient_age_at_order = dose_range_item.patient_age_at_order
));
supplemental_table.msg := supplemental_table.msg
|| out_of_range_row;
endif;
// Add the formatted row into the case_info_item
// Skip if it{{{SINGLE-QUOTE}}}s a duplicate single IV order (complex iv-additive)
if (is_duplicate_single_iv = false)
then
case_info_item.msg := case_info_item.msg || out_of_range_row;
endif;
enddo;
endif; //matching_case_found then
enddo; // ind in reverse_case_indices
found_med_data.processed_for_printing := true;
endif;
enddo; // med_data in med_data_list
// Generate the outside dose messages
dose_range_case_info_list := case_info_list where (case_info_list.case_type = "dose range");
dosage_outside_range_table_list := ();
for case_info_item in dose_range_case_info_list
do
if case_info_item.processed_for_printing is NULL
then
dosage_outside_table := case_info_item.based_on_text;
found_based_on_multum := dose_range_case_info_list WHERE
(dose_range_case_info_list.based_on_text = case_info_item.based_on_text
AND
dose_range_case_info_list.is_multum);
multum_case_count := count found_based_on_multum;
if (multum_case_count > 0)
then
has_notes := any (found_based_on_multum.has_notes);
has_date := any (found_based_on_multum.has_date);
// Create the table and the header row
table_heading := "\n"
|| ""
|| "| Usual Dose Range "
|| column_Multum_name
|| " | "
|| "" || order_rx || " | ";
// show start date if there are multiple administrations (complex order)
if has_date
then
table_heading := table_heading
|| "Starting On | ";
endif;
// add Note header
if has_notes
then
table_heading := table_heading
|| "Note | ";
endif;
if show_debug_statements
then
table_heading := table_heading
|| "(Debug) | ";
endif;
// finish off the row header
table_heading := table_heading || "
\n";
// Go through the cases and add the rows
table_rows := "";
for ind in (1 seqto multum_case_count)
do
if (ind > 1)
then
table_rows := table_rows
|| divisor_row;
endif;
table_rows := table_rows
|| found_based_on_multum[ind].msg;
enddo;
// Add the multum case table
dosage_outside_table := dosage_outside_table
|| table_heading
|| table_rows
|| "
\n\n";
// Mark the cases as processed
found_based_on_multum.processed_for_printing := true;
endif;
found_based_on_catalog := dose_range_case_info_list WHERE
(dose_range_case_info_list.based_on_text = case_info_item.based_on_text
AND
not dose_range_case_info_list.is_multum);
catalog_case_count := count found_based_on_catalog;
if (catalog_case_count > 0)
then
has_notes := any (found_based_on_catalog.has_notes);
has_date := any (found_based_on_catalog.has_date);
// Create the table and the header row
table_heading := "\n"
|| ""
|| "| Usual Dose Range "
|| column_catalog_name
||" | "
|| "" || order_rx || " | ";
// show start date if there are multiple administrations (complex order)
if has_date
then
table_heading := table_heading
|| "Starting On | ";
endif;
// add Note header
if has_notes
then
table_heading := table_heading
|| "Note | ";
endif;
if show_debug_statements
then
table_heading := table_heading
|| "(Debug) | ";
endif;
// finish off the row header
table_heading := table_heading || "
\n";
// Go through the cases and add the rows
table_rows := "";
for ind in (1 seqto catalog_case_count)
do
if (ind > 1)
then
table_rows := table_rows
|| divisor_row;
endif;
table_rows := table_rows
|| found_based_on_catalog[ind].msg;
enddo;
// Add the catalog case table
dosage_outside_table := dosage_outside_table
|| table_heading
|| table_rows
|| "
\n\n";
// Mark the cases as processed
found_based_on_catalog.processed_for_printing := true;
endif;
based_on_creatinine_criteria := last (found_based_on_multum.creatinine_criteria
where found_based_on_multum.creatinine_criteria is not null);
if ( based_on_creatinine_criteria is not null
AND based_on_creatinine_criteria <> "")
then
dosage_outside_table := dosage_outside_table
|| "NOTE"
|| " this applies to Creatinine Clearance Range "
|| based_on_creatinine_criteria
|| ". The dose could be out of range for other renal "
|| "conditions; see Supplemental Information.\n";
endif;
dosage_outside_range_table_list := dosage_outside_range_table_list,
dosage_outside_table;
endif;
enddo;
// Missing data for contraindication
missing_contraindication_case_list := case_info_list WHERE
(case_info_list.case_type = "missing data for contraindication");
for case_info_item in missing_contraindication_case_list
do
for ind in case_info_item.dosage_range_sort_number
do
dose_range_item := dosage_range_list[ind];
supplemental_table := last (supplemental_table_list WHERE
(supplemental_table_list.is_multum = dose_range_item.is_multum
AND
supplemental_table_list.route = case_info_item.route
AND
supplemental_table_list.is_contraindication = true
AND
supplemental_table_list.med_name = dose_range_item.med_name
AND
supplemental_table_list.patient_age_at_order = dose_range_item.patient_age_at_order
));
row_name := "missing_data_";
if supplemental_table.is_multum
then
row_name := row_name || "multum_";
if supplemental_table.is_contraindication
then
row_name := row_name || "contraindication";
else
row_name := row_name || "dose";
endif;
else
row_name := row_name || "catalog";
endif;
supplemental_table.msg := supplemental_table.msg
|| ""
|| "| " || dose_range_item.contraindication_msg || " | "
|| "" || case_info_item.conditions_text || " | "
|| "
\n";
enddo;
enddo;
// Close table tags for missing data tables
for supplemental_table_item in supplemental_table_list
do
supplemental_table_item.msg := supplemental_table_item.msg || "
\n";
enddo;
// If there are multiple groupers associated with the dnum,
// find out which grouper has corresponding dose ranges
supplemental_grouper_names := "";
if patient_info.DNum_Grouper.is_unmapped
then
missing_data_for_grouper := dosage_range_list where
( dosage_range_list.match_found = false
and dosage_range_list.is_multum = true
);
grouper_name_rows:= "";
grouper_info_list := patient_info.DNum_Grouper.value;
for grouper_info_item in grouper_info_list
do
grouper_info_item.dosage_range_found := grouper_info_item.grouper_id in missing_data_for_grouper.grouper_id;
if grouper_info_item.dosage_range_found
then
grouper_name_rows := grouper_name_rows
|| "
"
|| grouper_info_item.grouper_name
|| "";
endif;
enddo;
if any grouper_info_list.dosage_range_found
then
supplemental_grouper_names := "
"
|| "This medication has dosage ranges for the following groups of medications:"
|| "
\n"
|| "
\n"
|| grouper_name_rows
|| "
\n";
endif;
endif;
//-----------------------------------------------------
// Construct Cannot_Check_Object and Missing_Data_Object
// Lists.
//-----------------------------------------------------
// Initialize List Variables
cannot_check_list := ();
missing_data_list := ();
frequency_unchecked_list := ();
dnum_match_catalog_dose_range_list := ();
// get the catalog dose ranges that match the prescription only at the
// dnum level
if (not med_data_list[1].is_order)
then
dnum_match_catalog_dose_range_list := dosage_range_list where
dosage_range_list.match_found = false
AND dosage_range_list.is_multum = false
AND dosage_range_list.dnum_ic_match_found = true;
endif;
for med_name in medication_name_list
do
curr_med_data_list := med_data_list WHERE med_data_list.order_med_name = med_name;
curr_average_tracker_list := average_tracker_list WHERE average_tracker_list.med_name = med_name;
curr_total_tracker_list := total_tracker_list WHERE total_tracker_list.med_name = med_name;
//------------------------------------------------------
// Handle Show
Irregular Message
//------------------------------------------------------
// This message only applies to the Average Daily Dosage Range
// when there is a frequency that has an IRREGULAR Schedule.
IF show_irregular_message
and ANY curr_average_tracker_list.irregular_schedule_used
then
found_average_list := curr_average_tracker_list
where curr_average_tracker_list.irregular_schedule_used;
// For Irregular intervals set message about Average calculations
irregular_schedule_text := "Issue: Irregular User Schedule
\n"
|| "A User Scheduled frequency was selected "
|| "that used an Irregular schedule. There is an average daily "
|| "dosage range listed for the medication(s): "
|| med_name || ". However, for this type of "
|| "schedule the calculated average daily amount is invalid.";
// Create Cannot_Check_Object and Add to List
cannot_check := new cannot_check_object;
cannot_check_list := cannot_check_list, cannot_check;
// Populate Object
cannot_check.med_order_type := found_average_list[1].med_order_type;
cannot_check.med_name_list := med_name;
cannot_check.route := found_average_list[1].route;
cannot_check.uom := found_average_list[1].uom;
cannot_check.alert_msg_for_cannot_check := irregular_schedule_text;
cannot_check.alert_abstract := "Issue: Irregular User Schedule";
endif; //IF show_irregular_message
//------------------------------------------------------
// Handle Show WEEKLY Message
//------------------------------------------------------
// This message only applies to the Average Daily Dosage Range
// when there is a frequency that has an WEEKLY Schedule.
IF show_user_scheduled_weekly_message
and ANY curr_average_tracker_list.user_scheduled_weekly_used
then
found_average_list := curr_average_tracker_list
where curr_average_tracker_list.user_scheduled_weekly_used;
// For WEEKLY intervals set message about Average calculations
weekly_schedule_text := "Issue: Weekly User Schedule
\n"
|| "A User Scheduled frequency was selected "
|| "that used a Weekly schedule. There is an "
|| "average daily dosage range listed for the medication(s): "
|| med_name || ". However, for this type of "
|| "schedule the calculated average daily amount is invalid.";
// Create Cannot_Check_Object and Add to List
cannot_check := new cannot_check_object;
cannot_check_list := cannot_check_list, cannot_check;
// Populate Object
cannot_check.med_order_type := found_average_list[1].med_order_type;
cannot_check.med_name_list := med_name;
cannot_check.route := found_average_list[1].route;
cannot_check.uom := found_average_list[1].uom;
cannot_check.alert_msg_for_cannot_check := weekly_schedule_text;
cannot_check.alert_abstract := "Issue: Weekly User Schedule";
endif; //IF show_irregular_message
//------------------------------------
// Handle Show Under 24-Hour Message
//------------------------------------
If show_under_24_hour_message
AND (ANY curr_total_tracker_list.met_criteria_under_24_hours
or ANY curr_average_tracker_list.met_criteria_under_24_hours )
then
// Create Cannot_Check_Object and Add to List
cannot_check := new cannot_check_object;
cannot_check_list := cannot_check_list, cannot_check;
// Populate Cannot_Check Object
cannot_check.med_name_list := med_name;
// Select the Total and Average Objects Needing the Message
found_total_list := curr_total_tracker_list
where curr_total_tracker_list.met_criteria_under_24_hours;
found_average_list := curr_average_tracker_list
where curr_average_tracker_list.met_criteria_under_24_hours;
if exist found_total_list
then
cannot_check.med_order_type := found_total_list[1].med_order_type;
cannot_check.route := found_total_list[1].route;
cannot_check.uom := found_total_list[1].uom;
elseif exist found_average_list
then
cannot_check.med_order_type := found_average_list[1].med_order_type;
cannot_check.route := found_average_list[1].route;
cannot_check.uom := found_average_list[1].uom;
endif;
under_24_hr_duration_msg := "Issue: Under 24-Hour dose
\n"
|| "The average daily and total daily dosage cannot be calculated accurately "
|| "with regards to possible administration times "
|| "when a medication is given for less than 24 hours. "
|| "This affects the following medication(s): "
|| med_name || "\n";
cannot_check.alert_msg_for_cannot_check := under_24_hr_duration_msg;
cannot_check.alert_abstract := "Issue: Under 24-Hour dose";
endif; //If show_under_24_hour_message
//---------------------------------------
// Handle Show Has Shift based Frequency
//---------------------------------------
If show_has_shift_frequency_message
AND any curr_med_data_list.isShiftFrequency
then
// Display the warning for any component that has at least 1
// shift based frequency.
shiftData := curr_med_data_list where
(curr_med_data_list.isShiftFrequency = true);
found_total_list := curr_total_tracker_list where
(curr_total_tracker_list.med_order_type = shiftData[1].med_order_type
AND curr_total_tracker_list.med_name = shiftData[1].order_med_name
AND curr_total_tracker_list.uom = shiftData[1].order_med_units
AND curr_total_tracker_list.route = shiftData[1].order_med_route
);
found_average_list := curr_average_tracker_list where
(curr_average_tracker_list.med_order_type = shiftData[1].med_order_type
AND curr_average_tracker_list.med_name = shiftData[1].order_med_name
AND curr_average_tracker_list.uom = shiftData[1].order_med_units
AND curr_average_tracker_list.route = shiftData[1].order_med_route
);
// Create Cannot_Check_Object and Add to List
cannot_check := new cannot_check_object;
cannot_check_list := cannot_check_list, cannot_check;
// Populate Cannot_Check Object
cannot_check.med_name_list := med_name;
if exist found_total_list
then
cannot_check.med_order_type := found_total_list[1].med_order_type;
cannot_check.route := found_total_list[1].route;
cannot_check.uom := found_total_list[1].uom;
elseif exist found_average_list
then
cannot_check.med_order_type := found_average_list[1].med_order_type;
cannot_check.route := found_average_list[1].route;
cannot_check.uom := found_average_list[1].uom;
endif;
has_shift_freq_msg := "Issue: Shift based frequency
\n"
|| "A shift based frequency was selected for the medication(s): "
|| med_name || ". "
|| "The total daily dosage could not be calculated accurately "
|| "with regards to possible administration times.";
cannot_check.alert_msg_for_cannot_check := has_shift_freq_msg;
cannot_check.alert_abstract := "Issue: Shift based frequency";
endif; //If show_has_shift_frequency_message
//------------------------------------------------------------------------------
// MISSING DATA ALERT
//------------------------------------------------------------------------------
// Initialize Variables
// string constants used for the header
missing_data_str := "missing data";
data_not_current_str := "old data";
unmapped_data_str := "unmapped data";
issues_str := "issues";
// Process multum frequency issue alert messages
// This isn{{{SINGLE-QUOTE}}}t placed in the Missing Data block because dose ranges are checked
// even though the frequency could not be checked. So, if the dose ranges are valid,
// then we avoid executing the statements in the Missing Data block unnecessarily
if use_multum_dosage_data
and alert_if_missing_flags.unmapped_frequency
then
// get mapping objects with unmapped frequencies
// for the current medication. We only do this for dose ranges
// that could be checked.
unmapped_frequency_map_list := med_dosage_map_list
where med_dosage_map_list.med_name = med_name
and med_dosage_map_list.frequency_issue = dose_frequency_unmapped
and med_dosage_map_list.dosage_type = "single"
and med_dosage_map_list.match_found = true;
if exists unmapped_frequency_map_list
then
// get the medication objects referenced in
// the mapping objects
unmapped_freq_med_data_list := curr_med_data_list
where curr_med_data_list.sort_number in
unmapped_frequency_map_list.med_sort_number;
// Create missing data objects for frequencies that could not be mapped
// in the medication objects
if exists unmapped_freq_med_data_list
then
for unmapped_freq_med_data_item in unmapped_freq_med_data_list
do
freq := unmapped_freq_med_data_item.order_med_frequency;
if unmapped_freq_med_data_item.order_med_frequency is null
then
freq := "once";
endif;
frequency_unchecked_msg := "Unmapped: Frequency
"
|| "Notify your system administrator that the Frequency "
|| freq
|| " is not mapped";
frequency_unchecked_instance := new Missing_Data_Object;
frequency_unchecked_instance.criteria := "Frequency";
frequency_unchecked_instance.missing_data_error := true;
frequency_unchecked_instance.details := unmapped_data_str;
frequency_unchecked_instance.msg := frequency_unchecked_msg;
frequency_unchecked_instance.med_name := med_name;
frequency_unchecked_instance.unchecked_dose_range_type_list := ("dose range");
frequency_unchecked_instance.alert_abstract := "Unmapped: Frequency";
frequency_unchecked_list := frequency_unchecked_list, frequency_unchecked_instance;
enddo;
endif; // if exists unmapped_freq_dose_range_list
endif; // if exists unmapped_frequency_map_list
endif;
// Only Process Missing Patient Data Alert Messages
// when the flag is TRUE and there are missing data
if (any grouper_info_list.dosage_range_found
and alert_if_missing_flags.cannot_check_DNUM_Rx_to_Multum)
OR ( alert_if_missing_flags.cannot_check_Rx_to_IC
and exists (dnum_match_catalog_dose_range_list))
then
// Prescription dose range matching issues
// - Multiple Multum DRC groups found for given DNum
// - Multiple catalog dose ranges found for given DNum
rx_matching_issue_list := ("Multum", "Catalog");
for rx_matching_issue in rx_matching_issue_list
do
if rx_matching_issue = "Multum"
then
print_rx_matching_issue := ( any grouper_info_list.dosage_range_found
and alert_if_missing_flags.cannot_check_DNUM_Rx_to_Multum
);
missing_data_detail_msg := "Issue: Cannot determine which dosage range to check
\n"
|| "Please select the full name with strength and form "
|| "of the medication in Prescription Writer";
else
print_rx_matching_issue := ( alert_if_missing_flags.cannot_check_Rx_to_IC
and exists (dnum_match_catalog_dose_range_list)
);
missing_data_detail_msg := "Issue: Could not determine which dosage range to check "
|| column_catalog_name || "
\n"
|| "This medication has dosage ranges defined.";
endif; // if rx_matching_issue
if print_rx_matching_issue
then
missing_data_type := issues_str;
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "Rx Dnum";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := missing_data_type;
missing_data_instance.unchecked_dose_range_type_list := ("dose range", "contraindication");
missing_data_instance.med_name := med_name;
missing_data_instance.alert_abstract := "Issue: Cannot determine which dosage range to check";
missing_data_instance.msg := missing_data_detail_msg;
missing_data_list := missing_data_list, missing_data_instance;
endif; // if print_rx_matching_issue
enddo; // for rx_matching_issue in rx_matching_issue_list
//////////////////////////////////////////////////////////////////
// End prescription-only section
//////////////////////////////////////////////////////////////////
elseif (patient_info.Age.is_missing
and alert_if_missing_flags.patient_age)
OR (patient_info.Gender.is_missing
and alert_if_missing_flags.patient_gender)
OR (patient_info.Gender.unknown_other
and alert_if_missing_flags.patient_gender)
OR (patient_info.Gender.is_unmapped
and alert_if_missing_flags.unmapped_gender)
OR (( patient_info.Height.is_missing
or patient_info.Height.not_current)
and alert_if_missing_flags.patient_height)
OR (( patient_info.Weight.is_missing
or patient_info.Weight.not_current)
and alert_if_missing_flags.patient_weight)
OR (any curr_med_data_list.missing_route
and alert_if_missing_flags.route)
OR (any curr_med_data_list.unmapped_route
and alert_if_missing_flags.unmapped_route)
OR (any curr_med_data_list.uom_conversion_issue
and alert_if_missing_flags.uom_conversion)
OR (any curr_med_data_list.missing_uom
and alert_if_missing_flags.uom)
OR (any curr_med_data_list.unmapped_uom
and alert_if_missing_flags.unmapped_uom)
OR (any curr_med_data_list.unmapped_drug
and alert_if_missing_flags.unmapped_drug)
OR (any curr_med_data_list.unmapped_grouper
and alert_if_missing_flags.unmapped_grouper)
OR (any curr_med_data_list.generic_route
and alert_if_missing_flags.cannot_check_generic_route)
OR (any (curr_med_data_list.generic_route = false)
and alert_if_missing_flags.inapplicable_route)
then
//--------------------------------
// CHECK FOR MISSING PATIENT DATA
//--------------------------------
// retrieve the list of unchecked dose ranges by medication
unchecked_dose_range_list := dosage_range_list where (
dosage_range_list.med_name = med_name and
dosage_range_list.match_found = false );
// Determine if missing/unmapped Age alert is needed
// Cannot run multum check without age, so no multum dose ranges exist
age_item_cat_unchecked_dose_range_list := unchecked_dose_range_list
WHERE unchecked_dose_range_list.age_criteria is not null;
// Determine if missing AGE alert is needed
if patient_info.Age.is_missing
and alert_if_missing_flags.patient_age
and ( exists age_item_cat_unchecked_dose_range_list
or use_multum_dosage_data )
then
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "Age";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := (
"single catalog" || (any age_item_cat_unchecked_dose_range_list.dosage_type = "single"),
"average catalog" || (any age_item_cat_unchecked_dose_range_list.dosage_type = "average"),
"total catalog" || (any age_item_cat_unchecked_dose_range_list.dosage_type = "total"),
"multum " || use_multum_dosage_data
);
missing_data_instance.msg := "Missing data: Age
"
|| "Please enter a complete BIRTHDAY for this patient";
missing_data_instance.med_name := med_name; // all medications are affected
missing_data_instance.details.unchecked_dose_range_type_list := ("dose range");
missing_data_instance.alert_abstract := "Missing data: Age";
missing_data_list := missing_data_list, missing_data_instance;
endif; //if patient_info.Age.is_missing
// Determine if missing/unmapped GENDER alert is needed
gender_unchecked_dose_range_list := unchecked_dose_range_list
WHERE unchecked_dose_range_list.gender_criteria is not null;
if ( ( ( patient_info.Gender.is_missing
or patient_info.Gender.unknown_other
)
and alert_if_missing_flags.patient_gender
)
or ( patient_info.Gender.is_unmapped
and alert_if_missing_flags.unmapped_gender
)
)
and exists gender_unchecked_dose_range_list
then
missing_data_type := "";
missing_data_msg := "";
missing_data_alert_abstract := "";
if patient_info.Gender.unknown_other
then
missing_data_msg := "Issue: Unknown Gender
"
|| "This patient{{{SINGLE-QUOTE}}}s gender is "
|| patient_info.Gender.value
|| ". Only a gender of "
|| "MALE or FEMALE can be checked for dosage range.";
missing_data_alert_abstract := "Issue: Unknown Gender";
missing_data_type := issues_str;
elseif patient_info.Gender.is_unmapped
then
missing_data_msg := "Unmapped: Gender
"
|| "Notify your system administrator that the Gender, "
|| patient_info.Gender.value
|| " is not mapped";
missing_data_alert_abstract := "Unmapped: Gender";
missing_data_type := unmapped_data_str;
elseif patient_info.Gender.is_missing
then
missing_data_alert_abstract := "Missing data: Gender";
missing_data_msg := "Missing data: Gender";
missing_data_type := missing_data_str;
endif;
// is the data missing for a contraindication or a dose range?
unchecked_dose_range_type_list :=
( "dose range" where any gender_unchecked_dose_range_list.dosage_type in ("single", "average", "total"),
"contraindication" where any gender_unchecked_dose_range_list.dosage_type in ("contraindication")
);
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "Gender";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := missing_data_type;
missing_data_instance.msg := missing_data_msg;
missing_data_instance.med_name := med_name;
missing_data_instance.unchecked_dose_range_type_list := unchecked_dose_range_type_list;
missing_data_instance.alert_abstract := missing_data_alert_abstract;
missing_data_list := missing_data_list, missing_data_instance;
endif; //if missing_gender
// Determine if missing HEIGHT alert is needed
height_unchecked_dose_range_list := unchecked_dose_range_list WHERE
( unchecked_dose_range_list.height_criteria is not null
OR unchecked_dose_range_list.Is_PER_M2 is not null
);
if ( patient_info.Height.is_missing
or patient_info.Height.not_current )
and alert_if_missing_flags.patient_height
and exists height_unchecked_dose_range_list
then
missing_data_type := "";
missing_data_msg := "";
missing_data_alert_abstract := "";
if patient_info.Height.is_missing
then
missing_data_type := missing_data_str;
missing_data_msg := "Missing data: Height";
missing_data_alert_abstract := "Missing data: Height";
elseif patient_info.Height.not_current
then
missing_data_type := data_not_current_str;
missing_data_msg := "Data not current: Height";
missing_data_alert_abstract := "Data not current: Height";
endif;
// is the data missing for a contraindication or a dose range?
unchecked_dose_range_type_list :=
( "dose range" where any height_unchecked_dose_range_list.dosage_type in ("single", "average", "total"),
"contraindication" where any height_unchecked_dose_range_list.dosage_type in ("contraindication")
);
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "Height";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := missing_data_type;
missing_data_instance.unchecked_dose_range_type_list := unchecked_dose_range_type_list;
missing_data_instance.msg := missing_data_msg;
missing_data_instance.med_name := med_name;
missing_data_instance.alert_abstract := missing_data_alert_abstract;
missing_data_list := missing_data_list, missing_data_instance;
endif; //if patient_info.Height.is_missing
// Determine if missing WEIGHT alert is needed
weight_unchecked_dose_range_list := unchecked_dose_range_list WHERE
( unchecked_dose_range_list.weight_criteria is not null
OR unchecked_dose_range_list.Is_PER_M2 is not null
OR unchecked_dose_range_list.Is_PER_WT is not null
);
if ( patient_info.Weight.is_missing
or patient_info.Weight.not_current )
and alert_if_missing_flags.patient_weight
and exists weight_unchecked_dose_range_list
then
missing_data_type := "";
missing_data_msg := "";
missing_data_alert_abstract := "";
if patient_info.Weight.is_missing
then
missing_data_type := missing_data_str;
missing_data_msg := "Missing data: Weight";
missing_data_alert_abstract := "Missing data: Weight";
elseif patient_info.Weight.not_current
then
//data_not_current_header_list := data_not_current_header_list, "Weight";
missing_data_type := data_not_current_str;
missing_data_msg := "Data not current: Weight";
missing_data_alert_abstract := "Data not current: Weight";
endif;
// is the data missing for a contraindication or a dose range?
unchecked_dose_range_type_list :=
( "dose range" where any weight_unchecked_dose_range_list.dosage_type in ("single", "average", "total"),
"contraindication" where any weight_unchecked_dose_range_list.dosage_type in ("contraindication")
);
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "Weight";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := missing_data_type;
missing_data_instance.msg := missing_data_msg;
missing_data_instance.med_name := med_name;
missing_data_instance.unchecked_dose_range_type_list := unchecked_dose_range_type_list;
missing_data_instance.alert_abstract := missing_data_alert_abstract;
missing_data_list := missing_data_list, missing_data_instance;
endif; //if patient_info.Weight.is_missing
// display alert for unmapped/missing drug
if ( any curr_med_data_list.unmapped_drug
and alert_if_missing_flags.unmapped_drug)
then
missing_data_detail_msg := "Unmapped: Drug
"
|| "Notify your system administrator that the Drug "
|| med_name
|| " is not mapped.";
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "Unmapped Drug";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := "";
missing_data_instance.msg := missing_data_detail_msg;
missing_data_instance.med_name := med_name;
missing_data_instance.unchecked_dose_range_type_list := ("Dose Range");
missing_data_instance.alert_abstract := "Unmapped: Drug";
missing_data_list := missing_data_list, missing_data_instance;
endif; // if ( any med_data_list.unmapped_drug and alert_if_missing_flags.unmapped_drug)
// Determine if missing route alert is needed
// Since a complex order with IV additives can have child orders or IV additives
// with different routes, it{{{SINGLE-QUOTE}}}s possible for multiple routes to be both unmapped and missing.
if ( any curr_med_data_list.missing_route
and alert_if_missing_flags.route
)
then
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "Missing Route";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := med_name;
missing_data_instance.msg := "Missing data: Route";
missing_data_instance.med_name := med_name;
missing_data_instance.details.unchecked_dose_range_type_list := ("dose range");
missing_data_instance.alert_abstract := "Missing data: Route";
missing_data_list := missing_data_list, missing_data_instance;
endif; //if missing_route
// Determine if unmapped route alert is needed
// Since a complex order with IV additives can have child orders or IV additives
// with different routes, it{{{SINGLE-QUOTE}}}s possible for multiple routes to be both unmapped and missing.
if ( any curr_med_data_list.unmapped_route
and alert_if_missing_flags.unmapped_route
)
then
// get the sorted list of routes that are unmapped
unmapped_routes_med_list := curr_med_data_list where
curr_med_data_list.unmapped_route = true;
if exists (unmapped_routes_med_list)
then
missing_data_detail_msg := "Unmapped: Route
"
|| "Notify your system administrator that the";
unmapped_routes_list := sort (unmapped_routes_med_list.order_med_route);
// filter out duplicates
unique_unmapped_routes_list := ();
for item in unmapped_routes_list
do
if item not in unique_unmapped_routes_list
then
unique_unmapped_routes_list := unique_unmapped_routes_list, item;
endif;
enddo;
num_routes := count (unique_unmapped_routes_list);
if num_routes > 1
then
missing_data_detail_msg := missing_data_detail_msg
|| " Routes ";
else
missing_data_detail_msg := missing_data_detail_msg
|| " Route ";
endif;
for ind in (1 seqto num_routes)
do
if ind > 1
then
if ind < num_routes
then
missing_data_detail_msg := missing_data_detail_msg
|| ", ";
else
missing_data_detail_msg := missing_data_detail_msg
|| "and ";
endif;
endif;
missing_data_detail_msg := missing_data_detail_msg
|| ""
|| unique_unmapped_routes_list[ind]
|| "";
enddo;
if num_routes > 1
then
missing_data_detail_msg := missing_data_detail_msg
|| " are not mapped.";
else
missing_data_detail_msg := missing_data_detail_msg
|| " is not mapped.";
endif;
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "Unmapped Route";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := unique_unmapped_routes_list;
missing_data_instance.msg := missing_data_detail_msg;
missing_data_instance.med_name := med_name;
missing_data_instance.details.unchecked_dose_range_type_list := ("dose range");
missing_data_instance.alert_abstract := "Unmapped: Route";
missing_data_list := missing_data_list, missing_data_instance;
endif;
endif; //if unmapped_route
// Route conversion issue
// - unrecognized route
// - inapplicable route
route_conversion_issue_list := ("Unrecognized", "Inapplicable");
for route_conversion_issue in route_conversion_issue_list
do
if route_conversion_issue = "Unrecognized"
then
unrecognized_route_dose_range_list := unchecked_dose_range_list WHERE (
unchecked_dose_range_list.unrecognized_route_conversion_issue = true
);
print_route_issue := (exists unrecognized_route_dose_range_list
and alert_if_missing_flags.cannot_check_generic_route);
route_conversion_dose_range_list := unrecognized_route_dose_range_list;
else
inapplicable_route_dose_range_list := unchecked_dose_range_list WHERE (
unchecked_dose_range_list.inapplicable_route_conversion_issue= true
);
print_route_issue :=(exists inapplicable_route_dose_range_list
and alert_if_missing_flags.inapplicable_route );
route_conversion_dose_range_list := inapplicable_route_dose_range_list;
endif;
if print_route_issue
then
missing_data_type := issues_str;
// Unregonized route
route_conversion_issue_map := med_dosage_map_list WHERE
(med_dosage_map_list.dosage_range_sort_number in route_conversion_dose_range_list.sort_number);
// is the data missing for a contraindication or a dose range?
unchecked_dose_range_type_list :=
( "dose range" where any route_conversion_dose_range_list.dosage_type in ("single", "average", "total"),
"contraindication" where any route_conversion_dose_range_list.dosage_type in ("contraindication")
);
// create the route conversion issue message
route_conversion_map_list := ();
for map_item in route_conversion_issue_map
do
// NOTE - DO NOT USE THE curr_med_data_list or curr_total_tracker_list, curr_average_tracker_list
// here as we are using indexes to look up the item
if (map_item.dosage_type in ("single", "contraindication"))
then
medication_route := med_data_list[map_item.med_sort_number].order_med_route;
elseif (map_item.dosage_type = "total")
then
medication_route := total_tracker_list[map_item.med_sort_number].route;
elseif map_item.dosage_type = "average"
then
medication_route := average_tracker_list[map_item.med_sort_number].route;
endif;
// get the Conversion_Issue_Map_Object from route_conversion_map_list
// for this medication
route_conversion_issue_map_obj := first (route_conversion_map_list
where route_conversion_map_list.medication_val = medication_route
and route_conversion_map_list.med_name = med_name);
if route_conversion_issue_map_obj is null
then
route_conversion_issue_map_obj := new Conversion_Issue_Map_Object;
route_conversion_issue_map_obj.med_name := med_name;
route_conversion_issue_map_obj.medication_val:= medication_route;
route_conversion_issue_map_obj.unconvertible_val_list := ();
route_conversion_map_list := route_conversion_map_list, route_conversion_issue_map_obj;
endif;
dose_range_item := dosage_range_list[map_item.dosage_range_sort_number];
dose_range_route := dose_range_item.route;
if dose_range_route not in route_conversion_issue_map_obj.unconvertible_val_list
then
route_conversion_issue_map_obj.unconvertible_val_list :=
route_conversion_issue_map_obj.unconvertible_val_list, dose_range_route;
endif;
enddo;
// print out the unrecognized routes in alphabetical order
// for the drug
sorted_routes_list := sort(route_conversion_map_list.medication_val);
for sorted_route in sorted_routes_list
do
sorted_route_map_obj := first (route_conversion_map_list
where route_conversion_map_list.medication_val = sorted_route);
sorted_unconvertible_route_list := sort(sorted_route_map_obj.unconvertible_val_list);
sorted_unconvertible_route_str := "";
num_unconvertible_routes := count sorted_unconvertible_route_list;
for ind in (1 seqto num_unconvertible_routes)
do
if ind > 1
then
if ind < num_unconvertible_routes
then
sorted_unconvertible_route_str := sorted_unconvertible_route_str
|| ", ";
else
sorted_unconvertible_route_str := sorted_unconvertible_route_str
|| " and ";
endif;
endif;
sorted_unconvertible_route_str := sorted_unconvertible_route_str
|| ""
|| sorted_unconvertible_route_list[ind]
|| "";
enddo; // for ind in (1 seqto num_unconvertible_routes)
// Generate the message
if route_conversion_issue = "Unrecognized"
then
missing_data_detail_msg := "Issue: Unrecognized Route
"
|| "Please see below dosage ranges for "
|| sorted_unconvertible_route_str
|| " routes of administering the "
|| sorted_route
|| ".";
else
missing_data_detail_msg := "Issue: Inapplicable Route
"
|| "Dosage range information is not available for "
|| ""
|| sorted_route
|| " route."
|| " Please see below dosage ranges for "
|| sorted_unconvertible_route_str
|| " routes of administration.";
endif;
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := route_conversion_issue || " Route";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := route_conversion_map_list;
missing_data_instance.msg := missing_data_detail_msg;
missing_data_instance.med_name := med_name;
missing_data_instance.alert_abstract := "Issue: " || route_conversion_issue ||" Route";
missing_data_instance.details.unchecked_dose_range_type_list := unchecked_dose_range_type_list;
missing_data_list := missing_data_list, missing_data_instance;
enddo; // for sorted_route in sorted_routes_list
endif; //if print_route_issue
enddo; // route_conversion_issue
// display unmapped dose range group alert
if ( any curr_med_data_list.unmapped_grouper
and alert_if_missing_flags.unmapped_grouper)
then
// create one missing_data_object for each string.
missing_data_detail_msg := "Unmapped: Dose Range Group
"
|| "Notify your system administrator that "
|| med_name
|| " is not mapped to a Dose Range Group.";
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "Unmapped Grouper";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := med_name;
missing_data_instance.msg := missing_data_detail_msg;
missing_data_instance.med_name := med_name;
missing_data_instance.alert_abstract := "Unmapped: Dose Range Group";
missing_data_instance.unchecked_dose_range_type_list := ("Dose Range");
missing_data_list := missing_data_list, missing_data_instance;
endif; // if unmapped_grouper
// Determine if missing uom alert is needed
missing_uom_med := curr_med_data_list where curr_med_data_list.missing_uom = true;
missing_uom_med_dose_range_map := med_dosage_map_list
where med_dosage_map_list.med_sort_number in missing_uom_med.sort_number
and med_dosage_map_list.match_found = false;
if ( any curr_med_data_list.missing_uom
and alert_if_missing_flags.uom
and exists missing_uom_med_dose_range_map
)
then
// is the data missing for a contraindication or a dose range?
unchecked_dose_range_type_list :=
( "dose range" where any missing_uom_med_dose_range_map.dosage_type in ("single", "average", "total"),
"contraindication" where any missing_uom_med_dose_range_map.dosage_type in ("contraindication")
);
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "Missing UOM";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := med_name;
missing_data_instance.msg := "Missing data: Unit of Measure";
missing_data_instance.med_name := med_name;
missing_data_instance.alert_abstract := "Missing data: Unit of Measure";
missing_data_instance.details.unchecked_dose_range_type_list := unchecked_dose_range_type_list;
missing_data_list := missing_data_list, missing_data_instance;
endif; //if missing_uom
// Determine if unmapped uom alert is needed
unmapped_uom_med := curr_med_data_list where curr_med_data_list.unmapped_uom = true;
unmapped_uom_med_dose_range_map := med_dosage_map_list
where med_dosage_map_list.med_sort_number in unmapped_uom_med.sort_number
and med_dosage_map_list.match_found = false;
if ( any curr_med_data_list.unmapped_uom
and alert_if_missing_flags.unmapped_uom
and exists unmapped_uom_med_dose_range_map
)
then
// is the data missing for a contraindication or a dose range?
unchecked_dose_range_type_list :=
( "dose range" where any unmapped_uom_med_dose_range_map.dosage_type in ("single", "average", "total"),
"contraindication" where any unmapped_uom_med_dose_range_map.dosage_type in ("contraindication")
);
missing_data_detail_msg := "Unmapped: Unit of Measure
"
|| "Notify your system administrator that the";
// get the sorted list of uoms that are unmapped
unmapped_uom_list := curr_med_data_list
where curr_med_data_list.unmapped_uom = true;
unmapped_uom_list := sort (unmapped_uom_list.order_med_units);
// filter out duplicates
unique_unmapped_uom_list := ();
for item in unmapped_uom_list
do
if item not in unique_unmapped_uom_list
then
unique_unmapped_uom_list := unique_unmapped_uom_list, item;
endif;
enddo;
num_uoms := count (unique_unmapped_uom_list);
if num_uoms > 1
then
missing_data_detail_msg := missing_data_detail_msg
|| " Unit of Measures ";
else
missing_data_detail_msg := missing_data_detail_msg
|| " Unit of Measure ";
endif;
for ind in (1 seqto num_uoms)
do
if ind > 1
then
if ind < num_uoms
then
missing_data_detail_msg := missing_data_detail_msg
|| ", ";
else
missing_data_detail_msg := missing_data_detail_msg
|| "and ";
endif;
endif;
missing_data_detail_msg := missing_data_detail_msg
|| ""
|| unique_unmapped_uom_list[ind]
|| "";
enddo;
if num_uoms > 1
then
missing_data_detail_msg := missing_data_detail_msg
|| " are not mapped.";
else
missing_data_detail_msg := missing_data_detail_msg
|| " is not mapped.";
endif;
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "Unmapped UOM";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := unique_unmapped_uom_list;
missing_data_instance.msg := missing_data_detail_msg;
missing_data_instance.med_name := med_name;
missing_data_instance.alert_abstract := "Unmapped: Unit of Measure";
missing_data_instance.unchecked_dose_range_type_list := unchecked_dose_range_type_list;
missing_data_list := missing_data_list, missing_data_instance;
endif; //if unmapped_uom
// Determine if conversion problem uom alert is needed
uom_issue_dose_range_list := unchecked_dose_range_list
WHERE ( unchecked_dose_range_list.uom_conversion_issue = true);
if ( alert_if_missing_flags.uom_conversion
and exists uom_issue_dose_range_list
)
then
// populate the header criteria
uom_issue_med_dose_range_map := med_dosage_map_list
where ( med_dosage_map_list.match_found = false
and med_dosage_map_list.dosage_range_sort_number in uom_issue_dose_range_list.sort_number
);
// is the data missing for a contraindication or a dose range?
unchecked_dose_range_type_list :=
( "dose range" where any uom_issue_med_dose_range_map.dosage_type in ("single", "average", "total"),
"contraindication" where any uom_issue_med_dose_range_map.dosage_type in ("contraindication")
);
// create the unit of measure conversion issue message
uom_conversion_map_list := ();
for map_item in uom_issue_med_dose_range_map
do
if (map_item.dosage_type = "single")
then
medication_unit := med_data_list[map_item.med_sort_number].order_med_units;
elseif (map_item.dosage_type = "total")
then
medication_unit := total_tracker_list[map_item.med_sort_number].uom;
elseif map_item.dosage_type = "average"
then
medication_unit := average_tracker_list[map_item.med_sort_number].uom;
endif;
// get the Conversion_Issue_Map_Object from uom_conversion_map_list
// for this medication
uom_conversion_issue_map_obj := first (uom_conversion_map_list
where uom_conversion_map_list.medication_val = medication_unit);
if uom_conversion_issue_map_obj is null
then
uom_conversion_issue_map_obj := new Conversion_Issue_Map_Object;
uom_conversion_map_list := uom_conversion_map_list, uom_conversion_issue_map_obj;
uom_conversion_issue_map_obj.medication_val:= medication_unit;
uom_conversion_issue_map_obj.unconvertible_val_list := ();
endif;
dose_range_item := dosage_range_list[map_item.dosage_range_sort_number];
dose_range_uom := dose_range_item.unit_of_measure;
if dose_range_uom not in uom_conversion_issue_map_obj.unconvertible_val_list
then
uom_conversion_issue_map_obj.unconvertible_val_list :=
uom_conversion_issue_map_obj.unconvertible_val_list, dose_range_uom;
endif;
enddo;
// construct the messages in alphabetical order
sorted_order_med_units_list := sort(uom_conversion_map_list.medication_val);
for sorted_order_med_unit in sorted_order_med_units_list
do
sorted_uom_conversion_map_obj := first (uom_conversion_map_list
where uom_conversion_map_list.medication_val = sorted_order_med_unit);
missing_data_detail_msg := "Issue: Unit of measure conversion
"
|| "The current Unit of Measure, "
|| sorted_order_med_unit
|| " cannot be converted to ";
sorted_unconvertible_uom_list := sort(sorted_uom_conversion_map_obj.unconvertible_val_list);
num_unconvertible_uoms := count sorted_unconvertible_uom_list;
for ind in (1 seqto num_unconvertible_uoms)
do
if ind > 1
then
if ind < num_unconvertible_uoms
then
missing_data_detail_msg := missing_data_detail_msg
|| ", ";
else
missing_data_detail_msg := missing_data_detail_msg
|| " or ";
endif;
endif;
missing_data_detail_msg := missing_data_detail_msg
|| ""
|| sorted_unconvertible_uom_list[ind]
|| "";
enddo;
enddo;
missing_data_instance := new Missing_Data_Object;
missing_data_instance.criteria := "UOM Conversion Issue";
missing_data_instance.missing_data_error := true;
missing_data_instance.details := uom_conversion_map_list;
missing_data_instance.unchecked_dose_range_type_list := unchecked_dose_range_type_list;
missing_data_instance.msg := missing_data_detail_msg;
missing_data_instance.alert_abstract := "Issue: Unit of measure conversion";
missing_data_instance.med_name := med_name;
missing_data_list := missing_data_list, missing_data_instance;
endif; //if unit of conversion issue
endif; //if patient_info.Age.is_missing
enddo; // for med_name in medication_name_list
//----------------------------------------
// Assemble the BODY of the Alert Message
//----------------------------------------
// Initialize Variable
alert_detail_text := "";
//-------------------------------------------
// Assemble the HEADER of the Alert Message
//-------------------------------------------
// Prevent NULL from printing in the Frequency
//--------------------------------------------
if exist med_data_list[1].order_med_frequency
then
printable_order_med_frequency := " " || med_data_list[1].order_med_frequency;
if med_data_list[1].stop_after_value is not null
and med_data_list[1].stop_after_value > 0
and med_data_list[1].stop_after_option_type > 0
then
printable_order_med_frequency := printable_order_med_frequency
|| " x " || med_data_list[1].stop_after_value
|| " " || stop_after_type_list[med_data_list[1].stop_after_option_type];
endif;
else
printable_order_med_frequency := "";
endif; // if exist order_med_frequency
if exists med_data_list[1].order_med_route
then
printable_order_med_route := med_data_list[1].order_med_route;
else
printable_order_med_route := "";
endif;
// Set Dosage_Ordered
//--------------------
// If the lower dose and the upper dose are the same, print a singleton value
// If the lower dose adn the upper dose are not equal, then print a range
if exists med_data_list[1].order_med_units
then
printable_order_med_units := med_data_list[1].order_med_units;
else
printable_order_med_units := "";
endif;
if med_data_list[1].order_med_dose_low = med_data_list[1].order_med_dose_high
then
formated_order_med_dose_low := call add_commas with (,med_data_list[1].order_med_dose_low);
dosage_ordered:= formated_order_med_dose_low || " " || printable_order_med_units;
elseif order_med_dose_low <> order_med_dose_high
then
formated_order_med_dose_low := call add_commas with (,med_data_list[1].order_med_dose_low);
formated_order_med_dose_high := call add_commas with (,med_data_list[1].order_med_dose_high);
dosage_ordered:= formated_order_med_dose_low || " - "
|| formated_order_med_dose_high || " " || printable_order_med_units;
else
dosage_ordered:= "";
endif; //if med_data_list[1].order_med_dose_low
//------------------------------------------------------------------------------
// [New born birth-time missing]: Construct Missing birth time table
//------------------------------------------------------------------------------
birthtime_missing_detail_msg := "";
if has_alert_on_estimated_birthtime = true
then
if estimated_age_hours < 24
then
estimated_birthtimes := "Less than " || estimated_age_hours || " hour(s)";
else
estimated_birthtimes := "Between " || estimated_age_min_hours || "-" || estimated_age_hours || " hour(s)";
endif;
birthtime_missing_detail_msg := "Missing data: Birth-time"
|| "
";
endif;
//------------------------------------------------------------------------------
// Construct Contraindications table
//------------------------------------------------------------------------------
contraindication_detail_msg := "";
if any med_data_list.contraindication_found
then
patient_criteria_list := (
patient_info.Age,
(new Patient_Property_Obj with "Route"), // dummy entry to help build the table
patient_info.Weight,
patient_info.Gender,
patient_info.Renal,
patient_info.Creatinine,
patient_info.Liver
);
contraindication_dosage_range_list := dosage_range_list
where (dosage_range_list.match_found = true and
dosage_range_list.dosage_type in ("contraindication") );
for contraindication_dosage_range in contraindication_dosage_range_list
do
for_drug_str := "";
if is_iv_additive
then
for_drug_str := "For "
|| contraindication_dosage_range.med_name
|| ": ";
endif;
//--------------------------------------------------------
// construct the contraindication detail message
contraindication_detail_msg := contraindication_detail_msg
|| for_drug_str
|| contraindication_dosage_range.contraindication_msg;
// contraindication_criteria_headings and contraindication_criteria_list
// These two lists must be in sync
contraindication_criteria_list := (
contraindication_dosage_range.age_criteria,
contraindication_dosage_range.route,
contraindication_dosage_range.weight_criteria,
contraindication_dosage_range.gender_criteria,
contraindication_dosage_range.renal_criteria,
contraindication_dosage_range.creatinine_criteria,
contraindication_dosage_range.liver_criteria
);
if exist contraindication_criteria_list
then
// conditions table and patient info table
contraindication_detail_msg := contraindication_detail_msg
|| ""
|| ""
|| "| Conditions | "
|| "This Patient | "
|| "
";
indices := 1 seqto count contraindication_criteria_list;
for ind in indices
do
criteria_heading := contraindication_criteria_headings[ind];
criteria_val := contraindication_criteria_list[ind];
patient_info_obj := patient_criteria_list[ind];
patient_criteria_val := "";
// Create contraindication criteria listing
// e.g. "Age: <=12 years"
if exists criteria_val
then
if exist patient_info_obj
then
patient_criteria_val := "";
if (patient_info_obj.Type = "Route")
then
patient_criteria_val := patient_criteria_val
|| med_data_list[1].order_med_route;
elseif( patient_info_obj.TYPE = "Age"
and (contraindication_dosage_range.estimated_age_used = 1 or
contraindication_dosage_range.estimated_age_used = 2) )
then
//Using AgeMin or AgeMax in hours
patient_criteria_val := patient_criteria_val
|| contraindication_dosage_range.patient_age_at_order;
else
patient_criteria_val := patient_criteria_val
|| patient_info_obj.Value;
endif;
if patient_info_obj.TYPE = "Weight"
then
patient_criteria_val := patient_criteria_val
|| " kg";
endif;
if patient_info_obj.TYPE = "Creatinine"
then
patient_criteria_val := patient_criteria_val
|| " mL/min";
endif;
patient_criteria_val := patient_criteria_val
|| "";
if (patient_info_obj.type not in ("Gender", "Age"))
and patient_info_obj.Date is not null
then
// convert patient info date/time to evoking object{{{SINGLE-QUOTE}}}s visit time zone to support MTZ
patient_criteria_val := patient_criteria_val
|| "(" || (patient_info_obj.Date AS TIME visit_time_zone) formatted with "%.4t" || ")";
endif;
endif;
// fix this later when have time to go through contraindication headings
contraindication_detail_msg := contraindication_detail_msg
|| "| "
|| criteria_heading
|| criteria_val
|| " | "
|| ""
|| patient_criteria_val
|| " |
";
endif;
enddo;
contraindication_detail_msg := contraindication_detail_msg
|| "
";
endif; // if exist contraindication_criteria_list
contraindication_detail_msg := contraindication_detail_msg || "
";
enddo;
endif;
////////////////////////////////////////////
// Construct alert message headings and
// alert abstract components
////////////////////////////////////////////
// initialize warning count list
warning_count_list := ();
//[New born birth-time missing]: add warning object for estimated age warning
if has_alert_on_estimated_birthtime = true
then
if warning_count_instance_estimated_age is null
then
if medication_name_list is not null
then
med_name := medication_name_list[1];
endif;
warning_count_instance_estimated_age := new Warning_Count_Object;
warning_count_instance_estimated_age.med_name := med_name;
warning_count_instance_estimated_age.warning_count := 1;
warning_count_list := warning_count_list, warning_count_instance_estimated_age;
endif;
endif;
// construct the "dose range and contraindications could not be checked" header
dose_range_not_checked_header := "";
alert_abstract_dose_range_not_checked := "";
if exists missing_data_list
or exists cannot_check_list
then
dose_range_not_checked_header := "DOSE RANGE ";
alert_abstract_dose_range_not_checked := "DOSE RANGE ";
if any missing_data_list.unchecked_dose_range_type_list in ("contraindication")
then
dose_range_not_checked_header := dose_range_not_checked_header
|| "and CONTRAINDICATIONS ";
alert_abstract_dose_range_not_checked := alert_abstract_dose_range_not_checked
|| "and CONTRAINDICATIONS ";
endif;
dose_range_not_checked_header := dose_range_not_checked_header
|| "could NOT be CHECKED
\n"
|| "";
alert_abstract_dose_range_not_checked := alert_abstract_dose_range_not_checked
|| "could NOT be CHECKED. ";
// add messages in missing_data_list underneath header
// as a bulleted list
for med_name in medication_name_list
do
// print drug name if multiple drugs are being checked
for_drug_str := "";
alert_abstract_for_drug_str := "";
if is_iv_additive
then
for_drug_str := "For "
|| med_name
|| ": ";
alert_abstract_for_drug_str := "For "
|| med_name
|| ": ";
endif;
// print out the missing data objects for this medication
med_missing_data_list := missing_data_list where
missing_data_list.med_name = med_name;
for missing_data_item in med_missing_data_list
do
dose_range_not_checked_header := dose_range_not_checked_header
|| "- "
|| for_drug_str
|| missing_data_item.msg
|| "
";
alert_abstract_dose_range_not_checked := alert_abstract_dose_range_not_checked
|| alert_abstract_for_drug_str
|| missing_data_item.alert_abstract
|| ". ";
enddo;
// print out the cannot check objects for this medication
med_cannot_check_list := cannot_check_list where
cannot_check_list.med_name_list = med_name;
for cannot_check_item in med_cannot_check_list
do
dose_range_not_checked_header := dose_range_not_checked_header
|| "- "
|| for_drug_str
|| cannot_check_item.alert_msg_for_cannot_check
|| "
";
alert_abstract_dose_range_not_checked := alert_abstract_dose_range_not_checked
|| alert_abstract_for_drug_str
|| cannot_check_item.alert_abstract
|| ". ";
enddo;
// increment the warning count
warning_count_instance := last (warning_count_list where
warning_count_list.med_name
= med_name);
if warning_count_instance is null
then
warning_count_instance := new Warning_Count_Object;
warning_count_instance.med_name := med_name;
warning_count_instance.warning_count := 0;
warning_count_list := warning_count_list, warning_count_instance;
endif;
warning_count_instance.warning_count :=
warning_count_instance.warning_count
+ count(med_missing_data_list)
+ count(med_cannot_check_list);
enddo;
dose_range_not_checked_header := dose_range_not_checked_header
|| "
";
endif;
// construct the "Frequency could not be checked" header
frequency_not_checked_header := "";
alert_abstract_frequency_not_checked := "";
if exists frequency_unchecked_list
then
frequency_not_checked_header := "FREQUENCY "
|| "could NOT be CHECKED
\n"
|| "";
alert_abstract_frequency_not_checked := "FREQUENCY could NOT be CHECKED. ";
// add messages in missing_data_list underneath header
// as a bulleted list
for med_name in medication_name_list
do
// print drug name if multiple drugs are being checked
for_drug_str := "";
alert_abstract_for_drug_str := "";
if is_iv_additive
then
for_drug_str := "For "
|| med_name
|| ": ";
alert_abstract_for_drug_str := "For "
|| med_name
|| ": ";
endif;
// print out the missing data objects for this medication
med_frequency_unchecked_list := frequency_unchecked_list where
frequency_unchecked_list.med_name = med_name;
for med_frequency_unchecked_item in med_frequency_unchecked_list
do
frequency_not_checked_header := frequency_not_checked_header
|| "- "
|| for_drug_str
|| med_frequency_unchecked_item.msg
|| "
";
alert_abstract_frequency_not_checked := alert_abstract_frequency_not_checked
|| alert_abstract_for_drug_str
|| med_frequency_unchecked_item.alert_abstract
|| ". ";
enddo;
// increment the warning count
warning_count_instance := last (warning_count_list where
warning_count_list.med_name
= med_name);
if warning_count_instance is null
then
warning_count_instance := new Warning_Count_Object;
warning_count_instance.med_name := med_name;
warning_count_instance.warning_count := 0;
warning_count_list := warning_count_list, warning_count_instance;
endif;
warning_count_instance.warning_count :=
warning_count_instance.warning_count
+ count(med_frequency_unchecked_list);
enddo;
frequency_not_checked_header := frequency_not_checked_header
|| "
";
endif;
//[New born birth-time missing]: determine if alert is using estimated age
estimated_birthtime_header := "";
alert_abstract_estimated_birthtime := "";
if has_alert_on_estimated_birthtime = true
then
if estimated_age_hours < 24
then
estimated_birthtimes := "less than " || estimated_age_hours || " hour(s)";
else
estimated_birthtimes := estimated_age_min_hours || "-" || estimated_age_hours || " hour(s)";
endif;
estimated_birthtime_header := estimated_birthtime_header
|| "NEWBORN EXACT AGE IS ESTIMATED
"
|| "- Missing data: Birth-time
Dose range checked using estimated ages of "
|| estimated_birthtimes
|| ".
"
|| "The details of which age the alert applies to, is provided later in the alert message.
";
alert_abstract_estimated_birthtime := alert_abstract_estimated_birthtime
|| "NEWBORN EXACT AGE IS ESTIMATED. "
|| "Missing data: Birth-time. Dose range checked using estimated ages of "
|| estimated_birthtimes || ". "
|| "The details of which age the alert applies to, is provided later in the alert message.";
endif;
// CONTRAINDICATED header
contraindicated_header := "";
alert_abstract_contraindicated := "";
if any med_data_list.contraindication_found
then
contraindicated_header := "CONTRAINDICATED
\n";
alert_abstract_contraindicated := "CONTRAINDICATED. ";
// for each medication, print out the contraindications
for med_name in medication_name_list
do
for_drug_str := "";
alert_abstract_for_drug_str := "";
if is_iv_additive
then
for_drug_str := "For "
|| med_name
|| ": ";
alert_abstract_for_drug_str := "For "
|| med_name
|| ": ";
endif;
contraindication_list := dosage_range_list where
dosage_range_list.dosage_type = "contraindication"
and dosage_range_list.med_name = med_name
and dosage_range_list.match_found = true;
for contraindication_item in contraindication_list
do
contraindicated_header := contraindicated_header
|| "- "
|| for_drug_str
|| contraindication_item.contraindication_msg
|| "
";
alert_abstract_contraindicated := alert_abstract_contraindicated
|| alert_abstract_for_drug_str
|| contraindication_item.contraindication_msg
|| ". ";
enddo;
// increment the warning count
warning_count_instance := last (warning_count_list where
warning_count_list.med_name
= med_name);
if warning_count_instance is null
then
warning_count_instance := new Warning_Count_Object;
warning_count_instance.med_name := med_name;
warning_count_instance.warning_count := 0;
warning_count_list := warning_count_list, warning_count_instance;
endif;
warning_count_instance.warning_count :=
warning_count_instance.warning_count
+ count(contraindication_list);
enddo;
contraindicated_header := contraindicated_header
|| "
\n";
endif;
// Too Frequent header
too_frequent_header := "";
alert_abstract_too_frequent := "";
if any (med_dosage_map_list.frequency_issue = dose_too_frequent)
then
too_frequent_header := too_frequent_header
|| "FREQUENCY INTERVAL TOO SHORT
";
alert_abstract_too_frequent := alert_abstract_too_frequent
|| "FREQUENCY INTERVAL TOO SHORT. ";
// get the case item objects for multum dose ranges.
case_list := Case_Info_list where
Case_Info_list.case_type = "dose range"
and Case_Info_list.is_multum = true;
for case_item in case_list
do
// get all the med-dose range map objects attached to the case
// for the specified medication
case_map_list := med_dosage_map_list where
med_dosage_map_list.sort_number
in case_item.map_sort_number
and med_dosage_map_list.dosage_type in ("single")
and med_dosage_map_list.match_found = true
and med_dosage_map_list.frequency_issue = dose_too_frequent;
if exists case_map_list
then
too_frequent_str := "";
alert_abstract_too_frequent_str := "";
// get the list of frequencies from the map objects
frequency_list := case_map_list.dose_frequency;
for_drug_str := "";
alert_abstract_for_drug_str := "";
if is_iv_additive
then
for_drug_str := "For "
|| case_item.med_name
|| ": ";
alert_abstract_for_drug_str := "For "
|| case_item.med_name
|| ": ";
endif;
// add frequency warnings to the header
for frequency_item in frequency_list
do
too_frequent_header := too_frequent_header
|| "- "
|| for_drug_str
|| "Frequency: This dosing interval should not be more frequent than "
|| ""
|| frequency_item
|| " "
|| case_item.based_on_header_text
|| "
";
alert_abstract_too_frequent := alert_abstract_too_frequent
|| alert_abstract_for_drug_str
|| "This dosing interval should not be more frequent than "
|| frequency_item
|| " "
|| case_item.based_on_header_text
|| ". ";
enddo;
// increment the warning count with number of frequency warnings
warning_count_instance := last (warning_count_list where
warning_count_list.med_name
= case_item.med_name);
// get the warning item for this med object
// and add number of warnings to the total
if warning_count_instance is null
then
warning_count_instance := new Warning_Count_Object;
warning_count_instance.med_name := case_item.med_name;
warning_count_instance.warning_count := 0;
warning_count_list := warning_count_list, warning_count_instance;
endif;
warning_count_instance.warning_count :=
warning_count_instance.warning_count
+ count(frequency_list);
endif;
enddo;
too_frequent_header := too_frequent_header
|| "
\n";
endif;
// OUTSIDE USUAL DOSE RANGE header
outside_dose_range_header := "";
alert_abstract_outside_dose_range := "";
if any med_dosage_map_list.above_range or any med_dosage_map_list.below_range
then
outside_dose_range_header := outside_dose_range_header
|| "OUTSIDE USUAL DOSE RANGE
";
alert_abstract_outside_dose_range := alert_abstract_outside_dose_range
|| "OUTSIDE USUAL DOSE RANGE. ";
// get the case item objects for dose ranges
case_list := Case_Info_list where
Case_Info_list.case_type = "dose range";
for case_item in case_list
do
// get all the med-dose range map objects attached to the case
// for the specified medication
case_map_list := med_dosage_map_list where
med_dosage_map_list.sort_number
in case_item.map_sort_number
and med_dosage_map_list.dosage_type <> "contraindication"
and med_dosage_map_list.match_found = true
and ( med_dosage_map_list.above_range
or med_dosage_map_list.below_range);
if exist case_map_list
then
exceeds_and_below_str := "";
alert_abstract_exceeds_and_below_str := "";
if all case_map_list.above_range
then
exceeds_and_below_str := "Exceeds maximum ";
alert_abstract_exceeds_and_below_str := "Exceeds maximum ";
elseif all case_map_list.below_range
then
exceeds_and_below_str := "Below minimum ";
alert_abstract_exceeds_and_below_str := "Below minimum ";
elseif ( any case_map_list.above_range
AND any case_map_list.below_range)
then
// if both exceed and below range, then, it{{{SINGLE-QUOTE}}}s a special case
if (any (med_data_list.med_order_type = "Complex Order"))
then
exceeds_and_below_str := "Exceeds and Below ranges ";
alert_abstract_exceeds_and_below_str := "Exceeds and Below ranges ";
else
// construct the dose-type string for Exceeds sub-string
exceeds_dose_type_str := "";
if exists (case_map_list where case_map_list.above_range
and case_map_list.dosage_type = "single")
then
exceeds_dose_type_str := "Single Dose";
endif;
if exists (case_map_list where case_map_list.above_range
and case_map_list.dosage_type = "total")
then
if exceeds_dose_type_str <> ""
then
exceeds_dose_type_str := exceeds_dose_type_str || ", ";
endif;
exceeds_dose_type_str := exceeds_dose_type_str
|| "Total Daily Dose";
endif;
if exists (case_map_list where case_map_list.above_range
and case_map_list.dosage_type = "average")
then
if exceeds_dose_type_str <> ""
then
exceeds_dose_type_str := exceeds_dose_type_str || ", ";
endif;
exceeds_dose_type_str := exceeds_dose_type_str
|| "Average Daily Dose";
endif;
// construct the dose-type string for Below sub-string
below_dose_type_str := "";
// append single, total and daily strings
if exists (case_map_list where case_map_list.below_range
and case_map_list.dosage_type = "single")
then
below_dose_type_str := "Single Dose";
endif;
if exists (case_map_list where case_map_list.below_range
and case_map_list.dosage_type = "total")
then
if below_dose_type_str <> ""
then
below_dose_type_str := below_dose_type_str || ", ";
endif;
below_dose_type_str := below_dose_type_str
|| "Total Daily Dose";
endif;
if exists (case_map_list where case_map_list.below_range
and case_map_list.dosage_type = "average")
then
if below_dose_type_str <> ""
then
below_dose_type_str := below_dose_type_str || ", ";
endif;
below_dose_type_str := below_dose_type_str
|| "Average Daily Dose";
endif;
// finish constructing the entire string
exceeds_and_below_str := "Exceeds maximum "
|| exceeds_dose_type_str
|| " and Below minimum "
|| below_dose_type_str
|| " ";
alert_abstract_exceeds_and_below_str := "Exceeds maximum "
|| exceeds_dose_type_str
|| " and Below minimum "
|| below_dose_type_str
|| " ";
endif;
endif;
for_drug_str := "";
alert_abstract_for_drug_str := "";
if is_iv_additive
then
for_drug_str := "For "
|| case_item.med_name
|| ": ";
alert_abstract_for_drug_str := "For "
|| case_item.med_name
|| ": ";
endif;
outside_dose_range_header := outside_dose_range_header
|| "- "
|| for_drug_str
|| exceeds_and_below_str
|| case_item.based_on_header_text
|| "
";
alert_abstract_outside_dose_range := alert_abstract_outside_dose_range
|| alert_abstract_for_drug_str
|| alert_abstract_exceeds_and_below_str
|| case_item.based_on_header_text
|| ". ";
// increment the warning count
warning_count_instance := last (warning_count_list where
warning_count_list.med_name
= case_item.med_name);
// get the warning item for this med object
// and add number of warnings to the total
if warning_count_instance is null
then
warning_count_instance := new Warning_Count_Object;
warning_count_instance.med_name := case_item.med_name;
warning_count_instance.warning_count := 0;
warning_count_list := warning_count_list, warning_count_instance;
endif;
warning_count_instance.warning_count :=
warning_count_instance.warning_count + 1;
endif; //if exist case_map_list
enddo;
outside_dose_range_header := outside_dose_range_header
|| "
\n";
endif;
//------------------------------
// Create Medication Description with warning count
//------------------------------
alert_med_description:= "";
// stores warnings to be appended to the alert abstract text
alert_abstract_warnings := "";
if any (med_data_list.med_order_type in ("Complex Order", "IV-Additive"))
then
if any (med_data_list.med_order_type in ("Complex Order"))
then
// get the complex order item
med_complex_order := last ( med_data_list
where med_data_list.med_order_type = "Complex Order"
and ( med_data_list.is_iv_additive is null
or med_data_list.is_iv_additive = false ) );
// get the number of warnings for this med object
warning_count_instance := last (warning_count_list where
warning_count_list.med_name
= med_complex_order.order_med_name);
warning_msg := warning_count_instance.warning_count as string;
if (warning_count_instance.warning_count > 1)
then
warning_msg := warning_msg
|| " warnings for ";
else
warning_msg := warning_msg
|| " warning for ";
endif;
// Create a COMPLEX ORDER header message
alert_med_description:= alert_med_description
|| ""
|| warning_msg
|| "";
alert_abstract_warnings := alert_abstract_warnings
|| warning_msg
|| med_complex_order.order_med_name
|| ". ";
endif;
// Check if it is a Complex Order with IV-Additives in the Master Order
alert_abstract_iv_additive := "";
if any (med_data_list.is_iv_additive = true)
then
iv_solution_med_description := "";
// get the base solution single order
med_iv_base_soln := last ( med_data_list
where med_data_list.med_order_type = "IV-Additive"
and ( med_data_list.is_iv_additive is null
or med_data_list.is_iv_additive = false ) );
iv_additives_list := med_data_list
where (med_data_list.is_iv_additive = true);
// build a list containing unique iv additive items sorted
// by name
iv_additives_list := sort (iv_additives_list.order_med_name);
//Create an IV-ADDITIVE header message
num_additives := count(iv_additives_list);
for iv_additives_ind in (1 seqto num_additives)
do
iv_additive_header_modified := false;
if iv_additives_ind = 1
then
iv_solution_med_description:= iv_solution_med_description
|| ""
|| iv_additives_list[iv_additives_ind]
|| "";
alert_abstract_iv_additive := alert_abstract_iv_additive
|| iv_additives_list[iv_additives_ind];
iv_additive_header_modified := true;
elseif ( ( iv_additives_ind > 1 )
and ( iv_additives_list[iv_additives_ind]
<> iv_additives_list[iv_additives_ind - 1] ) )
then
if ( iv_additives_list[iv_additives_ind]
= iv_additives_list[num_additives] )
then
iv_solution_med_description:= iv_solution_med_description
|| " and ";
alert_abstract_iv_additive := alert_abstract_iv_additive
|| " and ";
elseif (iv_additives_ind < num_additives)
then
iv_solution_med_description:= iv_solution_med_description
|| ", ";
alert_abstract_iv_additive := alert_abstract_iv_additive
|| ", ";
endif;
iv_solution_med_description:= iv_solution_med_description
|| ""
|| iv_additives_list[iv_additives_ind]
|| "";
alert_abstract_iv_additive := alert_abstract_iv_additive
|| iv_additives_list[iv_additives_ind];
iv_additive_header_modified := true;
endif;
enddo;
if (alert_med_description <> "")
then
alert_med_description := alert_med_description
|| "
";
endif;
// add up the number of warnings for the iv additives
iv_additive_warning_total := sum (warning_count_list.warning_count
where warning_count_list.med_name
in iv_additives_list);
warning_msg := iv_additive_warning_total as string;
if (iv_additive_warning_total > 1)
then
warning_msg := warning_msg
|| " warnings for ";
else
warning_msg := warning_msg
|| " warning for ";
endif;
alert_med_description:= alert_med_description
|| ""
|| warning_msg
|| "";
alert_abstract_warnings := alert_abstract_warnings
|| ". ";
endif; //if any (med_data_list.med_order_type = "IV-Additive")
else // Regular orders and prescriptions
warning_msg := warning_count_instance[1].warning_count as string;
if (warning_count_instance.warning_count > 1)
then
warning_msg := warning_msg
|| " warnings for ";
else
warning_msg := warning_msg
|| " warning for ";
endif;
// Create a REGULAR medication header message
alert_med_description:= ""
|| warning_msg
|| ""
|| " " || dosage_ordered
|| " " || printable_order_med_route
|| printable_order_med_frequency
|| "";
alert_abstract_warnings := alert_abstract_warnings
|| warning_msg
|| med_data_list[1].order_med_name
|| " " || dosage_ordered
|| " " || printable_order_med_route
|| printable_order_med_frequency
|| ". ";
endif; // if med_order_type is in ("IV-Additive", "Complex Order")
//----------------------------------------------
// Put the pieces of the Header Message together
//----------------------------------------------
// insert warning message at top of alert
alert_heading_text := alert_med_description
|| "
"
|| estimated_birthtime_header
|| contraindicated_header
|| outside_dose_range_header
|| dose_range_not_checked_header
|| frequency_not_checked_header
|| too_frequent_header
|| "
";
//----------------------------------------------
// Put the pieces of the Alert Abstract together
//----------------------------------------------
alert_abstract := alert_abstract_warnings
|| alert_abstract_estimated_birthtime
|| alert_abstract_contraindicated
|| alert_abstract_outside_dose_range
|| alert_abstract_dose_range_not_checked
|| alert_abstract_frequency_not_checked
|| alert_abstract_too_frequent;
//-------------------------------------------
// Assemble the Patient Details
//-------------------------------------------
patient_details_header_text := "SUPPLEMENTAL INFORMATION:
"
|| "If entering a medication for a future date, note that the dose calculation "
|| "is based on the following information available at the time of entry.
";
// display the patient{{{SINGLE-QUOTE}}}s birthday and birth time
patient_birthdate_str := "";
patient_birthtime_str := "";
if exists birthday
then
PatientBirthDateObj := birthday as {{{SINGLE-QUOTE}}}System.DateTime{{{SINGLE-QUOTE}}};
if (birth_month_num = 0)
then
// only display the year if there is no month
patient_birthdate_str := call PatientBirthDateObj.ToString with "yyyy";
elseif (birth_day_num = 0)
then
// in this case, the month and year will exist
patient_birthdate_str := call PatientBirthDateObj.ToString with partial_composite_date_format;
else
// in this case, the entire date will exist
patient_birthdate_str := call PatientBirthDateObj.ToString with composite_date_format;
endif;
patient_details_header_text := patient_details_header_text
|| "Birthdate = "
|| patient_birthdate_str;
// only show the birth time if the age is less than one month
patient_age_in_months := (Now - birthday)/(1 month);
if exists birthtime and patient_age_in_months < 1
then
// Update the birthday to include birthtime
birth_time := (birthtime as time);
PatientBirthTimeObj := birth_time as {{{SINGLE-QUOTE}}}System.DateTime{{{SINGLE-QUOTE}}};
patient_birthtime_str := call PatientBirthTimeObj.ToString with time_format;
patient_details_header_text := patient_details_header_text
|| " at " || patient_birthtime_str || " (birth time)";
endif;
patient_details_header_text := patient_details_header_text
|| "
";
endif;
patient_properties := (
patient_info.Weight,
patient_info.Height,
patient_info.BSA,
patient_info.Gender,
patient_info.Liver,
patient_info.Renal,
patient_info.Creatinine,
patient_info.ICD9_List);
patient_other_details_txt := "";
for patient_property in patient_properties
do
if exists patient_property and exists patient_property.value
then
patient_other_details_txt := patient_other_details_txt
|| "";
// display the type of patient info property
if patient_property.type = "Creatinine"
then
patient_other_details_txt := patient_other_details_txt
|| "Creatinine Clearance = ";
else
patient_other_details_txt := patient_other_details_txt
|| patient_property.type || " = ";
endif;
patient_other_details_txt := patient_other_details_txt
|| patient_property.value;
// add units to end of patient info property value if required
if (patient_property.type = "Weight")
then
patient_other_details_txt := patient_other_details_txt
|| " kg";
elseif (patient_property.type = "Height")
then
patient_other_details_txt := patient_other_details_txt
|| " cm";
elseif (patient_property.type = "BSA")
then
patient_other_details_txt := patient_other_details_txt
|| " M2";
elseif (patient_property.type = "Creatinine")
then
patient_other_details_txt := patient_other_details_txt
|| " mL/min";
endif;
if (patient_property.type not in ("Gender", "BSA")
and patient_property.date is not null)
then
// convert patient property date/time to evoking object{{{SINGLE-QUOTE}}}s visit time zone to support MTZ
patient_other_details_txt := patient_other_details_txt
|| " (" || (patient_property.date AS TIME visit_time_zone) formatted with "%.4t" || ")";
endif;
patient_other_details_txt := patient_other_details_txt
|| "
\n";
endif;
enddo;
patient_details_text := patient_details_header_text
|| patient_other_details_txt;
//--------------------------------
// Assemble Entire Alert Message
//--------------------------------
dosage_outside_range_details := "\n";
for dosage_outside_range_table in dosage_outside_range_table_list
do
dosage_outside_range_details := dosage_outside_range_details
|| dosage_outside_range_table
|| "
";
enddo;
supplemental_data := "";
if (patient_info.DNum_Grouper.is_unmapped
and alert_if_missing_flags.cannot_check_DNUM_Rx_to_Multum
)
then
supplemental_data := "
"
|| supplemental_grouper_names;
endif;
if exists supplemental_table_list
then
supplemental_data := supplemental_data || "
";
for supplemental_table_item in supplemental_table_list
do
supplemental_data := supplemental_data
|| supplemental_table_item.msg
|| "
";
enddo;
endif;
standard_ccs := call CCS_MLM;
alert_detail_text := "" || standard_ccs || "\n"
|| alert_heading_text
|| birthtime_missing_detail_msg
|| contraindication_detail_msg
|| dosage_outside_range_details
|| patient_details_text
|| supplemental_data
|| "\n";
// Always Conclude True
conclude true;
;;
action:
return
alert_detail_text,
missing_data_list,
cannot_check_list,
alert_abstract;
;;
end: