From 0b502ce82646630eed35883a9e665232f25d8d49 Mon Sep 17 00:00:00 2001 From: Nelson Jovel Date: Wed, 20 Apr 2022 13:53:45 -0700 Subject: [PATCH] When calculating response rate, only take into account survey items with associated responses. Ignore any survey items with no responses. Finishes #181922483 --- app/models/student_response_rate.rb | 12 +++++------ app/models/teacher_response_rate.rb | 6 +++++- spec/models/response_rate_spec.rb | 32 ++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/app/models/student_response_rate.rb b/app/models/student_response_rate.rb index 2dc3ea21..9964b583 100644 --- a/app/models/student_response_rate.rb +++ b/app/models/student_response_rate.rb @@ -4,15 +4,13 @@ class StudentResponseRate private def survey_item_count - # @survey_item_count ||= @subcategory.measures.map { |measure| measure.student_survey_items.count }.sum @survey_item_count ||= begin survey = Survey.where(school: @school, academic_year: @academic_year).first - if survey.form == 'normal' - SurveyItem.includes(%i[scale measure]).student_survey_items.where("scale.measure": @subcategory.measures).count - else - SurveyItem.includes(%i[scale - measure]).student_survey_items.where("scale.measure": @subcategory.measures).where(on_short_form: true).count - end + survey_items = SurveyItem.includes(%i[scale + measure]).student_survey_items.where("scale.measure": @subcategory.measures) + survey_items = survey_items.where(on_short_form: true) if survey.form == 'short' + survey_items = survey_items.reject { |survey_item| survey_item.survey_item_responses.count == 0 } + survey_items.count end end diff --git a/app/models/teacher_response_rate.rb b/app/models/teacher_response_rate.rb index c7b49add..3bf72460 100644 --- a/app/models/teacher_response_rate.rb +++ b/app/models/teacher_response_rate.rb @@ -2,7 +2,11 @@ class TeacherResponseRate include ResponseRate def survey_item_count - @survey_item_count ||= @subcategory.measures.map { |measure| measure.teacher_survey_items.count }.sum + @survey_item_count ||= @subcategory.measures.map do |measure| + measure.teacher_survey_items.reject do |survey_item| + survey_item.survey_item_responses.where(school: @school, academic_year: @academic_year).count == 0 + end.count + end.sum end def response_count diff --git a/spec/models/response_rate_spec.rb b/spec/models/response_rate_spec.rb index a679c238..85dada30 100644 --- a/spec/models/response_rate_spec.rb +++ b/spec/models/response_rate_spec.rb @@ -12,6 +12,7 @@ describe ResponseRate, type: :model do let(:sufficient_scale_2) { create(:scale, measure: sufficient_measure_2) } let(:sufficient_teacher_survey_item) { create(:teacher_survey_item, scale: sufficient_scale_1) } let(:sufficient_student_survey_item_1) { create(:student_survey_item, scale: sufficient_scale_1) } + let(:insufficient_student_survey_item_1) { create(:student_survey_item, scale: sufficient_scale_1) } let(:sufficient_student_survey_item_2) { create(:student_survey_item, scale: sufficient_scale_2) } before :each do @@ -29,7 +30,7 @@ describe ResponseRate, type: :model do end context 'when the average number of student responses per question in a subcategory is equal to the student response threshold' do - it 'returns 100 percent' do + it 'returns a response rate equal to the response threshold' do expect(StudentResponseRate.new(subcategory:, school:, academic_year:).rate).to eq 25 end @@ -84,6 +85,20 @@ describe ResponseRate, type: :model do expect(StudentResponseRate.new(subcategory:, school:, academic_year:).rate).to eq 100 end end + + context 'when there is an imbalance in the response rate of the student items' do + context 'and one of the student items has no associated survey item responses' do + before do + create(:respondent, school:, academic_year:) + create(:survey, school:, academic_year:) + insufficient_student_survey_item_1 + end + it 'ignores the empty survey item and returns only the average response rate of student survey items with responses' do + expect(StudentResponseRate.new(subcategory:, school:, + academic_year:).rate).to eq 25 + end + end + end end describe TeacherResponseRate do @@ -95,6 +110,7 @@ describe ResponseRate, type: :model do let(:sufficient_teacher_survey_item_1) { create(:teacher_survey_item, scale: sufficient_scale_1) } let(:sufficient_teacher_survey_item_2) { create(:teacher_survey_item, scale: sufficient_scale_1) } let(:sufficient_teacher_survey_item_3) { create(:teacher_survey_item, scale: sufficient_scale_1) } + let(:insufficient_teacher_survey_item_4) { create(:teacher_survey_item, scale: sufficient_scale_1) } let(:sufficient_student_survey_item_1) { create(:student_survey_item, scale: sufficient_scale_1) } before :each do @@ -149,5 +165,19 @@ describe ResponseRate, type: :model do academic_year:).rate).to eq 100 end end + + context 'when there is an imbalance in the response rate of the teacher items' do + context 'and one of the teacher items has no associated survey item responses' do + before do + create(:respondent, school:, academic_year:) + create(:survey, school:, academic_year:) + insufficient_teacher_survey_item_4 + end + it 'ignores the empty survey item and returns only the average response rate of teacher survey items with responses' do + expect(TeacherResponseRate.new(subcategory:, school:, + academic_year:).rate).to eq 25 + end + end + end end end