Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: Clinical Rules - interval boundaries used in evaluating target instances #7161

Closed
hanksterr7 opened this issue Jan 10, 2024 · 1 comment · Fixed by #7268
Closed

bug: Clinical Rules - interval boundaries used in evaluating target instances #7161

hanksterr7 opened this issue Jan 10, 2024 · 1 comment · Fixed by #7268
Milestone

Comments

@hanksterr7
Copy link
Contributor

hanksterr7 commented Jan 10, 2024

My topic #4
Right-side boundary of intervals used in target evaluation should be now() instead of now() + warning interval or now - past due interval
This is necessary when more than one target exists in a target/action group
Without this fix, a target may be inappropriately considered not satisfied

Discussion:
In a target/action group, there can be multiple targets.
A target configuration includes defining an interval, such as 3 months, or 1 year.
In evaluating a rule against a patient's data, the filters are first checked.
If the filter check succeeds, then the targets in each target/action group are checked.
The collection of targets in a target group is checked against 3 possible intervals:
-- #1: now() + warning interval - target interval -> now() + warning interval (example: T - 11M - T + 1M)
-- #2: now() - target interval -> now(). (example: T - 12M -> T)
-- #3: now() - target interval - past due interval -> now - past due interval (example: T - 14 M -> T - 2M)
The examples are based on a warning interval of 1 month, a past due interval of 2 months, and a target interval of 1 year

Note that even though an interval can be specified when editing each target, only the most recently specified interval is saved and used in processing all targets across all target/action groups. The entered value is linked to the rule, not the target. It would be nice if the editor and the rule_target table allowed specifying a target-specific interval, but that does not seem to be the case

test_target() is called once for each interval, and in each call, it processes all of the targets in a target group
First, interval #1 is tested.
If instances of the targets in a target group are found with dates that are in interval #1, the rule is deemed "not due".
Otherwise, if instances of the targets are found with dates that are in interval #2, the rule is deemed "due soon"
Otherwise, if instances of the targets are found with dates that are in interval #3, the rule is deemed "due"
Otherwise, the rule is deemed "past due". This happens if the instances of the target have a date that is prior to the start of interval #3, or if no instances of the targets are found

Note that targets can be required or optional, much like filters
They can also be inclusion, or exclusion, and can have a frequency specified (i.e. the # of times an instance of the target needs to be found during an interval)
If some targets in a group are required, and others optional, only the required ones matter, and the specified number of instances of all required targets need to be found during an interval in order for the target group to be satisfied.
If all targets are optional, then the specified number of instances of at least one of the optional targets needs to be found in the interval.

The interval boundaries used by the logic cause difficulties when there is more that one target defined in a target/action group

Example: a rule's target/action group has two required targets. Each has a frequency of "= 1" and is required and "inclusion". The target interval is 3 months. The rule's warning interval is 2 weeks, and the past due interval is 1 month. Each target is looking for a completion of a custom form.
The logic will use intervals of
#1: T-3M+2W -> T+2W
#2: T-3M -> T
#3: T-3M-1M -> T-1M

Suppose an instance of a form for target #1 has a date of T-3M-1W, and an instance of a form for target #2 has a date of T-1W

The logic will first test interval #1. It will find an instance of target #2's form in the interval, but not target #1's form, so the test will fail and the status will not be "not due"
The logic will then test interval #2. It will again find an instance of target #2's form in the interval, but not target #1's form, so the test will fail and the status will not be "due soon"
The logic will then test interval #3. It will now not find an instance of target #2's form in the interval, but will find target #1's form. Since both are required, the test will again fail and the status will not be "due" (which would seem the appropriate status), and instead be declared to be "past due". This failure is inappropriate, and is due to interval's right-side boundary being T-1M. If it were T (which would seem appropriate), the test would have succeeded. An instance of both forms would have been found in this modified interval, and the targets in the target group declared satisfied

The simple fix to this issue is to modify sql_interval_string() to return intervals whose right-side boundary is T instead of
T + warning interval for the first interval
and
T - past due interval
for the third interval
(the right-side boundary is already T for the second interval)
The left side boundaries for the intervals would remain unchanged

@hanksterr7
Copy link
Contributor Author

@bradymiller, you have convinced me of the need to be able to evaluate rules against any time point, not just now()

This is necessary when running rule reports.

So, I have modified my solution described above to now compare a patient's data against these three intervals, based on the value of $dateTarget passed to test_rules_clinic():
-- $dateTarget + warning interval - target interval -> $dateTarget
-- $dateTarget - target interval -> $dateTarget
-- $dateTarget - past due interval - target interval - $dateTarget

I have not yet updated the code in the PR #7160. I will do that later today or tomorrow. Requires passing both $dateTarget and $dateFocus down from test_rules_clinic() through all its descendent calls all the way to sql_interval_string(), where the above intervals are calculated

bradymiller pushed a commit to bradymiller/openemr that referenced this issue Apr 3, 2024
- improved handling of filters/targets for inclusion/exclusion flags, and where multiple filters/targets exist across classes of patient data
- fixing right side of target interval used for target testing at value of $dateTarget passed to test_rules_clinic() instead of a value that floats with changes to left side of the interval
- fix to divide by zero error in evaluating percent of passing rules

more details at:
openemr#7153
openemr#7157
openemr#7161
bradymiller pushed a commit to bradymiller/openemr that referenced this issue Apr 7, 2024
- improved handling of filters/targets for inclusion/exclusion flags, and where multiple filters/targets exist across classes of patient data
- fixing right side of target interval used for target testing at value of $dateTarget passed to test_rules_clinic() instead of a value that floats with changes to left side of the interval
- fix to divide by zero error in evaluating percent of passing rules

more details at:
openemr#7153
openemr#7157
openemr#7161
bradymiller pushed a commit to bradymiller/openemr that referenced this issue Apr 17, 2024
- improved handling of filters/targets for inclusion/exclusion flags, and where multiple filters/targets exist across classes of patient data
- fixing right side of target interval used for target testing at value of $dateTarget passed to test_rules_clinic() instead of a value that floats with changes to left side of the interval
- fix to divide by zero error in evaluating percent of passing rules

more details at:
openemr#7153
openemr#7157
openemr#7161
bradymiller pushed a commit to bradymiller/openemr that referenced this issue Apr 21, 2024
- improved handling of filters/targets for inclusion/exclusion flags, and where multiple filters/targets exist across classes of patient data
- fixing right side of target interval used for target testing at value of $dateTarget passed to test_rules_clinic() instead of a value that floats with changes to left side of the interval
- fix to divide by zero error in evaluating percent of passing rules

more details at:
openemr#7153
openemr#7157
openemr#7161
@adunsulag adunsulag added this to the 7.0.2.1 milestone Apr 22, 2024
@adunsulag adunsulag changed the title Clinical Rules - interval boundaries used in evaluating target instances bug: Clinical Rules - interval boundaries used in evaluating target instances Apr 22, 2024
bradymiller pushed a commit to bradymiller/openemr that referenced this issue Apr 23, 2024
- improved handling of filters/targets for inclusion/exclusion flags, and where multiple filters/targets exist across classes of patient data
- fixing right side of target interval used for target testing at value of $dateTarget passed to test_rules_clinic() instead of a value that floats with changes to left side of the interval
- fix to divide by zero error in evaluating percent of passing rules

more details at:
openemr#7153
openemr#7157
openemr#7161
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants