/**
 * Process clinic rules via a batching method to improve performance and decrease memory overhead.
 *
 * 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). The structure of the returned results is dependent on the
 * $organize_mode and $mode parameters.
 * <pre>The results are dependent on the $organize_mode parameter settings
 *   'default' organize_mode:
 *     Returns a two-dimensional array of results organized by rules (dependent on the following $mode settings):
 *       'reminders-due' mode - returns an array of reminders (action array elements plus a 'pid' and 'due_status')
 *       'reminders-all' 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
 *   'plans' organize_mode:
 *     Returns similar to default, but organizes by the active plans
 * </pre>
 *
 * @param  integer      $provider      id of a selected provider. If blank, then will test entire clinic. If 'collate_outer' or 'collate_inner', then will test each provider in entire clinic; outer will nest plans  inside collated providers, while inner will nest the providers inside the plans (note inner and outer are only different if organize_mode is set to plans).
 * @param  string       $type          rule filter (active_alert,passive_alert,cqm,amc,patient_reminder). If blank then will test all rules.
 * @param  string/array $dateTarget    target date (format Y-m-d H:i:s). If blank then will test with current date as target. If an array, then is holding two dates ('dateBegin' and 'dateTarget').
 * @param  string       $mode          choose either 'report' or 'reminders-all' or 'reminders-due' (required)
 * @param  string       $plan          test for specific plan only
 * @param  string       $organize_mode Way to organize the results (default, plans). See above for organization structure of the results.
 * @param  array        $options       can hold various option (for now, used to hold the manual number of labs for the AMC report)
 * @param  string       $pat_prov_rel  How to choose patients that are related to a chosen provider. 'primary' selects patients that the provider is set as primary provider. 'encounter' selectes patients that the provider has seen. This parameter is only applicable if the $provider parameter is set to a provider or collation setting.
 * @param  integer      $batchSize     number of patients to batch (default is 100; plan to optimize this default setting in the future)
 * @param  integer      $report_id     id of report in database (if already bookmarked)
 * @return array                       See above for organization structure of the results.
 */
function test_rules_clinic_batch_method($provider = '', $type = '', $dateTarget = '', $mode = '', $plan = '', $organize_mode = 'default', $options = array(), $pat_prov_rel = 'primary', $batchSize = '', $report_id = NULL)
{
    // Default to a batchsize, if empty
    if (empty($batchSize)) {
        $batchSize = 100;
    }
    // Collect total number of pertinent patients (to calculate batching parameters)
    $totalNumPatients = buildPatientArray('', $provider, $pat_prov_rel, NULL, NULL, TRUE);
    // Cycle through the batches and collect/combine results
    if ($totalNumPatients % $batchSize > 0) {
        // not perfectly divisible
        $totalNumberBatches = floor($totalNumPatients / $batchSize) + 1;
    } else {
        // perfectly divisible
        $totalNumberBatches = floor($totalNumPatients / $batchSize);
    }
    // Fix things in the $options array(). This now stores the number of labs to be used in the denominator in the AMC report.
    // The problem with this variable is that is is added in every batch. So need to fix it by dividing this number by the number
    // of planned batches(note the fixed array will go into the test_rules_clinic function, however the original will be used
    // in the report storing/tracking engine.
    $options_modified = $options;
    if (!empty($options_modified['labs_manual'])) {
        $options_modified['labs_manual'] = $options_modified['labs_manual'] / $totalNumberBatches;
    }
    // Prepare the database to track/store results
    $fields = array('provider' => $provider, 'mode' => $mode, 'plan' => $plan, 'organize_mode' => $organize_mode, 'pat_prov_rel' => $pat_prov_rel);
    if (is_array($dateTarget)) {
        $fields = array_merge($fields, array(date_target => $dateTarget['dateTarget']));
        $fields = array_merge($fields, array(date_begin => $dateTarget['dateBegin']));
    } else {
        if (empty($dateTarget)) {
            $fields = array_merge($fields, array(date_target => date("Y-m-d H:i:s")));
        } else {
            $fields = array_merge($fields, array(date_target => $dateTarget));
        }
    }
    if (!empty($options)) {
        foreach ($options as $key => $value) {
            $fields = array_merge($fields, array($key => $value));
        }
    }
    $report_id = beginReportDatabase($type, $fields, $report_id);
    setTotalItemsReportDatabase($report_id, $totalNumPatients);
    for ($i = 0; $i < $totalNumberBatches; $i++) {
        $dataSheet_batch = test_rules_clinic($provider, $type, $dateTarget, $mode, '', $plan, $organize_mode, $options_modified, $pat_prov_rel, $batchSize * $i + 1, $batchSize);
        if ($i == 0) {
            // For first cycle, simply copy it to dataSheet
            $dataSheet = $dataSheet_batch;
        } else {
            //debug
            //error_log("CDR: ".print_r($dataSheet,TRUE),0);
            //error_log("CDR: ".($batchSize*$i)." records",0);
            // Integrate batch results into main dataSheet
            foreach ($dataSheet_batch as $key => $row) {
                if (!$row['is_sub']) {
                    //skip this stuff for the sub entries (and use previous main entry in percentage calculation)
                    $total_patients = $dataSheet[$key]['total_patients'] + $row['total_patients'];
                    $dataSheet[$key]['total_patients'] = $total_patients;
                    $excluded = $dataSheet[$key]['excluded'] + $row['excluded'];
                    $dataSheet[$key]['excluded'] = $excluded;
                    $pass_filter = $dataSheet[$key]['pass_filter'] + $row['pass_filter'];
                    $dataSheet[$key]['pass_filter'] = $pass_filter;
                }
                $pass_target = $dataSheet[$key]['pass_target'] + $row['pass_target'];
                $dataSheet[$key]['pass_target'] = $pass_target;
                $dataSheet[$key]['percentage'] = calculate_percentage($pass_filter, $excluded, $pass_target);
            }
        }
        //Update database to track results
        updateReportDatabase($report_id, $total_patients);
    }
    // Record results in database and send to screen, if applicable.
    finishReportDatabase($report_id, json_encode($dataSheet));
    return $dataSheet;
}
Example #2
0
/**
 * Function to update reminders via a batching method to improve performance and decrease memory overhead.
 *
 * Function that updates reminders and returns an array with a specific data structure.
 * <pre>The data structure of the return array includes the following elements
 *  '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.
 * </pre>
 *
 * @param  string   $dateTarget  target date (format Y-m-d H:i:s). If blank then will test with current date as target.
 * @param  integer  $batchSize   number of patients to batch (default is 25; plan to optimize this default setting in the future)
 * @param  integer  $report_id   id of report in database (if already bookmarked)
 * @param  boolean  $also_send   if TRUE, then will also call send_reminder when done
 * @return array                 see above for data structure of returned array
 */
function update_reminders_batch_method($dateTarget = '', $batchSize = 25, $report_id = NULL, $also_send = FALSE)
{
    // Default to a batchsize, if empty
    if (empty($batchSize)) {
        $batchSize = 25;
    }
    // Collect total number of pertinent patients (to calculate batching parameters)
    $totalNumPatients = buildPatientArray('', '', '', NULL, NULL, TRUE);
    // Cycle through the batches and collect/combine results
    if ($totalNumPatients % $batchSize > 0) {
        $totalNumberBatches = floor($totalNumPatients / $batchSize) + 1;
    } else {
        $totalNumberBatches = floor($totalNumPatients / $batchSize);
    }
    // Prepare the database to track/store results
    if ($also_send) {
        $report_id = beginReportDatabase("process_send_reminders", '', $report_id);
    } else {
        $report_id = beginReportDatabase("process_reminders", '', $report_id);
    }
    setTotalItemsReportDatabase($report_id, $totalNumPatients);
    $patient_counter = 0;
    for ($i = 0; $i < $totalNumberBatches; $i++) {
        $patient_counter = $batchSize * ($i + 1);
        if ($patient_counter > $totalNumPatients) {
            $patient_counter = $totalNumPatients;
        }
        $update_rem_log_batch = update_reminders($dateTarget, '', $batchSize * $i + 1, $batchSize);
        if ($i == 0) {
            // For first cycle, simply copy it to update_rem_log
            $update_rem_log = $update_rem_log_batch;
        } else {
            // Debug statements
            //error_log("CDR: ".print_r($update_rem_log,TRUE),0);
            //error_log("CDR: ".($batchSize*$i). " records",0);
            // Integrate batch results into main update_rem_log
            $update_rem_log['total_active_actions'] = $update_rem_log['total_active_actions'] + $update_rem_log_batch['total_active_actions'];
            $update_rem_log['total_pre_active_reminders'] = $update_rem_log['total_pre_active_reminders'] + $update_rem_log_batch['total_pre_active_reminders'];
            $update_rem_log['total_pre_unsent_reminders'] = $update_rem_log['total_pre_unsent_reminders'] + $update_rem_log_batch['total_pre_unsent_reminders'];
            $update_rem_log['number_new_reminders'] = $update_rem_log['number_new_reminders'] + $update_rem_log_batch['number_new_reminders'];
            $update_rem_log['number_updated_reminders'] = $update_rem_log['number_updated_reminders'] + $update_rem_log_batch['number_updated_reminders'];
            $update_rem_log['number_unchanged_reminders'] = $update_rem_log['number_unchanged_reminders'] + $update_rem_log_batch['number_unchanged_reminders'];
            $update_rem_log['number_inactivated_reminders'] = $update_rem_log['number_inactivated_reminders'] + $update_rem_log_batch['number_inactivated_reminders'];
            $update_rem_log['total_post_active_reminders'] = $update_rem_log['total_post_active_reminders'] + $update_rem_log_batch['total_post_active_reminders'];
            $update_rem_log['total_post_unsent_reminders'] = $update_rem_log['total_post_unsent_reminders'] + $update_rem_log_batch['total_post_unsent_reminders'];
        }
        //Update database to track results
        updateReportDatabase($report_id, $patient_counter);
    }
    // Create an array for saving to database (allows combining with the send log)
    $save_log = array();
    $save_log[] = $update_rem_log;
    // Send reminders, if this was selected
    if ($also_send) {
        $log_send = send_reminders();
        $save_log[] = $log_send;
    }
    // Record combo results in database
    finishReportDatabase($report_id, json_encode($save_log));
    // Just return the process reminders array
    return $update_rem_log;
}