Skip to content

Commit

Permalink
fixes: CDR engine fixes for duplicate use of actions across rules in …
Browse files Browse the repository at this point in the history
…addition to an optimization

The optimization both clarifies the code regarding which $reminder_due status is chosen and also minimizes the calls to reminder_results_integrate, which could get resource intensive if overuse it.
  • Loading branch information
bradymiller committed Apr 21, 2024
1 parent 4a991ed commit e752bb2
Showing 1 changed file with 102 additions and 67 deletions.
169 changes: 102 additions & 67 deletions library/clinical_rules.php
Original file line number Diff line number Diff line change
Expand Up @@ -1034,11 +1034,11 @@ function test_rules_clinic($provider = '', $type = '', $dateTarget = '', $mode =

//Set date counter and reminder token (applicable for reminders only)
if ($dateCounter == 1) {
$reminder_due = "soon_due";
$reminder_due = "not_due";
} elseif ($dateCounter == 2) {
$reminder_due = "due";
$reminder_due = "soon_due";
} else { // $dateCounter == 3
$reminder_due = "past_due";
$reminder_due = "due";
}

// Check if pass filter
Expand Down Expand Up @@ -1074,31 +1074,37 @@ function test_rules_clinic($provider = '', $type = '', $dateTarget = '', $mode =
$temp_track_pass = 1;
}

// send to reminder results for reminders-all when not_due (ie. $dateCounter == 1)
if (($mode == "reminders-all") && ($dateCounter == 1)) {
// place the completed actions into the reminder return array
if (
($mode != "report") &&
(($mode == "reminders-all") || (($mode != "reminders-all") && ($reminder_due != "not_due")))
) {
// Place the actions into the reminder return array.
// There are 2 reminder modes, reminders-due and reminders-all. The not_due reminders are not
// shown in reminders-due mode but are shown in reminders-all mode. So this block is skipped
// if due_status is 'not_due' and mode is not 'reminders-all'.
$actionArray = resolve_action_sql($rowRule['id'], '1');
foreach ($actionArray as $action) {
$action_plus = $action;
$action_plus['due_status'] = "not_due";
$action_plus['due_status'] = $reminder_due;
$action_plus['pid'] = $rowPatient['pid'];
$action_plus['rule_id'] = $rowRule['id'];
$results = reminder_results_integrate($results, $action_plus);
$results = reminder_results_integrate($results, $action_plus, $mode);
}
}

break;
} else {
// send to reminder results
if ($mode != "report") {
// place the uncompleted actions into the reminder return array
if (($mode != "report") && ($dateCounter == 3)) {
// Did not pass any of the target dates, so place the past_due actions into the reminder
// return array when runnning in one of the reminders mode (either reminders-due mode
// or reminders-all mode).
$actionArray = resolve_action_sql($rowRule['id'], '1');
foreach ($actionArray as $action) {
$action_plus = $action;
$action_plus['due_status'] = $reminder_due;
$action_plus['due_status'] = 'past_due';
$action_plus['pid'] = $rowPatient['pid'];
$action_plus['rule_id'] = $rowRule['id'];
$results = reminder_results_integrate($results, $action_plus);
$results = reminder_results_integrate($results, $action_plus, $mode);
}
}
}
Expand Down Expand Up @@ -1163,11 +1169,11 @@ function test_rules_clinic($provider = '', $type = '', $dateTarget = '', $mode =

//Set date counter and reminder token (applicable for reminders only)
if ($dateCounter == 1) {
$reminder_due = "soon_due";
$reminder_due = "not_due";
} elseif ($dateCounter == 2) {
$reminder_due = "due";
$reminder_due = "soon_due";
} else { // $dateCounter == 3
$reminder_due = "past_due";
$reminder_due = "due";
}

// Check if pass filter
Expand Down Expand Up @@ -1197,31 +1203,37 @@ function test_rules_clinic($provider = '', $type = '', $dateTarget = '', $mode =
$temp_track_pass = 1;
}

// send to reminder results for reminders-all when not_due (ie. $dateCounter == 1)
if (($mode == "reminders-all") && ($dateCounter == 1)) {
// place the completed actions into the reminder return array
if (
($mode != "report") &&
(($mode == "reminders-all") || (($mode != "reminders-all") && ($reminder_due != "not_due")))
) {
// Place the actions into the reminder return array.
// There are 2 reminder modes, reminders-due and reminders-all. The not_due reminders are not
// shown in reminders-due mode but are shown in reminders-all mode. So this block is skipped
// if due_status is 'not_due' and mode is not 'reminders-all'.
$actionArray = resolve_action_sql($rowRule['id'], $i);
foreach ($actionArray as $action) {
$action_plus = $action;
$action_plus['due_status'] = "not_due";
$action_plus['due_status'] = $reminder_due;
$action_plus['pid'] = $rowPatient['pid'];
$action_plus['rule_id'] = $rowRule['id'];
$results = reminder_results_integrate($results, $action_plus);
$results = reminder_results_integrate($results, $action_plus, $mode);
}
}

break;
} else {
// send to reminder results
if ($mode != "report") {
// place the actions into the reminder return array
if (($mode != "report") && ($dateCounter == 3)) {
// Did not pass any of the target dates, so place the past_due actions into the reminder
// return array when runnning in one of the reminders mode (either reminders-due mode
// or reminders-all mode).
$actionArray = resolve_action_sql($rowRule['id'], $i);
foreach ($actionArray as $action) {
$action_plus = $action;
$action_plus['due_status'] = $reminder_due;
$action_plus['due_status'] = 'past_due';
$action_plus['pid'] = $rowPatient['pid'];
$action_plus['rule_id'] = $rowRule['id'];
$results = reminder_results_integrate($results, $action_plus);
$results = reminder_results_integrate($results, $action_plus, $mode);
}
}
}
Expand Down Expand Up @@ -2777,30 +2789,6 @@ function collect_database_label($label, $table)
return $returnedLabel;
}

/**
* Simple function to avoid processing of duplicate actions
*
* @param array $actions 2-dimensional array with all current active targets
* @param array $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.
*
Expand Down Expand Up @@ -2886,46 +2874,93 @@ function calculate_reminder_dates($rule, string $dateTarget = null, $type = null
}

/**
* Adds an action into the reminder array
* Adds an action into the reminder/action array while dealing with duplicate actions.
*
* @param array $reminderOldArray Contains the current array of reminders
* @param array $reminderNew Array of a new reminder
* @return array Reminders
* @param string $mode Options are 'reminders-due' or 'reminders-all'
* @return array Reminders
*/
function reminder_results_integrate($reminderOldArray, $reminderNew)
function reminder_results_integrate($reminderOldArray, $reminderNew, $mode)
{
$results = [];

$results = array();

// If reminderArray is empty, then insert new reminder
// If reminderArray is empty, then insert new reminder
if (empty($reminderOldArray)) {
$results[] = $reminderNew;
return $results;
}

// If duplicate reminder, then replace the old one
$duplicate = false;
$duplicateFlag = false;
foreach ($reminderOldArray as $reminderOld) {
if (
$reminderOld['pid'] == $reminderNew['pid'] &&
$reminderOld['category'] == $reminderNew['category'] &&
$reminderOld['item'] == $reminderNew['item']
) {
$results[] = $reminderNew;
$duplicate = true;
if ($mode == "reminders-all") {
// in reminders-all mode, show the status of duplicate actions of different rules
// (which user can hover over to see the rule), however do not show duplicate actions
// within the same rule (and show only the highest priority due status in this case).
$duplicate = $reminderOld['pid'] == $reminderNew['pid'] &&
$reminderOld['category'] == $reminderNew['category'] &&
$reminderOld['item'] == $reminderNew['item'] &&
$reminderOld['rule_id'] == $reminderNew['rule_id'];
} else {
// In the standard reminders-due mode, do not show any duplicate actions
// and show only the highest priority due status if duplicate actions.
$duplicate = $reminderOld['pid'] == $reminderNew['pid'] &&
$reminderOld['category'] == $reminderNew['category'] &&
$reminderOld['item'] == $reminderNew['item'];
}

if ($duplicate) {
$duplicateFlag = true;
// The new action is a duplicate of an applicable old action (now need to figure out which action to keep).
// Only keep the action with the highest priority due status.
if (dueStatusCompare($reminderOld['due_status'], $reminderNew['due_status'])) {
// New action is higher priority (or same priority) than old action, so will remove old
// action and keep the new action.
$results[] = $reminderNew;
} else {
// Old action is higher priority than new action, so will keep the old action (and not keep
// the new action).
$results[] = $reminderOld;
}
} else {
// Not a duplicate, so will keep the old action.
$results[] = $reminderOld;
}
}

// If a new reminder, then insert the new reminder
if (!$duplicate) {
if (!$duplicateFlag) {
// The new action was not a duplicate, so will keep it.
$results[] = $reminderNew;
}

return $results;
}

/**
* Returns true if new due status is higher priority or the same priority
* (ie. high priority to lowest is past_due > due > soon_due > not_due)
*
* @param string $old (options are past_due, due, soon_due, not_due)
* @param string $new (options are past_due, due, soon_due, not_due)
* @return boolean
*/
function dueStatusCompare(string $old, string $new): bool
{
$comparisonArray = ["not_due" => 1, "soon_due" => 2, "due" => 3, "past_due" => 4];

// return false if either $old or $new are not valid strings
if (!array_key_exists($old, $comparisonArray) || !array_key_exists($new, $comparisonArray)) {
return false;
}

// return true if $new is higher priority or same priority as $old
if ($comparisonArray[$new] >= $comparisonArray[$old]) {
return true;
} else {
return false;
}
}

/**
* Compares number of items with requested comparison operator
*
Expand Down

0 comments on commit e752bb2

Please sign in to comment.