-
Notifications
You must be signed in to change notification settings - Fork 5
Fix smoking prevention check from rules #633
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
base: develop
Are you sure you want to change the base?
Changes from 2 commits
f497c37
aa3a3d4
839c963
758ffc7
d39d54c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -46,6 +46,9 @@ public class PreventionItem { | |||||||||||||
| Date nextDate = null; | ||||||||||||||
| String never = null; | ||||||||||||||
| boolean refused; | ||||||||||||||
| // Raw refused status value (0=active, 1=refused, 2=ineligible, 3=completedExternally). | ||||||||||||||
| // For the "Smoking" type: 0=Yes (current), 1=No (non-smoker), 2=Previous (ex-smoker). | ||||||||||||||
| private int refusedStatus = 0; | ||||||||||||||
|
||||||||||||||
| // Raw refused status value (0=active, 1=refused, 2=ineligible, 3=completedExternally). | |
| // For the "Smoking" type: 0=Yes (current), 1=No (non-smoker), 2=Previous (ex-smoker). | |
| private int refusedStatus = 0; | |
| // Raw refused status value (0=active, 1=refused, 2=ineligible, 3=completedExternally). | |
| // For the "Smoking" type: 0=Yes (current), 1=No (non-smoker), 2=Previous (ex-smoker). | |
| private int refusedStatus = -1; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/io/github/carlos_emr/carlos/prevention/PreventionItem.java`
around lines 49 - 51, The field refusedStatus in class PreventionItem is
defaulting to 0 (current smoker) which can misclassify items; change its default
to an explicit unknown sentinel (e.g., -1 or a named constant like
REFUSED_STATUS_UNKNOWN) and update the PreventionItem class to declare that
constant, initialize refusedStatus to it, and ensure all constructors and any
deserialization/hydration paths set refusedStatus explicitly (or leave as the
sentinel) so no instance is implicitly treated as 0; also update any logic that
checks refusedStatus (getters, isRefused/isSmoker methods, or switch handling)
to handle the sentinel case appropriately.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,6 +51,12 @@ | |
| // Status: isPreventionNever(String), isNextDateSet(String), isPassedNextDate(String), | ||
| // isInelligible(String), isLastPreventionWithinRange(String, String, String), | ||
| // isTodayinDateRange(String, String) | ||
| // Smoking: isCurrentlySmoking(String), getRefusedStatus(String) | ||
| // NOTE: isPreventionNever("Smoking") is INCORRECT for smoking checks — the | ||
| // "never" column is always 0 for all smoking states (Yes/No/Previous). | ||
| // The smoking answer is stored in the "refused" column: | ||
| // 0=Yes (current smoker), 1=No (non-smoker), 2=Previous (ex-smoker). | ||
| // Use isCurrentlySmoking("Smoking") to check for active smoking status. | ||
| // Sex: isMale(), isFemale() | ||
| // | ||
| // Consequence methods: | ||
|
|
@@ -1144,13 +1150,20 @@ end | |
| // LDCT: Low-Dose CT Lung Cancer Screening (2 rules) | ||
| // Canadian guideline (CTFPHC 2016): Annual LDCT for adults aged 55-74 who are | ||
| // high-risk smokers (30+ pack-years or equivalent significant smoking history) | ||
| // Rule 1: WARNING if no LDCT on record for patients aged 55-74 with positive smoking history | ||
| // Rule 1: WARNING if no LDCT on record for patients aged 55-74 who are current smokers | ||
| // Rule 2: WARNING if LDCT count is 1 or 2 and it is > 12 months old (annual x3 years) | ||
| // LDCT 2 stops firing after 3rd annual screen (count >= 3). | ||
| // Precondition (heavy smoker detection): Smoking assessment must be on record AND | ||
| // not marked as "never" (non-smoker). This uses the Prevention module's "Smoking" type. | ||
| // A Smoking record exists (getNumberOfPreventionType("Smoking") > 0) AND | ||
| // the record is NOT marked as never-smoked (!isPreventionNever("Smoking")). | ||
| // | ||
| // Smoking status check (LDCT 1): | ||
| // The Smoking prevention type uses the "refused" column (NOT the "never" column) to | ||
| // store the patient's smoking answer. The "never" column is always 0 for all smoking | ||
| // states, so isPreventionNever("Smoking") cannot be used here. | ||
| // Smoking refused column encoding: | ||
| // 0 = Yes (currently smoking) <-- LDCT rule should fire | ||
| // 1 = No (not smoking) <-- LDCT rule should NOT fire | ||
| // 2 = Previous (ex-smoker) <-- LDCT rule should NOT fire | ||
| // isCurrentlySmoking("Smoking") returns true only when refused = 0. | ||
| // | ||
| // Note: Full heavy-smoker detection (pack-years, cigarettes/day) requires measurement | ||
| // values (NOSK > 23, POSK > 0, SKST = yes, SMK = yes, SmkS > 23) which are stored in | ||
| // the measurements table and are not accessible from the Prevention DRL fact object. | ||
|
|
@@ -1162,7 +1175,7 @@ rule "LDCT 1" | |
| eval( prev.getAgeInYears() >= 55 ) | ||
| eval( prev.getAgeInYears() <= 74 ) | ||
| eval( prev.getNumberOfPreventionType("Smoking") > 0 ) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing the The comment block for the LDCT rules (lines 1150-1153) explicitly states that the logic should check that the patient is not a "never-smoker".
This change makes the implementation inconsistent with the documentation and the clinical purpose of the rule. The check should be restored. If this change is intentional, the comment block and the rule's warning message should be updated to reflect that it no longer targets only smokers. |
||
| eval( !prev.isPreventionNever("Smoking") ) | ||
| eval( prev.isCurrentlySmoking("Smoking") ) | ||
| eval( prev.getHowManyMonthsSinceLast("LDCT") == -1 ) | ||
| eval( !prev.isPreventionNever("LDCT") ) | ||
| eval( !prev.isInelligible("LDCT") ) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Harden raw refused decoding against unexpected DB values.
Line 252 assumes
refusedis always'0'..'3'. If data is malformed, this returns an out-of-contract value while JavaDoc promises 0–3.💡 Proposed fix
public int getRefusedRawValue() { - return refused - '0'; + if (refused >= '0' && refused <= '3') { + return refused - '0'; + } + return -1; }🤖 Prompt for AI Agents