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

Convert to Repository for DistrictAnalyticsQuery numbers #2436

Merged
merged 61 commits into from
May 10, 2021

Conversation

rsanheim
Copy link
Contributor

@rsanheim rsanheim commented Apr 19, 2021

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

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..
@harimohanraj89 harimohanraj89 temporarily deployed to simple-review-pr-2436 April 19, 2021 21:35 Inactive
@rsanheim rsanheim temporarily deployed to simple-review-pr-2436 April 20, 2021 16:28 Inactive
@harimohanraj89 harimohanraj89 temporarily deployed to simple-review-pr-2436 April 20, 2021 19:19 Inactive
@rsanheim rsanheim temporarily deployed to simple-review-pr-2436 April 20, 2021 20:22 Inactive
@rsanheim rsanheim temporarily deployed to simple-review-pr-2436 April 20, 2021 20:36 Inactive
@shortcut-integration
Copy link

This pull request has been linked to Clubhouse Story #2625: Registration counts on details and overview don't match.

@rsanheim rsanheim temporarily deployed to simple-review-pr-2436 April 21, 2021 17:53 Inactive
@shortcut-integration
Copy link

This pull request has been linked to Clubhouse Story #3343: Convert to Repository for DistrictAnalyticsQuery numbers.

@rsanheim rsanheim mentioned this pull request Apr 29, 2021
@rsanheim rsanheim requested a review from harimohanraj89 May 6, 2021 03:29
@rsanheim rsanheim marked this pull request as ready for review May 6, 2021 20:04
@harimohanraj89
Copy link
Contributor

Ah I see - so we're moving towards using the repository directly, but not retiring the existing DistrictAnalyticsQuery completely in one fell swoop. 👍

Copy link
Contributor

@harimohanraj89 harimohanraj89 left a 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})
Copy link
Contributor

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
Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

@vkrmis vkrmis left a 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 and FollowUpsQuery, can we consolidate these in one place?
  • Is this a good time to scrap DistrictAnalyticsQuery?, it doesn't do much that Repository 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))) %>
Copy link
Contributor

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

Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

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.

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) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename:

  • counts to user_counts
  • sum to user_ids

Copy link
Contributor

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)
Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor Author

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) %>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seconded.

@rsanheim rsanheim requested a review from claudiovallejo as a code owner May 7, 2021 18:52
Copy link
Contributor

@kpethtel kpethtel left a 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")
Copy link
Contributor

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)
Copy link
Contributor

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
Copy link
Contributor

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)
Copy link
Contributor

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| %>
Copy link
Contributor

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) %>
Copy link
Contributor

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))) %>
Copy link
Contributor

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)
Copy link
Contributor

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.

Copy link
Contributor Author

@rsanheim rsanheim left a 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)
Copy link
Contributor Author

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
Copy link
Contributor Author

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))) %>
Copy link
Contributor Author

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") }
Copy link
Contributor Author

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
Copy link
Contributor Author

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.

@rsanheim rsanheim merged commit 4341a40 into master May 10, 2021
@rsanheim rsanheim deleted the same-queries-for-details-numbers branch May 10, 2021 14:49
rsanheim added a commit that referenced this pull request May 10, 2021
rsanheim added a commit that referenced this pull request May 10, 2021
)

* Revert "Convert to Repository for DistrictAnalyticsQuery numbers (#2436)"

This reverts commit 4341a40.

* Disable intermittent failing test
@rsanheim rsanheim restored the same-queries-for-details-numbers branch May 10, 2021 15:54
@rsanheim rsanheim deleted the same-queries-for-details-numbers branch November 18, 2021 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants