From 8984023aa430cea4e3d4712e2e4cd29257bfdb35 Mon Sep 17 00:00:00 2001 From: Nelson Jovel Date: Thu, 31 Oct 2024 20:05:26 -0700 Subject: [PATCH] Show parent response rate --- app/models/parent.rb | 2 + app/models/survey_item_response.rb | 1 + app/presenters/overview/overview_presenter.rb | 4 ++ app/presenters/response_rate_presenter.rb | 1 - app/services/survey_item_values.rb | 10 +-- app/services/survey_responses_data_loader.rb | 27 ++++++-- db/migrate/20241031190531_create_parents.rb | 10 +++ ...5926_add_parent_to_survey_item_response.rb | 5 ++ db/schema.rb | 12 +++- spec/factories.rb | 5 ++ spec/models/parent_spec.rb | 5 ++ .../survey_responses_data_loader_spec.rb | 64 +++++++++---------- 12 files changed, 98 insertions(+), 48 deletions(-) create mode 100644 app/models/parent.rb create mode 100644 db/migrate/20241031190531_create_parents.rb create mode 100644 db/migrate/20241031205926_add_parent_to_survey_item_response.rb create mode 100644 spec/models/parent_spec.rb diff --git a/app/models/parent.rb b/app/models/parent.rb new file mode 100644 index 00000000..2d556d15 --- /dev/null +++ b/app/models/parent.rb @@ -0,0 +1,2 @@ +class Parent < ApplicationRecord +end diff --git a/app/models/survey_item_response.rb b/app/models/survey_item_response.rb index acdc9407..c1d8d270 100644 --- a/app/models/survey_item_response.rb +++ b/app/models/survey_item_response.rb @@ -8,6 +8,7 @@ class SurveyItemResponse < ActiveRecord::Base belongs_to :school belongs_to :survey_item, counter_cache: true belongs_to :student, foreign_key: :student_id, optional: true + belongs_to :parent, optional: true belongs_to :gender, optional: true belongs_to :income, optional: true belongs_to :ell, optional: true diff --git a/app/presenters/overview/overview_presenter.rb b/app/presenters/overview/overview_presenter.rb index 6c20e5dc..1b13f2b5 100644 --- a/app/presenters/overview/overview_presenter.rb +++ b/app/presenters/overview/overview_presenter.rb @@ -47,6 +47,10 @@ class Overview::OverviewPresenter ParentResponseRatePresenter.new(school: @school, academic_year: @academic_year) end + def parent_response_rate_presenter + ResponseRatePresenter.new(focus: :parent, school: @school, academic_year: @academic_year) + end + def presenter_for_measure(measure) score = measure.score(school: @school, academic_year: @academic_year) diff --git a/app/presenters/response_rate_presenter.rb b/app/presenters/response_rate_presenter.rb index fef8e097..23113e41 100644 --- a/app/presenters/response_rate_presenter.rb +++ b/app/presenters/response_rate_presenter.rb @@ -76,4 +76,3 @@ class ResponseRatePresenter respondents.enrollment_by_grade.keys end end - diff --git a/app/services/survey_item_values.rb b/app/services/survey_item_values.rb index f562bc34..36521830 100644 --- a/app/services/survey_item_values.rb +++ b/app/services/survey_item_values.rb @@ -67,11 +67,7 @@ class SurveyItemValues end def survey_item_response(survey_item:) - @survey_item_response ||= Hash.new do |memo, survey_item| - memo[survey_item] = survey_item_responses[[response_id, survey_item.id]] - end - - @survey_item_response[survey_item] + survey_item_responses[[response_id, survey_item.id]] end def survey_item_responses @@ -192,6 +188,10 @@ class SurveyItemValues @sped ||= Sped.to_designation(raw_sped) end + def number_of_children + @number_of_children ||= value_from(pattern: /Number\s*Of\s*Children/i).to_i + end + def value_from(pattern:) output = nil matches = headers.select do |header| diff --git a/app/services/survey_responses_data_loader.rb b/app/services/survey_responses_data_loader.rb index 1108e509..a80154f8 100644 --- a/app/services/survey_responses_data_loader.rb +++ b/app/services/survey_responses_data_loader.rb @@ -87,10 +87,20 @@ class SurveyResponsesDataLoader end def process_survey_items(row:) - student = Student.find_or_create_by(response_id: row.response_id, lasid: row.lasid) - student.races.delete_all - tmp_races = row.races.map { |race| races[race] } - student.races += tmp_races + student = nil + parent = nil + if row.respondent_type == :student + student = Student.find_or_create_by(response_id: row.response_id, lasid: row.lasid) + student.races.delete_all + tmp_races = row.races.map { |race| races[race] } + student.races += tmp_races + end + + if row.respondent_type == :parent + parent = Parent.find_or_create_by(response_id: row.response_id) + parent.number_of_children = row.number_of_children + parent.save + end row .survey_items @@ -103,12 +113,12 @@ class SurveyResponsesDataLoader end response = row.survey_item_response(survey_item:) - create_or_update_response(survey_item_response: response, likert_score:, row:, survey_item:, student:) + create_or_update_response(survey_item_response: response, likert_score:, row:, survey_item:, student:, parent:) end .compact end - def create_or_update_response(survey_item_response:, likert_score:, row:, survey_item:, student:) + def create_or_update_response(survey_item_response:, likert_score:, row:, survey_item:, student:, parent:) gender = genders[row.gender] grade = row.grade income = incomes[row.income.parameterize] @@ -124,6 +134,8 @@ class SurveyResponsesDataLoader survey_item_response.ell = ell survey_item_response.sped = sped survey_item_response.student = student + survey_item_response.parent = parent + survey_item_response else SurveyItemResponse.new( @@ -138,7 +150,8 @@ class SurveyResponsesDataLoader income:, ell:, sped:, - student: + student:, + parent: ) end end diff --git a/db/migrate/20241031190531_create_parents.rb b/db/migrate/20241031190531_create_parents.rb new file mode 100644 index 00000000..fe8270ce --- /dev/null +++ b/db/migrate/20241031190531_create_parents.rb @@ -0,0 +1,10 @@ +class CreateParents < ActiveRecord::Migration[7.1] + def change + create_table :parents do |t| + t.string :response_id + t.integer :number_of_children + + t.timestamps + end + end +end diff --git a/db/migrate/20241031205926_add_parent_to_survey_item_response.rb b/db/migrate/20241031205926_add_parent_to_survey_item_response.rb new file mode 100644 index 00000000..c16d61be --- /dev/null +++ b/db/migrate/20241031205926_add_parent_to_survey_item_response.rb @@ -0,0 +1,5 @@ +class AddParentToSurveyItemResponse < ActiveRecord::Migration[7.1] + def change + add_reference :survey_item_responses, :parent, foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index cff17e68..927278d4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_09_24_173209) do +ActiveRecord::Schema[7.1].define(version: 2024_10_31_205926) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -316,6 +316,13 @@ ActiveRecord::Schema[7.1].define(version: 2024_09_24_173209) do t.index ["subcategory_id"], name: "index_measures_on_subcategory_id" end + create_table "parents", force: :cascade do |t| + t.string "response_id" + t.integer "number_of_children" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "race_scores", force: :cascade do |t| t.bigint "measure_id", null: false t.bigint "school_id", null: false @@ -476,10 +483,12 @@ ActiveRecord::Schema[7.1].define(version: 2024_09_24_173209) do t.bigint "income_id" t.bigint "ell_id" t.bigint "sped_id" + t.bigint "parent_id" t.index ["academic_year_id"], name: "index_survey_item_responses_on_academic_year_id" t.index ["ell_id"], name: "index_survey_item_responses_on_ell_id" t.index ["gender_id"], name: "index_survey_item_responses_on_gender_id" t.index ["income_id"], name: "index_survey_item_responses_on_income_id" + t.index ["parent_id"], name: "index_survey_item_responses_on_parent_id" t.index ["response_id"], name: "index_survey_item_responses_on_response_id" t.index ["school_id", "academic_year_id", "survey_item_id"], name: "by_school_year_and_survey_item" t.index ["school_id", "survey_item_id", "academic_year_id", "grade"], name: "index_survey_responses_on_grade" @@ -535,6 +544,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_09_24_173209) do add_foreign_key "survey_item_responses", "ells" add_foreign_key "survey_item_responses", "genders" add_foreign_key "survey_item_responses", "incomes" + add_foreign_key "survey_item_responses", "parents" add_foreign_key "survey_item_responses", "schools" add_foreign_key "survey_item_responses", "speds" add_foreign_key "survey_item_responses", "students" diff --git a/spec/factories.rb b/spec/factories.rb index 7899d1c6..4d32450c 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -1,4 +1,9 @@ FactoryBot.define do + factory :parent do + response_id { "MyString" } + number_of_children { 1 } + end + factory :income do designation { "DefaultIncome" } end diff --git a/spec/models/parent_spec.rb b/spec/models/parent_spec.rb new file mode 100644 index 00000000..a37df499 --- /dev/null +++ b/spec/models/parent_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Parent, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/services/survey_responses_data_loader_spec.rb b/spec/services/survey_responses_data_loader_spec.rb index 731875e4..199f7cc1 100644 --- a/spec/services/survey_responses_data_loader_spec.rb +++ b/spec/services/survey_responses_data_loader_spec.rb @@ -21,6 +21,27 @@ describe SurveyResponsesDataLoader do district: lowell) end + let(:student_survey_items) do + ids = %w[ s-emsa-q1 s-emsa-q2 s-emsa-q3 + s-tint-q1 s-tint-q2 s-tint-q4 s-tint-q5 + s-acpr-q1 s-acpr-q2 s-acpr-q3 s-acpr-q4 + s-cure-q3 s-cure-q4 s-sten-q2 s-sten-q3 + s-sper-q1 s-sper-q2 s-sper-q3 s-sper-q4 + s-civp-q1 s-civp-q2 s-civp-q3 s-civp-q4 s-grmi-q1 + s-grmi-q4 s-appa-q1 + s-appa-q2 s-peff-q1 + s-peff-q2 s-peff-q3 s-peff-q4 s-peff-q5 s-peff-q6 + s-sbel-q1 s-sbel-q2 s-sbel-q3 s-sbel-q4 s-sbel-q5 + s-phys-q1 s-phys-q2 s-phys-q3 s-phys-q4 + s-vale-q1 s-vale-q2 s-vale-q3 s-vale-q4 + s-acst-q1 s-acst-q2 s-acst-q3 s-acst-q4 s-acst-q5 + s-grit-q1 s-grit-q2 s-grit-q3 s-grit-q4] + + ids.each do |id| + create(:survey_item, survey_item_id: id) + end + end + let(:t_pcom_q3) { create(:survey_item, survey_item_id: "t-pcom-q3") } let(:t_pcom_q2) { create(:survey_item, survey_item_id: "t-pcom-q2") } let(:t_coll_q1) { create(:survey_item, survey_item_id: "t-coll-q1") } @@ -30,22 +51,6 @@ describe SurveyResponsesDataLoader do let(:t_sach_q2) { create(:survey_item, survey_item_id: "t-sach-q2") } let(:t_sach_q3) { create(:survey_item, survey_item_id: "t-sach-q3") } - let(:s_phys_q1) { create(:survey_item, survey_item_id: "s-phys-q1") } - let(:s_phys_q2) { create(:survey_item, survey_item_id: "s-phys-q2") } - let(:s_phys_q3) { create(:survey_item, survey_item_id: "s-phys-q3") } - let(:s_phys_q4) { create(:survey_item, survey_item_id: "s-phys-q4") } - let(:s_vale_q1) { create(:survey_item, survey_item_id: "s-phys-q1") } - let(:s_vale_q2) { create(:survey_item, survey_item_id: "s-phys-q2") } - let(:s_vale_q3) { create(:survey_item, survey_item_id: "s-phys-q3") } - let(:s_vale_q4) { create(:survey_item, survey_item_id: "s-phys-q4") } - let(:s_acst_q1) { create(:survey_item, survey_item_id: "s-acst-q1") } - let(:s_acst_q2) { create(:survey_item, survey_item_id: "s-acst-q2") } - let(:s_acst_q3) { create(:survey_item, survey_item_id: "s-acst-q3") } - let(:s_acst_q4) { create(:survey_item, survey_item_id: "s-acst-q4") } - let(:s_emsa_q1) { create(:survey_item, survey_item_id: "s-emsa-q1") } - let(:s_emsa_q2) { create(:survey_item, survey_item_id: "s-emsa-q2") } - let(:s_emsa_q3) { create(:survey_item, survey_item_id: "s-emsa-q3") } - let(:female) { create(:gender, qualtrics_code: 1) } let(:male) { create(:gender, qualtrics_code: 2) } let(:another_gender) { create(:gender, qualtrics_code: 3) } @@ -83,21 +88,7 @@ describe SurveyResponsesDataLoader do t_sach_q1 t_sach_q2 t_sach_q3 - s_phys_q1 - s_phys_q2 - s_phys_q3 - s_phys_q4 - s_vale_q1 - s_vale_q2 - s_vale_q3 - s_vale_q4 - s_acst_q1 - s_acst_q2 - s_acst_q3 - s_acst_q4 - s_emsa_q1 - s_emsa_q2 - s_emsa_q3 + student_survey_items female male @@ -170,6 +161,7 @@ describe SurveyResponsesDataLoader do end it "updates the likert score to the score on the new csv file" do s_emsa_q1 = SurveyItem.find_by_survey_item_id "s-emsa-q1" + s_acst_q3 = SurveyItem.find_by_survey_item_id "s-acst-q3" expect(SurveyItemResponse.where(response_id: "student_survey_response_3", survey_item: s_emsa_q1).first.likert_score).to eq 1 expect(SurveyItemResponse.where(response_id: "student_survey_response_4", @@ -241,17 +233,21 @@ end def loads_student_survey_item_response_values expect(SurveyItemResponse.where(response_id: "student_survey_response_1").count).to eq 3 expect(SurveyItemResponse.where(response_id: "student_survey_response_2").count).to eq 0 - expect(SurveyItemResponse.where(response_id: "student_survey_response_3").count).to eq 12 - expect(SurveyItemResponse.where(response_id: "student_survey_response_4").count).to eq 15 - expect(SurveyItemResponse.where(response_id: "student_survey_response_5").count).to eq 14 + expect(SurveyItemResponse.where(response_id: "student_survey_response_3").count).to eq 30 + expect(SurveyItemResponse.where(response_id: "student_survey_response_4").count).to eq 27 + expect(SurveyItemResponse.where(response_id: "student_survey_response_5").count).to eq 30 end def student_survey_item_response_count_matches_expected + s_phys_q1 = SurveyItem.where(survey_item_id: "s-phys-q1") + s_phys_q2 = SurveyItem.where(survey_item_id: "s-phys-q2") expect(SurveyItemResponse.where(survey_item: s_phys_q1).count).to eq 6 expect(SurveyItemResponse.where(survey_item: s_phys_q2).count).to eq 5 end def captures_likert_scores_for_student_survey_item_responses + s_phys_q1 = SurveyItem.where(survey_item_id: "s-phys-q1") + s_phys_q2 = SurveyItem.where(survey_item_id: "s-phys-q2") expect(SurveyItemResponse.where(response_id: "student_survey_response_1").where(survey_item: s_phys_q1).first.likert_score).to eq 3 expect(SurveyItemResponse.where(response_id: "student_survey_response_1").where(survey_item: s_phys_q2)).to be_empty