diff --git a/app/models/survey_item_response.rb b/app/models/survey_item_response.rb index 0dc2e3f5..89a40e18 100644 --- a/app/models/survey_item_response.rb +++ b/app/models/survey_item_response.rb @@ -15,38 +15,59 @@ class SurveyItemResponse < ActiveRecord::Base end def self.score_for_measure(measure:, school:, academic_year:) - return nil unless sufficient_data?(measure: measure, school: school, academic_year: academic_year) + survey_item_responses = for_measure_meeting_threshold(measure: measure, school: school, academic_year: academic_year) - SurveyItemResponse.for_measure(measure) - .where(academic_year: academic_year, school: school) - .average(:likert_score) + if survey_item_responses.present? + survey_item_responses + .where(academic_year: academic_year, school: school) + .average(:likert_score) + end end private + def self.for_measure_meeting_threshold(measure:, school:, academic_year:) + meets_teacher_threshold = teacher_sufficient_data? measure: measure, school: school, academic_year: academic_year + meets_student_threshold = student_sufficient_data? measure: measure, school: school, academic_year: academic_year + meets_all_thresholds = meets_teacher_threshold && meets_student_threshold + + if meets_all_thresholds + SurveyItemResponse.for_measure(measure) + elsif meets_teacher_threshold + SurveyItemResponse.teacher_responses_for_measure(measure) + elsif meets_student_threshold + SurveyItemResponse.student_responses_for_measure(measure) + end + end + scope :for_measure, ->(measure) { joins(:survey_item).where('survey_items.measure_id': measure.id) } scope :for_measures, ->(measures) { joins(:survey_item).where('survey_items.measure_id': measures.map(&:id)) } scope :teacher_responses_for_measure, ->(measure) { for_measure(measure).where("survey_items.survey_item_id LIKE 't-%'") } scope :student_responses_for_measure, ->(measure) { for_measure(measure).where("survey_items.survey_item_id LIKE 's-%'") } def self.sufficient_data?(measure:, school:, academic_year:) - meets_teacher_threshold = true - meets_student_threshold = true - - if measure.includes_teacher_survey_items? - teacher_survey_item_responses = SurveyItemResponse.teacher_responses_for_measure(measure).where(academic_year: academic_year, school: school) - average_number_of_survey_item_responses = teacher_survey_item_responses.count / measure.teacher_survey_items.count - - meets_teacher_threshold = average_number_of_survey_item_responses >= TEACHER_RESPONSE_THRESHOLD - end + meets_teacher_threshold = teacher_sufficient_data?(measure: measure, school: school, academic_year: academic_year) + meets_student_threshold = student_sufficient_data?(measure: measure, school: school, academic_year: academic_year) + meets_teacher_threshold || meets_student_threshold + end + def self.student_sufficient_data?(measure:, school:, academic_year:) if measure.includes_student_survey_items? student_survey_item_responses = SurveyItemResponse.student_responses_for_measure(measure).where(academic_year: academic_year, school: school) average_number_of_survey_item_responses = student_survey_item_responses.count / measure.student_survey_items.count meets_student_threshold = average_number_of_survey_item_responses >= STUDENT_RESPONSE_THRESHOLD end + meets_student_threshold + end + + def self.teacher_sufficient_data?(measure:, school:, academic_year:) + if measure.includes_teacher_survey_items? + teacher_survey_item_responses = SurveyItemResponse.teacher_responses_for_measure(measure).where(academic_year: academic_year, school: school) + average_number_of_survey_item_responses = teacher_survey_item_responses.count / measure.teacher_survey_items.count - meets_teacher_threshold and meets_student_threshold + meets_teacher_threshold = average_number_of_survey_item_responses >= TEACHER_RESPONSE_THRESHOLD + end + meets_teacher_threshold end end diff --git a/app/presenters/measure_presenter.rb b/app/presenters/measure_presenter.rb index 1fd52adb..415dfb0e 100644 --- a/app/presenters/measure_presenter.rb +++ b/app/presenters/measure_presenter.rb @@ -23,11 +23,11 @@ class MeasurePresenter end def data_item_presenters - output = Array.new - output << StudentSurveyPresenter.new(measure_id: @measure.measure_id, survey_items: @measure.student_survey_items) if @measure.student_survey_items.any? - output << TeacherSurveyPresenter.new(measure_id: @measure.measure_id, survey_items: @measure.teacher_survey_items) if @measure.teacher_survey_items.any? - output << AdminDataPresenter.new(measure_id: @measure.measure_id, admin_data_items: @measure.admin_data_items) if @measure.admin_data_items.any? - output + Array.new.tap do |array| + array << StudentSurveyPresenter.new(measure_id: @measure.measure_id, survey_items: @measure.student_survey_items) if @measure.student_survey_items.any? + array << TeacherSurveyPresenter.new(measure_id: @measure.measure_id, survey_items: @measure.teacher_survey_items) if @measure.teacher_survey_items.any? + array << AdminDataPresenter.new(measure_id: @measure.measure_id, admin_data_items: @measure.admin_data_items) if @measure.admin_data_items.any? + end end private diff --git a/spec/factories.rb b/spec/factories.rb index a9d31a37..e34f1aed 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -36,8 +36,8 @@ FactoryBot.define do end after(:create) do |subcategory, evaluator| create_list(:measure, evaluator.measures_count, subcategory: subcategory). each do |measure| - survey_item = create(:survey_item, measure: measure) - create(:survey_item_response, survey_item: survey_item) + survey_item = create(:teacher_survey_item, measure: measure) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: survey_item) end end end @@ -54,11 +54,17 @@ FactoryBot.define do end factory :survey_item do - survey_item_id { rand.to_s } prompt { 'What do YOU think?' } measure + factory :teacher_survey_item do + survey_item_id { "t-#{rand.to_s}" } + end + factory :student_survey_item do + survey_item_id { "s-#{rand.to_s}" } + end end + factory :survey_item_response do likert_score { 3 } response_id { rand.to_s } diff --git a/spec/models/survey_item_response_spec.rb b/spec/models/survey_item_response_spec.rb index 586b7a36..1dea46d2 100644 --- a/spec/models/survey_item_response_spec.rb +++ b/spec/models/survey_item_response_spec.rb @@ -186,31 +186,23 @@ describe SurveyItemResponse, type: :model do context 'and there is sufficient teacher data and insufficient student data' do before :each do - SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD.times do - create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school) - end - (SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1).times do - create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school) - end + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 5) + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD - 1, survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 1) end - it 'returns nil' do - expect(SurveyItemResponse.score_for_measure(measure: measure, school: school, academic_year: ay)).to be_nil + it 'returns the average of the likert scores of the teacher survey items' do + expect(SurveyItemResponse.score_for_measure(measure: measure, school: school, academic_year: ay)).to eq 5 end end context 'and there is insufficient teacher data and sufficient student data' do before :each do - (SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1).times do - create(:survey_item_response, survey_item: teacher_survey_item_1, academic_year: ay, school: school) - end - SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD.times do - create(:survey_item_response, survey_item: student_survey_item_1, academic_year: ay, school: school) - end + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1, survey_item: teacher_survey_item_1, academic_year: ay, school: school, likert_score: 1) + create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: student_survey_item_1, academic_year: ay, school: school, likert_score: 5) end - it 'returns nil' do - expect(SurveyItemResponse.score_for_measure(measure: measure, school: school, academic_year: ay)).to be_nil + it 'returns the average of the likert scores of the student survey items' do + expect(SurveyItemResponse.score_for_measure(measure: measure, school: school, academic_year: ay)).to eq 5 end end diff --git a/spec/presenters/measure_presenter_spec.rb b/spec/presenters/measure_presenter_spec.rb index 278a3aac..c2faa4df 100644 --- a/spec/presenters/measure_presenter_spec.rb +++ b/spec/presenters/measure_presenter_spec.rb @@ -3,27 +3,24 @@ require 'rails_helper' describe MeasurePresenter do let(:academic_year) { create(:academic_year, range: '1989-90') } let(:school) { create(:school, name: 'Best School') } - let(:measure) do - create(:measure, measure_id: 'measure-id').tap do |measure| - survey_item = create(:survey_item, measure: measure) - create(:survey_item_response, survey_item: survey_item, academic_year: academic_year, school: school, likert_score: 1) - create(:survey_item_response, survey_item: survey_item, academic_year: academic_year, school: school, likert_score: 5) - end - end + let(:measure) { create(:measure, measure_id: 'measure-id') } let(:measure_presenter) { MeasurePresenter.new(measure: measure, academic_year: academic_year, school: school) } - it 'creates a gauge presenter that presents the average likert score' do - expect(measure_presenter.gauge_presenter.title).to eq 'Growth' - end - it 'has an id for use in the data item accordions' do expect(measure_presenter.data_item_accordion_id).to eq 'data-item-accordion-measure-id' end context 'when the measure contains only teacher data' do before :each do - create(:survey_item, measure: measure, survey_item_id: 't-something', prompt: 'A teacher survey item prompt') - create(:survey_item, measure: measure, survey_item_id: 't-something-else', prompt: 'Another teacher survey item prompt') + survey_item1 = create(:teacher_survey_item, measure: measure, prompt: 'A teacher survey item prompt') + survey_item2 = create(:teacher_survey_item, measure: measure, prompt: 'Another teacher survey item prompt') + + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: survey_item1, academic_year: academic_year, school: school, likert_score: 1) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: survey_item2, academic_year: academic_year, school: school, likert_score: 5) + end + + it 'creates a gauge presenter that presents the average likert score' do + expect(measure_presenter.gauge_presenter.title).to eq 'Growth' end it 'returns a list of data item presenters that has only one element, and that element has a title of "Teacher survey"' do diff --git a/spec/presenters/subcategory_presenter_spec.rb b/spec/presenters/subcategory_presenter_spec.rb index 72cdce6e..dcb41f94 100644 --- a/spec/presenters/subcategory_presenter_spec.rb +++ b/spec/presenters/subcategory_presenter_spec.rb @@ -6,14 +6,14 @@ describe SubcategoryPresenter do let(:subcategory) { create(:subcategory, name: 'A great subcategory', description: 'A great description') } let(:subcategory_presenter) do measure1 = create(:measure, watch_low_benchmark: 4, growth_low_benchmark: 4.25, approval_low_benchmark: 4.5, ideal_low_benchmark: 4.75, subcategory: subcategory) - survey_item1 = create(:survey_item, measure: measure1) - create(:survey_item_response, survey_item: survey_item1, academic_year: academic_year, school: school, likert_score: 1) - create(:survey_item_response, survey_item: survey_item1, academic_year: academic_year, school: school, likert_score: 5) + survey_item1 = create(:teacher_survey_item, measure: measure1) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: survey_item1, academic_year: academic_year, school: school, likert_score: 1) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: survey_item1, academic_year: academic_year, school: school, likert_score: 5) measure2 = create(:measure, watch_low_benchmark: 1.25, growth_low_benchmark: 1.5, approval_low_benchmark: 1.75, ideal_low_benchmark: 2.0, subcategory: subcategory) - survey_item2 = create(:survey_item, measure: measure2) - create(:survey_item_response, survey_item: survey_item2, academic_year: academic_year, school: school, likert_score: 1) - create(:survey_item_response, survey_item: survey_item2, academic_year: academic_year, school: school, likert_score: 5) + survey_item2 = create(:teacher_survey_item, measure: measure2) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: survey_item2, academic_year: academic_year, school: school, likert_score: 1) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: survey_item2, academic_year: academic_year, school: school, likert_score: 5) measure_of_only_admin_data = create(:measure, watch_low_benchmark: 0, growth_low_benchmark: 0, approval_low_benchmark: 0, ideal_low_benchmark: 0, subcategory: subcategory) create(:admin_data_item, measure: measure_of_only_admin_data) @@ -48,8 +48,8 @@ describe SubcategoryPresenter do end def create_survey_item_responses_for_different_years_and_schools(survey_item) - create(:survey_item_response, survey_item: survey_item, school: school, likert_score: 1) - create(:survey_item_response, survey_item: survey_item, academic_year: academic_year, likert_score: 1) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: survey_item, school: school, likert_score: 1) + create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: survey_item, academic_year: academic_year, likert_score: 1) end end diff --git a/spec/views/sqm_categories/show.html.erb_spec.rb b/spec/views/sqm_categories/show.html.erb_spec.rb index dfddfc8b..5bc53fa1 100644 --- a/spec/views/sqm_categories/show.html.erb_spec.rb +++ b/spec/views/sqm_categories/show.html.erb_spec.rb @@ -12,14 +12,14 @@ describe 'sqm_categories/show.html.erb' do subcategory2 = create(:subcategory_with_measures, sqm_category: category, name: 'Another subcategory', description: 'Another description of the subcategory') measure1 = create(:measure, subcategory: subcategory1, watch_low_benchmark: 1.5, growth_low_benchmark: 2.5, approval_low_benchmark: 3.5, ideal_low_benchmark: 4.5) - survey_item1 = create(:survey_item, measure: measure1) + survey_item1 = create(:student_survey_item, measure: measure1) create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: survey_item1, academic_year: academic_year, school: school, likert_score: 1) measure2 = create(:measure, name: 'The second measure name', description: 'The second measure description', subcategory: subcategory1, watch_low_benchmark: 1.5, growth_low_benchmark: 2.5, approval_low_benchmark: 3.5, ideal_low_benchmark: 4.5) - student_survey_item = create(:survey_item, measure: measure2, survey_item_id: "s-abc", prompt: "Some prompt for student data") + student_survey_item = create(:student_survey_item, measure: measure2, prompt: "Some prompt for student data") create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: student_survey_item, academic_year: academic_year, school: school, likert_score: 5) - teacher_survey_item = create(:survey_item, measure: measure2, survey_item_id: "t-abc", prompt: "Some prompt for teacher data") + teacher_survey_item = create(:teacher_survey_item, measure: measure2, prompt: "Some prompt for teacher data") create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: teacher_survey_item, academic_year: academic_year, school: school, likert_score: 3) admin_data_item = create(:admin_data_item, measure: measure2, description: "Some admin data item description")