mirror of
https://github.com/edcommonwealth/sqm-dashboards.git
synced 2026-03-07 21:48:16 -08:00
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
This commit is contained in:
parent
a8507d817c
commit
9c954f97ec
9 changed files with 95 additions and 16 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
19
doc/architectural_decision_records/7.md
Normal file
19
doc/architectural_decision_records/7.md
Normal file
|
|
@ -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,15 +108,26 @@ 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
|
||||
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
|
||||
|
||||
context 'and the measure includes high-school-only items' do
|
||||
before do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue