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

1972 lines
85 KiB
Plaintext

maintenance:
title: Checks the Single, Average-Daily, and Total-Daily Dose Ranges;;
mlmname: STD_FUNC_DOSAGE_RULES;;
arden: version 2.5;;
version: 18.4;;
institution: Allscripts, Standard MLM;;
author: Allscripts Healthcare Solutions, Inc.;;
specialist: ;;
date: 2018-10-26;;
validation: testing;;
/* P r o p r i e t a r y N o t i c e */
/* Unpublished (c) 2013 - 2018 Allscripts Healthcare, LLC. and/or its affiliates. All Rights Reserved.
P r o p r i e t a r y N o t i c e: This software has been provided pursuant to a License Agreement, with
Allscripts Healthcare, LLC. and/or its affiliates, containing restrictions on its use. This software contains
valuable trade secrets and proprietary information of Allscripts Healthcare, LLC. and/or its affiliates and is
protected by trade secret and copyright law. This software may not be copied or distributed in any form or medium,
disclosed to any third parties, or used in any manner not provided for in said License Agreement except with prior
written authorization from Allscripts Healthcare, LLC. and/or its affiliates. Notice to U.S. Government Users:
This software is {{{SINGLE-QUOTE}}}Commercial Computer Software{{{SINGLE-QUOTE}}}.
All product names are the trademarks or registered trademarks of Allscripts Healthcare, LLC. and/or its affiliates.
*/
/* P r o p r i e t a r y N o t i c e */
library:
purpose: The MLM assists the STD_Dosage MLM to determine if a medication dose
may be out of range.
;;
explanation: This MLM, the STD_FUNC_DOSAGE_CAT MLM and the STD_Func_Dosage_Multum
contain the rules that determine if the SINGLE DOSE, AVERAGE DAILY DOSE,
or the TOTAL DAILY DOSE are out of range.
;;
keywords: single dose; average daily dose; total daily dose; dosage range
;;
knowledge:
type: data-driven;;
data:
// include common data structures
std_dosage_includes := MLM {{{SINGLE-QUOTE}}}std_func_dosage_includes{{{SINGLE-QUOTE}}};
include std_dosage_includes;
(
chart_guid,
user_data_code,
user_value,
user_data_touched_when,
use_multum_dosage_data,
use_item_catalog_dosage_data,
catalog_drc_type_const,
core_uom_const,
ht_cm,
show_irregular_message,
show_under_24_hour_message,
show_has_shift_frequency_message,
show_user_scheduled_weekly_message,
intentionally_unmapped_frequency_list,
alert_if_missing_flags,
med_data_list,
patient_info,
valid_height_days_for_age,
valid_weight_days_for_age,
Creatinine_Clearance_Result_name,
Creatinine_Clearance_Result_valid_days,
EstCrCl_equation_preference,
EstCrC_calculate_with_BSA_preference,
show_Debug_statements,
column_catalog_name,
column_Multum_name
) := ARGUMENT;
/*******************Make Changes To Spelling And Flags In This Section***************/
// Set to true if logging is needed.
log_execution_info := false;
/*************************************************************************************/
// DO NOT CHANGE the following System-defined values
dose_per_string:= "Dose Per";
dose_reg_string:= "Dose Reg";
/*=================================================================================*/
/* Declare the MLMs that can be called */
calc_BSA := MLM {{{SINGLE-QUOTE}}}sys_calc_BSA{{{SINGLE-QUOTE}}};
func_dosage_cat := MLM {{{SINGLE-QUOTE}}}STD_func_dosage_cat{{{SINGLE-QUOTE}}};
func_dosage_messages := MLM {{{SINGLE-QUOTE}}}STD_func_dosage_messages{{{SINGLE-QUOTE}}};
func_dosage_tracker := MLM {{{SINGLE-QUOTE}}}STD_func_dosage_tracker{{{SINGLE-QUOTE}}};
func_dosage_trim := MLM {{{SINGLE-QUOTE}}}STD_func_dosage_trim{{{SINGLE-QUOTE}}};
func_dosage_trim_adjusted := MLM {{{SINGLE-QUOTE}}}STD_func_dosage_trim_adjusted{{{SINGLE-QUOTE}}};
func_dosage_multum := MLM {{{SINGLE-QUOTE}}}STD_func_dosage_multum{{{SINGLE-QUOTE}}};
func_calc_est_crcl := MLM {{{SINGLE-QUOTE}}}SYS_CALC_EST_CRCL{{{SINGLE-QUOTE}}};
dosage_range_list := ();
med_dosage_map_list := ();
/* Get current visit timezone. */
(visit_timezone) := read last
{ClientVisit: timezone };
/* Get the patient{{{SINGLE-QUOTE}}}s birthday and other relevant data */
(client_guid,
birthdatetime,
birthday,
birthMonthNum,
birthDayNum,
birthtime,
patient_gender,
intl_patient_gender,
client_info_obj ) := read last
{ ClientInfo: GUID, BirthdateTime, Birthdate, BirthMonthNum, BirthDayNum, BirthTime, GenderCode,
GenderTypeIntlCode, this, };
//MTZ: set birthday with evoking object visit time zone
birthday := birthday as Time OVERRIDETIMEZONE visit_timezone;
// Get the BSA calculation preference used by the MLMS:
// SYS_CALC_BSA MLM and SYS_CALC_EST_CRCL
BSA_formula_preference := read last
{"SELECT Value "
|| " FROM HVCEnvProfile "
|| " WHERE Code = {{{SINGLE-QUOTE}}}BSAFormula{{{SINGLE-QUOTE}}} "
|| " AND HierarchyCode = {{{SINGLE-QUOTE}}}Client Info{{{SINGLE-QUOTE}}} " };
/* Get the Units of Measure info */
(uom_facility_code,
uom_sys_code,
uom_drug_catalog_key):= read
{"SELECT Code, CoreUOM, DrugCatalogKey "
|| " FROM CV3UnitOfMeasure"
|| " WHERE Active = 1" };
if use_multum_dosage_data
then
/* Get the patient dialysis type*/
/* Retrieve the facility{{{SINGLE-QUOTE}}}s scope preference for dialysis type */
general_scope_for_dialysis := read last
{"SELECT CASE WHEN ScopeLevel = 3 THEN 1 ELSE 0 END "
|| " FROM CV3PhysicalNoteType "
|| " WHERE Code = " || SQLEX("Dialysis")};
/* Set the scope to retrieve the Dialysis */
if general_scope_for_dialysis = 1
then dialysis_patient_chart_str:= "";
else dialysis_patient_chart_str:= " AND ChartGUID = " || SQLEX(chart_guid);
endif;
/* Retrieve from database*/
/* Warning--keep SQL in synch with business rules on patient height */
(dialysis_type_str,
dialysis_date) := read last
{"SELECT Text, TouchedWhen "
|| " FROM CV3PhysicalNoteDeclaration"
|| " WHERE ClientGUID = " || SQLEX(client_guid)
|| dialysis_patient_chart_str
|| " AND Active = 1 "
|| " AND TypeCode = " || SQLEX("DIALYSIS")
|| " AND Status = " || SQLEX("Active")
, PrimaryTime = TouchedWhen };
/* Retrieve the facility{{{SINGLE-QUOTE}}}s scope preference for has liver disease*/
general_scope_for_liver := read last
{"SELECT CASE WHEN ScopeLevel = 3 THEN 1 ELSE 0 END "
|| " FROM CV3PhysicalNoteType "
|| " WHERE Code = " || SQLEX("LIVERFUNC")};
/* Set the scope to retrieve the has liver disease string */
if general_scope_for_liver = 1
then liver_patient_chart_str:= "";
else liver_patient_chart_str:= " AND ChartGUID = " || SQLEX(chart_guid);
endif;
/* Retrieve from database*/
/* Warning--keep SQL in synch with business rules on patient liver disease */
(has_liver_disease_str,
has_liver_disease_date) := read last
{"SELECT Text, TouchedWhen "
|| " FROM CV3PhysicalNoteDeclaration"
|| " WHERE ClientGUID = " || SQLEX(client_guid)
|| liver_patient_chart_str
|| " AND Active = 1 "
|| " AND TypeCode = " || SQLEX("LIVERFUNC")
|| " AND Status = " || SQLEX("Active")
, PrimaryTime = TouchedWhen };
// patient info obj property value for liver disease
patient_info.Liver := new Patient_Property_Obj;
patient_info.Liver.type := "Liver Disease";
patient_info.Liver.date := has_liver_disease_date;
if has_liver_disease_str is null
then
has_liver_disease_str:= "Unknown";
patient_info.Liver.is_missing := true;
endif; /* if has_liver_disease_str */
// set has_liver_disease_bit
if has_liver_disease_str = "Yes"
then
has_liver_disease_bit := 1;
elseif has_liver_disease_str = "No"
then
has_liver_disease_bit := 0;
else
has_liver_disease_bit := null;
endif;
patient_info.Liver.value := has_liver_disease_str;
// If Dialysis is HEMO or Peritoneal then do not need to retrieve Creatinine
if ( dialysis_type_str in ("Hemo", "Peritoneal"))
then
patient_info.Renal := new Patient_Property_Obj;
patient_info.Renal.type := "Renal";
if (dialysis_type_str = "Hemo")
then
patient_info.Renal.value := "hemodialysis";
else
patient_info.Renal.value := "peritoneal dialysis";
endif;
patient_info.Renal.date := dialysis_date;
else
creatinine_OBJECT := object [
value,
enteredDate,
isSerum
];
creatinine_list := ();
creatinine_on_order_form := false;
// Get the creatinine values from the Order entry form if the control exists
// This value will always be assumed to be the correct and latest
// Code first checks for the Creatinine Clearance values and if not found then looks for
// the Serum Creatinine.
//MTZ: when building data initial time, the enteredDate will be enterprise tz and convert to visit tz later
creatinine_order_str := first (user_value where user_data_code = "CreatCrClValue_ECLP") as String;
if creatinine_order_str <> "null" and length of creatinine_order_str > 0
then
//creatinine_order_date := first (user_value where user_data_code = "CreatCrClEntered_ECLP");
creatinine_order_date := now; // Assume now since Order User Data has priority over the DB
creatinine_clearance_order := new creatinine_OBJECT;
creatinine_clearance_order.Value := creatinine_order_str as number;
time of creatinine_clearance_order := creatinine_order_date;
creatinine_clearance_order.enteredDate := creatinine_order_date;
creatinine_clearance_order.isSerum := false;
creatinine_on_order_form := true;
creatinine_list := creatinine_list, creatinine_clearance_order;
else
creatinine_order_str := first (user_value where user_data_code = "CreatSCRValue_ECLP") as String;
if creatinine_order_str <> "null" and length of creatinine_order_str > 0
then
//creatinine_order_date := first (user_value where user_data_code = "CreatSCREntered_ECLP");
creatinine_order_date := now; // Assume now since Order User Data has priority over the DB
serum_creatinine_order := new creatinine_OBJECT;
serum_creatinine_order.Value := creatinine_order_str as number;
time of serum_creatinine_order := creatinine_order_date;
serum_creatinine_order.enteredDate := creatinine_order_date;
serum_creatinine_order.isSerum := true;
creatinine_on_order_form := true;
creatinine_list := creatinine_list, serum_creatinine_order;
endif;
endif;
// If there is no Creatinine defined on the order form then need to check
// the database.
if not creatinine_on_order_form
then
// Get the Serum result name and valid days from the Environment Profile
(Serum_Creatinine_Result_Name,
Serum_Creatinine_Result_valid_days) := read last
{ "select ( select value from HVCEnvProfile " ||
" where HierarchyCode={{{SINGLE-QUOTE}}}CDS|Expert Drug Profile{{{SINGLE-QUOTE}}} AND " ||
" Code={{{SINGLE-QUOTE}}}Serum Creatinine Result Name{{{SINGLE-QUOTE}}}) as Name, " ||
" ( select value from HVCEnvProfile " ||
" where HierarchyCode={{{SINGLE-QUOTE}}}CDS|Expert Drug Profile{{{SINGLE-QUOTE}}} AND " ||
" Code={{{SINGLE-QUOTE}}}Valid Serum Creatinine Days{{{SINGLE-QUOTE}}}) as ValidDays" };
// Retrieve a serum creatinine from the Physical Note Declaration. Make sure
// it is still valid.
validDate := now - (Serum_Creatinine_Result_valid_days as number) days;
isFromPhysicalNote := 1;
(creatinine_physicalNote_str,
creatinine_physicalNote_date) := read last
{ "EXEC SCMSerumCreatinineOrClearanceSelPR "
|| SQLEX(client_guid) || " ,"
|| SQLEX("SCR") || " ,"
|| SQL(validDate) || " ," //no need to convert to datetimeoffset
|| SQLEX(isFromPhysicalNote )
, PrimaryTime = PerformedDtm}; //PerformedDtm is CV3PhysicalNoteDeclaration.TouchedWhen
if creatinine_physicalNote_str is not null
then
creatinine_physicalNote := new creatinine_OBJECT;
creatinine_physicalNote.value := creatinine_physicalNote_str as number;
time of creatinine_physicalNote := creatinine_physicalNote_date;
creatinine_physicalNote.enteredDate := creatinine_physicalNote_date;
creatinine_physicalNote.isSerum := true;
creatinine_list := creatinine_list, creatinine_physicalNote;
endif;
if Serum_Creatinine_Result_Name is not null
then
validDate := now - (Serum_Creatinine_Result_valid_days as number) days;
isFromPhysicalNote := 0;
(creatinine_result_str,
creatinine_result_date) := read last
{ "EXEC SCMSerumCreatinineOrClearanceSelPR "
|| SQLEX(client_guid) || " ,"
|| SQLEX(Serum_Creatinine_Result_Name) || " ,"
|| SQL(validDate) || " ," // no need to convert to datetimeoffset
|| SQLEX(isFromPhysicalNote)
, PrimaryTime = PerformedDtm}; //PerformedDtm is CV3BasicObservationView.PerformedDtm
if creatinine_result_str is not null
then
creatinine_result := new creatinine_OBJECT;
creatinine_result.value := creatinine_result_str as number;
time of creatinine_result := creatinine_result_date;
creatinine_result.enteredDate := creatinine_result_date;
creatinine_result.isSerum := true;
creatinine_list := creatinine_list, creatinine_result;
endif;
endif;
if Creatinine_Clearance_Result_name is not null
then
validDate := now - (Creatinine_Clearance_Result_valid_days as number) days;
isFromPhysicalNote := 0;
(creatinine_clearance_result_str,
creatinine_clearance_result_date) := read last
{ "EXEC SCMSerumCreatinineOrClearanceSelPR "
|| SQLEX(client_guid) || " ,"
|| SQLEX(Creatinine_Clearance_Result_name) || " ,"
|| SQL(validDate) || " ," // no need to convert to datetimeoffset
|| SQLEX(isFromPhysicalNote)
, PrimaryTime = PerformedDtm}; //PerformedDtm is CV3BasicObservationView.PerformedDtm
if creatinine_clearance_result_str is not null
then
creatinine_clearance_result := new creatinine_OBJECT;
creatinine_clearance_result.value := creatinine_clearance_result_str as number;
time of creatinine_clearance_result := creatinine_clearance_result_date;
creatinine_clearance_result.enteredDate := creatinine_clearance_result_date;
creatinine_clearance_result.isSerum := false;
creatinine_list := creatinine_list, creatinine_clearance_result;
endif;
endif;
endif;
calc_needed := false;
patient_info.Creatinine := new Patient_Property_Obj;
patient_info.Creatinine.type := "Creatinine";
latest_creatinine := creatinine_list[last index maximum 1 from (creatinine_list.enteredDate)];
// Need to calculate the estimated creatinine clearance if the latest creatinine value
// retrieved is a serum.
if latest_creatinine.isSerum
then
( error_message, EstCrCl_number_rounded,
EstCrCl_formula, weight_used, BSA_used ) := call func_calc_est_crcl with
EstCrCl_equation_preference,
BSA_formula_preference,
patient_info.Height.value,
patient_info.Weight.value,
latest_creatinine.value,
EstCrC_calculate_with_BSA_preference,
client_Info_obj;
if error_message is not null AND length of error_message > 0
then
patient_info.Creatinine.value := null;
patient_info.Creatinine.is_missing := true;
else
patient_info.Creatinine.value := EstCrCl_number_rounded;
patient_info.Creatinine.is_missing := false;
endif;
else
patient_info.Creatinine.value := latest_creatinine.value;
endif;
//MTZ: convert enteredDate to visit time zone from enterprise
patient_info.Creatinine.date := latest_creatinine.enteredDate as time visit_timezone;
endif;
endif;
// Check to see if gender is required for any dose critiera
patient_info.Gender := new Patient_Property_Obj;
patient_info.Gender.type := "Gender";
patient_info.Gender.value := patient_gender;
if not exist patient_gender
then
patient_info.Gender.is_missing := TRUE;
else
patient_info.Gender.is_missing := FALSE;
endif; //if not exist patient_gender
if intl_patient_gender = "U" or intl_patient_gender = "O"
then
patient_info.Gender.unknown_other := TRUE;
else
patient_info.Gender.unknown_other := FALSE;
endif; //if intl_patient_gender = "U" or "O"
if exist patient_gender and
not exist intl_patient_gender
then
patient_info.Gender.is_unmapped := TRUE;
else
patient_info.Gender.is_unmapped := FALSE;
endif;
//Create objects that summarize data needed for
//Total Daily Dose and Average Daily Dose checking
(total_tracker_list,
average_tracker_list )
:= call func_dosage_tracker with med_data_list;
;;
evoke:
;;
logic:
//------------------------------------------------
// Process each Medication in the Med_Data Object
//------------------------------------------------
for med_data in med_data_list do
missing_data_msg := "";
drug_name := med_data.order_med_name ;
catalog_item_obj:= med_data.order_catalog_item_obj;
// Significant_date is important in several calculations and cannot
// be NULL. Set it to be the first calculated admin time. If this
// is null then take the calcStart_dtm.
if med_data.order_med_significant_date is null
then
med_data.order_med_significant_date := first med_data.admin_dtm_list;
if med_data.order_med_significant_date is null
then
med_data.order_med_significant_date := med_data.calcStart_dtm;
endif;
endif;
//-----------------------------------------------------
// Determine if DOSE PER or DOSE REG Should be Used for Range Check
//-----------------------------------------------------
// The SINGLE dose should always be checked with the setting from the order.
single_order_calc_per_uom := med_data.updated_calc_med_per_uom;
// Complex Order should have their AVERAGE and TOTAL doses check with DOSE REG.
// by setting the variable below to NULL.
// All other orders should use the setting from the order.
If med_data.med_order_type = "Complex Order"
then
average_order_calc_per_uom := NULL;
total_order_calc_per_uom := NULL;
else
average_order_calc_per_uom := med_data.updated_calc_med_per_uom;
total_order_calc_per_uom := med_data.updated_calc_med_per_uom;
endif;
/*----------------------------------------------------------------*/
/* Set the WEIGHT and associated data for the Dosage Range Checks */
/*----------------------------------------------------------------*/
calc_text := med_data.calc_text;
dose_basis := med_data.dose_basis;
wt_kg := med_data.wt_kg;
//---------------------------
// Calculate the Patient Age
//---------------------------
// A valid birthday is required for the appropriate age calculation
// The age of adults and older children can be calculated with the birth-year
// when the month and day are not available.
// However, the age of an infant can be over-estimated based solely
// on the birth-year. Therefore infant must have
// a valid birth-month and birth-year before an age calculation is attempted.
// If the patient{{{SINGLE-QUOTE}}}s birth month is 0,
// then only the birth-year is available for the age calculation.
// In this case, don{{{SINGLE-QUOTE}}}t use the age-based dosage range data for
// infants or children under age 4 years.
if birthday is time then
has_valid_birthdate:= true;
patient_birthday_info_on_order := new Patient_Birthday_Info_Obj;
order_significant_date := med_data.order_med_significant_date;
age_value:= (order_significant_date-birthday)/(1 year);
if birthMonthNum = 0 and age_value < 4 then
has_valid_birthdate:= false;
endif;
month_value := (order_significant_date-birthday)/(1 month);
if has_valid_birthdate and BirthDayNum = 0 and month_value < 4 then
has_valid_birthdate:= false;
endif;
// Calculate the patient age in days
// Patient age in days
patient_age_in_days := (order_significant_date - birthday)/(1 day);
// if patient age < 4 days, then recalculate total using formula:
// Order.SignificantDtm (Birthday at 00:00 + HH:MM of birth time from CV3Client.BirthTime)
if has_valid_birthdate and patient_age_in_days < 4
then
if not exists birthtime
then
//[New born birth-time missing]: check on birth time range, Birthday "from" and "to" value will be needed.
//Birthday To value set to 23:59:
if patient_age_in_days >= 1 then
birth_time_to := ("23:59:00" as time);
estimated_birthday_to := birthday + (birth_time_to - (day floor of birth_time_to));
else
estimated_birthday_to := now as time visit_timezone;
endif;
else
// Update the birthday to include birthtime when baby is less than 4 days old
birthday := birthdatetime;
Endif;
endif;
sig_extract_year := extract year order_significant_date;
birthday_extract_year := extract year birthday;
sig_extract_month := extract month order_significant_date;
birthday_extract_month := extract month birthday;
sig_extract_day := extract day order_significant_date;
birthday_extract_day := extract day birthday;
had_birthday := true;
if (sig_extract_month = birthday_extract_month)
then
if (sig_extract_day < birthday_extract_day)
then
had_birthday := false;
endif;
elseif (sig_extract_month < birthday_extract_month)
then
had_birthday := false;
endif;
age_years_value := sig_extract_year - birthday_extract_year;
if (had_birthday = false)
then
age_years_value := age_years_value - 1;
endif;
// construct the string used to display the age
age_months_value := (order_significant_date - birthday) / (1 month);
age_days_value := (order_significant_date - birthday) / (1 day);
age_hours_value := (order_significant_date - birthday) / (1 hour);
age_str := "";
if (age_years_value >= 1)
then
age_str := age_years_value formatted with "%d" || " year(s)";
elseif (age_months_value >= 1)
then
age_str := age_months_value formatted with "%d" || " month(s)";
elseif (age_days_value >= 1)
then
age_str := age_days_value formatted with "%d" || " day(s)";
elseif (age_hours_value >= 1)
then
age_str := age_hours_value formatted with "%d" || " hour(s)";
endif;
//[New born birth-time missing]: fillup birthday related info structure
patient_birthday_info_on_order.birthday := birthday;
patient_birthday_info_on_order.age_str := age_str;
patient_birthday_info_on_order.age_year_value := age_years_value;
patient_birthday_info_on_order.age_month_value := age_months_value;
patient_birthday_info_on_order.age_week_value := (order_significant_date - birthday) / (1 week);
patient_birthday_info_on_order.age_day_value := age_days_value;
patient_birthday_info_on_order.age_hour_value := age_hours_value;
patient_birthday_info_on_order.age_max_inhour_str := patient_birthday_info_on_order.age_hour_value formatted with "%d" || " hour(s)";
if estimated_birthday_to is not null then
patient_birthday_info_on_order.is_estimated_birthday := true;
patient_birthday_info_on_order.estimated_birthday_to := estimated_birthday_to;
patient_birthday_info_on_order.age_year_min_value := (order_significant_date - estimated_birthday_to) / (1 year);
patient_birthday_info_on_order.age_month_min_value := (order_significant_date - estimated_birthday_to) / (1 month);
patient_birthday_info_on_order.age_week_min_value := (order_significant_date - estimated_birthday_to) / (1 week);
patient_birthday_info_on_order.age_day_min_value := (order_significant_date - estimated_birthday_to) / (1 day);
patient_birthday_info_on_order.age_hour_min_value := (order_significant_date - estimated_birthday_to) / (1 hour);
patient_birthday_info_on_order.age_min_inhour_str := patient_birthday_info_on_order.age_hour_min_value formatted with "%d" || " hour(s)";
endif;
else
has_valid_birthdate := false;
endif;
//-----------------------------------------
// Perform weight/height currentness check
//-----------------------------------------
if has_valid_birthdate
then
patient_age := order_significant_date - birthday;
// Perform weight validity check
valid_weight_duration := last (valid_weight_days_for_age.duration
where (valid_weight_days_for_age.FromAge <= patient_age and
valid_weight_days_for_age.ToAge > patient_age ));
// compute weight duration
weight_duration := now - patient_info.Weight.date;
// Weight is not current, set it to zero
if (weight_duration > valid_weight_duration)
then
wt_kg := null;
endif;
// Perform height validity check
valid_height_duration := last (valid_height_days_for_age.duration
where (valid_height_days_for_age.FromAge <= patient_age and
valid_height_days_for_age.ToAge > patient_age ));
// compute the height duration
height_duration := now - patient_info.Height.date;
// if height is not current, set it to zero
if (height_duration > valid_height_duration)
then
ht_cm := null;
endif;
// Update the is missing flag
if (wt_kg is number and wt_kg > 0)
then patient_info.Weight.not_current := FALSE;
else patient_info.Weight.not_current := TRUE;
endif; //if wt_kg is number
// Check to see if height is present
if ht_cm is number
and ht_cm > 0
then patient_info.Height.not_current := FALSE;
else patient_info.Height.not_current := TRUE;
endif; //if ht_cm is number
endif;
//-------------------
// Calculate the BSA
//-------------------
if ht_cm is number
and wt_kg is number
and ht_cm > 0
and wt_kg > 0
then
BSA_number_rounded:= Call calc_BSA with
BSA_formula_preference, ht_cm, wt_kg, client_info_obj;
patient_info.BSA := new Patient_Property_Obj;
patient_info.BSA.type := "BSA";
patient_info.BSA.value := BSA_number_rounded;
patient_info.BSA.is_missing := ((BSA_number_rounded is NULL) or (BSA_number_rounded = 0));
endif; /* if ht_cm is number */
//----------------------------------
// Check SINGLE Dosage Range
//----------------------------------
// Find the SINGLE Dose medications with the same Name, UOM, Route, and PerUOM
// OR both PerUOM are NULL.
//-----------------------------------------------------------------------------
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)
)
AND ((med_data_list.calc_med_per_uom = med_data.calc_med_per_uom)
OR (med_data_list.calc_med_per_uom is null
AND med_data.calc_med_per_uom is null))
AND (med_data_list.order_med_dose_low is not null AND
med_data.order_med_dose_low is not null )
AND // If complex order (complex order or complex order with IV additive), don{{{SINGLE-QUOTE}}}t process the master complex order
( ( (any (med_data_list.med_order_type = "Complex Order")) AND (med_data.sort_number > 1))
OR
(not any (med_data_list.med_order_type = "Complex Order")) // not a complex order
)
AND med_data_list.order_med_significant_date = med_data.order_med_significant_date
);
// Find the dosage range for the SINGLE DOSE
//------------------------------------------
// Only retreive the dosage range data once for each Item-Catalog/Multum
// by checking to see if the dosage range data has already been retrieved
if (not exist med_data.retrieved_dose_range_data
and exist med_data.order_med_dose_low )
then
if use_item_catalog_dosage_data
then
(item_cat_dosage_range_list,
item_cat_missing_route,
item_cat_unmapped_route,
item_cat_missing_uom,
item_cat_unmapped_uom,
item_cat_uom_conversion_issue
):= call func_dosage_cat with
(
drug_name,
med_data.is_order,
catalog_item_obj,
med_data.grouper_id,
med_data.multum_dnum,
med_data.multum_mmdc,
med_data.order_med_route,
med_data.order_med_route_id,
med_data.generic_route,
med_data.order_med_significant_date,
med_data.order_med_units,
med_data.order_med_uom_id,
single_order_calc_per_uom,
average_order_calc_per_uom,
total_order_calc_per_uom,
patient_birthday_info_on_order,
has_valid_birthdate,
wt_kg,
BSA_number_rounded,
intl_patient_gender,
core_uom_const,
alert_if_missing_flags,
patient_info
);
// Performed item catalog dosage look up for the medication
found_med_data.retrieved_dose_range_data := true;
found_med_data.missing_route := found_med_data.missing_route or item_cat_missing_route;
found_med_data.unmapped_route := found_med_data.unmapped_route or item_cat_unmapped_route;
found_med_data.missing_uom := found_med_data.missing_uom or item_cat_missing_uom;
found_med_data.unmapped_uom := found_med_data.unmapped_uom or item_cat_unmapped_uom;
found_med_data.uom_conversion_issue:= found_med_data.uom_conversion_issue
or item_cat_uom_conversion_issue;
item_cat_dosage_range_list.patient_age_at_order := age_str;
// create map between medication and the single or contraindication multum values
single_item_cat_dosage_range_list := item_cat_dosage_range_list
where (item_cat_dosage_range_list.dosage_type in ("single"));
found_single_dose := any (single_item_cat_dosage_range_list where single_item_cat_dosage_range_list.match_found = true);
// add the item catalog for single dosage ranges to the dosage range list
if ((exists single_item_cat_dosage_range_list) and (count single_item_cat_dosage_range_list > 0))
then
single_item_cat_dosage_range_list.dosage_type := "single";
dosage_range_list := dosage_range_list, single_item_cat_dosage_range_list;
// update the sort number
list_count := count dosage_range_list;
dosage_range_list.sort_number := 1 seqto list_count;
// create map between medication and the single item catalog dosage range value
for single_item_cat_dosage_range in single_item_cat_dosage_range_list
do
if single_item_cat_dosage_range.match_found
then
for found_med_data_item in found_med_data
do
map_item := new Medication_Dosage_Range_Map;
med_dosage_map_list := med_dosage_map_list, map_item;
map_item.med_sort_number := found_med_data_item.sort_number;
map_item.med_name := found_med_data_item.order_med_name;
map_item.dosage_range_sort_number := single_item_cat_dosage_range.sort_number;
map_item.dosage_type := single_item_cat_dosage_range.dosage_type;
map_item.match_found := single_item_cat_dosage_range.match_found;
enddo;
else // missing data dosage range is just mapped to first occurence of the medication
found_med_data_item := last found_med_data[1];
map_item := new Medication_Dosage_Range_Map;
med_dosage_map_list := med_dosage_map_list, map_item;
map_item.med_sort_number := found_med_data_item.sort_number;
map_item.med_name := found_med_data_item.order_med_name;
map_item.dosage_range_sort_number := single_item_cat_dosage_range.sort_number;
map_item.dosage_type := single_item_cat_dosage_range.dosage_type;
map_item.match_found := single_item_cat_dosage_range.match_found;
endif; // if single_item_cat_dosage_range.match_found
enddo; // for single_item_cat_dosage_range in single_item_cat_dosage_range_list
endif; // if (count single_item_cat_dosage_range_list > 0)
endif;
if ( use_multum_dosage_data
and has_valid_birthdate )
then
if med_data.is_order
then
if (catalog_item_obj.DrcGrouperID is null
and exists catalog_item_obj.DrugCatalogKey
and not catalog_item_obj.DrugCatalogKeyIsIgnored)
then
found_med_data.unmapped_grouper := true;
endif;
if (catalog_item_obj.DrugCatalogKey is null
and not catalog_item_obj.DrugCatalogKeyIsIgnored)
then
found_med_data.unmapped_drug := true;
endif;
endif;
// Get the corresponding dosage range data from multum
(multum_dosage_range_list,
multum_missing_route,
multum_unmapped_route,
multum_missing_uom,
multum_unmapped_uom,
multum_uom_conversion_issue ):= call func_dosage_multum with
(
med_data.grouper_id,
drug_name,
med_data.multum_dnum,
med_data.multum_mmdc,
med_data.order_med_route,
med_data.order_med_route_id,
med_data.generic_route,
med_data.order_med_significant_date,
med_data.order_med_units,
med_data.order_med_uom_id,
med_data.order_med_frequency,
med_data.multum_freq_id,
med_data.med_order_type,
patient_birthday_info_on_order,
wt_kg,
BSA_number_rounded,
intl_patient_gender,
has_liver_disease_bit,
dialysis_type_str,
patient_info.Creatinine.value,
intentionally_unmapped_frequency_list,
alert_if_missing_flags,
med_data.is_order,
patient_info,
core_uom_const
);
// Performed multum dosage range data look up for this medication
found_med_data.retrieved_dose_range_data := true;
found_med_data.uom_conversion_issue :=found_med_data.uom_conversion_issue or multum_uom_conversion_issue;
found_med_data.missing_route := found_med_data.missing_route or multum_missing_route;
found_med_data.unmapped_route := found_med_data.unmapped_route or multum_unmapped_route;
found_med_data.missing_uom := found_med_data.missing_uom or multum_missing_uom;
found_med_data.unmapped_uom := found_med_data.unmapped_uom or multum_unmapped_uom;
multum_dosage_range_list.patient_age_at_order := age_str;
// add the item catalog for single dosage ranges to the dosage range list
if (count multum_dosage_range_list > 0)
then
dosage_range_list := dosage_range_list, multum_dosage_range_list;
// update the sort number
list_count := count dosage_range_list;
dosage_range_list.sort_number := 1 seqto list_count;
// create map between medication and the single or contraindication multum values
single_contraindication_multum_dosage_list := multum_dosage_range_list
where (multum_dosage_range_list.dosage_type in ("single", "contraindication"));
for multum_dosage_range_item in single_contraindication_multum_dosage_list
do
if ( multum_dosage_range_item.match_found
and multum_dosage_range_item.is_range )
then
for found_med_data_item in found_med_data
do
map_item := new Medication_Dosage_Range_Map;
med_dosage_map_list := med_dosage_map_list, map_item;
map_item.med_sort_number := found_med_data_item.sort_number;
map_item.med_name := found_med_data_item.order_med_name;
map_item.dosage_range_sort_number := multum_dosage_range_item.sort_number;
map_item.dosage_type := multum_dosage_range_item.dosage_type;
map_item.match_found := multum_dosage_range_item.match_found;
map_item.dose_frequency := multum_dosage_range_item.dose_frequency;
map_item.frequency_issue := multum_dosage_range_item.frequency_issue;
enddo;
else
// missing criteria (match not found) or contraindication
// These items should be mapped to the medicaiton as dosage comparion will not be done
found_med_data_item := last found_med_data[1];
map_item := new Medication_Dosage_Range_Map;
med_dosage_map_list := med_dosage_map_list, map_item;
map_item.med_sort_number := found_med_data_item.sort_number;
map_item.med_name := found_med_data_item.order_med_name;
map_item.dosage_range_sort_number := multum_dosage_range_item.sort_number;
map_item.dosage_type := multum_dosage_range_item.dosage_type;
map_item.match_found := multum_dosage_range_item.match_found;
// if match found, and not a range means it{{{SINGLE-QUOTE}}}s a contraindication
if (multum_dosage_range_item.match_found and
multum_dosage_range_item.dosage_type = "contraindication")
then
found_med_data_item.contraindication_found := true;
endif;
endif; // if multum_dosage_range_item.found_match
enddo; // for multum_dosage_range_item in single_contraindication_multum_dosage_list
endif; //if (count multum_dosage_range_list > 0)
// Set the Single Dosage Criteria in the Med_Data objects
// that have the same Name, Route, UOM, and PerUOM
// OR both PerUOM are NULL.
single_dosage_ranges := dosage_range_list where dosage_range_list.dosage_type = "single";
endif;
endif; //if not exist med_data.retrieved_dose_range_data
// Compare the medication single dose with the dosage range data
all_single_dosage_range := dosage_range_list where (dosage_range_list.match_found AND
dosage_range_list.dosage_type = "single" );
found_maps := med_dosage_map_list where (med_dosage_map_list.med_sort_number = med_data.sort_number AND
med_dosage_map_list.dosage_range_sort_number in all_single_dosage_range.sort_number AND
med_dosage_map_list.dosage_type = "single");
for map_item in found_maps
do
dosage_range := last dosage_range_list[map_item.dosage_range_sort_number];
// Set the Low & High Values for the SINGLE DOSE
//----------------------------------------------
// Set compound versus simple //
if dosage_range.dose_calc_method = dose_per_string
then
// Set the single dose for the COMPOUND UOM (xxx/kg or xxx/m2)
map_item.med_dose_high := med_data.calc_med_dose_high;
map_item.med_dose_low := med_data.calc_med_dose_low;
map_item.med_dose_uom := med_data.order_med_units || "/" || med_data.calc_med_per_uom;
sample_vals := med_data.calc_med_dose_low, dosage_range.lower_dose, dosage_range.upper_dose;
else
// Set the single dose for the SIMPLE UOM (mg, cc, etc.)
map_item.med_dose_high:= med_data.order_med_dose_high;
map_item.med_dose_low:= med_data.order_med_dose_low;
map_item.med_dose_uom := med_data.order_med_units;
sample_vals := med_data.order_med_dose_low, dosage_range.lower_dose, dosage_range.upper_dose;
endif; // if dosage_range.dose_calc_method = dose_per_string
// Apply unit conversion if necessary
high_low_list := (
map_item.med_dose_high,
map_item.med_dose_low);
// Call the MLM to trim the decimals
rounded_high_low_list := call func_dosage_trim_adjusted with
sample_vals, dosage_range.conversion_factor, high_low_list;
map_item.adjusted_dose_high := rounded_high_low_list[1];
map_item.adjusted_dose_low := rounded_high_low_list[2];
map_item.adjusted_dose_uom := dosage_range.corrected_uom;
// CLINICAL RULE -- Determine if Dose is Out of Range for SINGLE DOSE
//--------------------------------------------------------------------
map_item.above_range := false;
map_item.below_range := false;
if (map_item.adjusted_dose_low < dosage_range.lower_dose)
then
map_item.below_range := true;
elseif (map_item.adjusted_dose_high > dosage_range.upper_dose)
then
map_item.above_range := true;
endif;
enddo;
med_data.outside_single_dosage_range := any found_maps.above_range
or any found_maps.below_range;
//----------------------------------
// Check TOTAL-DAILY Dosage Range
//----------------------------------
// Find the TOTAL-DAILY Dose medications
// with the same Name, UOM, and Route as the SINGLE DOSE
//--------------------------------------------------------------------
found_total_tracker := 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))
AND (total_tracker_list.start_date = med_data.order_med_significant_date));
for total_tracker in found_total_tracker do
// Only retreive the TOTAL DAILY dosage range criteria once for each Item-Catalog
// by checking to see if the criteria has already been stored in the object
if not exist total_tracker.retrieved_dose_range_data
AND exist med_data.retrieved_dose_range_data
then
// Find the dosage range for TOTAL DAILY DOSE
//--------------------------------------------
if use_item_catalog_dosage_data
then
// create map between medication and the total item catalog values
total_item_cat_dosage_range_list := item_cat_dosage_range_list
where (item_cat_dosage_range_list.dosage_type in ("total"));
// Set the Total Dosage Criteria in the Total_Tracker objects
//-----------------------------------------------------------
// Performed item catalog dosage look up for the medication
found_total_tracker.retrieved_dose_range_data := true;
// add the item catalog for total dosage ranges to the dosage range list
if ((exists total_item_cat_dosage_range_list) and (count total_item_cat_dosage_range_list > 0))
then
total_item_cat_dosage_range_list.dosage_type := "total";
dosage_range_list := dosage_range_list, total_item_cat_dosage_range_list;
// update the sort number
list_count := count dosage_range_list;
dosage_range_list.sort_number := 1 seqto list_count;
// create map between medication and the total item catalog dosage range value
for total_item_cat_dosage_range in total_item_cat_dosage_range_list
do
if total_item_cat_dosage_range.match_found
then
for found_total_tracker_item in found_total_tracker
do
map_item := new Medication_Dosage_Range_Map;
med_dosage_map_list := med_dosage_map_list, map_item;
map_item.med_sort_number := found_total_tracker_item.sort_number;
map_item.med_name := found_total_tracker_item.med_name;
map_item.dosage_range_sort_number := total_item_cat_dosage_range.sort_number;
map_item.dosage_type := total_item_cat_dosage_range.dosage_type;
map_item.match_found := total_item_cat_dosage_range.match_found;
enddo;
else // missing data dosage range is just mapped to first occurence of the medication
found_total_tracker_item := last found_total_tracker[1];
map_item := new Medication_Dosage_Range_Map;
med_dosage_map_list := med_dosage_map_list, map_item;
map_item.med_sort_number := found_total_tracker_item.sort_number;
map_item.med_name := found_total_tracker_item.med_name;
map_item.dosage_range_sort_number := total_item_cat_dosage_range.sort_number;
map_item.dosage_type := total_item_cat_dosage_range.dosage_type;
map_item.match_found := total_item_cat_dosage_range.match_found;
endif; // if total_item_cat_dosage_range.match_found
enddo; // for total_item_cat_dosage_range in total_item_cat_dosage_range_list
endif; // if ((exists total_item_cat_dosage_range_list) and (count total_item_cat_dosage_range_list > 0))
endif; //if use_item_catalog_dosage_data
if use_multum_dosage_data
then
total_dosage_ranges := dosage_range_list where dosage_range_list.dosage_type = "total";
found_total_tracker.retrieved_dose_range_data := true;
// create map between medication and the single or contraindication multum values
total_multum_dosage_list := multum_dosage_range_list
where (multum_dosage_range_list.dosage_type in ("total"));
for multum_dosage_range_item in total_multum_dosage_list
do
if ( multum_dosage_range_item.match_found
and multum_dosage_range_item.is_range )
then
for found_total_tracker_item in found_total_tracker
do
map_item := new Medication_Dosage_Range_Map;
med_dosage_map_list := med_dosage_map_list, map_item;
map_item.med_sort_number := found_total_tracker_item.sort_number;
map_item.med_name := found_total_tracker_item.med_name;
map_item.dosage_range_sort_number := multum_dosage_range_item.sort_number;
map_item.dosage_type := multum_dosage_range_item.dosage_type;
map_item.match_found := multum_dosage_range_item.match_found;
enddo;
else
// missing criteria (match not found)
// These items should be mapped to the medicaiton as dosage comparion will not be done
found_total_tracker_item := last found_total_tracker[1];
map_item := new Medication_Dosage_Range_Map;
med_dosage_map_list := med_dosage_map_list, map_item;
map_item.med_sort_number := found_total_tracker_item.sort_number;
map_item.med_name := found_total_tracker_item.med_name;
map_item.dosage_range_sort_number := multum_dosage_range_item.sort_number;
map_item.dosage_type := multum_dosage_range_item.dosage_type;
map_item.match_found := multum_dosage_range_item.match_found;
endif; // if multum_dosage_range_item.found_match
enddo; // for multum_dosage_range_item in total_multum_dosage_list
endif; // if use_multum_dosage_data
found_total_tracker.found_total_daily_dose := any (total_item_cat_dosage_range.match_found)
or any (total_multum_dosage_list.match_found);
endif; //if not exist total_tracker.retrieved_dose_range_data
// Process Clinical Rule Once for each Total Tracker
// by checking if it has already been processed
// the field outside_total_daily_dose is NULL if it has not been processed.
//--------------------------------------------------------------------------
// Compare the medication total dose with the dosage range data
all_total_dosage_range := dosage_range_list where (dosage_range_list.match_found AND
dosage_range_list.dosage_type = "total" );
found_maps := med_dosage_map_list where (med_dosage_map_list.med_sort_number = total_tracker.sort_number AND
med_dosage_map_list.dosage_range_sort_number in all_total_dosage_range.sort_number AND
med_dosage_map_list.dosage_type = "total");
for map_item in found_maps
do
dosage_range := last dosage_range_list[map_item.dosage_range_sort_number];
// Set the Low & High Values for the TOTAL DAILY DOSE
//----------------------------------------------------
if dosage_range.dose_calc_method = dose_per_string
then // Set the total dose for the COMPOUND UOM (xxx/kg or xxx/m2)
// Find the correct conversion factor
if dosage_range.calc_per_core_uom = core_uom_const.M2_string
then conversion_factor_total := BSA_number_rounded;
elseif dosage_range.calc_per_core_uom = core_uom_const.kg_string
then conversion_factor_total := wt_kg;
elseif dosage_range.calc_per_core_uom = core_uom_const.gm_string
then conversion_factor_total := wt_kg * 1000;
elseif dosage_range.calc_per_core_uom = core_uom_const.lb_string
then conversion_factor_total := wt_kg * 2.2045855 ;
elseif dosage_range.calc_per_core_uom = core_uom_const.ounce_string
then conversion_factor_total := wt_kg * 2.2045855 * 16 ;
else
conversion_factor_total := 1 ;
endif; //if dosage_range.calc_per_core_uom
// Calculate and Set the dose for the COMPOUND UOM
order_total_dose_high:= total_tracker.total_dose_high / conversion_factor_total;
order_total_dose_low:= total_tracker.total_dose_low / conversion_factor_total;
// Round the DOSE-PER number to within 1 decimal point of the criteria.
//----------------------------------------------------------------------
// Example: If the upper dose criteria has 2 decimal points,
// then round to 3 decimals.
// Initalize Variables
high_low_list := order_total_dose_high, order_total_dose_low;
sample_vals := med_data.calc_med_dose_low, dosage_range.lower_dose, dosage_range.upper_dose;
// Call the MLM to trim the decimals
rounded_high_low_list := call func_dosage_trim with
sample_vals, high_low_list;
// Save the Calculated COMPOUND UOM into the Total_Tracker Object
total_tracker.total_calc_med_dose_high := rounded_high_low_list[1];
total_tracker.total_calc_med_dose_low := rounded_high_low_list[2];
map_item.med_dose_high := total_tracker.total_calc_med_dose_high;
map_item.med_dose_low := total_tracker.total_calc_med_dose_low;
map_item.med_dose_uom := med_data.order_med_units || "/" || med_data.calc_med_per_uom;
sample_vals := med_data.calc_med_dose_low, dosage_range.lower_dose, dosage_range.upper_dose;
else
/* Set the total dose for the SIMPLE UOM (mg, cc, etc.) */
order_total_dose_high:= total_tracker.total_dose_high;
order_total_dose_low:= total_tracker.total_dose_low;
map_item.med_dose_high := total_tracker.total_dose_high;
map_item.med_dose_low := total_tracker.total_dose_low;
map_item.med_dose_uom := med_data.order_med_units;
sample_vals := med_data.order_med_dose_low, dosage_range.lower_dose, dosage_range.upper_dose;
endif; // if dosage_range.dose_calc_method = dose_per_string
// Apply unit conversion if necessary
high_low_list := (
map_item.med_dose_high,
map_item.med_dose_low );
// Call the MLM to trim the decimals
rounded_high_low_list := call func_dosage_trim_adjusted with
sample_vals, dosage_range.conversion_factor, high_low_list;
map_item.adjusted_dose_high := rounded_high_low_list[1];
map_item.adjusted_dose_low := rounded_high_low_list[2];
map_item.adjusted_dose_uom := dosage_range.corrected_uom;
// CLINICAL RULE -- Determine if Dose is Out of Range for TOTAL DAILY DOSE
//-------------------------------------------------------------------------
// use the dose values before rounding to compare
map_item.above_range := false;
map_item.below_range := false;
IF (map_item.adjusted_dose_high > dosage_range.upper_dose)
then
map_item.above_range := true;
elseif (map_item.adjusted_dose_low < dosage_range.lower_dose)
then
// low dose out of range, needs more checking.
if total_tracker.has_full_24hrs_doses = false and total_tracker.is_last_24hr_interval = true
then
if total_tracker.med_order_type <> "Complex Order"
then
map_item.below_range := true;
endif; // if total_tracker.med_order_type <> "Complex Order"
else
map_item.below_range := true;
endif; // if total_tracker.is_24hr_doses = false
endif; // if map_item.adjusted_dose_high > dosage_range.upper_dose
enddo; // for map_item in found_maps
total_tracker.outside_total_daily_dose := any found_maps.above_range
or any found_maps.below_range;
enddo; // for total_tracker
//----------------------------------
// Check AVERAGE-DAILY Dosage Range
//----------------------------------
// Average-Daily Dosage Range should be checked for Regular and IV-Additives.
// If a Complex Order does NOT have a Total-Daily dosage-range criteria,
// then substitute the Average-Daily criteria to do a dosage-range check
// for the Total-Daily.
if med_data.med_order_type is in ("Regular", "IV-Additive")
or (med_data.med_order_type = "Complex Order"
and NO (found_total_tracker.found_total_daily_dose where it is present))
// Note: {{{SINGLE-QUOTE}}}where it is present{{{SINGLE-QUOTE}}} assures that the list does not contain
// any NULL values before processing it with the NO operator.
then
// Find the AVERAGE-DAILY Dose medications
// with the same Name, UOM, and Route as the SINGLE DOSE
//-------------------------------------------------------------------
found_average_tracker := 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))
AND (average_tracker_list.start_date = med_data.order_med_significant_date)
);
for average_tracker in found_average_tracker do
// Only retreive the AVERAGE DAILY dosage range criteria once for each Item-Catalog
// by checking to see if the criteria has already been stored in the object
if not exist average_tracker.retrieved_dose_range_data
AND exist med_data.retrieved_dose_range_data
then
// Find the dosage range AVERAGE DAILY DOSE
//------------------------------------------
if use_item_catalog_dosage_data
then
// create map between medication and the average item catalog values
average_item_cat_dosage_range_list := item_cat_dosage_range_list
where (item_cat_dosage_range_list.dosage_type in ("average"));
// Set the Total Dosage Criteria in the Average_Tracker objects
//--------------------------------------------------------------
found_average_tracker.retrieved_dose_range_data := true;
found_average_tracker.found_average_daily_dose := any (average_item_cat_dosage_range_list.match_found);
// add the item catalog for average dosage ranges to the dosage range list
if ((exists average_item_cat_dosage_range_list) and (count average_item_cat_dosage_range_list > 0))
then
average_item_cat_dosage_range_list.dosage_type := "average";
dosage_range_list := dosage_range_list, average_item_cat_dosage_range_list;
// update the sort number
list_count := count dosage_range_list;
dosage_range_list.sort_number := 1 seqto list_count;
// create map between medication and the average item catalog dosage range value
for average_item_cat_dosage_range in average_item_cat_dosage_range_list
do
if average_item_cat_dosage_range.match_found
then
for found_average_tracker_item in found_average_tracker
do
map_item := new Medication_Dosage_Range_Map;
med_dosage_map_list := med_dosage_map_list, map_item;
map_item.med_sort_number := found_average_tracker_item.sort_number;
map_item.med_name := found_average_tracker_item.med_name;
map_item.dosage_range_sort_number := average_item_cat_dosage_range.sort_number;
map_item.dosage_type := average_item_cat_dosage_range.dosage_type;
map_item.match_found := average_item_cat_dosage_range.match_found;
enddo;
else // missing data dosage range is just mapped to first occurence of the medication
found_average_tracker_item := last found_average_tracker[1];
map_item := new Medication_Dosage_Range_Map;
med_dosage_map_list := med_dosage_map_list, map_item;
map_item.med_sort_number := found_average_tracker_item.sort_number;
map_item.med_name := found_average_tracker_item.med_name;
map_item.dosage_range_sort_number := average_item_cat_dosage_range.sort_number;
map_item.dosage_type := average_item_cat_dosage_range.dosage_type;
map_item.match_found := average_item_cat_dosage_range.match_found;
endif; // if average_item_cat_dosage_range.match_found
enddo; // for average_item_cat_dosage_range in average_item_cat_dosage_range_list
endif; // if ((exists average_item_cat_dosage_range_list) and (count average_item_cat_dosage_range_list > 0))
endif; // if use_item_catalog_dosage_data
endif; //if not exist average_tracker.retrieved_dose_range_data
// Process Clinical Rule Once for each Average Tracker
// by checking if it has already been processed
// the field outside_total_daily_dose is NULL if it has not been processed.
//--------------------------------------------------------------------------
// Compare the medication average dose with the dosage range data
all_average_dosage_range := dosage_range_list where (dosage_range_list.match_found AND
dosage_range_list.dosage_type = "average" );
found_maps := med_dosage_map_list where (med_dosage_map_list.med_sort_number = average_tracker.sort_number AND
med_dosage_map_list.dosage_range_sort_number in all_average_dosage_range.sort_number AND
med_dosage_map_list.dosage_type = "average");
for map_item in found_maps
do
dosage_range := last dosage_range_list[map_item.dosage_range_sort_number];
// Set the Low & High Values for the AVERAGE DAILY DOSE
//------------------------------------------------------
if dosage_range.dose_calc_method = dose_per_string
then // Set the average dose for the COMPOUND UOM (xxx/kg or xxx/m2)
// Find the correct conversion factor
if dosage_range.calc_per_core_uom = core_uom_const.M2_string
then conversion_factor_ave := BSA_number_rounded;
elseif dosage_range.calc_per_core_uom = core_uom_const.kg_string
then conversion_factor_ave := wt_kg;
elseif dosage_range.calc_per_core_uom = core_uom_const.gm_string
then conversion_factor_ave := wt_kg * 1000;
elseif dosage_range.calc_per_core_uom = core_uom_const.lb_string
then conversion_factor_ave := wt_kg * 2.2045855 ;
elseif dosage_range.calc_per_core_uom = core_uom_const.ounce_string
then conversion_factor_ave := wt_kg * 2.2045855 * 16 ;
else
conversion_factor_ave := 1 ;
endif; //if dosage_range.calc_per_core_uom
// Calculate and Set the dose for the COMPOUND UOM
order_average_dose_high :=
average_tracker.average_dose_high / conversion_factor_ave;
order_average_dose_low :=
average_tracker.average_dose_low / conversion_factor_ave;
// Round the DOSE-PER number to within 1 decimal point of the criteria.
//----------------------------------------------------------------------
// Example: If the upper dose criteria has 2 decimal points,
// then round to 3 decimals.
// Initalize Variables
high_low_list := order_average_dose_high, order_average_dose_low;
sample_vals := dosage_range.lower_dose, dosage_range.upper_dose;
// Call the MLM to round to one extra decimal point based on the low/high numbers for the DRC range.
// uom_conversion_factor is the conversion factor between the order dose UOM and dose range UOM. For example,
// 1. if order dose is in G, DRC range UOM is G, uom_conversion_factor = 1000;
// 2. if order dose is in MG, DRC range UOM is G, uom_conversion_factor = 0.001;
// 3. if order dose UOM and DRC range UOM are same, uom_conversion_factor = 1.
// "sample_vals / dosage_range.uom_conversion_factor" is used to be the sample values to trim the extra
// decimal points. So the rounded values will have one extra decimal point based on the DRC range low/high
// number in the scenario where UOM conversion is involved. uom_conversion_factor values are saved in core load
// table SXAUnitOfMeasureConversion. Currently the values in this table are all dividable.
rounded_high_low_list := call func_dosage_trim with
sample_vals / dosage_range.uom_conversion_factor, high_low_list;
// Save the Calculated COMPOUND UOM into the Average_Tracker Object
average_tracker.average_calc_med_dose_high := rounded_high_low_list[1];
average_tracker.average_calc_med_dose_low := rounded_high_low_list[2];
map_item.med_dose_high := average_tracker.average_calc_med_dose_high;
map_item.med_dose_low := average_tracker.average_calc_med_dose_low;
map_item.med_dose_uom := med_data.order_med_units || "/" || med_data.calc_med_per_uom;
sample_vals := med_data.calc_med_dose_low, dosage_range.lower_dose, dosage_range.upper_dose;
else
/* Set the average dose for the SIMPLE UOM (mg, cc, etc.) */
order_average_dose_high:= average_tracker.average_dose_high;
order_average_dose_low:= average_tracker.average_dose_low;
map_item.med_dose_high := order_average_dose_high;
map_item.med_dose_low := order_average_dose_low;
map_item.med_dose_uom := med_data.order_med_units;
high_low_list := (
map_item.med_dose_high,
map_item.med_dose_low );
sample_vals := dosage_range.lower_dose, dosage_range.upper_dose;
// Call the MLM to round to one extra decimal point based on the low/high numbers for the DRC range.
// uom_conversion_factor is the conversion factor between the order dose UOM and dose range UOM. For example,
// 1. if order dose is in G, DRC range UOM is G, uom_conversion_factor = 1000;
// 2. if order dose is in MG, DRC range UOM is G, uom_conversion_factor = 0.001;
// 3. if order dose UOM and DRC range UOM are same, uom_conversion_factor = 1.
// "sample_vals / dosage_range.uom_conversion_factor" is used to be the sample values to trim the extra
// decimal points. So the rounded values will have one extra decimal point based on the DRC range low/high
// number in the scenario where UOM conversion is involved. uom_conversion_factor values are saved in core load
// table SXAUnitOfMeasureConversion. Currently the values in this table are all dividable.
rounded_high_low_list := call func_dosage_trim with
sample_vals / dosage_range.uom_conversion_factor, high_low_list;
map_item.med_dose_high := rounded_high_low_list[1];
map_item.med_dose_low := rounded_high_low_list[2];
sample_vals := med_data.order_med_dose_low, dosage_range.lower_dose, dosage_range.upper_dose;
endif; // if dosage_range.dose_calc_method = dose_per_string
// Apply unit conversion if necessary
high_low_list := (
map_item.med_dose_high,
map_item.med_dose_low );
// Call the MLM to trim the decimals
rounded_high_low_list := call func_dosage_trim_adjusted with
sample_vals, dosage_range.conversion_factor, high_low_list;
map_item.adjusted_dose_high := rounded_high_low_list[1];
map_item.adjusted_dose_low := rounded_high_low_list[2];
map_item.adjusted_dose_uom := dosage_range.corrected_uom;
// CLINICAL RULE -- Determine if Dose is Out of Range for AVERAGE DAILY DOSE
//---------------------------------------------------------------------------
map_item.above_range := false;
map_item.below_range := false;
if map_item.adjusted_dose_high > dosage_range.upper_dose
then
map_item.above_range := true;
elseif (map_item.adjusted_dose_low < dosage_range.lower_dose)
then
// low dose out of range, needs more checking.
if average_tracker.has_full_24hrs_doses = false and average_tracker.is_last_24hr_interval = true
then
if average_tracker.med_order_type <> "Complex Order"
then
map_item.below_range := true;
endif; // if average_tracker.med_order_type <> "Complex Order"
else
map_item.below_range := true;
endif; // if average_tracker.has_full_24hrs_doses = false and average_tracker.is_last_24hr_interval = true
endif; // if order_average_dose_high > dosage_range.upper_dose
enddo; //for map_item in found_maps
average_tracker.outside_average_daily_dose := any found_maps.below_range
or any found_maps.above_range;
enddo; //for average_tracker
endif; //if med_data.med_order_type is in ("Regular", "IV-Additive")
enddo; // for med_data
//-------------------------------
// Special Creatinine Rules
//-------------------------------
// Extra creatinine values were retrieved.
// We only need to display these values when there{{{SINGLE-QUOTE}}}s a dialysis outside range, or creatinine outside range
all_creatinine_dose_ranges := dosage_range_list where (dosage_range_list.creatinine_criteria is not null);
patient_criteria_dose_ranges := all_creatinine_dose_ranges where all_creatinine_dose_ranges.crcl_within_range;
// Check if there{{{SINGLE-QUOTE}}}s dialysis or creatinine outside range
show_other_creatinine_values := count (med_dosage_map_list where
med_dosage_map_list.dosage_range_sort_number in patient_criteria_dose_ranges.sort_number
AND
( // patient crcl range in supplemental
med_dosage_map_list.match_found = false
OR
// patient crcl range is contraindication
med_dosage_map_list.dosage_type = "contraindication"
OR
// patient crcl range is outside range
( med_dosage_map_list.above_range = true OR med_dosage_map_list.below_range = true)
)) > 0;
if (count all_creatinine_dose_ranges > 0 and not show_other_creatinine_values)
then
// When the patient creatinine dose range is within range, remove the default and
// other creatinine (these dose ranges already have match_found as false)
// When there is no patient creatinine dose range found, remove the other creatinine
// values (which already have match_found as false).
// - The default range value won{{{SINGLE-QUOTE}}}t exist if there are other dose ranges with match_found is true.
// - If the default range is the only one that matches patient critieria, it will have the
// match_found as true, and will be kept
dose_ranges_to_remove := dosage_range_list where
(
dosage_range_list.match_found = false
AND ( dosage_range_list.is_default = true
OR dosage_range_list.sort_number in all_creatinine_dose_ranges.sort_number
)
);
// There{{{SINGLE-QUOTE}}}s no renal outside range
// Remove the additional creatinine maps from the map list
no_creatinine_med_dosage_map_list := med_dosage_map_list where
(med_dosage_map_list.dosage_range_sort_number not in
dose_ranges_to_remove.sort_number);
med_dosage_map_list := no_creatinine_med_dosage_map_list;
endif;
//--------------------------------
// CLINICAL RULES -- Missing Data
//--------------------------------
patient_info.Age := new Patient_Property_Obj;
patient_info.Age.type := "Age";
patient_info.Age.value := age_str;
patient_info.Age.is_missing := not has_valid_birthdate;
// If any medication has missing route or uom conversion issue set the value
missing_route := any med_data_list.missing_route;
unmapped_route := any med_data_list.unmapped_route;
missing_uom := any med_data_list.missing_uom;
unmapped_uom := any med_data_list.unmapped_uom;
uom_conversion_issue := any med_data_list.uom_conversion_issue;
//------------------------------------------
// Clinical Rule For Weekly <User Schedule>
//------------------------------------------
// The Average Daily Dose for a Weekly schedule cannot be determined
// because there can be days in the week when a patient does not receive any medications.
// The formula for Average Daily Dosage assumes that the patient receives
// medication each day in order to compute an average.
// RULE: Suppress any Average Daily Dose alert
// when the Frequency is <User Schedule>
// and the schedule in "Weekly"
if ANY (med_data_list.order_interval = "Weekly" )
and ANY (med_data_list.order_med_frequency = "<User Schedule>" )
and ANY (average_tracker_list.found_average_daily_dose )
then
// Find all average dosage range and average maps
average_dosage_range := dosage_range_list where (dosage_range_list.match_found AND
dosage_range_list.dosage_type = "average" );
average_maps := med_dosage_map_list where ( med_dosage_map_list.dosage_type = "average");
// Set <User Scheduled> Weekly Flag to true
average_tracker_list.user_scheduled_weekly_used := TRUE;
// Suppress Alert for Outside Average Daily Dose by setting it to false.
// And set the Suppress_Alert audit trail flag
average_tracker_list.outside_average_daily_dose := FALSE;
average_tracker_list.suppress_alert := TRUE;
average_dosage_range.match_found := false;
average_maps.above_range := false;
average_maps.below_range := false;
endif; //if ANY (med_data_list.order_interval = "Weekly" )
//---------------------------------------------
// Clinical Rule For Irregular <User Schedule>
//---------------------------------------------
// If the frequency is <User Schedule>
// and the type of schedule is "Irregular"
// and the order is a "Regular" or "IV-Additive Order"
// and there are average-daily dose criteria
// and the flag for showing irregular message is true
// then show the Alert that average-daily dose could not be checked.
//
// This rules does not apply to Complex Orders
// because we do not check their average-daily doses and
// because the user cannot select an "Irregular" schedule
if ANY (med_data_list.order_interval = "Irregular" )
and ANY (med_data_list.order_med_frequency = "<User Schedule>" )
and ANY (average_tracker_list.found_average_daily_dose )
then
// Find all average dosage range and average maps
average_dosage_range := dosage_range_list where (dosage_range_list.match_found AND
dosage_range_list.dosage_type = "average" );
average_maps := med_dosage_map_list where ( med_dosage_map_list.dosage_type = "average");
// Set Irregular Flag to true
average_tracker_list.irregular_schedule_used := TRUE;
// Suppress Alert for Outside Average Daily Dose
// by setting it to false.
average_tracker_list.outside_average_daily_dose := FALSE;
average_tracker_list.suppress_alert := TRUE;
average_dosage_range.match_found := false;
average_maps.above_range := false;
average_maps.below_range := false;
endif; //if ANY (med_data_list.order_interval = "Irregular" )
//----------------------------------------------------
// Clinical Rule For Doses Administered Under 24 Hours
//----------------------------------------------------
// DO NOT alert if the order is a loading dose for
// a NOW & THEN complex order. This type of order has
// a NULL frequency and a time interval of 1 minute.
//
// If the user has selected StopAfter
// and the duration of the order is < 24 hours
// and (Total Dose Criteria exists or Average Dose Criteria Exists)
// 1. DO NOT alert if the user selected StopAfter X-Times or StopAfter X-Days
// because the Total Dose and Average Dose can be determined.
// 2. DO Alert if the user selected StopAter X-Minutes or StopAfter X-Hours
// that resuls in a duration under 24 hours
// because the Total Dose and Average Dose cannot be determined.
//
// If the user has NOT selected StopAfter
// and ((StopDtm - SignificantDtm) < 24 hours
// and (Total Dose Criteria exists or Average Dose Criteria Exists)
// then Alert Total Dose and/or Average Dose cannot be determined.
for med_data in med_data_list do
// Initialize Variable
met_criteria_under_24_hours := FALSE;
//Calculate the Duration of the Order
if med_data.stop_after_option_type = 1
then order_duration := med_data.stop_after_value DAY;
elseif med_data.stop_after_option_type = 2
then order_duration := med_data.stop_after_value HOUR;
elseif med_data.stop_after_option_type = 3
then order_duration := med_data.stop_after_value MINUTE;
elseif exist med_data.stop_dtm
then order_duration := med_data.stop_dtm - med_data.order_med_significant_date;
else
order_duration := NULL;
endif;
// Determine if Order has Met the Criteria for Duration Under 24 Hours
if order_duration < 24 hours
then
if med_data.med_order_type = "Complex Order"
and med_data.order_med_frequency is NULL
and order_duration = 1 minute
then
// This is a loading dose for a NOW and THEN order
// so do not alert about under 24-hours.
met_criteria_under_24_hours := FALSE;
elseif med_data.stop_after_option_type = 1 //days
or med_data.stop_after_option_type = 4 //times
then
met_criteria_under_24_hours := FALSE;
elseif ( med_data.stop_after_option_type = 2 //hours
or med_data.stop_after_option_type = 3 ) //minutes
and med_data.admin_dtm_list_calc_method = "MLM" // estimated method
then
met_criteria_under_24_hours := TRUE;
elseif exist med_data.stop_dtm
and (med_data.stop_after_option_type = 0 //not a stopafter
or med_data.stop_after_option_type is NULL)
and med_data.admin_dtm_list_calc_method = "MLM" // estimated method
then
met_criteria_under_24_hours := TRUE;
else
met_criteria_under_24_hours := FALSE; // formally TRUE
endif;
endif; //order_duration < 24 hours
// Find the Matching Average Tracker and Total Tracker Objects
// That have Average Daily or Total Daily Dose Criteria
if met_criteria_under_24_hours
then
found_average_tracker := 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
AND average_tracker_list.route = med_data.order_med_route
AND average_tracker_list.found_average_daily_dose );
found_total_tracker := 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
AND total_tracker_list.route = med_data.order_med_route
AND total_tracker_list.found_total_daily_dose );
all_average_dosage_range := dosage_range_list where (dosage_range_list.match_found AND
dosage_range_list.dosage_type = "average" );
found_average_maps := med_dosage_map_list where (med_dosage_map_list.med_sort_number in found_average_tracker.sort_number AND
med_dosage_map_list.dosage_range_sort_number in all_average_dosage_range.sort_number AND
med_dosage_map_list.dosage_type = "average");
found_average_dosage_range := dosage_range_list where (
dosage_range_list.sort_number in found_average_maps.dosage_range_sort_number);
all_total_dosage_range := dosage_range_list where (dosage_range_list.match_found AND
dosage_range_list.dosage_type = "total" );
found_total_maps := med_dosage_map_list where (med_dosage_map_list.med_sort_number in found_total_tracker.sort_number AND
med_dosage_map_list.dosage_range_sort_number in all_total_dosage_range.sort_number AND
med_dosage_map_list.dosage_type = "total");
found_total_dosage_range := dosage_range_list where (
dosage_range_list.sort_number in found_total_maps.dosage_range_sort_number);
if exist found_average_tracker
then
// Set flags in Object
found_average_tracker.met_criteria_under_24_hours := met_criteria_under_24_hours;
// Suppress Alert for Outside Average Daily Dose by setting it to false.
// And setting the Suppress_Alert flag as a audit trail.
found_average_tracker.outside_average_daily_dose := FALSE;
found_average_tracker.suppress_alert := TRUE;
found_average_maps.above_range := false;
found_average_maps.below_range := false;
found_average_dosage_range.match_found := false;
endif;
if exist found_total_tracker
then
// Set flags in Object
found_total_tracker.met_criteria_under_24_hours := met_criteria_under_24_hours;
// Suppress Alert for Outside Total Daily Dose by setting it to false.
// And setting the Suppress_Alert flag as a audit trail.
found_total_tracker.outside_total_daily_dose := FALSE;
found_total_tracker.suppress_alert := TRUE;
found_total_maps.above_range := false;
found_total_maps.below_range := false;
found_total_dosage_range.match_found := false;
endif;
endif; // if met_criteria_under_24_hours
enddo; //for med_data
// If any fequency in the component list is based on shift then
// a warning needs to be displayed.
if any med_data_list.isShiftFrequency = true
then
shiftData := med_data_list where
(med_data_list.isShiftFrequency = true);
// Only warn if an Average or Total warning was calculated.
found_average_tracker := average_tracker_list where
(average_tracker_list.med_order_type is in (shiftData.med_order_type)
AND average_tracker_list.med_name is in (shiftData.order_med_name)
AND average_tracker_list.uom is in (shiftData.order_med_units)
AND average_tracker_list.route is in (shiftData.order_med_route)
AND average_tracker_list.found_average_daily_dose
AND average_tracker_list.outside_average_daily_dose );
found_total_tracker := total_tracker_list where
(total_tracker_list.med_order_type is in (shiftData.med_order_type)
AND total_tracker_list.med_name is in (shiftData.order_med_name)
AND total_tracker_list.uom is in (shiftData.order_med_units)
AND total_tracker_list.route is in (shiftData.order_med_route)
AND total_tracker_list.found_total_daily_dose
AND total_tracker_list.outside_total_daily_dose );
all_average_dosage_range := dosage_range_list where (dosage_range_list.match_found AND
dosage_range_list.dosage_type = "average" );
found_average_maps := med_dosage_map_list where (med_dosage_map_list.med_sort_number in found_average_tracker.sort_number AND
med_dosage_map_list.dosage_range_sort_number in all_average_dosage_range.sort_number AND
med_dosage_map_list.dosage_type = "average");
found_average_dosage_range := dosage_range_list where (
dosage_range_list.sort_number in found_average_maps.dosage_range_sort_number);
all_total_dosage_range := dosage_range_list where (dosage_range_list.match_found AND
dosage_range_list.dosage_type = "total" );
found_total_maps := med_dosage_map_list where (med_dosage_map_list.med_sort_number in found_total_tracker.sort_number AND
med_dosage_map_list.dosage_range_sort_number in all_total_dosage_range.sort_number AND
med_dosage_map_list.dosage_type = "total");
found_total_dosage_range := dosage_range_list where (
dosage_range_list.sort_number in found_total_maps.dosage_range_sort_number);
// If some administration times were generated, they need to be supressed
// for the items that used the shift based frequency
if exists found_average_tracker then
found_average_tracker.met_criteria_has_shift_frequency := true;
// Suppress Alert for Outside Average Daily Dose by setting it to false.
// And setting the Suppress_Alert flag as a audit trail.
found_average_tracker.outside_average_daily_dose := FALSE;
found_average_tracker.suppress_alert := TRUE;
found_average_maps.above_range := false;
found_average_maps.below_range := false;
found_average_dosage_range.match_found := false;
endif;
if exists found_total_tracker then
found_total_tracker.met_criteria_has_shift_frequency := true;
// Suppress Alert for Outside Total Daily Dose by setting it to false.
// And setting the Suppress_Alert flag as a audit trail.
found_total_tracker.outside_total_daily_dose := FALSE;
found_total_tracker.suppress_alert := TRUE;
found_total_maps.above_range := false;
found_total_maps.below_range := false;
found_total_dosage_range.match_found := false;
endif;
endif;
med_dosage_map_list.sort_number := 1 seqto (count med_dosage_map_list);
hard_stop_low_doses := dosage_range_list where dosage_range_list.hard_stop_low = true;
hard_stop_high_doses := dosage_range_list where dosage_range_list.hard_stop_high = true;
med_with_hard_Stop := exists (med_dosage_map_list
where (med_dosage_map_list.dosage_range_sort_number in hard_stop_low_doses.sort_number and med_dosage_map_list.below_range)
or (med_dosage_map_list.dosage_range_sort_number in hard_stop_high_doses.sort_number and med_dosage_map_list.above_range)
or (med_dosage_map_list.dosage_type = "contraindication" and med_dosage_map_list.match_found = true and
(med_dosage_map_list.dosage_range_sort_number in hard_stop_low_doses.sort_number or med_dosage_map_list.dosage_range_sort_number in hard_stop_high_doses.sort_number)));
inapplicable_route_found := exists( dosage_range_list where dosage_range_list.inapplicable_route_conversion_issue = true );
map_with_frequency_issue_list := med_dosage_map_list
where med_dosage_map_list.dose_frequency not in intentionally_unmapped_frequency_list
and med_dosage_map_list.frequency_issue is not null;
show_frequency_warning := exists (map_with_frequency_issue_list)
and ( ( alert_if_missing_flags.unmapped_frequency
and any (map_with_frequency_issue_list.frequency_issue = "unmapped"))
or ( any (map_with_frequency_issue_list.frequency_issue = "too frequent")));
// get the catalog dose ranges that match the prescription only at the
// dnum level
dnum_match_catalog_dose_range_list := ();
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;
/*----------------------------------*/
/* Format Alert Range Error Details */
/*----------------------------------*/
if any med_data_list.outside_single_dosage_range
OR any med_data_list.contraindication_found
OR any average_tracker_list.outside_average_daily_dose
OR any total_tracker_list.outside_total_daily_dose
OR (any average_tracker_list.user_scheduled_weekly_used
and show_user_scheduled_weekly_message )
OR (any average_tracker_list.irregular_schedule_used
and show_irregular_message )
OR (any total_tracker_list.met_criteria_under_24_hours
and show_under_24_hour_message)
OR (any average_tracker_list.met_criteria_under_24_hours
and show_under_24_hour_message)
OR (any total_tracker_list.met_criteria_has_shift_frequency
and show_has_shift_frequency_message)
OR (any average_tracker_list.met_criteria_has_shift_frequency
and show_has_shift_frequency_message)
OR (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.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 (missing_route
and alert_if_missing_flags.route)
OR (unmapped_route
and alert_if_missing_flags.unmapped_route)
OR (uom_conversion_issue
and alert_if_missing_flags.uom_conversion)
OR (missing_uom
and alert_if_missing_flags.uom)
OR (unmapped_uom
and alert_if_missing_flags.unmapped_uom)
OR (patient_info.Gender.is_unmapped
and alert_if_missing_flags.unmapped_gender)
OR (any med_data_list.unmapped_drug
and alert_if_missing_flags.unmapped_drug)
OR (any med_data_list.unmapped_grouper
and alert_if_missing_flags.unmapped_grouper)
OR (any patient_info.DNum_Grouper.is_unmapped
and alert_if_missing_flags.cannot_check_DNUM_Rx_To_Multum)
OR (exists (dnum_match_catalog_dose_range_list)
and alert_if_missing_flags.cannot_check_Rx_to_IC )
OR (any med_data_list.generic_route
and alert_if_missing_flags.cannot_check_generic_route)
OR ( inapplicable_route_found
and alert_if_missing_flags.inapplicable_route )
OR ( show_frequency_warning )
then
(alert_detail_text,
missing_data_list,
cannot_check_list,
alert_abstract ):= call func_dosage_messages with
(
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
) ;
endif; //if any med_data_list.outside_single_dosage_range
/* Always Conclude True to Return Data */
conclude true;
;;
action:
return
(alert_detail_text,
average_tracker_list,
total_tracker_list,
missing_data_list,
cannot_check_list,
med_with_hard_stop,
show_frequency_warning,
alert_abstract);
;;
end: