From 2d9fba1b92f323ecb6c4470fa61a39c3b8255bee Mon Sep 17 00:00:00 2001 From: bradymiller Date: Fri, 26 Nov 2010 01:08:22 -0800 Subject: [PATCH] Interim development of a clinical decision making engine. Engine depends on rules, filters, targets, and actions. Basically, if a patient fits in the filter, and the target(s) is false, then the action(s) happens. The current scheme allows one filter and multiple targets and actions per rule, is very flexible, and supports internationalization. Engine is used for clinical decision support, clinical quality measures (CQM) and patient reminders. FUNCTIONALITY: 1) Clinical Decision Support widget can be found in the top right of the patient summary screen. 2) Clinical Reminder widget can be found in bottom left (above vitals widget) of the patient summary screen. 3) Clinical Reminder page can be found at Administration->Patient Reminders. The batch to send the messages can be run from this script by clicking the Send REminder Batch button. 4) CQM report can be found at Reports->Clinic->Quality Measures. TODO: 1. Finish rules for the 10 CQM rules (will require algorithm adjustments to deal with the encounter types and frequencies that are used in the CQM rules). 2. Ensure NIST is accomplished for CQM and clinical decision support. 3. Get the email and voice patient reminder mechanisms to work (may ask Visolve to help with testing the modified mavix//voice email scripts). 4. Ensure NIST is accomplished for the patient reminders. 5. Add a admin gui to allow per patient customization (note the mechanism to do this already exist, so just need a simple gui for it) 6. Add mechanism to allow multiple filters per rule. 7. Add a admin gui to allow rule modification and creation of new rules. 8. Add a mechanism for plans. --- .../batchcom/batch_phone_notification.php | 250 ++++ interface/batchcom/batch_reminders.php | 73 + interface/main/left_nav.php | 6 + .../reminder/patient_reminders.php | 242 ++++ interface/patient_file/rules/patient_data.php | 228 ++++ .../summary/clinical_reminders_fragment.php | 27 + .../patient_file/summary/demographics.php | 52 +- .../summary/patient_reminders_fragment.php | 27 + interface/reports/cqm.php | 301 +++++ library/clinical_rules.php | 1172 +++++++++++++++++ library/forms.inc | 27 +- library/globals.inc.php | 28 + library/maviq_phone_api.php | 129 ++ library/patient.inc | 19 +- library/reminders.php | 302 +++++ .../batch_phone_notification.php | 250 ++++ .../sms_email_reminder/batch_reminders.php | 74 ++ sql/database.sql | 725 ++++++++++ 18 files changed, 3919 insertions(+), 13 deletions(-) create mode 100644 interface/batchcom/batch_phone_notification.php create mode 100644 interface/batchcom/batch_reminders.php create mode 100644 interface/patient_file/reminder/patient_reminders.php create mode 100644 interface/patient_file/rules/patient_data.php create mode 100644 interface/patient_file/summary/clinical_reminders_fragment.php create mode 100644 interface/patient_file/summary/patient_reminders_fragment.php create mode 100644 interface/reports/cqm.php create mode 100644 library/clinical_rules.php create mode 100644 library/maviq_phone_api.php create mode 100644 library/reminders.php create mode 100644 modules/sms_email_reminder/batch_phone_notification.php create mode 100644 modules/sms_email_reminder/batch_reminders.php diff --git a/interface/batchcom/batch_phone_notification.php b/interface/batchcom/batch_phone_notification.php new file mode 100644 index 00000000000..e6dcaadaa8a --- /dev/null +++ b/interface/batchcom/batch_phone_notification.php @@ -0,0 +1,250 @@ + +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +//////////////////////////////////////////////////////////////////// +// Package: cron_phone_notification +// Purpose: to be run by cron every hour, look for appointments +// in the pre-notification period and send an phone reminder +// Based on cron_email_notification by Larry Lart +// Created by: +// Updated by: Maviq on 01/12/2010 +//////////////////////////////////////////////////////////////////// + +$backpic = ""; +//phone notification +$ignoreAuth=1; + +//Set the working directory to the path of the file +$current_dir = dirname($_SERVER['SCRIPT_FILENAME']); +chdir($current_dir); + +//SANITIZE ALL ESCAPES +$sanitize_all_escapes=true; + +//STOP FAKE REGISTER GLOBALS +$fake_register_globals=false; + +require_once("../../interface/globals.php"); +require_once("$srcdir/maviq_phone_api.php"); +require_once("$srcdir/formdata.inc.php"); + +$type = "Phone"; +$before_trigger_hours = 72; // 3 days is default +//Get the values from Global +$before_trigger_hours = $GLOBALS['phone_notification_hour']; +//set up the phone notification settings for external phone service +$phone_url = $GLOBALS['phone_gateway_url'] ; +$phone_id = $GLOBALS['phone_gateway_username']; +$phone_token = $GLOBALS['phone_gateway_password']; +$phone_time_range = $GLOBALS['phone_time_range']; + +//get the facility_id-message map +$facilities = cron_getFacilitiesMap(); +//print_r($facilities); +$fac_phone_map = $facilities['phone_map']; +$fac_msg_map = $facilities['msg_map']; + +// get patient data for send alert +$db_patient = cron_getPhoneAlertpatientData($type, $before_trigger_hours); +echo "
" . htmlspecialchars( xl("Total Records Found") . ": " . count($db_patient), ENT_QUOTES); + +//Create a new instance of the phone service client +$client = new MaviqClient($phone_id, $phone_token, $phone_url); + +for($p=0;$p $prow['fname'], + "lastName" => $prow['lname'], + "phone" => $prow['phone_home'], + "apptDate" => $appt_date, + "apptTime" => $appt_time, + "doctor" => $prow['pc_aid'], + "greeting" => $greeting, + "timeRange" => $phone_time_range, + "type" => "appointment", + "timeZone" => date('P'), + "callerId" => $fac_phone_map[$prow['pc_facility']] + ); + + //Make the call + $response = $client->sendRequest("appointment", "POST", $data); + + // check response for success or error + if($response->IsError) { + $strMsg = "Error starting phone call for {$prow['fname']} | {$prow['lname']} | {$prow['phone_home']} | {$appt_date} | {$appt_time} | {$response->ErrorMessage}\n"; + } + else { + $strMsg = "\n========================".$type." || ".date("Y-m-d H:i:s")."========================="; + $strMsg .= "\nPhone reminder sent successfully: {$prow['fname']} | {$prow['lname']} | | {$prow['phone_home']} | {$appt_date} | {$appt_time} "; + // insert entry in notification_log table + cron_InsertNotificationLogEntry($prow,$greeting,$phone_url); + + //update entry >> pc_sendalertsms='Yes' + cron_updateentry($type,$prow['pid'],$prow['pc_eid']); + + } + + //echo $strMsg; + WriteLog( $strMsg ); + +} + +sqlClose(); + +//////////////////////////////////////////////////////////////////// +// Function: cron_updateentry +// Purpose: update status yes if alert send to patient +//////////////////////////////////////////////////////////////////// +function cron_updateentry($type,$pid,$pc_eid) +{ + + $query = "update openemr_postcalendar_events set "; + + // larry :: and here again same story - this time for sms pc_sendalertsms - no such field in the table + if($type=='SMS') + $query.=" pc_sendalertsms='YES' "; + elseif ($type=='Email') + $query.=" pc_sendalertemail='YES' "; + //Added by Yijin for phone reminder.. Uses the same field as SMS. + elseif($type=='Phone') + $query.=" pc_sendalertsms='YES' "; + + $query .=" where pc_pid=? and pc_eid=? "; + //echo "
".$query; + $db_sql = (sqlStatement($query, array($pid, $pc_eid))); +} + +//////////////////////////////////////////////////////////////////// +// Function: cron_getPhoneAlertpatientData +// Purpose: get patient data for send to alert +//////////////////////////////////////////////////////////////////// +function cron_getPhoneAlertpatientData( $type, $trigger_hours ) +{ + + //Added by Yijin 1/12/10 to handle phone reminders. Patient needs to have hipaa Voice flag set to yes and a home phone + if($type=='Phone'){ + $ssql = " and pd.hipaa_voice='YES' and pd.phone_home<>'' and ope.pc_sendalertsms='NO' and ope.pc_apptstatus != '*' "; + + $check_date = date("Y-m-d", mktime(date("H")+$trigger_hours, 0, 0, date("m"), date("d"), date("Y"))); + + } + + $patient_field = "pd.pid,pd.title,pd.fname,pd.lname,pd.mname,pd.phone_cell,pd.email,pd.hipaa_allowsms,pd.hipaa_allowemail,pd.phone_home,pd.hipaa_voice,"; + $ssql .= " and (ope.pc_eventDate=?)"; + + $query = "select $patient_field pd.pid,ope.pc_eid,ope.pc_pid,ope.pc_title, + ope.pc_hometext,ope.pc_eventDate,ope.pc_endDate, + ope.pc_duration,ope.pc_alldayevent,ope.pc_startTime,ope.pc_endTime,ope.pc_facility + from + openemr_postcalendar_events as ope ,patient_data as pd + where + ope.pc_pid=pd.pid $ssql + order by + ope.pc_eventDate,ope.pc_endDate,pd.pid"; + + $db_patient = (sqlStatement($query) , array($check_date) ); + $patient_array = array(); + $cnt=0; + while ($prow = sqlFetchArray($db_patient)) + { + $patient_array[$cnt] = $prow; + $cnt++; + } + return $patient_array; +} + +//////////////////////////////////////////////////////////////////// +// Function: cron_InsertNotificationLogEntry +// Purpose: insert log entry in table +//////////////////////////////////////////////////////////////////// +function cron_InsertNotificationLogEntry($prow,$phone_msg,$phone_gateway) +{ + $patient_info = $prow['title']." ".$prow['fname']." ".$prow['mname']." ".$prow['lname']."|||".$prow['phone_home']; + + $message = $phone_msg; + + $sql_loginsert = "INSERT INTO `notification_log` ( `iLogId` , `pid` , `pc_eid` , `message`, `type` , `patient_info` , `smsgateway_info` , `pc_eventDate` , `pc_endDate` , `pc_startTime` , `pc_endTime` , `dSentDateTime` ) VALUES "; + $sql_loginsert .= "(NULL , ?, ?, ?, 'Phone', ?, ?, ?, ?, ?, ?, ?)"; + $db_loginsert = ( sqlStatement( $sql_loginsert ), array($prow[pid], $prow[pc_eid], $message, $patient_info, $phone_gateway, $prow[pc_eventDate], $prow[pc_endDate], $prow[pc_startTime], $prow[pc_endTime], date("Y-m-d H:i:s")) ); +} + +//////////////////////////////////////////////////////////////////// +// Function: WriteLog +// Purpose: written log into file +//////////////////////////////////////////////////////////////////// +function WriteLog( $data ) +{ + $log_file = $GLOBALS['phone_reminder_log_dir']; + + if ($log_file != null) { + + $filename = $log_file . "/"."phone_reminder_cronlog_".date("Ymd").".html"; + + if (!$fp = fopen($filename, 'a')) + { + print "Cannot open file ($filename)"; + + }else { + + $sdata = "\n====================================================================\n"; + + if (!fwrite($fp, $data.$sdata)) + { + print "Cannot write to file ($filename)"; + } + + fclose($fp); + } + } +} +//////////////////////////////////////////////////////////////////// +// Function: cron_getFacilities +// Purpose: get facilities data once and store in map +//////////////////////////////////////////////////////////////////// +function cron_getFacilitiesMap() +{ + //get the facility_name-message map from Globals + $message_map = $GLOBALS['phone_appt_message']; + //create a new array to store facility_id to message map + $facility_msg_map = array(); + $facility_phone_map = array(); + //get facilities from the database + $query = "select fac.id, fac.name, fac.phone from facility as fac"; + $db_res = (sqlStatement($query)); + while ($prow = sqlFetchArray($db_res)) + { + $facility_msg_map[$prow['id']] = $message_map[$prow['name']]; + $facility_phone_map[$prow['id']] = $prow['phone']; + } + + $facility_map = array( + 'msg_map' => $facility_msg_map, + 'phone_map' => $facility_phone_map + ); + + return $facility_map; + +} +?> + diff --git a/interface/batchcom/batch_reminders.php b/interface/batchcom/batch_reminders.php new file mode 100644 index 00000000000..3ef9ac62dfb --- /dev/null +++ b/interface/batchcom/batch_reminders.php @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + +

+ + + +
+
+
+
+
+
+
+
+
+
+ + + +

+
+
+
+
+
+
+ +

+ +



+
+

+ + + diff --git a/interface/main/left_nav.php b/interface/main/left_nav.php index e1694269140..5e553854022 100644 --- a/interface/main/left_nav.php +++ b/interface/main/left_nav.php @@ -990,6 +990,7 @@ function selpopup(selobj) { + @@ -1015,6 +1016,11 @@ function selpopup(selobj) { +
  • +
      + +
    +
    • diff --git a/interface/patient_file/reminder/patient_reminders.php b/interface/patient_file/reminder/patient_reminders.php new file mode 100644 index 00000000000..8128778fa2a --- /dev/null +++ b/interface/patient_file/reminder/patient_reminders.php @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + +
      +   + + + +
      +
      + class="css_button" onclick="top.restoreSession()"> + + +
      + +
      +   +
      + +" . + "\"".htmlspecialchars(xl('Sort"; +} +for($i = 0; $i < count($sort); $i++) { + if($sortby == $sort[$i]) { + switch($sortorder) { + case "asc" : $sortlink[$i] = "" . + "\"".htmlspecialchars(xl('Sort"; + break; + case "desc" : $sortlink[$i] = "" . + "\"".htmlspecialchars(xl('Sort"; + break; + } break; + } +} +// This is for managing page numbering and display beneath the Patient Reminders table. +$listnumber = 25; +$sqlBindArray = array(); +if (!empty($patient_id)) { + $add_sql = "AND a.pid=? "; + array_push($sqlBindArray,$patient_id); +} +$sql = "SELECT a.id, a.due_status, a.category, a.item, a.date_created, a.date_sent, b.fname, b.lname " . + "FROM `patient_reminders` as a, `patient_data` as b " . + "WHERE a.active='1' AND a.pid=b.pid ".$add_sql; +$result = sqlStatement($sql, $sqlBindArray); +if(sqlNumRows($result) != 0) { + $total = sqlNumRows($result); +} +else { + $total = 0; +} +if($begin == "" or $begin == 0) { + $begin = 0; +} +$prev = $begin - $listnumber; +$next = $begin + $listnumber; +$start = $begin + 1; +$end = $listnumber + $start - 1; +if($end >= $total) { + $end = $total; +} +if($end < $start) { + $start = 0; +} +if($prev >= 0) { + $prevlink = "<<"; +} +else { + $prevlink = "<<"; +} + +if($next < $total) { + $nextlink = ">>"; +} +else { + $nextlink = ">>"; +} +?> + +
      + + + + + +
      +
      + + + + +
      + +
      +
      +
      + + + + + +
      +
      + + + + + + + + +
      +
      +
      +
      + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      '1','list_id'=>'rule_action_category'),$myrow['category']) . " : " . + generate_display_field(array('data_type'=>'1','list_id'=>'rule_action'),$myrow['item']); ?>'1','list_id'=>'rule_reminder_due_opt'),$myrow['due_status']); ?>
      +
      + + + + + diff --git a/interface/patient_file/rules/patient_data.php b/interface/patient_file/rules/patient_data.php new file mode 100644 index 00000000000..72ceff014a7 --- /dev/null +++ b/interface/patient_file/rules/patient_data.php @@ -0,0 +1,228 @@ + +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +//SANITIZE ALL ESCAPES +$sanitize_all_escapes=true; +// + +//STOP FAKE REGISTER GLOBALS +$fake_register_globals=false; +// + +require_once("../../globals.php"); +require_once("$srcdir/acl.inc"); +require_once("$srcdir/options.inc.php"); + +?> + + + + + + + + + + + + + + + + + + +(" . htmlspecialchars( xl('Not authorized'), ENT_NOQUOTES) . ")

      \n"; + echo "\n\n"; + exit(); +} + +if ($_POST['form_complete']) { + // Save that form as a row in rule_patient_data table + // and then close the window/modul. + + // Collect and trim variables + if (isset($_POST['form_entryID'])) $form_entryID = trim($_POST['form_entryID']); + $form_date = trim($_POST['form_date']); + $form_category = trim($_POST['form_category']); + $form_item = trim($_POST['form_item']); + $form_complete = trim($_POST['form_complete']); + $form_result = trim($_POST['form_result']); + + if (!isset($form_entryID)) { + // Insert new row of data into rule_patient_data table + sqlInsert("INSERT INTO `rule_patient_data` (`date`, `pid`, `category`, `item`, `complete`, `result`) " . + "VALUES (?,?,?,?,?,?)", array($form_date, $pid, $form_category, $form_item, $form_complete, $form_result) ); + } + else { // $form_mode == "edit" + // Modify selected row in rule_patient_data table + sqlStatement("UPDATE `rule_patient_data` " . + "SET `date`=?, `complete`=?, `result`=? " . + "WHERE `id`=?", array($form_date,$form_complete,$form_result,$form_entryID) ); + } + + // Close this window and refresh the patient summary display. + echo "\n\n\n\n\n"; + exit(); +} + +// Display the form +// Collect and trim variables +$category = trim($_GET['category']); +$item = trim($_GET['item']); +if (isset($_GET['entryID'])) $entryID = trim($_GET['entryID']); + +// Collect data if a specific entry is selected +if (isset($entryID)) { + $selectedEntry = sqlQuery("SELECT `date`, `complete`, `result` " . + "FROM `rule_patient_data` " . + "WHERE `id`=?", array($entryID) ); + $form_date = $selectedEntry['date']; + $form_complete = $selectedEntry['complete']; + $form_result = $selectedEntry['result']; +} + +?> + + + + + + +
      '1','list_id'=>'rule_action_category'),$category) . +" - " . generate_display_field(array('data_type'=>'1','list_id'=>'rule_action'),$item); ?>   
      + +

      +
      + + "; + + echo ""; + + echo ""; + echo "
      "; + echo htmlspecialchars( xl('Date/Time'), ENT_NOQUOTES); + echo ":"; + echo ""; + echo "[?]"; + echo ""; + echo "
      "; + echo htmlspecialchars( xl('Completed'), ENT_NOQUOTES); + echo ":"; + generate_form_field(array('data_type'=>1,'field_id'=>'complete','list_id'=>'yesno','empty_title'=>'SKIP'), ($form_complete) ? $form_complete : "YES"); + echo "
      "; + echo htmlspecialchars( xl('Results/Details'), ENT_NOQUOTES); + echo ":"; + echo ""; + echo "
      "; + echo ""; + echo ""; + if (isset($entryID)) { + echo ""; + } +?> +
      + +
      +
      +
      +
      += 1) { //display table ?> + + + + + + + + "; + } + else { + echo ""; + } + if (isset($entryID) && ($entryID == $row['id'])) { + // hide the edit button + echo ""; + } + else { // show the edit button + echo ""; + } + echo ""; + echo ""; + echo ""; + echo ""; + } ?> +
       
       " . + "" . htmlspecialchars( xl('Edit'), ENT_NOQUOTES) . "" . + "" . htmlspecialchars( $row['date'], ENT_NOQUOTES) . "" . htmlspecialchars( $row['complete'], ENT_NOQUOTES) . "" . nl2br( htmlspecialchars( $row['result'], ENT_NOQUOTES) ) . "
      +" . htmlspecialchars( xl('No previous entries.'), ENT_NOQUOTES) . "

      "; +} ?> +
      + + + diff --git a/interface/patient_file/summary/clinical_reminders_fragment.php b/interface/patient_file/summary/clinical_reminders_fragment.php new file mode 100644 index 00000000000..1403e735c0f --- /dev/null +++ b/interface/patient_file/summary/clinical_reminders_fragment.php @@ -0,0 +1,27 @@ + + diff --git a/interface/patient_file/summary/demographics.php b/interface/patient_file/summary/demographics.php index f4f8c3d02e7..70543eb25b0 100644 --- a/interface/patient_file/summary/demographics.php +++ b/interface/patient_file/summary/demographics.php @@ -171,7 +171,21 @@ function toggleIndicator(target,div) { $("#pnotes_ps_expand").load("pnotes_fragment.php"); $("#disclosures_ps_expand").load("disc_fragment.php"); $("#vitals_ps_expand").load("vitals_fragment.php"); - + $("#clinical_reminders_ps_expand").load("clinical_reminders_fragment.php", { 'embeddedScreen' : true }, function() { + // (note need to place javascript code here also to get the dynamic link to work) + $(".medium_modal").fancybox( { + 'overlayOpacity' : 0.0, + 'showCloseButton' : true, + 'frameHeight' : 500, + 'frameWidth' : 800, + 'centerOnScroll' : false, + 'callbackOnClose' : function() { + refreshme(); + } + }); + }); + $("#patient_reminders_ps_expand").load("patient_reminders_fragment.php"); + // fancy box enable_modals(); @@ -581,7 +595,26 @@ function toggleIndicator(target,div) {

      - + + + + +
      +

      + + + + "; + echo "

      "; + echo ""; + // appointments expand collapse widget $widgetTitle = xl("Appointments"); $widgetLabel = "appointments"; diff --git a/interface/patient_file/summary/patient_reminders_fragment.php b/interface/patient_file/summary/patient_reminders_fragment.php new file mode 100644 index 00000000000..7fd5495069b --- /dev/null +++ b/interface/patient_file/summary/patient_reminders_fragment.php @@ -0,0 +1,27 @@ + + diff --git a/interface/reports/cqm.php b/interface/reports/cqm.php new file mode 100644 index 00000000000..26d36b77cb2 --- /dev/null +++ b/interface/reports/cqm.php @@ -0,0 +1,301 @@ + + // + // This program is free software; you can redistribute it and/or + // modify it under the terms of the GNU General Public License + // as published by the Free Software Foundation; either version 2 + // of the License, or (at your option) any later version. + + // This report shows upcoming appointments with filtering and + // sorting by patient, practitioner, appointment type, and date. + +//SANITIZE ALL ESCAPES +$sanitize_all_escapes=true; +// + +//STOP FAKE REGISTER GLOBALS +$fake_register_globals=false; +// + +require_once("../globals.php"); +require_once("../../library/patient.inc"); +require_once("$srcdir/formatting.inc.php"); +require_once "$srcdir/options.inc.php"; +require_once "$srcdir/formdata.inc.php"; +require_once "$srcdir/clinical_rules.php"; + +// Collect parameters (set defaults if empty) +$target_date = (isset($_POST['form_target_date'])) ? trim($_POST['form_target_date']) : date('Y-m-d H:i:s'); +$rule_filter = (isset($_POST['form_rule_filter'])) ? trim($_POST['form_rule_filter']) : $rule_filter = "cqm"; +$provider = trim($_POST['form_provider']); + +?> + + + + + + + + +<?php echo htmlspecialchars( xl('Clinical Quality Measures'), ENT_NOQUOTES); ?> + + + + + + + + + + + + + + + + + - + + +
      + +
      + + + + + + +
      +
      + + + + + + + + + + + + + +
      + : + + '> + [?]'> +
      + : + +   + : + + \n"; + echo "
      + +
      + +
      + + + + +
      + +
      +
      + +
      + + + + +
      + + + + + + + + + + + + + + + + + + + + "; + if ($firstLabelFlag) { + echo "".generate_display_field(array('data_type'=>'1','list_id'=>'clinical_rules'),$element).""; + $firstLabelFlag = 0; + } + else { + echo htmlspecialchars( $element, ENT_NOQUOTES); + } + echo ""; + } + } + else { // $row[0] == "sub" + array_shift($row); + foreach($row as $element) { + echo ""; + } + } + ?> + + + + +
      + + + + + + + + + +
      "; + if ($firstLabelFlag) { + $titles = explode("::",$element); + echo generate_display_field(array('data_type'=>'1','list_id'=>'rule_action_category'),$titles[0]) . + ": " . generate_display_field(array('data_type'=>'1','list_id'=>'rule_action'),$titles[1]); + $firstLabelFlag = 0; + } + else { + echo htmlspecialchars( $element, ENT_NOQUOTES); + } + echo "
      +
      + +
      + +
      + + + + +
      + + + + + + + + + + + + diff --git a/library/clinical_rules.php b/library/clinical_rules.php new file mode 100644 index 00000000000..8aab75d6193 --- /dev/null +++ b/library/clinical_rules.php @@ -0,0 +1,1172 @@ + +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// Functions are kept here that will support the clinical rules. + +require_once(dirname(__FILE__) . "/patient.inc"); +require_once(dirname(__FILE__) . "/forms.inc"); +require_once(dirname(__FILE__) . "/formdata.inc.php"); +require_once(dirname(__FILE__) . "/options.inc.php"); + +// Display the clinical summary widget. +// Parameters: +// $patient_id - pid of selected patient +// $dateTarget - target date. If blank then will test with current date as target. +function clinical_summary_widget($patient_id,$dateTarget='') { + + // Set date to current if not set + $dateTarget = ($dateTarget) ? $dateTarget : date('Y-m-d H:i:s'); + + // Collect active actions + $actions = test_rules_clinic('','passive_alert',$dateTarget,'reminders',$patient_id); + + // Display the actions + foreach ($actions as $action) { + + if ($action['custom_flag']) { + // Start link for reminders that use the custom rules input screen + echo ""; + } + else if ($action['clin_rem_link']) { + // Start link for reminders that use the custom rules input screen + echo ""; + } + else { + // continue, since no link will be created + } + + // Display Reminder Details + echo generate_display_field(array('data_type'=>'1','list_id'=>'rule_action_category'),$action['category']) . + ": " . generate_display_field(array('data_type'=>'1','list_id'=>'rule_action'),$action['item']); + + if ($action['custom_flag'] || $action['clin_rem_link']) { + // End link for reminders that use an html link + echo ""; + } + + // Display due status + if ($action['due_status']) { + // Color code the status (red for past due, yellow for due, and black for soon due) + if ($action['due_status'] == "past_due") { + echo "  ("; + } + else if ($action['due_status'] == "due") { + echo "  ("; + } + else { + echo "  ("; + } + echo generate_display_field(array('data_type'=>'1','list_id'=>'rule_reminder_due_opt'),$action['due_status']) . ")
      "; + } + else { + echo "
      "; + } + + } +} + +// Test the clinic rules of entire clinic and create a report or patient reminders +// (can also test on one patient or patients of one provider) +// Parameters: +// $provider - id of a selected provider. If blank, then will test entire clinic. +// $type - rule filter (active_alert,passive_alert,cqm,patient_reminder). If blank then will test all rules. +// $dateTarget - target date. If blank then will test with current date as target. +// $mode - choose either 'report' or 'reminders' (required) +// $patient_id - pid of patient. If blank then will check all patients. +// Return: +// Returns a two-dimensional array of results that depends on the mode: +// reminders mode - returns an array of reminders (action array elements plus a 'pid' and 'due_status') +// report mode - returns an array of rows for the Clinical Quality Measures (CQM) report +function test_rules_clinic($provider='',$type='',$dateTarget='',$mode='',$patient_id='') { + + // Set date to current if not set + $dateTarget = ($dateTarget) ? $dateTarget : date('Y-m-d H:i:s'); + + // Prepare the results array + $results = array(); + + // Collect all patient ids + $patientData = array(); + if (!empty($patient_id)) { + // only look at the selected patient + array_push($patientData,$patient_id); + } + else { + if (empty($provider)) { + // Look at entire practice + $rez = sqlStatement("SELECT `pid` FROM `patient_data`"); + for($iter=0; $row=sqlFetchArray($rez); $iter++) { + $patientData[$iter]=$row; + } + } + else { + // Look at one provider + $rez = sqlStatement("SELECT `pid` FROM `patient_data` " . + "WHERE providerID=?", array($provider) ); + for($iter=0; $row=sqlFetchArray($rez); $iter++) { + $patientData[$iter]=$row; + } + } + } + // Go through each patient(s) + // + // If in report mode, then tabulate for each rule: + // Total Patients + // Patients that pass the filter + // Patients that pass the target + // If in reminders mode, then create reminders for each rule: + // Reminder that action is due soon + // Reminder that action is due + // Reminder that action is post-due + + //Collect applicable rules + if ($mode == "reminders") { + // Use per patient custom rules (if exist) + $rules = resolve_rules_sql($type,$patient_id); + } + else { // $mode = "report" + // Only use default rules (do not use patient custom rules + $rules = resolve_rules_sql($type); + } + + foreach( $rules as $rowRule ) { + + // If in reminder mode then need to collect the measurement dates + // from rule_reminder table + + $target_dates = array(); + if ($mode == "reminders") { + // Calculate the dates to check for + if ($type == "patient_reminder") { + $reminder_interval_type = "patient_reminder"; + } + else { // $type == "passive_alert" or $type == "active_alert" + $reminder_interval_type = "clinical_reminder"; + } + $target_dates = calculate_reminder_dates($rowRule['id'], $dateTarget, $reminder_interval_type); + } + else { // $mode == "reports" + // Only use the target date in the report + $target_dates[0] = $dateTarget; + } + + //Reset the counters + $total_patients = 0; + $pass_filter = 0; + $pass_target = 0; + + foreach( $patientData as $rowPatient ) { + + // Count the total patients + $total_patients++; + + $dateCounter = 1; // for reminder mode to keep track of which date checking + foreach ( $target_dates as $dateFocus ) { + + //Set date counter and reminder token (applicable for reminders only) + if ($dateCounter == 1) { + $reminder_due = "soon_due"; + } + else if ($dateCounter == 2) { + $reminder_due = "due"; + } + else { // $dateCounter == 3 + $reminder_due = "past_due"; + } + + // Check if pass filter + $passFilter = test_filter($rowPatient['pid'],$rowRule['id'],$dateFocus); + if ($passFilter) { + $pass_filter++; + } + else { + continue; + } + + // Check if pass target + $passTarget = test_targets($rowPatient['pid'],$rowRule['id'],'',$dateFocus); + if ($passTarget) { + $pass_target++; + break; + } + else { + if ($mode == "reminders") { + // place the actions into the reminder return array + $actionArray = resolve_action_sql($rowRule['id'],'1'); + foreach ($actionArray as $action) { + $action_plus = $action; + $action_plus['due_status'] = $reminder_due; + $action_plus['pid'] = $rowPatient['pid']; + $results = reminder_results_integrate($results, $action_plus); + } + } + } + $dateCounter++; + } + } + + // Calculate and save the data for the rule + if ($pass_filter > 0) { + $percentage = number_format(($pass_target/$pass_filter)*100) . xl('%'); + } + else { + $percentage = "0". xl('%'); + } + if ($mode == "report") { + $newRow=array("main", $rowRule['id'], $total_patients, $pass_filter, $pass_target, $percentage); + array_push($results, $newRow); + } + + // Find the number of target groups, and go through each one if more than one + $targetGroups = numberTargetGroups($rowRule['id']); + if ($targetGroups > 1) { + if ($mode == "reminders") { + $start_id = 2; + } + else { // $mode == "report" + $start_id = 1; + } + for ($i = $start_id; $i <= $targetGroups; $i++){ + + //Reset the target counter + $pass_target = 0; + + foreach( $patientData as $rowPatient ) { + + $dateCounter = 1; // for reminder mode to keep track of which date checking + foreach ( $target_dates as $dateFocus ) { + + //Set date counter and reminder token (applicable for reminders only) + if ($dateCounter == 1) { + $reminder_due = "soon_due"; + } + else if ($dateCounter == 2) { + $reminder_due = "due"; + } + else { // $dateCounter == 3 + $reminder_due = "past_due"; + } + + //Check if pass target + $passTarget = test_targets($rowPatient['pid'],$rowRule['id'],$i,$dateFocus); + if ($passTarget) { + $pass_target++; + break; + } + else { + if ($mode == "reminders") { + // place the actions into the reminder return array + $actionArray = resolve_action_sql($rowRule['id'],$i); + foreach ($actionArray as $action) { + $action_plus = $action; + $action_plus['due_status'] = $reminder_due; + $action_plus['pid'] = $rowPatient['pid']; + $results = reminder_results_integrate($results, $action_plus); + } + } + } + $dateCounter++; + } + } + + // Calculate and save the data for the rule + if ($pass_filter > 0) { + $percentage = number_format(($pass_target/$pass_filter)*100) . xl('%'); + } + else { + $percentage = "0". xl('%'); + } + + // Collect action for title (just use the first one, if more than one) + $actionArray = resolve_action_sql($rowRule['id'],$i); + $action = $actionArray[0]; + if ($mode == "report") { + $newRow=array("sub", $action['category']."::".$action['item'], " ", " ", $pass_target, $percentage); + array_push($results, $newRow); + } + } + } + } + + // Return the data + return $results; +} + +// Test filter of a selected rule on a selected patient +// Parameters: +// $patient_id - pid of selected patient. +// $rule - id(string) of selected rule +// $dateTarget - target date. +// Return: +// boolean (if pass filter then true, otherwise false) +function test_filter($patient_id,$rule,$dateTarget) { + + // Set date to current if not set + $dateTarget = ($dateTarget) ? $dateTarget : date('Y-m-d H:i:s'); + + // Collect patient information + $patientData = getPatientData($patient_id, "sex, DATE_FORMAT(DOB,'%Y %m %d') as DOB_TS"); + + // -------- Special Filters -------- + // Check for special flag required by many of the CQM rules, that uses a standard + // measurement year (Jan1-Dec31). This adjusted date would then be used for + // date to calculate patient age and as the start range if filtering for clinic + // appointments. The value (usually will be 1) of this + // contains how many years to include. + $adjustedDate1 = ''; + $adjustedDate2 = ''; + $filter = resolve_filter_sql($rule,'filt_measure_period'); + if (!empty($filter)) { + $row = $filter[0]; + if ($row['method_detail'] == "year") { + $tempDateArray = explode("-",$dateTarget); + $tempYear = $tempDateArray[0]; + // Set too one second before the measurement period + $adjustedDate1 = ($tempYear - $row['value']) . "-12-31 23:59:59"; + // Set too the first second of the measurement period + $adjustedDate2 = ($tempYear - ($row['value']-1)) . "-01-01 00:00:00"; + // Set target date to the last second of the measurement period + $dateTarget = ($tempYear - ($row['value']-1)) . "-12-31 23:59:59"; + } + } + + // -------- Age Filter ------------ + // Calculate patient age in years and months + if (!empty($adjustedDate1)) { + // See above Special Filters section in for details. + $patientAgeYears = convertDobtoAgeYearDecimal($patientData['DOB_TS'],$adjustedDate1); + $patientAgeMonths = convertDobtoAgeMonthDecimal($patientData['DOB_TS'],$adjustedDate1); + } + else { + $patientAgeYears = convertDobtoAgeYearDecimal($patientData['DOB_TS'],$dateTarget); + $patientAgeMonths = convertDobtoAgeMonthDecimal($patientData['DOB_TS'],$dateTarget); + } + // Min age (year) Filter (includes) (assume that there in not more than one of each) + $filter = resolve_filter_sql($rule,'filt_age_min'); + if (!empty($filter)) { + $row = $filter[0]; + if ($row ['method_detail'] == "year") { + if ( $row['value'] && ($row['value'] > $patientAgeYears) ) { + return false; + } + } + if ($row ['method_detail'] == "month") { + if ( $row['value'] && ($row['value'] > $patientAgeMonths) ) { + return false; + } + } + } + // Max age (year) Filter (includes) (assume that there in not more than one of each) + $filter = resolve_filter_sql($rule,'filt_age_max'); + if (!empty($filter)) { + $row = $filter[0]; + if ($row ['method_detail'] == "year") { + if ( $row['value'] && ($row['value'] < $patientAgeYears) ) { + return false; + } + } + if ($row ['method_detail'] == "month") { + if ( $row['value'] && ($row['value'] < $patientAgeMonths) ) { + return false; + } + } + } + + // -------- Gender Filter --------- + // Gender Filter (includes) (assume that there in not more than one of each) + $filter = resolve_filter_sql($rule,'filt_sex'); + if (!empty($filter)) { + $row = $filter[0]; + if ( $row['value'] && ($row['value'] != $patientData['sex']) ) { + return false; + } + } + + // -------- Database Filter ------ + // Database Filter (includes) + $filter = resolve_filter_sql($rule,'filt_database'); + if ((!empty($filter)) && !database_check($patient_id,$filter,'',$dateTarget)) return false; + + // -------- Diagnosis Filter ---- + // Set up diagnosis filter (includes) + $filter = resolve_filter_sql($rule,'filt_diagnosis'); + if ((!empty($filter)) && !diagnosis_check($patient_id,$filter,$dateTarget)) return false; + // Set up diagnosis filter (excludes) + $filter = resolve_filter_sql($rule,'filt_diagnosis',0); + if ((!empty($filter)) && diagnosis_check($patient_id,$filter,$dateTarget)) return false; + + // -------- Clinic Visit(s) Filter -------- + $filter = resolve_filter_sql($rule,'filt_encounter_min'); + if (!empty($filter)) { + $row = $filter[0]; + // For total number of appointments, simply get number of encounters + if (!empty($adjustedDate2)) { + // See above Special Filters section in for details. + $encounters = getEncounters($patient_id,$adjustedDate2,$dateTarget); + } + else { + $encounters = getEncounters($patient_id,'',$dateTarget); + } + (empty($encounters)) ? $totalNumberAppt = 0 : $totalNumberAppt = count($encounters); + if ($row['value'] && $totalNumberAppt < $row['value']) return false; + } + + // Passed all filters, so return true. + return true; +} + +// Return the number of target groups of a selected rule +// Parameters: +// $rule - id(string) of rule +// Return: +// integer, number of target groups associated with rule +function numberTargetGroups($rule) { + $numberGroups = 1; + + $sql = sqlQuery("SELECT max(`group_id`) as numberGroups FROM `rule_target` " . + "WHERE `id`=?", array($rule) ); + + if ($sql['numberGroups']) $numberGroups = $sql['numberGroups']; + + return $numberGroups; +} + +// Test targets of a selected rule on a selected patient +// Parameters: +// $patient_id - pid of selected patient. +// $rule - id(string) of selected rule (if blank, then will ignore grouping) +// $group_id - group id of target group +// $dateTarget - target date. +// Return: +// boolean (if target passes then true, otherwise false) +function test_targets($patient_id,$rule,$group_id='',$dateTarget) { + + // -------- Interval Target ---- + $interval = resolve_target_sql($rule,$group_id,'target_interval'); + + // -------- Database Target ---- + // Database Target (includes) + $target = resolve_target_sql($rule,$group_id,'target_database'); + if ((!empty($target)) && !database_check($patient_id,$target,$interval,$dateTarget)) return false; + + // Passed all target tests, so return true. + return true; +} + +// Function to return active rules +// Parameters: +// $type - rule filter (active_alert,passive_alert,cqm,patient_reminder) +// $patient_id - pid of selected patient. (if custom rule does not exist then +// will use the default rule. +// Return: array containing rules +function resolve_rules_sql($type='',$patient_id='0') { + + // Collect all default rules into an array + $sql = sqlStatement("SELECT * FROM `clinical_rules` WHERE `pid`=0 ORDER BY `id`"); + $returnArray= array(); + for($iter=0; $row=sqlFetchArray($sql); $iter++) { + array_push($returnArray,$row); + } + + // Now collect the pertinent rules + $newReturnArray = array(); + + // Need to select rules (use custom if exist) + foreach ($returnArray as $rule) { + $customRule = sqlQuery("SELECT * FROM `clinical_rules` WHERE `id`=? AND `pid`=?", array($rule['id'],$patient_id) ); + + // Decide if use default vs custom rule (preference given to custom rule) + if (!empty($customRule)) { + $goRule = $customRule; + } + else { + $goRule = $rule; + } + + // Use the chosen rule if set + if (!empty($type)) { + if ($goRule['active'] == 1 && $goRule["${type}_flag"] == 1) { + // active, so use the rule + array_push($newReturnArray,$goRule); + } + } + else { + if ($goRule['active'] == 1) { + // active, so use the rule + array_push($newReturnArray,$goRule); + } + } + } + $returnArray = $newReturnArray; + + return $returnArray; +} + +// Function to return applicable reminder dates (relative) +// Parameters: +// $rule - id(string) of selected rule +// $reminder_method - string label of filter type +// Return: array containing reminder features +function resolve_reminder_sql($rule,$reminder_method) { + $sql = sqlStatement("SELECT `method_detail`, `value` FROM `rule_reminder` " . + "WHERE `id`=? AND `method`=?", array($rule, $reminder_method) ); + + $returnArray= array(); + for($iter=0; $row=sqlFetchArray($sql); $iter++) { + array_push($returnArray,$row); + } + return $returnArray; +} + +// Function to return applicable filters +// Parameters: +// $rule - id(string) of selected rule +// $filter_method - string label of filter type +// $include_flag - to allow selection for included or excluded filters +// Return: array containing filters +function resolve_filter_sql($rule,$filter_method,$include_flag=1) { + $sql = sqlStatement("SELECT `method_detail`, `value`, `required_flag` FROM `rule_filter` " . + "WHERE `id`=? AND `method`=? AND `include_flag`=?", array($rule, $filter_method, $include_flag) ); + + $returnArray= array(); + for($iter=0; $row=sqlFetchArray($sql); $iter++) { + array_push($returnArray,$row); + } + return $returnArray; +} + +// Function to return applicable targets +// Parameters: +// $rule - id(string) of selected rule +// $group_id - group id of target group (if blank, then will ignore grouping) +// $target_method - string label of target type +// $include_flag - to allow selection for included or excluded targets +// Return: array containing targets +function resolve_target_sql($rule,$group_id='',$target_method,$include_flag=1) { + + if ($group_id) { + $sql = sqlStatement("SELECT `value`, `required_flag`, `interval` FROM `rule_target` " . + "WHERE `id`=? AND `group_id`=? AND `method`=? AND `include_flag`=?", array($rule, $group_id, $target_method, $include_flag) ); + } + else { + $sql = sqlStatement("SELECT `value`, `required_flag`, `interval` FROM `rule_target` " . + "WHERE `id`=? AND `method`=? AND `include_flag`=?", array($rule, $target_method, $include_flag) ); + } + + $returnArray= array(); + for($iter=0; $row=sqlFetchArray($sql); $iter++) { + array_push($returnArray,$row); + } + return $returnArray; +} + +// Function to return applicable actions +// Parameters: +// $rule - id(string) of selected rule +// $group_id - group id of target group (if blank, then will ignore grouping) +// Return: array containing actions +function resolve_action_sql($rule,$group_id='') { + + if ($group_id) { + $sql = sqlStatement("SELECT b.category, b.item, b.clin_rem_link, b.reminder_message, b.custom_flag " . + "FROM `rule_action` as a " . + "JOIN `rule_action_item` as b " . + "ON a.category = b.category AND a.item = b.item " . + "WHERE a.id=? AND a.group_id=?", array($rule,$group_id) ); + } + else { + $sql = sqlStatement("SELECT b.category, b.item, b.value, b.custom_flag " . + "FROM `rule_action` as a " . + "JOIN `rule_action_item` as b " . + "ON a.category = b.category AND a.item = b.item " . + "WHERE a.id=?", array($rule) ); + } + + $returnArray= array(); + for($iter=0; $row=sqlFetchArray($sql); $iter++) { + array_push($returnArray,$row); + } + return $returnArray; +} + +// Function to check database filters and targets +// Parameters: +// $patient_id - pid of selected patient. +// $filter - array containing filter/target elements +// $interval - used for the interval elements +// $dateTarget - target date. blank is current date. +// Return: boolean if check passed, otherwise false +function database_check($patient_id,$filter,$interval='',$dateTarget='') { + $isMatch = false; //matching flag + + // Set date to current if not set + $dateTarget = ($dateTarget) ? $dateTarget : date('Y-m-d H:i:s'); + + // Unpackage interval information + // (Assume only one for now and only pertinent for targets) + $intervalType = ''; + $intervalValue = ''; + if (!empty($interval)) { + $intervalType = $interval[0]['value']; + $intervalValue = $interval[0]['interval']; + } + + foreach( $filter as $row ) { + $temp_df = explode("::",$row['value']); + if ($temp_df[3] == "EXIST" || $temp_df[3] == "lt") { + if (exist_database_item($patient_id, $temp_df[0], $temp_df[1], $temp_df[2], $temp_df[4], $intervalType, $intervalValue, $dateTarget, $temp_df[3])) { + // Record the match + $isMatch = true; + } + else { + // If this is a required entry then return false + if ($row['required_flag']) return false; + } + } + else if ($temp_df[3] == "CUSTOM") { + if (exist_custom_item($patient_id, $temp_df[0], $temp_df[1], $temp_df[2], $temp_df[4], $intervalType, $intervalValue, $dateTarget)) { + // Record the match + $isMatch = true; + } + else { + // If this is a required entry then return false + if ($row['required_flag']) return false; + } + } + else if ($temp_df[3] == "LIFESTYLE") { + if (exist_lifestyle_item($patient_id, $temp_df[1], $temp_df[2], $dateTarget)) { + // Record the match + $isMatch = true; + } + else { + // If this is a required entry then return false + if ($row['required_flag']) return false; + } + } + else { + + } + } + + // return results of check + return $isMatch; +} + +// Function to check diagnosis filters and targets +// Parameters: +// $patient_id - pid of selected patient. +// $filter - array containing diagnosis filter/target elements +// $dateTarget - target date. blank is current date. +// Return: boolean if check passed, otherwise false +function diagnosis_check($patient_id,$filter,$dateTarget) { + $isMatch = false; //matching flag + + // Set date to current if not set + $dateTarget = ($dateTarget) ? $dateTarget : date('Y-m-d H:i:s'); + + foreach ( $filter as $row ) { + $temp_df = explode("::",$row['value']); + if (exist_diagnosis_item($patient_id, $temp_df[0], $temp_df[1], $dateTarget)) { + // Record the match + $isMatch = true; + } + else { + // If this is a required entry then return false + if ($row['required_flag']) return false; + } + } + + // return results of check + return $isMatch; +} + +// Function to check for existance of data in database for a patient +// Parameters: +// $patient_id - pid of selected patient. +// $table - selected mysql table +// $column - selected mysql column +// $data - selected data in the mysql database +// $min_items - mininum number of times the data element is recorded +// $intervalType - type of interval (ie. year) +// $intervalValue - searched for within this many times of the interval type +// $dateTarget - target date. +// $method - method of database check (EXIST or lt) +// Return: boolean if check passed, otherwise false +function exist_database_item($patient_id,$table,$column,$data,$min_items,$intervalType='',$intervalValue='',$dateTarget='',$method='EXIST') { + + // Set date to current if not set + $dateTarget = ($dateTarget) ? $dateTarget : date('Y-m-d H:i:s'); + + // Collect the correct column label for patient id in the table + $patient_id_label = collect_database_label('pid',$table); + + // Get the interval sql query string + $dateSql = sql_interval_string($table,$intervalType,$intervalValue,$dateTarget); + + // check for items + if (empty($column)) { + // simple search for any table entries + $sql = sqlStatement("SELECT * " . + "FROM `" . add_escape_custom($table) . "` " . + "WHERE `" . add_escape_custom($patient_id_label) . "`=?", array($patient_id) ); + } + else if (empty($data)) { + // search for number of non blank items + $sql = sqlStatement("SELECT `" . add_escape_custom($column) . "` " . + "FROM `" . add_escape_custom($table) . "` " . + "WHERE `" . add_escape_custom($column) ."`!='' " . + "AND `" . add_escape_custom($patient_id_label) . "`=?", array($patient_id) ); + } + else { + if ($method == "EXIST") { + // search for number of specific items + $sql = sqlStatement("SELECT `" . add_escape_custom($column) . "` " . + "FROM `" . add_escape_custom($table) . "` " . + "WHERE `" . add_escape_custom($column) ."`=? " . + "AND `" . add_escape_custom($patient_id_label) . "`=? " . + $dateSql, array($data,$patient_id) ); + } + else if ($method == "lt") { + // search for number of specific items less than $data + $sql = sqlStatement("SELECT `" . add_escape_custom($column) . "` " . + "FROM `" . add_escape_custom($table) . "` " . + "WHERE `" . add_escape_custom($column) ."`? " . + "AND `" . add_escape_custom($patient_id_label) . "`=? " . + $dateSql, array($data,$patient_id) ); + } + else { //$method == "ge" + // search for number of specific items greater than or equal to $data + $sql = sqlStatement("SELECT `" . add_escape_custom($column) . "` " . + "FROM `" . add_escape_custom($table) . "` " . + "WHERE `" . add_escape_custom($column) ."`>=? " . + "AND `" . add_escape_custom($patient_id_label) . "`=? " . + $dateSql, array($data,$patient_id) ); + } + } + + // return whether the mininum number of items exist + if (sqlNumRows($sql) >= $min_items) { + return true; + } + else { + return false; + } +} + +// Function to check for existance of data for a patient in the rule_patient_data table +// Parameters: +// $patient_id - pid of selected patient. +// $category - label in category column +// $item - label in item column +// $complete - label in complete column +// $min_items - mininum number of times the data element is recorded +// $intervalType - type of interval (ie. year) +// $intervalValue - searched for within this many times of the interval type +// $dateTarget - target date. +// Return: boolean if check passed, otherwise false +function exist_custom_item($patient_id,$category,$item,$complete,$min_items,$intervalType='',$intervalValue='',$dateTarget) { + + // Set the table + $table = 'rule_patient_data'; + + // Collect the correct column label for patient id in the table + $patient_id_label = collect_database_label('pid',$table); + + // Get the interval sql query string + $dateSql = sql_interval_string($table,$intervalType,$intervalValue,$dateTarget); + + // search for number of specific items + $sql = sqlStatement("SELECT `result` " . + "FROM `" . add_escape_custom($table) . "` " . + "WHERE `category`=? " . + "AND `item`=? " . + "AND `complete`=? " . + "AND `" . add_escape_custom($patient_id_label) . "`=? " . + $dateSql, array($category,$item,$complete,$patient_id) ); + + // return whether the mininum number of items exist + if (sqlNumRows($sql) >= $min_items) { + return true; + } + else { + return false; + } +} + +// Function to check for existance of data for a patient in lifestyle section +// Parameters: +// $patient_id - pid of selected patient. +// $lifestyle - selected label of mysql column of patient history +// $status - specific status of selected lifestyle element +// $dateTarget - target date. blank is current date. +// Return: boolean if check passed, otherwise false +function exist_lifestyle_item($patient_id,$lifestyle,$status,$dateTarget) { + + // Set date to current if not set + $dateTarget = ($dateTarget) ? $dateTarget : date('Y-m-d H:i:s'); + + // Collect pertinent history data + $history = getHistoryData($patient_id, $lifestyle,'',$dateTarget); + + // See if match + $stringFlag = strstr($history[$lifestyle], "|".$status); + if (empty($status)) { + // Only ensuring any data has been entered into the field + $stringFlag = true; + } + if ( $history[$lifestyle] && + $history[$lifestyle] != '|0|' && + $stringFlag ) { + return true; + } + else { + return false; + } +} + +// Function to check for diagnosis of a patient +// Parameters: +// $patient_id - pid of selected patient. +// $code_type - code type (ie. ICD9) +// $diagnosis - diagnosis code or label +// $dateTarget - target date. blank is current date. +// Return: boolean if check passed, otherwise false +function exist_diagnosis_item($patient_id,$code_type,$diagnosis,$dateTarget) { + + // Set date to current if not set + $dateTarget = ($dateTarget) ? $dateTarget : date('Y-m-d H:i:s'); + + if ($code_type=='CUSTOM') { + // Deal with custom code first (title column in lists table) + $response = sqlQuery("SELECT * FROM `lists` " . + "WHERE `type`='medical_problem' " . + "AND `date`<=? " . + "AND `pid`=? " . + "AND `title`=?", array($dateTarget,$patient_id,$diagnosis) ); + if (!empty($response)) return true; + } + else { + // Deal with the set code types (diagnosis column in lists table) + $response = sqlQuery("SELECT * FROM `lists` " . + "WHERE `type`='medical_problem' " . + "AND `date`<=? " . + "AND `pid`=? " . + "AND `diagnosis` LIKE ?", array($dateTarget,$patient_id,"%".$code_type.":".$diagnosis."%") ); + if (!empty($response)) return true; + } + + return false; +} + +// Function to return part of sql query to deal with interval +// Parameters: +// $table - selected mysql table +// $intervalType - type of interval (ie. year) +// $intervalValue - searched for within this many times of the interval type +// $dateTarget - target date. +// Return: string containing pertinent date interval filter for mysql query +function sql_interval_string($table,$intervalType,$intervalValue,$dateTarget) { + + $dateSql=""; + + // Collect the correct column label for date in the table + $date_label = collect_database_label('date',$table); + + // Deal with interval + if (!empty($intervalType)) { + switch($intervalType) { + case "year": + $dateSql = "AND (`" . add_escape_custom($date_label) . + "` BETWEEN DATE_SUB('" . add_escape_custom($dateTarget) . + "', INTERVAL " . add_escape_custom($intervalValue) . + " YEAR) AND '" . add_escape_custom($dateTarget) . "') "; + break; + case "month": + $dateSql = "AND (`" . add_escape_custom($date_label) . + "` BETWEEN DATE_SUB('" . add_escape_custom($dateTarget) . + "', INTERVAL " . add_escape_custom($intervalValue) . + " MONTH) AND '" . add_escape_custom($dateTarget) . "') "; + break; + case "week": + $dateSql = "AND (`" . add_escape_custom($date_label) . + "` BETWEEN DATE_SUB('" . add_escape_custom($dateTarget) . + "', INTERVAL " . add_escape_custom($intervalValue) . + " WEEK) AND '" . add_escape_custom($dateTarget) . "') "; + break; + case "day": + $dateSql = "AND (`" . add_escape_custom($date_label) . + "` BETWEEN DATE_SUB('" . add_escape_custom($dateTarget) . + "', INTERVAL " . add_escape_custom($intervalValue) . + " DAY) AND '" . add_escape_custom($dateTarget) . "') "; + break; + case "hour": + $dateSql = "AND (`" . add_escape_custom($date_label) . + "` BETWEEN DATE_SUB('" . add_escape_custom($dateTarget) . + "', INTERVAL " . add_escape_custom($intervalValue) . + " HOUR) AND '" . add_escape_custom($dateTarget) . "') "; + break; + case "minute": + $dateSql = "AND (`" . add_escape_custom($date_label) . + "` BETWEEN DATE_SUB('" . add_escape_custom($dateTarget) . + "', INTERVAL " . add_escape_custom($intervalValue) . + " MINUTE) AND '" . add_escape_custom($dateTarget) . "') "; + break; + case "second": + $dateSql = "AND (`" . add_escape_custom($date_label) . + "` BETWEEN DATE_SUB('" . add_escape_custom($dateTarget) . + "', INTERVAL " . add_escape_custom($intervalValue) . + " SECOND) AND '" . add_escape_custom($dateTarget) . "') "; + break; + case "flu_season": + // Flu season to be hard-coded as September thru February + // (Should make this modifiable in the future) + // ($intervalValue is not used) + $dateArray = explode("-",$dateTarget); + $Year = $dateArray[0]; + $dateThisYear = $Year . "-09-01"; + $dateLastYear = ($Year-1) . "-09-01"; + $dateSql =" " . + "AND ((" . + "MONTH('" . add_escape_custom($dateTarget) . "') < 9 " . + "AND `" . add_escape_custom($date_label) . "` >= '" . $dateLastYear . "' ) " . + "OR (" . + "MONTH('" . add_escape_custom($dateTarget) . "') >= 9 " . + "AND `" . add_escape_custom($date_label) . "` >= '" . $dateThisYear . "' ))" . + "AND `" . add_escape_custom($date_label) . "` <= '" . add_escape_custom($dateTarget) . "' "; + break; + } + } + else { + $dateSql = "AND `" . add_escape_custom($date_label) . + "` <= '" . add_escape_custom($dateTarget) . "' "; + } + + // return the sql interval string + return $dateSql; +} + +// Function to collect generic column labels from tables. +// It currently works for date and pid. +// Will need to expand this as algorithm grows. +// Parameters: +// $label - element (pid or date) +// $table - selected mysql table +// Return: string containing official label of selected element +function collect_database_label($label,$table) { + + if ($table == 'immunizations') { + // return requested label for immunization table + if ($label == "pid") { + $returnedLabel = "patient_id"; + } + else if ($label == "date") { + $returnedLabel = "administered_date"; + } + else { + // unknown label, so return the original label + $returnedLabel = $label; + } + } + else { + // return requested label for default tables + if ($label == "pid") { + $returnedLabel = "pid"; + } + else if ($label == "date") { + $returnedLabel = "date"; + } + else { + // unknown label, so return the original label + $returnedLabel = $label; + } + } + + return $returnedLabel; +} + +// Simple function to avoid processing of duplicate actions +// Parameters: +// $actions - 2-dimensional array with all current active targets +// $action - array of selected target to test for duplicate +// Return: boolean, true if duplicate, false if not duplicate +function is_duplicate_action($actions,$action) { + foreach ($actions as $row) { + if ($row['category'] == $action['category'] && + $row['item'] == $action['item'] && + $row['value'] == $action['value']) { + // Is a duplicate + return true; + } + } + + // Not a duplicate + return false; +} + +// Calculate the reminder dates. +// Parameters: +// $rule - id(string) of selected rule +// $dateTarget - target date. If blank then will test with current date as target. +// $type - either 'patient_reminder' or 'clinical_reminder' +// For now, will always return an array of 3 dates: +// first date is before the target date (past_due) (default of 1 month) +// second date is the target date (due) +// third date is after the target date (soon_due) (default of 2 weeks) +function calculate_reminder_dates($rule, $dateTarget='',$type) { + + // Set date to current if not set + $dateTarget = ($dateTarget) ? $dateTarget : date('Y-m-d H:i:s'); + + // Collect the past_due date + $past_due_date == ""; + $res = resolve_reminder_sql($rule, $type.'_post'); + if (!empty($res)) { + $row = $res[0]; + if ($row ['method_detail'] == "week") { + $past_due_date = date("Y-m-d H:i:s", strtotime($dateTarget . " -" . $row ['value'] . " week")); + } + if ($row ['method_detail'] == "month") { + $past_due_date = date("Y-m-d H:i:s", strtotime($dateTarget . " -" . $row ['value'] . " month")); + } + } + else { + // empty settings, so use default of one month + $past_due_date = date("Y-m-d H:i:s", strtotime($dateTarget . " -1 month")); + } + + // Collect the soon_due date + $soon_due_date == ""; + $res = resolve_reminder_sql($rule, $type.'_pre'); + if (!empty($res)) { + $row = $res[0]; + if ($row ['method_detail'] == "week") { + $soon_due_date = date("Y-m-d H:i:s", strtotime($dateTarget . " +" . $row ['value'] . " week")); + } + if ($row ['method_detail'] == "month") { + $soon_due_date = date("Y-m-d H:i:s", strtotime($dateTarget . " +" . $row ['value'] . " month")); + } + } + else { + // empty settings, so use default of one month + $soon_due_date = date("Y-m-d H:i:s", strtotime($dateTarget . " +2 week")); + } + + // Return the array of three dates + return array($soon_due_date,$dateTarget,$past_due_date); +} + +// Adds an action into the reminder array +// Parameters: +// $reminderOldArray - Contains the current array of reminders +// $reminderNew - Array of a new reminder +// Return: +// An array of reminders +function reminder_results_integrate($reminderOldArray, $reminderNew) { + + $results = array(); + + // If reminderArray is empty, then insert new reminder + if (empty($reminderOldArray)) { + array_push($results, $reminderNew); + return $results; + } + + // If duplicate reminder, then replace the old one + $duplicate = false; + foreach ($reminderOldArray as $reminderOld) { + if ( $reminderOld['pid'] == $reminderNew['pid'] && + $reminderOld['category'] == $reminderNew['category'] && + $reminderOld['item'] == $reminderNew['item']) { + array_push($results, $reminderNew); + $duplicate = true; + } + else { + array_push($results, $reminderOld); + } + } + + // If a new reminder, then insert the new reminder + if (!$duplicate) { + array_push($results, $reminderNew); + } + + return $results; +} + +// Function to find age in years (with decimal) on the target date +// Parameters: +// $dob - date of birth +// $target - date to calculate age on +// Return: decimal, years(decimal) from dob to target(date) +function convertDobtoAgeYearDecimal($dob,$target) { + + // Grab year, month, and day from dob and dateTarget + $dateDOB = explode(" ",$dob); + $dateTarget = explode(" ",$target); + + // Collect differences + $iDiffYear = $dateTarget[0] - $dateDOB[0]; + $iDiffMonth = $dateTarget[1] - $dateDOB[1]; + $iDiffDay = $dateTarget[2] - $dateDOB[2]; + + // If birthday has not happen yet for this year, subtract 1. + if ($iDiffMonth < 0 || ($iDiffMonth == 0 && $iDiffDay < 0)) + { + $iDiffYear--; + } + + return $iDiffYear; +} + +// Function to find age in months (with decimal) on the target date +// Parameters: +// $dob - date of birth +// $target - date to calculate age on +// Return: decimal, months(decimal) from dob to target(date) +function convertDobtoAgeMonthDecimal($dob,$target) { + + // Grab year, month, and day from dob and dateTarget + $dateDOB = explode(" ",$dob); + $dateTarget = explode(" ",$target); + + // Collect differences + $iDiffYear = $dateTarget[0] - $dateDOB[0]; + $iDiffMonth = $dateTarget[1] - $dateDOB[1]; + $iDiffDay = $dateTarget[2] - $dateDOB[2]; + + // If birthday has not happen yet for this year, subtract 1. + if ($iDiffMonth < 0 || ($iDiffMonth == 0 && $iDiffDay < 0)) + { + $iDiffYear--; + } + + return (12 * $iDiffYear) + $iDiffMonth; +} + +?> + diff --git a/library/forms.inc b/library/forms.inc index 447e1d0faf7..9c112e40ec7 100644 --- a/library/forms.inc +++ b/library/forms.inc @@ -75,16 +75,27 @@ function authorizeForm($id, $authorized = "1") sqlQuery("update forms set authorized = '$authorized' where id = '$id'"); } -function getEncounters($pid) +function getEncounters($pid,$dateStart='',$dateEnd='') { - $res = sqlStatement("select distinct encounter from form_encounter where pid = ? order by date desc;", array($pid) ); - - for($iter=0; $row=sqlFetchArray($res); $iter++) - { - $all[$iter] = $row; - } - return $all; + if ($dateStart && $dateEnd) { + $res = sqlStatement("select distinct encounter from form_encounter where pid = ? and date >= ? and date <= ? order by date desc;", array($pid,$dateStart,$dateEnd) ); + } + else if ($dateStart && !$dateEnd) { + $res = sqlStatement("select distinct encounter from form_encounter where pid = ? and date >= ? order by date desc;", array($pid,$dateStart) ); + } + else if (!$dateStart && $dateEnd) { + $res = sqlStatement("select distinct encounter from form_encounter where pid = ? and date <= ? order by date desc;", array($pid,$dateEnd) ); + } + else { + $res = sqlStatement("select distinct encounter from form_encounter where pid = ? order by date desc;", array($pid) ); + } + + for($iter=0; $row=sqlFetchArray($res); $iter++) + { + $all[$iter] = $row; + } + return $all; } function getEncounterDateByEncounter($encounter) diff --git a/library/globals.inc.php b/library/globals.inc.php index 3a763aa0349..b919c257b90 100644 --- a/library/globals.inc.php +++ b/library/globals.inc.php @@ -692,6 +692,34 @@ xl('API key for SMS Gateway.') ), + 'phone_notification_hour' => array( + xl('Phone Notification Hour'), + 'num', // data type + '50', // default + xl('Number of hours in advance to send Phone notification.') + ), + + 'phone_gateway_username' => array( + xl('Phone Gateway Username'), + 'text', // data type + '', // default + xl('Username for Phone Gateway. Automated VOIP service provided by Maviq. Please visit http://signup.maviq.com for more information.') + ), + + 'phone_gateway_password' => array( + xl('Phone Gateway Password'), + 'text', // data type + '', // default + xl('Password for Phone Gateway. Automated VOIP service provided by Maviq. Please visit http://signup.maviq.com for more information.') + ), + + 'phone_gateway_url' => array( + xl('Phone Gateway URL'), + 'text', // data type + '', // default + xl('URL for Phone Gateway. Automated VOIP service provided by Maviq. Please visit http://signup.maviq.com for more information.') + ), + ), // Miscellaneous Tab diff --git a/library/maviq_phone_api.php b/library/maviq_phone_api.php new file mode 100644 index 00000000000..aa9b93e988d --- /dev/null +++ b/library/maviq_phone_api.php @@ -0,0 +1,129 @@ + +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// + if(!extension_loaded("curl")) + throw(new Exception( + "Curl extension is required")); + + class MaviqClient { + + protected $Endpoint; + protected $SiteId; + protected $Token; + + public function __construct($siteId, $token, $endpoint) { + $this->SiteId = $siteId; + $this->Token = $token; + $this->Endpoint = $endpoint; + + } + + public function sendRequest($path, $method="POST", $vars=array()){ + + echo "Path: {$path}\n"; + + $encoded = ""; + foreach($vars AS $key=>$value) + $encoded .= "$key=".urlencode($value)."&"; + $encoded = substr($encoded, 0, -1); + $tmpfile = ""; + $fp = null; + + // construct full url + $url = "{$this->Endpoint}/$path"; + + echo "Url: {$url}\n"; + + // if GET and vars, append them + if($method == "GET") + $url .= (FALSE === strpos($path, '?')?"?":"&").$encoded; + + // initialize a new curl object + $curl = curl_init($url); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); + switch(strtoupper($method)) { + case "GET": + curl_setopt($curl, CURLOPT_HTTPGET, TRUE); + break; + case "POST": + curl_setopt($curl, CURLOPT_POST, TRUE); + curl_setopt($curl, CURLOPT_POSTFIELDS, $encoded); + break; + case "PUT": + // curl_setopt($curl, CURLOPT_PUT, TRUE); + curl_setopt($curl, CURLOPT_POSTFIELDS, $encoded); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT"); + file_put_contents($tmpfile = tempnam("/tmp", "put_"), + $encoded); + curl_setopt($curl, CURLOPT_INFILE, $fp = fopen($tmpfile, + 'r')); + curl_setopt($curl, CURLOPT_INFILESIZE, + filesize($tmpfile)); + break; + case "DELETE": + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE"); + break; + default: + throw(new Exception("Unknown method $method")); + break; + } + + // send credentials + curl_setopt($curl, CURLOPT_USERPWD, + $pwd = "{$this->SiteId}:{$this->Token}"); + + // do the request. If FALSE, then an exception occurred + if(FALSE === ($result = curl_exec($curl))) + throw(new Exception( + "Curl failed with error " . curl_error($curl))); + + // get result code + $responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + + // unlink tmpfiles + if($fp) + fclose($fp); + if(strlen($tmpfile)) + unlink($tmpfile); + + return new RestResponse($url, $result, $responseCode); + } + + } + + class RestResponse { + + public $ResponseText; + public $ResponseXml; + public $HttpStatus; + public $Url; + public $QueryString; + public $IsError; + public $ErrorMessage; + + public function __construct($url, $text, $status) { + preg_match('/([^?]+)\??(.*)/', $url, $matches); + $this->Url = $matches[1]; + $this->QueryString = $matches[2]; + $this->ResponseText = $text; + $this->HttpStatus = $status; + if($this->HttpStatus != 204) + $this->ResponseXml = @simplexml_load_string($text); + + if($this->IsError = ($status >= 400)) + $this->ErrorMessage = + (string)$this->ResponseXml->RestException->Message; + + } + + } + +?> + diff --git a/library/patient.inc b/library/patient.inc index e970cdeba58..27e4bb2fa24 100644 --- a/library/patient.inc +++ b/library/patient.inc @@ -302,10 +302,23 @@ function getEthnoRacials() { return $returnval; } -function getHistoryData($pid, $given = "*") +function getHistoryData($pid, $given = "*", $dateStart='',$dateEnd='') { - $sql = "select $given from history_data where pid=? order by date DESC limit 0,1"; - return sqlQuery($sql, array($pid) ); + + if ($dateStart && $dateEnd) { + $res = sqlQuery("select $given from history_data where pid = ? and date >= ? and date <= ? order by date DESC limit 0,1", array($pid,$dateStart,$dateEnd) ); + } + else if ($dateStart && !$dateEnd) { + $res = sqlQuery("select $given from history_data where pid = ? and date >= ? order by date DESC limit 0,1", array($pid,$dateStart) ); + } + else if (!$dateStart && $dateEnd) { + $res = sqlQuery("select $given from history_data where pid = ? and date <= ? order by date DESC limit 0,1", array($pid,$dateEnd) ); + } + else { + $res = sqlQuery("select $given from history_data where pid=? order by date DESC limit 0,1", array($pid) ); + } + + return $res; } // function getInsuranceData($pid, $type = "primary", $given = "insd.*, DATE_FORMAT(subscriber_DOB,'%m/%d/%Y') as subscriber_DOB, ic.name as provider_name") diff --git a/library/reminders.php b/library/reminders.php new file mode 100644 index 00000000000..4007239dcff --- /dev/null +++ b/library/reminders.php @@ -0,0 +1,302 @@ + +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +// Functions are kept here that will support reminders. + +require_once(dirname(__FILE__) . "/clinical_rules.php"); + + +// Display the patient reminder widget. +// Parameters: +// $patient_id - pid of selected patient +// $dateTarget - target date. If blank then will test with current date as target. +function patient_reminder_widget($patient_id,$dateTarget='') { + + // Set date to current if not set + $dateTarget = ($dateTarget) ? $dateTarget : date('Y-m-d H:i:s'); + + // Update reminders for patient + update_reminders($dateTarget, $patient_id); + + // Fetch the active reminders + $listReminders = fetch_reminders($patient_id); + + if (empty($listReminders)) { + // No reminders to show. + echo htmlspecialchars( xl('No active patient reminders.'), ENT_NOQUOTES); + return; + } + + echo ""; + foreach ($listReminders as $reminder) { + echo ""; + } + echo "
      "; + // show reminder label + echo generate_display_field(array('data_type'=>'1','list_id'=>'rule_action_category'),$reminder['category']) . + ": " . generate_display_field(array('data_type'=>'1','list_id'=>'rule_action'),$reminder['item']); + echo ""; + // show reminder due status + echo generate_display_field(array('data_type'=>'1','list_id'=>'rule_reminder_due_opt'),$reminder['due_status']); + echo ""; + // show reminder sent date + if (empty($reminder['date_sent'])) { + echo htmlspecialchars( xl('Reminder Not Sent Yet'), ENT_NOQUOTES); + } + else { + echo htmlspecialchars( xl('Reminder Sent On').": ".$reminder['date_sent'], ENT_NOQUOTES); + } + echo "
      "; +} + +// Function to update reminders. +// Parameters: +// $dateTarget - target date. If blank then will test with current date as target. +// $patient_id - pid of patient. If blank then will check all patients. +// Return: +// Returns a array with following element: +// 'total_active_actions' - Number of active actions. +// 'total_pre_active_reminders' - Number of active reminders before processing. +// 'total_pre_unsent_reminders' - Number of unsent reminders before processing. +// 'total_post_active_reminders' - Number of active reminders after processing. +// 'total_post_unsent_reminders' - Number of unsent reminders after processing. +// 'number_new_reminders' - Number of new reminders +// 'number_updated_reminders' - Number of updated reminders (due_status change) +// 'number_inactivated_reminders' - Number of inactivated reminders. +// 'number_unchanged_reminders' - Number of unchanged reminders. +function update_reminders($dateTarget='', $patient_id='') { + + $logging = array(); + + // Set date to current if not set + $dateTarget = ($dateTarget) ? $dateTarget : date('Y-m-d H:i:s'); + + // Collect reminders (note that this function removes redundant and keeps the most distant + // reminder (ie. prefers 'past_due' over 'due' over 'soon_due') + $collectedReminders = test_rules_clinic('','patient_reminder',$dateTarget,'reminders',$patient_id); + $logging['total_active_actions'] = count($collectedReminders); + + // For logging purposes only: + // Collect number active of active and unsent reminders + $logging['total_pre_active_reminders'] = count(fetch_reminders($patient_id)); + $logging['total_pre_unsent_reminders'] = count(fetch_reminders($patient_id, 'unsent')); + + // Migrate reminders into the patient_reminders table + $logging['number_new_reminders'] = 0; + $logging['number_updated_reminders'] = 0; + $logging['number_unchanged_reminders'] = 0; + foreach ($collectedReminders as $reminder) { + + // See if a reminder already exist + $sql = "SELECT `id`, `pid`, `due_status`, `category`, `item` FROM `patient_reminders` WHERE " . + "`active`='1' AND `pid`=? AND `category`=? AND `item`=?"; + $result = sqlQuery($sql, array($reminder['pid'], $reminder['category'], $reminder['item']) ); + + if (empty($result)) { + // It does not yet exist, so add a new reminder + $sql = "INSERT INTO `patient_reminders` (`pid`, `due_status`, `category`, `item`, `date_created`) " . + "VALUES (?, ?, ?, ?, NOW())"; + sqlStatement($sql, array($reminder['pid'], $reminder['due_status'], $reminder['category'], $reminder['item']) ); + $logging['number_new_reminders']++; + } + else { + // It already exist (see if if needs to be updated via adding a new reminder) + if ($reminder['due_status'] == $result['due_status']) { + // No change in due status, so no need to update + $logging['number_unchanged_reminders']++; + continue; + } + else { + // Change in due status, so inactivate current reminder and create a new one + // First, inactivate the previous reminder + $sql = "UPDATE `patient_reminders` SET `active` = '0', `reason_inactivated` = 'due_status_update', " . + "`date_inactivated` = NOW() WHERE `id`=?"; + sqlStatement($sql, array($result['id']) ); + // Then, add the new reminder + $sql = "INSERT INTO `patient_reminders` (`pid`, `due_status`, `category`, `item`, `date_created`) " . + "VALUES (?, ?, ?, ?, NOW())"; + sqlStatement($sql, array($reminder['pid'], $reminder['due_status'], $reminder['category'], $reminder['item']) ); + } + } + } + + // Inactivate reminders that no longer exist + // Go through each active reminder and ensure it is in the current list + $sqlReminders = fetch_reminders($patient_id); + $logging['number_inactivated_reminders'] = 0; + foreach ( $sqlReminders as $row ) { + $inactivateFlag = true; + foreach ($collectedReminders as $reminder) { + if ( ($row['pid'] == $reminder['pid']) && + ($row['category'] == $reminder['category']) && + ($row['item'] == $reminder['item']) && + ($row['due_status'] == $reminder['due_status']) ) { + // The sql reminder has been confirmed, so do not inactivate it + $inactivateFlag = false; + break; + } + } + if ($inactivateFlag) { + // The sql reminder was not confirmed, so inactivate it + $sql = "UPDATE `patient_reminders` SET `active` = '0', `reason_inactivated` = 'auto', " . + "`date_inactivated` = NOW() WHERE `id`=?"; + sqlStatement($sql, array($row['id']) ); + $logging['number_inactivated_reminders'] = 0; + } + } + + // For logging purposes only: + // Collect number of active and unsent reminders + $logging['total_post_active_reminders'] = count(fetch_reminders($patient_id)); + $logging['total_post_unsent_reminders'] = count(fetch_reminders($patient_id, 'unsent')); + + return $logging; + +} + +// Function to send reminders +// Return: +// Returns a array with following element: +// 'total_pre_unsent_reminders' - Number of reminders before processing. +// 'total_post_unsent_reminders' - Number of reminders after processing. +// 'number_success_emails' - Number of successfully sent email reminders. +// 'number_failed_emails' - Number of failed sent email reminders. +// 'number_success_calls' - Number of successfully call reminders. +// 'number_failed_calls' - Number of failed call reminders. +function send_reminders() { + + $logging = array(); + + // Collect active reminders that have not yet been sent. + $active_unsent_reminders = fetch_reminders($patient_id, 'unsent'); + $logging['total_pre_unsent_reminders'] = count($active_unsent_reminders); + + // Send the unsent reminders + $logging['number_success_emails'] = 0; + $logging['number_failed_emails'] = 0; + $logging['number_success_calls'] = 0; + $logging['number_failed_calls'] = 0; + foreach ( $active_unsent_reminders as $reminder ) { + + // Collect patient information that reminder is going to. + $sql = "SELECT `fname`, `lname`, `email`, `phone_home`, `hipaa_voice`, `hipaa_allowemail` from `patient_data` where `pid`=?"; + $result = sqlQuery($sql, array($reminder['pid']) ); + $patientfname = $rez['fname']; + $patientlname = $rez['lname']; + $patientemail = $rez['email']; + $patientphone = $rez['phone_home']; + $hipaa_voice = $rez['hipaa_voice']; + $hipaa_allowemail = $rez['hipaa_allowemail']; + + // Email to patient if Allow Email and set reminder sent flag. + if ($hipaa_allowemail == "YES") { + $mail = new MyMailer(); + $mail->FromName = $sender_name; // required + $mail->Sender = $sender_name; // required + $mail->From = $email_address; // required + $mail->AddAddress($patientemail, $patientfname.", ".$patientlname); // required + $mail->AddReplyTo($email_address,$sender_name); // required + $mail->Body = str_replace("[[sender]]", $sender_name, str_replace("[[patient_name]]", $patientfname, $GLOBALS['reminder_message'])); + $mail->Subject = "Clinic Reminder"; + if ($mail->Send()) { + // deal with and keep track of this successful email + sqlQuery("UPDATE `patient_reminders` SET `email_status`='1', `date_sent`=NOW() WHERE id=?", array($reminder['id']) ); + $logging['number_success_emails']++; + } + else { + // deal with and keep track of this unsuccesful email + $logging['number_failed_emails']++; + } + } + + // Call to patient if Allow Voice Message and set reminder sent flag. + if ($hipaa_voice == "YES") { + // Automated VOIP service provided by Maviq. Please visit http://signup.maviq.com for more information. + $siteId = $GLOBALS['phone_gateway_username']; + $token = $GLOBALS['phone_gateway_password']; + $endpoint = $GLOBALS['phone_gateway_url']; + $client = new MaviqClient($siteId, $token, $endpoint); + //Set up params. + $data = array( + "firstName" => $patientfname, + "lastName" => $patientlname, + "phone" => $patientphone, + //"apptDate" => "$scheduled_date[1]/$scheduled_date[2]/$scheduled_date[0]", + "timeRange" => "10-18", + "type" => "reminder", + "timeZone" => date('P'), + "greeting" => str_replace("[[sender]]", $sender_name, str_replace("[[patient_name]]", $patientfname, $myrow['reminder_content'])) + ); + + // Make the call. + $response = $client->sendRequest("appointment", "POST", $data); + + if ($response->IsError) { + // deal with and keep track of this unsuccessful call + $logging['number_failed_calls']++; + } + else { + // deal with and keep track of this succesful call + sqlQuery("UPDATE `patient_reminders` SET `voice_status`='1', `date_sent`=NOW() WHERE id=?", array($reminder['id']) ); + $logging['number_success_calls']++; + } + } + } + + // For logging purposes only: + // Collect active reminders that have not yet been sent. + $logging['total_post_unsent_reminders'] = count(fetch_reminders($patient_id, 'unsent')); + + return $logging; +} + +// Function to fetch reminders +// Parameters: +// $patient_id - pid of patient. If blank then will check all patients. +// $type - unsent (unsent) vs all active (BLANK) reminders +// $due_status - due status of reminders (soon_due,due,past_due). If blank, +// then will return all. +// $select - Select component of select statement. If blank, then +// will return all columns. +// Return: +// Returns a array of reminders +function fetch_reminders($patient_id='',$type='',$due_status='',$select='*') { + + $arraySqlBind = array(); + + if (!empty($patient_id)) { + $where = "`pid`=? AND "; + array_push($arraySqlBind,$patient_id); + } + + if (!empty($due_status)) { + $where .= "`due_status`=? AND "; + array_push($arraySqlBind,$due_status); + } + + if (empty($type)) { + $where .= "`active`='1'"; + } + else { // $type == 'unsent' + $where .= "`active`='1' AND `date_sent` IS NULL"; + } + + $order = "`due_status`, `date_created`"; + + $sql = "SELECT " . $select . " FROM `patient_reminders` WHERE " . + $where . " ORDER BY " . $order; + $rez = sqlStatement($sql, $arraySqlBind); + + for($iter=0; $row=sqlFetchArray($rez); $iter++) + $returnval[$iter]=$row; + + return $returnval; +} + +?> + diff --git a/modules/sms_email_reminder/batch_phone_notification.php b/modules/sms_email_reminder/batch_phone_notification.php new file mode 100644 index 00000000000..e6dcaadaa8a --- /dev/null +++ b/modules/sms_email_reminder/batch_phone_notification.php @@ -0,0 +1,250 @@ + +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +//////////////////////////////////////////////////////////////////// +// Package: cron_phone_notification +// Purpose: to be run by cron every hour, look for appointments +// in the pre-notification period and send an phone reminder +// Based on cron_email_notification by Larry Lart +// Created by: +// Updated by: Maviq on 01/12/2010 +//////////////////////////////////////////////////////////////////// + +$backpic = ""; +//phone notification +$ignoreAuth=1; + +//Set the working directory to the path of the file +$current_dir = dirname($_SERVER['SCRIPT_FILENAME']); +chdir($current_dir); + +//SANITIZE ALL ESCAPES +$sanitize_all_escapes=true; + +//STOP FAKE REGISTER GLOBALS +$fake_register_globals=false; + +require_once("../../interface/globals.php"); +require_once("$srcdir/maviq_phone_api.php"); +require_once("$srcdir/formdata.inc.php"); + +$type = "Phone"; +$before_trigger_hours = 72; // 3 days is default +//Get the values from Global +$before_trigger_hours = $GLOBALS['phone_notification_hour']; +//set up the phone notification settings for external phone service +$phone_url = $GLOBALS['phone_gateway_url'] ; +$phone_id = $GLOBALS['phone_gateway_username']; +$phone_token = $GLOBALS['phone_gateway_password']; +$phone_time_range = $GLOBALS['phone_time_range']; + +//get the facility_id-message map +$facilities = cron_getFacilitiesMap(); +//print_r($facilities); +$fac_phone_map = $facilities['phone_map']; +$fac_msg_map = $facilities['msg_map']; + +// get patient data for send alert +$db_patient = cron_getPhoneAlertpatientData($type, $before_trigger_hours); +echo "
      " . htmlspecialchars( xl("Total Records Found") . ": " . count($db_patient), ENT_QUOTES); + +//Create a new instance of the phone service client +$client = new MaviqClient($phone_id, $phone_token, $phone_url); + +for($p=0;$p $prow['fname'], + "lastName" => $prow['lname'], + "phone" => $prow['phone_home'], + "apptDate" => $appt_date, + "apptTime" => $appt_time, + "doctor" => $prow['pc_aid'], + "greeting" => $greeting, + "timeRange" => $phone_time_range, + "type" => "appointment", + "timeZone" => date('P'), + "callerId" => $fac_phone_map[$prow['pc_facility']] + ); + + //Make the call + $response = $client->sendRequest("appointment", "POST", $data); + + // check response for success or error + if($response->IsError) { + $strMsg = "Error starting phone call for {$prow['fname']} | {$prow['lname']} | {$prow['phone_home']} | {$appt_date} | {$appt_time} | {$response->ErrorMessage}\n"; + } + else { + $strMsg = "\n========================".$type." || ".date("Y-m-d H:i:s")."========================="; + $strMsg .= "\nPhone reminder sent successfully: {$prow['fname']} | {$prow['lname']} | | {$prow['phone_home']} | {$appt_date} | {$appt_time} "; + // insert entry in notification_log table + cron_InsertNotificationLogEntry($prow,$greeting,$phone_url); + + //update entry >> pc_sendalertsms='Yes' + cron_updateentry($type,$prow['pid'],$prow['pc_eid']); + + } + + //echo $strMsg; + WriteLog( $strMsg ); + +} + +sqlClose(); + +//////////////////////////////////////////////////////////////////// +// Function: cron_updateentry +// Purpose: update status yes if alert send to patient +//////////////////////////////////////////////////////////////////// +function cron_updateentry($type,$pid,$pc_eid) +{ + + $query = "update openemr_postcalendar_events set "; + + // larry :: and here again same story - this time for sms pc_sendalertsms - no such field in the table + if($type=='SMS') + $query.=" pc_sendalertsms='YES' "; + elseif ($type=='Email') + $query.=" pc_sendalertemail='YES' "; + //Added by Yijin for phone reminder.. Uses the same field as SMS. + elseif($type=='Phone') + $query.=" pc_sendalertsms='YES' "; + + $query .=" where pc_pid=? and pc_eid=? "; + //echo "
      ".$query; + $db_sql = (sqlStatement($query, array($pid, $pc_eid))); +} + +//////////////////////////////////////////////////////////////////// +// Function: cron_getPhoneAlertpatientData +// Purpose: get patient data for send to alert +//////////////////////////////////////////////////////////////////// +function cron_getPhoneAlertpatientData( $type, $trigger_hours ) +{ + + //Added by Yijin 1/12/10 to handle phone reminders. Patient needs to have hipaa Voice flag set to yes and a home phone + if($type=='Phone'){ + $ssql = " and pd.hipaa_voice='YES' and pd.phone_home<>'' and ope.pc_sendalertsms='NO' and ope.pc_apptstatus != '*' "; + + $check_date = date("Y-m-d", mktime(date("H")+$trigger_hours, 0, 0, date("m"), date("d"), date("Y"))); + + } + + $patient_field = "pd.pid,pd.title,pd.fname,pd.lname,pd.mname,pd.phone_cell,pd.email,pd.hipaa_allowsms,pd.hipaa_allowemail,pd.phone_home,pd.hipaa_voice,"; + $ssql .= " and (ope.pc_eventDate=?)"; + + $query = "select $patient_field pd.pid,ope.pc_eid,ope.pc_pid,ope.pc_title, + ope.pc_hometext,ope.pc_eventDate,ope.pc_endDate, + ope.pc_duration,ope.pc_alldayevent,ope.pc_startTime,ope.pc_endTime,ope.pc_facility + from + openemr_postcalendar_events as ope ,patient_data as pd + where + ope.pc_pid=pd.pid $ssql + order by + ope.pc_eventDate,ope.pc_endDate,pd.pid"; + + $db_patient = (sqlStatement($query) , array($check_date) ); + $patient_array = array(); + $cnt=0; + while ($prow = sqlFetchArray($db_patient)) + { + $patient_array[$cnt] = $prow; + $cnt++; + } + return $patient_array; +} + +//////////////////////////////////////////////////////////////////// +// Function: cron_InsertNotificationLogEntry +// Purpose: insert log entry in table +//////////////////////////////////////////////////////////////////// +function cron_InsertNotificationLogEntry($prow,$phone_msg,$phone_gateway) +{ + $patient_info = $prow['title']." ".$prow['fname']." ".$prow['mname']." ".$prow['lname']."|||".$prow['phone_home']; + + $message = $phone_msg; + + $sql_loginsert = "INSERT INTO `notification_log` ( `iLogId` , `pid` , `pc_eid` , `message`, `type` , `patient_info` , `smsgateway_info` , `pc_eventDate` , `pc_endDate` , `pc_startTime` , `pc_endTime` , `dSentDateTime` ) VALUES "; + $sql_loginsert .= "(NULL , ?, ?, ?, 'Phone', ?, ?, ?, ?, ?, ?, ?)"; + $db_loginsert = ( sqlStatement( $sql_loginsert ), array($prow[pid], $prow[pc_eid], $message, $patient_info, $phone_gateway, $prow[pc_eventDate], $prow[pc_endDate], $prow[pc_startTime], $prow[pc_endTime], date("Y-m-d H:i:s")) ); +} + +//////////////////////////////////////////////////////////////////// +// Function: WriteLog +// Purpose: written log into file +//////////////////////////////////////////////////////////////////// +function WriteLog( $data ) +{ + $log_file = $GLOBALS['phone_reminder_log_dir']; + + if ($log_file != null) { + + $filename = $log_file . "/"."phone_reminder_cronlog_".date("Ymd").".html"; + + if (!$fp = fopen($filename, 'a')) + { + print "Cannot open file ($filename)"; + + }else { + + $sdata = "\n====================================================================\n"; + + if (!fwrite($fp, $data.$sdata)) + { + print "Cannot write to file ($filename)"; + } + + fclose($fp); + } + } +} +//////////////////////////////////////////////////////////////////// +// Function: cron_getFacilities +// Purpose: get facilities data once and store in map +//////////////////////////////////////////////////////////////////// +function cron_getFacilitiesMap() +{ + //get the facility_name-message map from Globals + $message_map = $GLOBALS['phone_appt_message']; + //create a new array to store facility_id to message map + $facility_msg_map = array(); + $facility_phone_map = array(); + //get facilities from the database + $query = "select fac.id, fac.name, fac.phone from facility as fac"; + $db_res = (sqlStatement($query)); + while ($prow = sqlFetchArray($db_res)) + { + $facility_msg_map[$prow['id']] = $message_map[$prow['name']]; + $facility_phone_map[$prow['id']] = $prow['phone']; + } + + $facility_map = array( + 'msg_map' => $facility_msg_map, + 'phone_map' => $facility_phone_map + ); + + return $facility_map; + +} +?> + diff --git a/modules/sms_email_reminder/batch_reminders.php b/modules/sms_email_reminder/batch_reminders.php new file mode 100644 index 00000000000..6b4fa02f687 --- /dev/null +++ b/modules/sms_email_reminder/batch_reminders.php @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + +

      + + + +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      + + + +

      +
      +
      +
      +
      +
      +
      + +


      +
      +

      + + + diff --git a/sql/database.sql b/sql/database.sql index 02e4c86788c..48af7fb85e0 100644 --- a/sql/database.sql +++ b/sql/database.sql @@ -3163,6 +3163,7 @@ CREATE TABLE `user_settings` ( INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'allergy_ps_expand', '1'); INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'appointments_ps_expand', '1'); +INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'clinical_reminders_ps_expand', '1'); INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'demographics_ps_expand', '0'); INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'dental_ps_expand', '1'); INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'directives_ps_expand', '1'); @@ -3172,6 +3173,7 @@ INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'medical_problem_ps_expand', '1'); INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'medication_ps_expand', '1'); INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'pnotes_ps_expand', '0'); +INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'clinical_reminders_ps_expand', '0'); INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'prescriptions_ps_expand', '1'); INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'surgery_ps_expand', '1'); INSERT INTO user_settings ( setting_user, setting_label, setting_value ) VALUES (0, 'vitals_ps_expand', '1'); @@ -3488,3 +3490,726 @@ CREATE TABLE version ( v_database int(11) NOT NULL DEFAULT 0 ) ENGINE=MyISAM; INSERT INTO version (v_major, v_minor, v_patch, v_tag, v_database) VALUES (0, 0, 0, '', 0); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `clinical_rules` +-- + +DROP TABLE IF EXISTS `clinical_rules`; +CREATE TABLE `clinical_rules` ( + `id` varchar(31) NOT NULL DEFAULT '' COMMENT 'Unique and maps to list_options list clinical_rules', + `pid` bigint(20) NOT NULL DEFAULT '0' COMMENT '0 is default for all patients, while > 0 is id from patient_data table', + `active` tinyint(1) NOT NULL default 1, + `active_alert_flag` tinyint(1) NOT NULL default 0, + `passive_alert_flag` tinyint(1) NOT NULL default 0, + `cqm_flag` tinyint(1) NOT NULL default 0, + `cqm_code` varchar(10) NOT NULL default '', + `patient_reminder_flag` tinyint(1) NOT NULL default 0, + PRIMARY KEY (`id`,`pid`) +) ENGINE=MyISAM ; + +-- +-- CQM rules first +-- +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_htn_bp_measure_cqm', 0, 1, 0, 0, 1, '0013', 0); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_tob_use_assess_cqm', 0, 1, 0, 0, 1, '0028a', 0); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_tob_cess_inter_cqm', 0, 1, 0, 0, 1, '0028b', 0); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_adult_wt_screen_fu_cqm', 0, 1, 0, 0, 1, '0421', 0); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_wt_assess_couns_child_cqm', 0, 1, 0, 0, 1, '0024', 0); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_influenza_ge_50_cqm', 0, 1, 0, 0, 1, '0041', 0); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_child_immun_stat_cqm', 0, 1, 0, 0, 1, '0038', 0); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_pneumovacc_ge_65_cqm', 0, 1, 0, 0, 1, '0043', 0); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_dm_eye_cqm', 0, 1, 0, 0, 1, '0055', 0); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_dm_foot_cqm', 0, 1, 0, 0, 1, '0056', 0); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_dm_bp_control_cqm', 0, 1, 0, 0, 1, '0061', 0); + +-- +-- Standard clinical rules +-- +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_htn_bp_measure', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_tob_use_assess', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_tob_cess_inter', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_adult_wt_screen_fu', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_wt_assess_couns_child', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_influenza_ge_50', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_child_immun_stat', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_pneumovacc_ge_65', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_dm_hemo_a1c', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_dm_urine_alb', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_dm_eye', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_dm_foot', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_cs_mammo', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_cs_pap', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_cs_colon', 0, 1, 0, 1, 0, '', 1); +INSERT INTO `clinical_rules` ( `id`, `pid`, `active`, `active_alert_flag`, `passive_alert_flag`, `cqm_flag`, `cqm_code`, `patient_reminder_flag` ) VALUES ('rule_cs_prostate', 0, 1, 0, 1, 0, '', 1); + +-- Clinical rule titles +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'clinical_rules','Clinical Rules', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_htn_bp_measure_cqm', 'Hypertension: Blood Pressure Measurement (CQM)', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_tob_use_assess_cqm', 'Tobacco Use Assessment (CQM)', 20, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_tob_cess_inter_cqm', 'Tobacco Cessation Intervention (CQM)', 30, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_adult_wt_screen_fu_cqm', 'Adult Weight Screening and Follow-Up (CQM)', 40, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_wt_assess_couns_child_cqm', 'Weight Assessment and Counseling for Children and Adolescents (CQM)', 50, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_influenza_ge_50_cqm', 'Influenza Immunization for Patients >= 50 Years Old (CQM)', 60, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_child_immun_stat_cqm', 'Childhood immunization Status (CQM)', 70, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_pneumovacc_ge_65_cqm', 'Pneumonia Vaccination Status for Older Adults (CQM)', 80, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_dm_eye_cqm', 'Diabetes: Eye Exam (CQM)', 90, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_dm_foot_cqm', 'Diabetes: Foot Exam (CQM)', 100, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_dm_bp_control_cqm', 'Diabetes: Blood Pressure Management (CQM)', 110, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_htn_bp_measure', 'Hypertension: Blood Pressure Measurement', 500, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_tob_use_assess', 'Tobacco Use Assessment', 510, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_tob_cess_inter', 'Tobacco Cessation Intervention', 520, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_adult_wt_screen_fu', 'Adult Weight Screening and Follow-Up', 530, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_wt_assess_couns_child', 'Weight Assessment and Counseling for Children and Adolescents', 540, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_influenza_ge_50', 'Influenza Immunization for Patients >= 50 Years Old', 550, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_child_immun_stat', 'Childhood immunization Status', 560, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_pneumovacc_ge_65', 'Pneumonia Vaccination Status for Older Adults', 570, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_dm_hemo_a1c', 'Diabetes: Hemoglobin A1C', 570, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_dm_urine_alb', 'Diabetes: Urine Microalbumin', 590, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_dm_eye', 'Diabetes: Eye Exam', 600, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_dm_foot', 'Diabetes: Foot Exam', 610, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_cs_mammo', 'Cancer Screening: Mammogram', 620, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_cs_pap', 'Cancer Screening: Pap Smear', 630, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_cs_colon', 'Cancer Screening: Colon Cancer Screening', 640, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('clinical_rules', 'rule_cs_prostate', 'Cancer Screening: Prostate Cancer Screening', 650, 0); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `rule_filter` +-- + +DROP TABLE IF EXISTS `rule_filter`; +CREATE TABLE `rule_filter` ( + `id` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to the id column in the clinical_rules table', + `include_flag` tinyint(1) NOT NULL default 0 COMMENT '0 is exclude and 1 is include', + `required_flag` tinyint(1) NOT NULL default 0 COMMENT '0 is required and 1 is optional', + `method` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options list rule_filters', + `method_detail` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options lists rule__intervals', + `value` varchar(255) NOT NULL DEFAULT '', + KEY (`id`) +) ENGINE=MyISAM ; + +-- +-- CQM rule filters first +-- + +-- NQF 0013 Hypertension: Blood Pressure Measurement +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure_cqm', 1, 0, 'filt_diagnosis', '', 'CUSTOM::HTN'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure_cqm', 1, 0, 'filt_diagnosis', '', 'ICD9::401'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure_cqm', 1, 0, 'filt_diagnosis', '', 'ICD9::402'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure_cqm', 1, 0, 'filt_diagnosis', '', 'ICD9::403'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure_cqm', 1, 0, 'filt_diagnosis', '', 'ICD9::404'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure_cqm', 1, 0, 'filt_diagnosis', '', 'ICD9::405'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure_cqm', 1, 1, 'filt_age_min', 'year', '18'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure_cqm', 1, 1, 'filt_encounter_min', '', '2'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure_cqm', 1, 1, 'filt_measure_period', 'year', '1'); + +-- NQF 0028a Tobacco Use Assessment +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_use_assess_cqm', 1, 1, 'filt_age_min', 'year', '18'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_use_assess_cqm', 1, 1, 'filt_encounter_min', '', '2'); + +-- NQF 0028b Tobacco Cessation Intervention +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_cess_inter_cqm', 1, 1, 'filt_database', '', 'history_data::tobacco::current::LIFESTYLE::1'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_cess_inter_cqm', 1, 1, 'filt_age_min', 'year', '18'); + +-- NQF 0421 Adult Weight Screening and Follow-Up + +-- NQF 0024 Weight Assessment and Counseling for Children and Adolescents +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_wt_assess_couns_child_cqm', 1, 1, 'filt_age_max', 'year', '18'); + +-- NQF 0041 Influenza Immunization for Patients >= 50 Years Old +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_influenza_ge_50_cqm', 1, 1, 'filt_age_min', 'year', '50'); + +-- NQF 0038 Childhood immunization Status +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_child_immun_stat_cqm', 1, 1, 'filt_age_min', 'year', '1'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_child_immun_stat_cqm', 1, 1, 'filt_age_max', 'year', '18'); + +-- NQF 0043 Pneumonia Vaccination Status for Older Adults +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_pneumovacc_ge_65_cqm', 1, 1, 'filt_age_min', 'year', '65'); + +-- NQF 0055 Diabetes: Eye Exam +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_eye_cqm', 1, 0, 'filt_diagnosis', '', 'CUSTOM::diabetes'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_eye_cqm', 1, 0, 'filt_diagnosis', '', 'ICD9::250'); + +-- NQF 0056 Diabetes: Foot Exam +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_foot_cqm', 1, 0, 'filt_diagnosis', '', 'CUSTOM::diabetes'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_foot_cqm', 1, 0, 'filt_diagnosis', '', 'ICD9::250'); + +-- NQF 0061 Diabetes: Blood Pressure Management +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_bp_control_cqm', 1, 0, 'filt_diagnosis', '', 'CUSTOM::diabetes'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_bp_control_cqm', 1, 0, 'filt_diagnosis', '', 'ICD9::250'); + +-- +-- Standard clinical rule filters +-- + +-- Hypertension: Blood Pressure Measurement +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure', 1, 0, 'filt_diagnosis', '', 'CUSTOM::HTN'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure', 1, 0, 'filt_diagnosis', '', 'ICD9::401'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure', 1, 0, 'filt_diagnosis', '', 'ICD9::402'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure', 1, 0, 'filt_diagnosis', '', 'ICD9::403'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure', 1, 0, 'filt_diagnosis', '', 'ICD9::404'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure', 1, 0, 'filt_diagnosis', '', 'ICD9::405'); + +-- Tobacco Use Assessment +-- no filters + +-- Tobacco Cessation Intervention +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_cess_inter', 1, 1, 'filt_database', '', 'history_data::tobacco::current::LIFESTYLE::1'); + +-- Adult Weight Screening and Follow-Up +-- no filters + +-- Weight Assessment and Counseling for Children and Adolescents +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_wt_assess_couns_child', 1, 1, 'filt_age_max', 'year', '18'); + +-- Influenza Immunization for Patients >= 50 Years Old +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_influenza_ge_50', 1, 1, 'filt_age_min', 'year', '50'); + +-- Childhood immunization Status +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_child_immun_stat', 1, 1, 'filt_age_min', 'year', '1'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_child_immun_stat', 1, 1, 'filt_age_max', 'year', '18'); + +-- Pneumonia Vaccination Status for Older Adults +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_pneumovacc_ge_65', 1, 1, 'filt_age_min', 'year', '65'); + +-- Diabetes: Hemoglobin A1C +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_hemo_a1c', 1, 0, 'filt_diagnosis', '', 'CUSTOM::diabetes'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_hemo_a1c', 1, 0, 'filt_diagnosis', '', 'ICD9::250'); + +-- Diabetes: Urine Microalbumin +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_urine_alb', 1, 0, 'filt_diagnosis', '', 'CUSTOM::diabetes'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_urine_alb', 1, 0, 'filt_diagnosis', '', 'ICD9::250'); + +-- Diabetes: Eye Exam +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_eye', 1, 0, 'filt_diagnosis', '', 'CUSTOM::diabetes'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_eye', 1, 0, 'filt_diagnosis', '', 'ICD9::250'); + +-- Diabetes: Foot Exam +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_foot', 1, 0, 'filt_diagnosis', '', 'CUSTOM::diabetes'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_foot', 1, 0, 'filt_diagnosis', '', 'ICD9::250'); + +-- Cancer Screening: Mammogram +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_mammo', 1, 1, 'filt_age_min', 'year', '40'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_mammo', 1, 1, 'filt_sex', '', 'Female'); + +-- Cancer Screening: Pap Smear +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_pap', 1, 1, 'filt_age_min', 'year', '18'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_pap', 1, 1, 'filt_sex', '', 'Female'); + +-- Cancer Screening: Colon Cancer Screening +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_colon', 1, 1, 'filt_age_min', 'year', '50'); + +-- Cancer Screening: Prostate Cancer Screening +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_prostate', 1, 1, 'filt_age_min', 'year', '50'); +INSERT INTO `rule_filter` ( `id`, `include_flag`, `required_flag`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_prostate', 1, 1, 'filt_sex', '', 'Male'); + +-- +-- Associated lists +-- + +-- Clinical rule filter methods +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_filters','Clinical Rule Filter Methods', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_filters', 'filt_database', 'Database', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_filters', 'filt_diagnosis', 'Diagnosis', 20, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_filters', 'filt_sex', 'Gender', 30, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_filters', 'filt_age_max', 'Maximum Age', 40, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_filters', 'filt_age_min', 'Minimum Age', 50, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_filters', 'filt_encounter_min', 'Minimum Total Number of Encounters', 60, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_filters', 'filt_measure_period', 'Measurement Period Range', 70, 0); + +-- Clinical rule age intervals +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_age_intervals', 'Clinical Rules Age Intervals', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_age_intervals' ,'year', 'Year', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_age_intervals' ,'month', 'Month', 20, 0); + +-- Clinical rule measurement intervals (mostly for CQM stuff) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_measure_intervals', 'Clinical Rules Measurement Intervals', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_measure_intervals' ,'year', 'Year', 10, 0); + +-- Encounter Types (used by CQM rules) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_enc_types', 'Clinical Rules Encounter Types', 3, 0); +-- CQM 0013(need 2),0041(need 2),0043(need 1),0421(need 1) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_outpatient', 'encounter outpatient', 10, 0); +-- CQM 0013(need 2),0041(need 1) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_nurs_fac', 'encounter nursing facility', 20, 0); +-- CQM 0028a(need 2),0028b(need 2) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_off_vis', 'encounter office visit', 30, 0); +-- CQM 0028a(need 2),0028b(need 2) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_hea_and_beh', 'encounter health and behavior assessment', 40, 0); +-- CQM 0028a(need 2),0028b(need 2) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_occ_ther', 'encounter occupational therapy', 50, 0); +-- CQM 0028a(need 2),0028b(need 2) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_psych_and_psych', 'encounter psychiatric & psychologic', 60, 0); +-- CQM 0028a(need 1),0028b(need 1) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_pre_med_ser_18_older', 'encounter preventive medicine services 18 and older', 70, 0); +-- CQM 0028a(need 1),0028b(need 1),0041(need 1) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_pre_ind_counsel', 'encounter preventive medicine - individual counseling', 80, 0); +-- CQM 0028a(need 1),0028b(need 1),0041(need 1) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_pre_med_group_counsel', 'encounter preventive medicine group counseling', 90, 0); +-- CQM 0028a(need 1),0028b(need 1),0041(need 1) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_pre_med_other_serv', 'encounter preventive medicine other services', 100, 0); +-- CQM 0024(need 1),0038(need 1) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_out_pcp_obgyn', 'encounter outpatient w/PCP & obgyn', 110, 0); +-- CQM 0024(exclude) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_pregnancy', 'encounter pregnancy', 120, 0); +-- CQM 0041(need 1) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_nurs_discharge', 'encounter nursing discharge', 130, 0); +-- CQM 0055(need 1),0056(need 1),0061(need 1) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_acute_inp_or_ed', 'encounter acute inpatient or ED', 130, 0); +-- CQM 0055(need 2),0056(need 2),0061(need 2) +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_enc_types' ,'enc_nonac_inp_out_or_opth', 'Encounter: encounter non-acute inpt, outpatient, or ophthalmology', 140, 0); + + +-- -------------------------------------------------------- + +-- +-- Table structure for table `rule_target` +-- + +DROP TABLE IF EXISTS `rule_target`; +CREATE TABLE `rule_target` ( + `id` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to the id column in the clinical_rules table', + `group_id` bigint(20) NOT NULL DEFAULT 1 COMMENT 'Contains group id to identify collection of targets in a rule', + `include_flag` tinyint(1) NOT NULL default 0 COMMENT '0 is exclude and 1 is include', + `required_flag` tinyint(1) NOT NULL default 0 COMMENT '0 is required and 1 is optional', + `method` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options list rule_targets', + `value` varchar(255) NOT NULL DEFAULT '' COMMENT 'Data is dependent on the method', + `interval` bigint(20) NOT NULL DEFAULT 0 COMMENT 'Only used in interval entries', + KEY (`id`) +) ENGINE=MyISAM ; + +-- +-- CQM rule targets first +-- + +-- NQF 0013 Hypertension: Blood Pressure Measurement +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_htn_bp_measure_cqm', 1, 1, 1, 'target_database', 'form_vitals::bps::::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_htn_bp_measure_cqm', 1, 1, 1, 'target_database', 'form_vitals::bpd::::EXIST::1', 0); + +-- NQF 0028a Tobacco Use Assessment +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_tob_use_assess_cqm', 1, 1, 1, 'target_database', 'history_data::tobacco::::LIFESTYLE::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_tob_use_assess_cqm', 1, 1, 1, 'target_interval', 'year', 2); + +-- NQF 0028b Tobacco Cessation Intervention +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_tob_cess_inter_cqm', 1, 1, 1, 'target_database', 'act_cat_inter::act_tobacco::YES::CUSTOM::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_tob_cess_inter_cqm', 1, 1, 1, 'target_interval', 'year', 2); + +-- NQF 0421 Adult Weight Screening and Follow-Up +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_adult_wt_screen_fu_cqm', 1, 1, 1, 'target_database', 'form_vitals::weight::::EXIST::2', 0); + +-- NQF 0024 Weight Assessment and Counseling for Children and Adolescents +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_wt_assess_couns_child_cqm', 1, 1, 1, 'target_database', 'form_vitals::weight::::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_wt_assess_couns_child_cqm', 2, 1, 1, 'target_database', 'act_cat_edu::act_wt::YES::CUSTOM::1', 0); + +-- NQF 0041 Influenza Immunization for Patients >= 50 Years Old +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_influenza_ge_50_cqm', 1, 1, 1, 'target_interval', 'flu_season', 1); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_influenza_ge_50_cqm', 1, 1, 0, 'target_database', 'immunizations::immunization_id::30::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_influenza_ge_50_cqm', 1, 1, 0, 'target_database', 'immunizations::immunization_id::31::EXIST::1', 0); + +-- NQF 0038 Childhood immunization Status +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_child_immun_stat_cqm', 1, 1, 1, 'target_database', 'immunizations::::::EXIST::1', 0); + +-- NQF 0043 Pneumonia Vaccination Status for Older Adults +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_pneumovacc_ge_65_cqm', 1, 1, 0, 'target_database', 'immunizations::immunization_id::19::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_pneumovacc_ge_65_cqm', 1, 1, 0, 'target_database', 'immunizations::immunization_id::20::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_pneumovacc_ge_65_cqm', 1, 1, 0, 'target_database', 'immunizations::immunization_id::21::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_pneumovacc_ge_65_cqm', 1, 1, 0, 'target_database', 'immunizations::immunization_id::22::EXIST::1', 0); + +-- NQF 0055 Diabetes: Eye Exam +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_eye_cqm', 1, 1, 1, 'target_interval', 'year', 1); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_eye_cqm', 1, 1, 1, 'target_database', 'act_cat_exam::act_eye::YES::CUSTOM::1', 0); + +-- NQF 0056 Diabetes: Foot Exam +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_foot_cqm', 1, 1, 1, 'target_interval', 'year', 1); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_foot_cqm', 1, 1, 1, 'target_database', 'act_cat_exam::act_foot::YES::CUSTOM::1', 0); + +-- NQF 0061 Diabetes: Blood Pressure Management +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_bp_control_cqm', 1, 1, 1, 'target_database', 'form_vitals::bps::140::lt::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_bp_control_cqm', 1, 1, 1, 'target_database', 'form_vitals::bpd::90::lt::1', 0); + +-- +-- Standard clinical rule targets +-- + +-- Hypertension: Blood Pressure Measurement +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_htn_bp_measure', 1, 1, 1, 'target_database', 'form_vitals::bps::::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_htn_bp_measure', 1, 1, 1, 'target_database', 'form_vitals::bpd::::EXIST::1', 0); + +-- Tobacco Use Assessment +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_tob_use_assess', 1, 1, 1, 'target_database', 'history_data::tobacco::::LIFESTYLE::1', 0); + +-- Tobacco Cessation Intervention +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_tob_cess_inter', 1, 1, 1, 'target_database', 'act_cat_inter::act_tobacco::YES::CUSTOM::1', 0); + +-- Adult Weight Screening and Follow-Up +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_adult_wt_screen_fu', 1, 1, 1, 'target_database', 'form_vitals::weight::::EXIST::2', 0); + +-- Weight Assessment and Counseling for Children and Adolescents +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_wt_assess_couns_child', 1, 1, 1, 'target_database', 'form_vitals::weight::::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_wt_assess_couns_child', 2, 1, 1, 'target_database', 'act_cat_edu::act_wt::YES::CUSTOM::1', 0); + +-- Influenza Immunization for Patients >= 50 Years Old +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_influenza_ge_50', 1, 1, 1, 'target_interval', 'flu_season', 1); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_influenza_ge_50', 1, 1, 0, 'target_database', 'immunizations::immunization_id::30::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_influenza_ge_50', 1, 1, 0, 'target_database', 'immunizations::immunization_id::31::EXIST::1', 0); + +-- Childhood immunization Status +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_child_immun_stat', 1, 1, 1, 'target_database', 'immunizations::::::EXIST::1', 0); + +-- Pneumonia Vaccination Status for Older Adults +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_pneumovacc_ge_65', 1, 1, 0, 'target_database', 'immunizations::immunization_id::19::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_pneumovacc_ge_65', 1, 1, 0, 'target_database', 'immunizations::immunization_id::20::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_pneumovacc_ge_65', 1, 1, 0, 'target_database', 'immunizations::immunization_id::21::EXIST::1', 0); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_pneumovacc_ge_65', 1, 1, 0, 'target_database', 'immunizations::immunization_id::22::EXIST::1', 0); + +-- Diabetes: Hemoglobin A1C +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_hemo_a1c', 1, 1, 1, 'target_interval', 'month', 3); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_hemo_a1c', 1, 1, 1, 'target_database', 'act_cat_measure::act_hemo_a1c::YES::CUSTOM::1', 0); + +-- Diabetes: Urine Microalbumin +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_urine_alb', 1, 1, 1, 'target_interval', 'year', 1); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_urine_alb', 1, 1, 1, 'target_database', 'act_cat_measure::act_urine_alb::YES::CUSTOM::1', 0); + +-- Diabetes: Eye Exam +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_eye', 1, 1, 1, 'target_interval', 'year', 1); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_eye', 1, 1, 1, 'target_database', 'act_cat_exam::act_eye::YES::CUSTOM::1', 0); + +-- Diabetes: Foot Exam +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_foot', 1, 1, 1, 'target_interval', 'year', 1); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_dm_foot', 1, 1, 1, 'target_database', 'act_cat_exam::act_foot::YES::CUSTOM::1', 0); + +-- Cancer Screening: Mammogram +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_cs_mammo', 1, 1, 1, 'target_interval', 'year', 1); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_cs_mammo', 1, 1, 1, 'target_database', 'act_cat_measure::act_mammo::YES::CUSTOM::1', 0); + +-- Cancer Screening: Pap Smear +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_cs_pap', 1, 1, 1, 'target_interval', 'year', 1); +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_cs_pap', 1, 1, 1, 'target_database', 'act_cat_exam::act_pap::YES::CUSTOM::1', 0); + +-- Cancer Screening: Colon Cancer Screening +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_cs_colon', 1, 1, 1, 'target_database', 'act_cat_assess::act_colon_cancer_screen::YES::CUSTOM::1', 0); + +-- Cancer Screening: Prostate Cancer Screening +INSERT INTO `rule_target` ( `id`, `group_id`, `include_flag`, `required_flag`, `method`, `value`, `interval` ) VALUES ('rule_cs_prostate', 1, 1, 1, 'target_database', 'act_cat_assess::act_prostate_cancer_screen::YES::CUSTOM::1', 0); + +-- +-- Associated lists +-- + +-- Clinical rule target methods +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_targets', 'Clinical Rule Target Methods', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_targets' ,'target_database', 'Database', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_targets' ,'target_interval', 'Interval', 20, 0); + +-- Clinical rule target intervals +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_target_intervals', 'Clinical Rules Target Intervals', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_target_intervals' ,'year', 'Year', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_target_intervals' ,'month', 'Month', 20, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_target_intervals' ,'week', 'Week', 30, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_target_intervals' ,'day', 'Day', 40, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_target_intervals' ,'hour', 'Hour', 50, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_target_intervals' ,'minute', 'Minute', 60, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_target_intervals' ,'second', 'Second', 70, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_target_intervals' ,'flu_season', 'Flu Season', 80, 0); + +-- Clinical rule comparisons +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_comparisons', 'Clinical Rules Comparisons', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_comparisons' ,'EXIST', 'Exist', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_comparisons' ,'lt', 'Less Than', 20, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_comparisons' ,'le', 'Less Than or Equal To', 30, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_comparisons' ,'gt', 'Greater Than', 40, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_comparisons' ,'ge', 'Greater Than or Equal To', 50, 0); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `rule_action` +-- + +DROP TABLE IF EXISTS `rule_action`; +CREATE TABLE `rule_action` ( + `id` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to the id column in the clinical_rules table', + `group_id` bigint(20) NOT NULL DEFAULT 1 COMMENT 'Contains group id to identify collection of targets in a rule', + `category` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to the category item in the rule_action_item table', + `item` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to the item column in the rule_action_item table', + KEY (`id`) +) ENGINE=MyISAM ; + +-- +-- CQM rule targets first +-- +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_wt_assess_couns_child_cqm', 1, 'act_cat_measure', 'act_wt'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_wt_assess_couns_child_cqm', 2, 'act_cat_edu', 'act_wt'); + +-- +-- Standard clinical rule targets +-- +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_htn_bp_measure', 1, 'act_cat_measure', 'act_bp'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_tob_use_assess', 1, 'act_cat_assess', 'act_tobacco'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_tob_cess_inter', 1, 'act_cat_inter', 'act_tobacco'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_adult_wt_screen_fu', 1, 'act_cat_measure', 'act_wt'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_wt_assess_couns_child', 1, 'act_cat_measure', 'act_wt'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_wt_assess_couns_child', 2, 'act_cat_edu', 'act_wt'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_influenza_ge_50', 1, 'act_cat_treat', 'act_influvacc'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_child_immun_stat', 1, 'act_cat_assess', 'act_vaccs'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_pneumovacc_ge_65', 1, 'act_cat_treat', 'act_pneumovacc'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_dm_hemo_a1c', 1, 'act_cat_measure', 'act_hemo_a1c'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_dm_urine_alb', 1, 'act_cat_measure', 'act_urine_alb'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_dm_eye', 1, 'act_cat_exam', 'act_eye'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_dm_foot', 1, 'act_cat_exam', 'act_foot'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_cs_mammo', 1, 'act_cat_measure', 'act_mammo'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_cs_pap', 1, 'act_cat_exam', 'act_pap'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_cs_colon', 1, 'act_cat_assess', 'act_colon_cancer_screen'); +INSERT INTO `rule_action` ( `id`, `group_id`, `category`, `item` ) VALUES ('rule_cs_prostate', 1, 'act_cat_assess', 'act_prostate_cancer_screen'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `rule_action_item` +-- + +DROP TABLE IF EXISTS `rule_action_item`; +CREATE TABLE `rule_action_item` ( + `category` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options list rule_action_category', + `item` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options list rule_action', + `clin_rem_link` varchar(255) NOT NULL DEFAULT '' COMMENT 'Custom html link in clinical reminder widget', + `reminder_message` text NOT NULL DEFAULT '' COMMENT 'Custom message in patient reminder', + `custom_flag` tinyint(1) NOT NULL default 0 COMMENT '1 indexed to rule_patient_data, 0 indexed within main schema', + PRIMARY KEY (`category`,`item`) +) ENGINE=MyISAM ; + +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_measure', 'act_bp', '', '', 0); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_assess', 'act_tobacco', '', '', 0); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_inter', 'act_tobacco', '', '', 1); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_measure', 'act_wt', '', '', 0); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_edu', 'act_wt', '', '', 1); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_treat', 'act_influvacc', '', '', 0); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_assess', 'act_vaccs', '', '', 0); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_treat', 'act_pneumovacc', '', '', 0); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_measure', 'act_hemo_a1c', '', '', 1); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_measure', 'act_urine_alb', '', '', 1); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_exam', 'act_eye', '', '', 1); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_exam', 'act_foot', '', '', 1); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_measure', 'act_mammo', '', '', 1); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_exam', 'act_pap', '', '', 1); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_assess', 'act_colon_cancer_screen', '', '', 1); +INSERT INTO `rule_action_item` ( `category`, `item`, `clin_rem_link`, `reminder_message`, `custom_flag` ) VALUES ('act_cat_assess', 'act_prostate_cancer_screen', '', '', 1); + +-- +-- Associated lists +-- + +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_action_category', 'Clinical Rule Action Category', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action_category' ,'act_cat_assess', 'Assessment', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action_category' ,'act_cat_edu', 'Education', 20, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action_category' ,'act_cat_exam', 'Examination', 30, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action_category' ,'act_cat_inter', 'Intervention', 40, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action_category' ,'act_cat_measure', 'Measurement', 50, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action_category' ,'act_cat_treat', 'Treatment', 60, 0); + +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_action', 'Clinical Rule Action Item', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_bp', 'Blood Pressure', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_influvacc', 'Influenza Vaccine', 20, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_tobacco', 'Tobacco', 30, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_wt', 'Weight', 40, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_vaccs', 'Vaccines', 50, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_pneumovacc', 'Pneumococcal Vaccine', 60, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_hemo_a1c', 'Hemoglobin A1C', 70, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_urine_alb', 'Urine Microalbumin', 80, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_eye', 'Opthalmic', 90, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_foot', 'Podiatric', 100, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_mammo', 'Mammogram', 110, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_pap', 'Pap Smear', 120, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_colon_cancer_screen', 'Colon Cancer Screening', 130, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_action' ,'act_prostate_cancer_screen', 'Prostate Cancer Screening', 140, 0); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `rule_patient_data` +-- + +DROP TABLE IF EXISTS `rule_patient_data`; +CREATE TABLE `rule_patient_data` ( + `id` bigint(20) NOT NULL auto_increment, + `date` datetime DEFAULT NULL, + `pid` bigint(20) NOT NULL, + `category` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to the category item in the rule_action_item table', + `item` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to the item column in the rule_action_item table', + `complete` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options list yesno', + `result` varchar(255) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + KEY (`pid`), + KEY (`category`,`item`) +) ENGINE=MyISAM AUTO_INCREMENT=1 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `rule_reminder` +-- + +DROP TABLE IF EXISTS `rule_reminder`; +CREATE TABLE `rule_reminder` ( + `id` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to the id column in the clinical_rules table', + `method` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options list rule_reminder_methods', + `method_detail` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options list rule_reminder_intervals', + `value` varchar(255) NOT NULL DEFAULT '', + KEY (`id`) +) ENGINE=MyISAM ; + +-- Hypertension: Blood Pressure Measurement +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_htn_bp_measure', 'patient_reminder_post', 'month', '1'); + +-- Tobacco Use Assessment +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_use_assess', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_use_assess', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_use_assess', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_use_assess', 'patient_reminder_post', 'month', '1'); + +-- Tobacco Cessation Intervention +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_cess_inter', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_cess_inter', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_cess_inter', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_tob_cess_inter', 'patient_reminder_post', 'month', '1'); + +-- Adult Weight Screening and Follow-Up +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_adult_wt_screen_fu', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_adult_wt_screen_fu', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_adult_wt_screen_fu', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_adult_wt_screen_fu', 'patient_reminder_post', 'month', '1'); + +-- Weight Assessment and Counseling for Children and Adolescents +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_wt_assess_couns_child', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_wt_assess_couns_child', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_wt_assess_couns_child', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_wt_assess_couns_child', 'patient_reminder_post', 'month', '1'); + +-- Influenza Immunization for Patients >= 50 Years Old +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_influenza_ge_50', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_influenza_ge_50', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_influenza_ge_50', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_influenza_ge_50', 'patient_reminder_post', 'month', '1'); + +-- Childhood immunization Status +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_child_immun_stat', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_child_immun_stat', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_child_immun_stat', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_child_immun_stat', 'patient_reminder_post', 'month', '1'); + +-- Pneumonia Vaccination Status for Older Adults +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_pneumovacc_ge_65', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_pneumovacc_ge_65', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_pneumovacc_ge_65', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_pneumovacc_ge_65', 'patient_reminder_post', 'month', '1'); + +-- Diabetes: Hemoglobin A1C +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_hemo_a1c', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_hemo_a1c', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_hemo_a1c', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_hemo_a1c', 'patient_reminder_post', 'month', '1'); + +-- Diabetes: Urine Microalbumin +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_urine_alb', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_urine_alb', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_urine_alb', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_urine_alb', 'patient_reminder_post', 'month', '1'); + +-- Diabetes: Eye Exam +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_eye', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_eye', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_eye', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_eye', 'patient_reminder_post', 'month', '1'); + +-- Diabetes: Foot Exam +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_foot', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_foot', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_foot', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_dm_foot', 'patient_reminder_post', 'month', '1'); + +-- Cancer Screening: Mammogram +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_mammo', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_mammo', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_mammo', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_mammo', 'patient_reminder_post', 'month', '1'); + +-- Cancer Screening: Pap Smear +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_pap', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_pap', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_pap', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_pap', 'patient_reminder_post', 'month', '1'); + +-- Cancer Screening: Colon Cancer Screening +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_colon', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_colon', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_colon', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_colon', 'patient_reminder_post', 'month', '1'); + +-- Cancer Screening: Prostate Cancer Screening +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_prostate', 'clinical_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_prostate', 'clinical_reminder_post', 'month', '1'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_prostate', 'patient_reminder_pre', 'week', '2'); +INSERT INTO `rule_reminder` ( `id`, `method`, `method_detail`, `value` ) VALUES ('rule_cs_prostate', 'patient_reminder_post', 'month', '1'); + +-- +-- Associated lists +-- + +-- Clinical rule reminder intervals +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_reminder_intervals', 'Clinical Rules Reminder Intervals', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_intervals' ,'month', 'Month', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_intervals' ,'week', 'Week', 20, 0); + +-- Clinical rule reminder methods +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_reminder_methods', 'Clinical Rules Reminder Methods', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_methods' ,'clinical_reminder_pre', 'Past Due Interval (Clinical Reminders)', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_methods' ,'patient_reminder_pre', 'Past Due Interval (Patient Reminders)', 20, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_methods' ,'clinical_reminder_post', 'Soon Due Interval (Clinical Reminders)', 30, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_methods' ,'patient_reminder_pre', 'Past Due Interval (Patient Reminders)', 40, 0); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `patient_reminders` +-- + +DROP TABLE IF EXISTS `patient_reminders`; +CREATE TABLE `patient_reminders` ( + `id` bigint(20) NOT NULL auto_increment, + `active` tinyint(1) NOT NULL default 1 COMMENT '1 if active and 0 if not active', + `date_inactivated` datetime DEFAULT NULL, + `reason_inactivated` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options list rule_reminder_inactive_opt', + `due_status` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options list rule_reminder_due_opt', + `pid` bigint(20) NOT NULL COMMENT 'id from patient_data table', + `category` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to the category item in the rule_action_item table', + `item` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to the item column in the rule_action_item table', + `date_created` datetime DEFAULT NULL, + `date_sent` datetime DEFAULT NULL, + `voice_status` tinyint(1) NOT NULL default 0 COMMENT '0 if not sent and 1 if sent', + `sms_status` tinyint(1) NOT NULL default 0 COMMENT '0 if not sent and 1 if sent', + `email_status` tinyint(1) NOT NULL default 0 COMMENT '0 if not sent and 1 if sent', + `mail_status` tinyint(1) NOT NULL default 0 COMMENT '0 if not sent and 1 if sent', + PRIMARY KEY (`id`), + KEY `pid` (`pid`), + KEY (`category`,`item`) +) ENGINE=MyISAM AUTO_INCREMENT=1; + +-- Clinical rule reminder due options +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_reminder_due_opt', 'Clinical Rules Reminder Due Options', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_due_opt' ,'due', 'Due', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_due_opt' ,'soon_due', 'Due Soon', 20, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_due_opt' ,'past_due', 'Past Due', 30, 0); + +-- Clinical rule reminder inactivate options +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('lists' ,'rule_reminder_inactive_opt', 'Clinical Rules Reminder Inactivation Options', 3, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_inactive_opt' ,'auto', 'Automatic', 10, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_inactive_opt' ,'due_status_update', 'Due Status Update', 20, 0); +INSERT INTO `list_options` ( `list_id`, `option_id`, `title`, `seq`, `is_default` ) VALUES ('rule_reminder_inactive_opt' ,'manual', 'Manual', 20, 0); +