-
Notifications
You must be signed in to change notification settings - Fork 39
Sc 17708 #5753
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: dm-dashboard-new-controlled-bp-statin-cards
Are you sure you want to change the base?
Sc 17708 #5753
Conversation
| } | ||
| end | ||
|
|
||
| def dm_controlled_bp_query(entry, systolic_threshold:, diastolic_threshold:, with_ltfu: false) |
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.
Can this whole calculation be persisted under reporting_facility_states, as this is going to be our standard dashboard design going forward?
The numbers can then be used for metabase reports as well.
| version: 12, | ||
| revert_to_version: 11, | ||
| materialized: true | ||
| end |
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.
Changing the matview definition like this is efficient but it creates them with data. Currently in BD this takes 1.14 hours to refresh this data.
India it takes 3.17 hours
Semaphore will timeout by then.
We need to drop the mat view and recreate it without data. Then do a refresh of this later after deployment.
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.
Okay
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'under_care') AS diabetes_patients_under_care, | ||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'lost_to_follow_up') AS diabetes_patients_lost_to_follow_up, | ||
|
|
||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'under_care' AND months_since_visit < 3 AND systolic < 140 AND diastolic < 90 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_140_90_under_care, |
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.
can we rename dm_bp_140_90_under_care to dm_bp_below_140_90_under_care ? This makes it more clear on what data the field is holding.
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'lost_to_follow_up') AS diabetes_patients_lost_to_follow_up, | ||
|
|
||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'under_care' AND months_since_visit < 3 AND systolic < 140 AND diastolic < 90 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_140_90_under_care, | ||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state IN ('under_care', 'lost_to_follow_up') AND months_since_visit < 3 AND systolic < 140 AND diastolic < 90 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_140_90_ltfu_under_care, |
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.
might not be required.
|
|
||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'under_care' AND months_since_visit < 3 AND systolic < 140 AND diastolic < 90 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_140_90_under_care, | ||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state IN ('under_care', 'lost_to_follow_up') AND months_since_visit < 3 AND systolic < 140 AND diastolic < 90 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_140_90_ltfu_under_care, | ||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'under_care' AND months_since_visit < 3 AND systolic < 130 AND diastolic < 80 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_130_80_under_care, |
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.
dm_bp_130_80_under_care -> dm_bp_below_130_80_under_care
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'under_care' AND months_since_visit < 3 AND systolic < 140 AND diastolic < 90 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_140_90_under_care, | ||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state IN ('under_care', 'lost_to_follow_up') AND months_since_visit < 3 AND systolic < 140 AND diastolic < 90 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_140_90_ltfu_under_care, | ||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'under_care' AND months_since_visit < 3 AND systolic < 130 AND diastolic < 80 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_130_80_under_care, | ||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state IN ('under_care', 'lost_to_follow_up') AND months_since_visit < 3 AND systolic < 130 AND diastolic < 80 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_130_80_ltfu_under_care |
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.
might not be required
| region_period_cached_query(__method__, with_ltfu: with_ltfu) do |entry| | ||
| slug, period = entry.slug, entry.period | ||
| denominator = with_ltfu ? adjusted_diabetes_patients_with_ltfu[slug][period] : adjusted_diabetes_patients_without_ltfu[slug][period] | ||
| numerator = dm_patients_with_controlled_bp_140_90(with_ltfu: with_ltfu)[slug][period] |
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.
Do we need to calculate with_ltfu here?
In all the other charts, "with_ltfu" is used to include the lost to follow up patients in the denominator only.
Adding this in the numerator seems counter-intuitive. Patients who are ltfu - will never qualify BP controlled indicator because they should have atleast one visit in the past 3 months - which implies they are not ltfu.
We only calculate the rates based on a different ltfu denominator, because then the percentages would change.
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.
We should include the LTFU toggle option here as it's a denominator change.
With LTFU shows all patients assigned, without showing patients under care, which is more accurate.
This pattern follows the design for the outcomes section of the dashboard (Controlled, uncontrolled, missed), where only the denominator values change aswell.
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.
Yes, only the denominator should have the ltfu change, the numerator remains same in both case (with or without ltfu).
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.
Okay, I will remove this from the numerator.
| region_period_cached_query(__method__, with_ltfu: with_ltfu) do |entry| | ||
| slug, period = entry.slug, entry.period | ||
| denominator = with_ltfu ? adjusted_diabetes_patients_with_ltfu[slug][period] : adjusted_diabetes_patients_without_ltfu[slug][period] | ||
| numerator = dm_patients_with_controlled_bp_130_80(with_ltfu: with_ltfu)[slug][period] |
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.
same as above
| else | ||
| values_at("adjusted_dm_bp_140_90_under_care") | ||
| end | ||
| end |
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.
just a suggestion to use tertiary operator, reads better
field = with_ltfu ? "adjusted_dm_bp_140_90_ltfu_under_care" : "adjusted_dm_bp_140_90_under_care" values_at(field)
app/models/reports/region_summary.rb
Outdated
| adjusted_fasting_bs_over_300_under_care | ||
| adjusted_hba1c_bs_over_300_under_care | ||
| adjusted_dm_bp_below_130_80_under_care | ||
| adjusted_dm_bp_below_130_80_ltfu_under_care |
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.
We probably don't need this. A patient can either be under_care or ltfu.
We anyways don't need this value because this value will be used as a numerator for this chart, which doesn't include ltfu patients.
| adjusted_dm_bp_below_130_80_ltfu_under_care | ||
| adjusted_dm_bp_below_140_90_under_care | ||
| adjusted_dm_bp_below_140_90_ltfu_under_care | ||
| diabetes_total_appts_scheduled |
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.
same as above
| diabetes_missed_visits_rates | ||
| visited_without_bs_taken_rates | ||
| dm_controlled_bp_140_90_rates | ||
| dm_controlled_bp_130_80_rates |
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.
We probably need dm_controlled_bp_140_90_with_ltfu_rates and dm_controlled_bp_130_80_with_ltfu_rates here
db/structure.sql
Outdated
| count(DISTINCT reporting_patient_states.patient_id) FILTER (WHERE (reporting_patient_states.htn_care_state = 'lost_to_follow_up'::text)) AS diabetes_patients_lost_to_follow_up | ||
| count(DISTINCT reporting_patient_states.patient_id) FILTER (WHERE (reporting_patient_states.htn_care_state = 'lost_to_follow_up'::text)) AS diabetes_patients_lost_to_follow_up, | ||
| count(DISTINCT reporting_patient_states.patient_id) FILTER (WHERE ((reporting_patient_states.htn_care_state = 'under_care'::text) AND (reporting_patient_states.months_since_visit < (3)::double precision) AND (reporting_patient_states.systolic < (140)::double precision) AND (reporting_patient_states.diastolic < (90)::double precision) AND (reporting_patient_states.systolic IS NOT NULL) AND (reporting_patient_states.diastolic IS NOT NULL))) AS dm_bp_below_140_90_under_care, | ||
| count(DISTINCT reporting_patient_states.patient_id) FILTER (WHERE ((reporting_patient_states.htn_care_state IN ('under_care'::text, 'lost_to_follow_up'::text)) AND (reporting_patient_states.months_since_visit < (3)::double precision) AND (reporting_patient_states.systolic < (140)::double precision) AND (reporting_patient_states.diastolic < (90)::double precision) AND (reporting_patient_states.systolic IS NOT NULL) AND (reporting_patient_states.diastolic IS NOT NULL))) AS dm_bp_below_140_90_ltfu_under_care, |
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.
we don't need this value.
db/structure.sql
Outdated
| count(DISTINCT reporting_patient_states.patient_id) FILTER (WHERE ((reporting_patient_states.htn_care_state = 'under_care'::text) AND (reporting_patient_states.months_since_visit < (3)::double precision) AND (reporting_patient_states.systolic < (140)::double precision) AND (reporting_patient_states.diastolic < (90)::double precision) AND (reporting_patient_states.systolic IS NOT NULL) AND (reporting_patient_states.diastolic IS NOT NULL))) AS dm_bp_below_140_90_under_care, | ||
| count(DISTINCT reporting_patient_states.patient_id) FILTER (WHERE ((reporting_patient_states.htn_care_state IN ('under_care'::text, 'lost_to_follow_up'::text)) AND (reporting_patient_states.months_since_visit < (3)::double precision) AND (reporting_patient_states.systolic < (140)::double precision) AND (reporting_patient_states.diastolic < (90)::double precision) AND (reporting_patient_states.systolic IS NOT NULL) AND (reporting_patient_states.diastolic IS NOT NULL))) AS dm_bp_below_140_90_ltfu_under_care, | ||
| count(DISTINCT reporting_patient_states.patient_id) FILTER (WHERE ((reporting_patient_states.htn_care_state = 'under_care'::text) AND (reporting_patient_states.months_since_visit < (3)::double precision) AND (reporting_patient_states.systolic < (130)::double precision) AND (reporting_patient_states.diastolic < (80)::double precision) AND (reporting_patient_states.systolic IS NOT NULL) AND (reporting_patient_states.diastolic IS NOT NULL))) AS dm_bp_below_130_80_under_care, | ||
| count(DISTINCT reporting_patient_states.patient_id) FILTER (WHERE ((reporting_patient_states.htn_care_state IN ('under_care'::text, 'lost_to_follow_up'::text)) AND (reporting_patient_states.months_since_visit < (3)::double precision) AND (reporting_patient_states.systolic < (130)::double precision) AND (reporting_patient_states.diastolic < (80)::double precision) AND (reporting_patient_states.systolic IS NOT NULL) AND (reporting_patient_states.diastolic IS NOT NULL))) AS dm_bp_below_130_80_ltfu_under_care |
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.
we don't need this value.
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'lost_to_follow_up') AS diabetes_patients_lost_to_follow_up, | ||
|
|
||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'under_care' AND months_since_visit < 3 AND systolic < 140 AND diastolic < 90 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_below_140_90_under_care, | ||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state IN ('under_care', 'lost_to_follow_up') AND months_since_visit < 3 AND systolic < 140 AND diastolic < 90 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_below_140_90_ltfu_under_care, |
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.
we don't need this value.
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'under_care' AND months_since_visit < 3 AND systolic < 140 AND diastolic < 90 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_below_140_90_under_care, | ||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state IN ('under_care', 'lost_to_follow_up') AND months_since_visit < 3 AND systolic < 140 AND diastolic < 90 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_below_140_90_ltfu_under_care, | ||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state = 'under_care' AND months_since_visit < 3 AND systolic < 130 AND diastolic < 80 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_below_130_80_under_care, | ||
| COUNT(distinct(patient_id)) FILTER (WHERE htn_care_state IN ('under_care', 'lost_to_follow_up') AND months_since_visit < 3 AND systolic < 130 AND diastolic < 80 AND systolic IS NOT NULL AND diastolic IS NOT NULL) AS dm_bp_below_130_80_ltfu_under_care |
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.
not needed
| adjusted_diabetes_outcomes.diabetes_patients_lost_to_follow_up AS adjusted_diabetes_patients_lost_to_follow_up, | ||
|
|
||
| adjusted_diabetes_outcomes.dm_bp_below_140_90_under_care AS adjusted_dm_bp_below_140_90_under_care, | ||
| adjusted_diabetes_outcomes.dm_bp_below_140_90_ltfu_under_care AS adjusted_dm_bp_below_140_90_ltfu_under_care, |
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.
not needed
| adjusted_diabetes_outcomes.dm_bp_below_140_90_under_care AS adjusted_dm_bp_below_140_90_under_care, | ||
| adjusted_diabetes_outcomes.dm_bp_below_140_90_ltfu_under_care AS adjusted_dm_bp_below_140_90_ltfu_under_care, | ||
| adjusted_diabetes_outcomes.dm_bp_below_130_80_under_care AS adjusted_dm_bp_below_130_80_under_care, | ||
| adjusted_diabetes_outcomes.dm_bp_below_130_80_ltfu_under_care AS adjusted_dm_bp_below_130_80_ltfu_under_care, |
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.
not needed
| expect(schema.dm_controlled_bp_130_80_rates[facility_1.region.slug]["Mar 2020".to_period]).to eq(25) | ||
| expect(schema.dm_controlled_bp_130_80_rates(with_ltfu: true)[facility_1.region.slug]["Mar 2020".to_period]).to eq(25) | ||
| end | ||
| end |
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.
would be nice to have specs around 140_90_with_ltfu_rates and 130_80_with_ltfu_rates
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.
Okay
|
|
||
| def dm_controlled_bp_130_80_with_ltfu_rates | ||
| dm_controlled_bp_130_80_rates(with_ltfu: true) | ||
| end |
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.
do we need these methods. My understanding is that we can get ltfu rates by just calling dm_controlled_bp_130_80_rates(with_ltfu: true)
I could not find where dm_controlled_bp_140_90_with_ltfu_rates and dm_controlled_bp_130_80_with_ltfu_rates are called
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.
Thanks for pointing this out. These are no longer needed, I missed removing them earlier. I will clean this up.
Story card: sc-17708
Because
The DM dashboard "DM patients with controlled BP" card was using dummy data and needed backend support to display real metrics.
This addresses
Test instructions
Suit test cases.