Update admin data collection rate numbers on browse page. Also, if all admin data has been collected, do not show 'insufficient data' indicator. Finishes #181754853

pull/1/head
Nelson Jovel 4 years ago
parent a8507d817c
commit 9c954f97ec

@ -6,7 +6,7 @@ class Measure < ActiveRecord::Base
has_many :survey_item_responses, through: :survey_items
def none_meet_threshold?(school:, academic_year:)
!sufficient_data?(school:, academic_year:)
!sufficient_survey_responses?(school:, academic_year:)
end
def teacher_survey_items
@ -49,9 +49,10 @@ class Measure < ActiveRecord::Base
@score ||= Hash.new do |memo|
meets_student_threshold = sufficient_student_data?(school:, academic_year:)
meets_teacher_threshold = sufficient_teacher_data?(school:, academic_year:)
meets_admin_data_threshold = all_admin_data_collected?(school:, academic_year:)
lacks_sufficient_data = !meets_student_threshold && !meets_teacher_threshold && !includes_admin_data_items?
next Score.new(nil, false, false) if lacks_sufficient_data
next Score.new(nil, false, false, false) if lacks_sufficient_data
scores = []
scores << teacher_scales.map { |scale| scale.score(school:, academic_year:) }.average if meets_teacher_threshold
@ -64,10 +65,10 @@ class Measure < ActiveRecord::Base
end
average = scores.flatten.compact.average
next Score.new(nil, false, false) if average.nan?
next Score.new(nil, false, false, false) if average.nan?
memo[[school, academic_year]] =
Score.new(average, meets_teacher_threshold, meets_student_threshold)
Score.new(average, meets_teacher_threshold, meets_student_threshold, meets_admin_data_threshold)
end
@score[[school, academic_year]]
@ -105,7 +106,17 @@ class Measure < ActiveRecord::Base
subcategory.teacher_response_rate(school:, academic_year:).meets_teacher_threshold?
end
def sufficient_data?(school:, academic_year:)
def all_admin_data_collected?(school:, academic_year:)
total_possible_admin_data_items = scales.map { |scale| scale.admin_data_items.count }.sum
total_collected_admin_data_items = scales.map do |scale|
scale.admin_data_items.map do |admin_data_item|
admin_data_item.admin_data_values.where(school:, academic_year:).count
end
end.flatten.sum
total_possible_admin_data_items == total_collected_admin_data_items
end
def sufficient_survey_responses?(school:, academic_year:)
sufficient_student_data?(school:, academic_year:) || sufficient_teacher_data?(school:, academic_year:)
end

@ -1,2 +1,2 @@
class Score < Struct.new(:average, :meets_teacher_threshold?, :meets_student_threshold?)
class Score < Struct.new(:average, :meets_teacher_threshold?, :meets_student_threshold?, :meets_admin_data_threshold?)
end

@ -1,6 +1,6 @@
class AdminDataPresenter < DataItemPresenter
def initialize(measure_id:, admin_data_items:)
super(measure_id:, has_sufficient_data: false)
def initialize(measure_id:, admin_data_items:, has_sufficient_data:)
super(measure_id:, has_sufficient_data:)
@admin_data_items = admin_data_items
end

@ -37,7 +37,7 @@ class MeasurePresenter
end
if @measure.admin_data_items.any?
array << AdminDataPresenter.new(measure_id: @measure.measure_id,
admin_data_items: @measure.admin_data_items)
admin_data_items: @measure.admin_data_items, has_sufficient_data: score_for_measure.meets_admin_data_threshold?)
end
end
end

@ -42,7 +42,7 @@ class SubcategoryPresenter
end
def admin_collection_rate
rate = [0, admin_data_item_count]
rate = [admin_data_values_count, admin_data_item_count]
format_a_non_applicable_rate rate
end
@ -54,6 +54,16 @@ class SubcategoryPresenter
private
def admin_data_values_count
@subcategory.measures.map do |measure|
measure.scales.map do |scale|
scale.admin_data_items.map do |admin_data_item|
admin_data_item.admin_data_values.where(school: @school, academic_year: @academic_year).count
end
end
end.flatten.sum
end
def admin_data_item_count
return AdminDataItem.for_measures(@subcategory.measures).count if @school.is_hs

@ -0,0 +1,19 @@
# Decision record 7
# Intruduce concept of sufficiency for admin data items
## Status
Completed
## Context
The browse page contains accordions that inform the user if some data of missing data. In the case of survey items, a response rate of less than 25 percent will mean no scores for that scale will be reflected in the gauge graph. In the case of admin data, there is no such thing as response rate. Data was either collected or not. But we still want to inform the user that not all data was collected. if some admin data was not collected, we still want to let the user know not all data is included.
## Decision
We inform users of insufficient data if, for a measure, any admin data items could not be collected. If there are five admin data items for a measure, there must be a corresponding five admin data values in the database to be considered 'sufficient'. Otherwise we inform the user of missing admin data on the browse page.
## Consequences
At the moment, the admin_data_presenter class only knows if a measure has sufficient admin data or not. It does not know which admin data items lack corresponding values. We are not yet informing the user which admin data values are missing. A later story will need to be written to correct this.

@ -77,6 +77,9 @@ FactoryBot.define do
factory :student_scale do
scale_id { "s-#{rand}" }
end
factory :admin_scale do
scale_id { 'a-{rand' }
end
end
factory :survey_item do

@ -5,6 +5,7 @@ RSpec.describe Measure, type: :model do
let(:scale) { create(:scale, measure:) }
let(:teacher_scale) { create(:teacher_scale, measure:) }
let(:student_scale) { create(:student_scale, measure:) }
let(:admin_scale) { create(:admin_scale, measure:) }
let(:school) { create(:school) }
let(:academic_year) { create(:academic_year) }
@ -473,5 +474,25 @@ RSpec.describe Measure, type: :model do
end
end
end
context 'when the measure includes admin data' do
let(:admin_data_item) { create(:admin_data_item, scale: admin_scale) }
let(:admin_data_item_2) { create(:admin_data_item, scale: admin_scale) }
context 'and the admin data does not meet the sufficiency threshold' do
it 'affirms the returned score does not meet the admin data threshold' do
expect(measure.score(school:, academic_year:).meets_admin_data_threshold?).to be false
end
end
context 'and the admin data does meet the sufficiency threshold' do
before :each do
create(:admin_data_value, admin_data_item:, school:, academic_year:)
create(:admin_data_value, admin_data_item: admin_data_item_2, school:, academic_year:)
end
it 'affirms the returned score does meet the admin data threshold' do
expect(measure.score(school:, academic_year:).meets_admin_data_threshold?).to be true
end
end
end
end
end

@ -6,6 +6,10 @@ describe SubcategoryPresenter do
let(:subcategory) do
create(:subcategory, name: 'A great subcategory', subcategory_id: 'A', description: 'A great description')
end
let(:measure_of_only_admin_data) { create(:measure, subcategory:) }
let(:scale_of_only_admin_data) { create(:scale, measure: measure_of_only_admin_data) }
let(:admin_data_item_1) { create(:admin_data_item, scale: scale_of_only_admin_data, hs_only_item: false) }
let(:admin_data_item_2) { create(:admin_data_item, scale: scale_of_only_admin_data, hs_only_item: false) }
let(:subcategory_presenter) do
measure1 = create(:measure, subcategory:)
teacher_scale_1 = create(:teacher_scale, measure: measure1)
@ -104,13 +108,24 @@ describe SubcategoryPresenter do
context 'and the school is not a high school' do
context 'and the measure does not include high-school-only admin data items' do
before do
measure_of_only_admin_data = create(:measure, subcategory:)
scale_of_only_admin_data = create(:scale, measure: measure_of_only_admin_data)
create(:admin_data_item, scale: scale_of_only_admin_data, hs_only_item: false)
create(:admin_data_item, scale: scale_of_only_admin_data, hs_only_item: false)
measure_of_only_admin_data
scale_of_only_admin_data
admin_data_item_1
admin_data_item_2
end
it 'returns the admin collection rate' do
expect(subcategory_presenter.admin_collection_rate).to eq [0, 2]
context 'and there are no admin data values in the database' do
it 'returns the admin collection rate' do
expect(subcategory_presenter.admin_collection_rate).to eq [0, 2]
end
end
context 'and there are admin data values present in the database ' do
before do
create(:admin_data_value, admin_data_item: admin_data_item_1, school:, academic_year:)
create(:admin_data_value, admin_data_item: admin_data_item_2, school:, academic_year:)
end
it 'returns the admin collection rate' do
expect(subcategory_presenter.admin_collection_rate).to eq [2, 2]
end
end
end

Loading…
Cancel
Save