-
Notifications
You must be signed in to change notification settings - Fork 36
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
Convert to Repository for DistrictAnalyticsQuery numbers #2436
Conversation
this make up the details tab of reports, so to keep things consistent we should grab them from the same repository that backs up other parts of the app..
This pull request has been linked to Clubhouse Story #2625: Registration counts on details and overview don't match. |
getting this all consistent so the tables are easier to manage
This pull request has been linked to Clubhouse Story #3343: Convert to Repository for DistrictAnalyticsQuery numbers. |
we can't change this interface or it could easily break some other clients using this class
Ah I see - so we're moving towards using the repository directly, but not retiring the existing |
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.
This is the right direction, but it sounds like we've still got some work to do in terms of:
- Consistent use of the repository
- Retiring legacy "query" classes like
DistrictAnalyticsQuery
Can we roughly story up the new few big refactors necessary to see this to completion?
patients | ||
.hypertension_follow_ups_by_period(*args) | ||
.where(blood_pressures: {facility: self}) | ||
patients.hypertension_follow_ups_by_period(*args).where(blood_pressures: {facility: self}) |
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.
[nitpick] I find this less readable than the multiline version
@formatter = lambda { |v| @period_type == :quarter ? Period.quarter(v) : Period.month(v) } | ||
end | ||
|
||
def hypertension |
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.
This is partially replicated in the with
method, can we just call with
instead?
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 do one of:
- Keep all the
FollowUpsQuery
scopes in Patient and remove.hypertension
here - Move all these ^ scopes to
FollowUpsQuery
Doing both is a bit confusing.
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.
I'm trying to limit the amount of creeping change going on in this PR...its already getting pretty unwieldy. Our current scopes are called from all over the place, so I wanted to start w/ the hypertension one (needed for the reports) and the with
helper to get things consolidated. I'll move the others in a future PR, which we will need to consolidate things from the progress tab.
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.
Some overall thoughts:
- There's some follow ups logic that's distributed between
Patient
andFollowUpsQuery
, can we consolidate these in one place? - Is this a good time to scrap
DistrictAnalyticsQuery
?, it doesn't do much thatRepository
doesn't give us directly.
Prabhanshu & vkrm
<td class="ta-center"> | ||
<%= number_with_delimiter(dash_if_zero(@dashboard_analytics.dig(resource.id, :bp_measures_by_period, date))) %> | ||
<%= number_with_delimiter(dash_if_zero(@dashboard_analytics.dig(resource.id, :bp_measures_by_period, period.value))) %> |
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 get bp_measures_by_period
from the repository instead? It looks like this is the only place we're still using data from @dashboard_analytics
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.
It's also being used by the new monthly district report but I think we can remove that after this is merged.
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.
The repository doesn't have that query wired up yet, but it will come soon...
recorded_at: second_follow_up_date) | ||
end | ||
|
||
describe ".follow_ups" do |
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.
Since this is testing Patient.follow_ups_by_period
, shouldn't these be in Patient
instead?
Alternatively, we could test a call to FollowUpsQuery
here.
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.
I'm trying to consolidate queries that have lots going on (like follow ups) into their own objects, and then can test them from one spec file. We have so much surface area exposed by scopes from Patient, Facility, and elsewhere....if all those scopes eventually call the same query object, at least there is one place to look and one spec file to read.
All that said, consider the current follow up specs and query a work in progress.
@formatter = lambda { |v| @period_type == :quarter ? Period.quarter(v) : Period.month(v) } | ||
end | ||
|
||
def hypertension |
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 do one of:
- Keep all the
FollowUpsQuery
scopes in Patient and remove.hypertension
here - Move all these ^ scopes to
FollowUpsQuery
Doing both is a bit confusing.
app/models/reports/repository.rb
Outdated
registration_counts_by_user.each_with_object({}) do |(slug, period_counts), totals| | ||
totals[slug] = {} | ||
# collect all the user ids in a region that we need to count for | ||
user_ids = period_counts.each_with_object(Set.new) { |(period, counts), sum| sum.merge(counts.keys) } |
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:
counts
touser_counts
sum
touser_ids
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 be simplified to something like user_ids = period_counts.values.map(&:keys).flatten.to_set
@@ -209,7 +256,7 @@ def denominator(region, period) | |||
# region_2_slug: { period_1: value, period_2: value } | |||
# } | |||
# | |||
def cached_query(calculation, &block) | |||
def region_period_cached_query(calculation, &block) |
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.
Have we added other _cached_queries
? Wondering why we're being more specific here. Is cached_query
not descriptive enough?
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.
I vote for keeping the change. I know from experience with this service object that a lot of the data is in form of { region: { period1: ..., period2: ...}}
this makes it clear at a glance that this should be structured that way.
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.
Yeah there are other cached queries that return region based items instead of region/period based items.
</td> | ||
<% end %> | ||
</tr> | ||
<% current_admin.accessible_users(:view_reports).order(:full_name).each do |resource| %> | ||
<% if @dashboard_analytics[resource.id].present? %> | ||
<tr> | ||
<td class="row-title"> | ||
<%= link_to resource.send(:full_name), send(:admin_user_path, resource, period: @period) %> | ||
<%= link_to resource.full_name, admin_user_path(resource, period: @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.
❤️
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.
Seconded.
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.
Really nice!
CREATED_TIME ||= File.ctime("config/data/medications.yml").in_time_zone("UTC") | ||
UPDATED_TIME ||= File.mtime("config/data/medications.yml").in_time_zone("UTC") | ||
CREATED_TIME = File.ctime("config/data/medications.yml").in_time_zone("UTC") | ||
UPDATED_TIME = File.mtime("config/data/medications.yml").in_time_zone("UTC") |
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.
Thank you. I was wondering about this.
@@ -159,11 +159,11 @@ def inspect | |||
"<Period type:#{type} value=#{value}>" | |||
end | |||
|
|||
def to_s | |||
def to_s(format = :mon_year) |
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.
This is a nice usability addition.
@@ -58,6 +58,8 @@ def initialize(regions, periods:) | |||
end | |||
end | |||
|
|||
# Adjusted patient counts are the patient counts from three months ago (the adjusted period) that |
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.
Thank you for adding these comments. I find them useful when I haven't been in this code recently. Once you're more familiar with this object, the methods seem pretty intuitive, but before that, the comments help reduce the amount of code you have read to understand what's really happening.
@@ -209,7 +256,7 @@ def denominator(region, period) | |||
# region_2_slug: { period_1: value, period_2: value } | |||
# } | |||
# | |||
def cached_query(calculation, &block) | |||
def region_period_cached_query(calculation, &block) |
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.
I vote for keeping the change. I know from experience with this service object that a lot of the data is in form of { region: { period1: ..., period2: ...}}
this makes it clear at a glance that this should be structured that way.
@@ -49,14 +50,14 @@ | |||
Total registered<br> | |||
patients | |||
</th> | |||
<% dates_for_periods(@period.type, 6, include_current_period: @show_current_period).each do |date| %> | |||
<% @period_range.each do |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.
Much appreciated.
</td> | ||
<% end %> | ||
</tr> | ||
<% current_admin.accessible_users(:view_reports).order(:full_name).each do |resource| %> | ||
<% if @dashboard_analytics[resource.id].present? %> | ||
<tr> | ||
<td class="row-title"> | ||
<%= link_to resource.send(:full_name), send(:admin_user_path, resource, period: @period) %> | ||
<%= link_to resource.full_name, admin_user_path(resource, period: @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.
Seconded.
<td class="ta-center"> | ||
<%= number_with_delimiter(dash_if_zero(@dashboard_analytics.dig(resource.id, :bp_measures_by_period, date))) %> | ||
<%= number_with_delimiter(dash_if_zero(@dashboard_analytics.dig(resource.id, :bp_measures_by_period, period.value))) %> |
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.
It's also being used by the new monthly district report but I think we can remove that after this is merged.
end | ||
|
||
patients_2.each do |patient| | ||
create(:blood_pressure, patient: patient, facility: facility_2) | ||
create(:blood_pressure, patient: patient, facility: facility_2, user: user) |
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.
I assume because the factories were making unique users per bp reading. This is definitely the kind of thing that makes factorybot hard to use efficiently.
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.
Some responses to feedback.
@@ -209,7 +256,7 @@ def denominator(region, period) | |||
# region_2_slug: { period_1: value, period_2: value } | |||
# } | |||
# | |||
def cached_query(calculation, &block) | |||
def region_period_cached_query(calculation, &block) |
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.
Yeah there are other cached queries that return region based items instead of region/period based items.
@formatter = lambda { |v| @period_type == :quarter ? Period.quarter(v) : Period.month(v) } | ||
end | ||
|
||
def hypertension |
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.
I'm trying to limit the amount of creeping change going on in this PR...its already getting pretty unwieldy. Our current scopes are called from all over the place, so I wanted to start w/ the hypertension one (needed for the reports) and the with
helper to get things consolidated. I'll move the others in a future PR, which we will need to consolidate things from the progress tab.
<td class="ta-center"> | ||
<%= number_with_delimiter(dash_if_zero(@dashboard_analytics.dig(resource.id, :bp_measures_by_period, date))) %> | ||
<%= number_with_delimiter(dash_if_zero(@dashboard_analytics.dig(resource.id, :bp_measures_by_period, period.value))) %> |
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.
The repository doesn't have that query wired up yet, but it will come soon...
@@ -1,6 +1,9 @@ | |||
Time::DATE_FORMATS[:mon_year] = "%b-%Y" | |||
Date::DATE_FORMATS[:mon_year] = "%b-%Y" | |||
|
|||
Date::DATE_FORMATS[:mon_year_multiline] = lambda { |date| date.strftime("%b-%Y").tr("-", "\n") } | |||
Time::DATE_FORMATS[:mon_year_multiline] = lambda { |date| date.strftime("%b-%Y").tr("-", "\n") } |
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.
the answer is yes 👍
recorded_at: second_follow_up_date) | ||
end | ||
|
||
describe ".follow_ups" do |
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.
I'm trying to consolidate queries that have lots going on (like follow ups) into their own objects, and then can test them from one spec file. We have so much surface area exposed by scopes from Patient, Facility, and elsewhere....if all those scopes eventually call the same query object, at least there is one place to look and one spec file to read.
All that said, consider the current follow up specs and query a work in progress.
…)" This reverts commit 4341a40.
This make up the details tab of reports, so to keep things consistent we should grab them from the same repository object that backs up other parts of the app.
Story card: ch2625 and ch3343
Because
We are trying to consolidate more queries to one consistent path
This addresses
Moving part of the 'analytics queries' to repository