finish up adding socio economic disag filter

main-eol
rebuilt 6 months ago
parent a258b32b39
commit cab0a3955e

@ -17,7 +17,7 @@ class Benefit < ApplicationRecord
puts "************************************"
puts "******** ERROR **********"
puts ""
puts "Error parsing Income column. '#{benefits}' is not a known value. Halting execution"
puts "Error parsing benefits column. '#{benefits}' is not a known value. Halting execution"
puts ""
puts "************************************"
exit

@ -27,7 +27,7 @@ class Education < ApplicationRecord
puts "************************************"
puts "******** ERROR **********"
puts ""
puts "Error parsing Income column. '#{education}' is not a known value. Halting execution"
puts "Error parsing Education column. '#{education}' is not a known value. Halting execution"
puts ""
puts "************************************"
exit

@ -5,23 +5,23 @@ class Employment < ApplicationRecord
return "Unknown" if employment.blank? or employment.nil?
case employment
in /^1$/i
in /^1$|^1100$/i
"Two adults with full-time employment"
in /^2$/i
in /^2$|^2100$/i
"One adult with full-time employment"
in /^3$/i
in /^3$|^3100$/i
"Two adults with part-time employment"
in /^4$/i
in /^4$|^4100$/i
"One adult with part-time employment"
in /^5$/i
in /^5$|^5100$/i
"No full-time or part-time employment"
in /^99$|^100$/i
in /^99$|^100$|^99100$/i
"Unknown"
else
puts "************************************"
puts "******** ERROR **********"
puts ""
puts "Error parsing Income column. '#{employment}' is not a known value. Halting execution"
puts "Error parsing Employment column. '#{employment}' is not a known value. Halting execution"
puts ""
puts "************************************"
exit

@ -75,6 +75,10 @@ class SurveyItemResponse < ActiveRecord::Base
SurveyItemResponse.joins([parent: :languages]).where(languages: { designation: designations }, survey_item: survey_items, school:, academic_year:).group(:survey_item).average(:likert_score)
}
scope :averages_for_socio_economic_status, lambda { |survey_items, school, academic_year, socio_economic_status|
SurveyItemResponse.joins(:parent).where(parent: { socio_economic_status: }, survey_item: survey_items, school:, academic_year:).group(:survey_item).average(:likert_score)
}
def self.grouped_responses(school:, academic_year:)
@grouped_responses ||= Hash.new do |memo, (school, academic_year)|
memo[[school, academic_year]] =

@ -0,0 +1,39 @@
# frozen_string_literal: true
module Analyze
module Graph
module Column
module Parent
class SocioEconomicStatus < Base
attr_reader :socio_economic_status, :label
def initialize(socio_economic_status:, label:, show_irrelevancy_message:)
@socio_economic_status = socio_economic_status
@label = label
@show_irrelevancy_message = show_irrelevancy_message
end
def n_size(construct:, school:, academic_year:)
SurveyItemResponse.joins(:parent).where(parent: { socio_economic_status: }, survey_item: construct.parent_survey_items, school:, academic_year:).select(:parent_id).distinct.count
end
def score(construct:, school:, academic_year:)
return Score::NIL_SCORE if n_size(construct:, school:, academic_year:) < 10
averages = SurveyItemResponse.averages_for_socio_economic_status(construct.parent_survey_items, school, academic_year,
socio_economic_status)
average = bubble_up_averages(construct:, averages:).round(2)
Score.new(average:,
meets_teacher_threshold: false,
meets_student_threshold: true,
meets_admin_data_threshold: false)
end
def designations
language.map(&:designation)
end
end
end
end
end
end

@ -0,0 +1,38 @@
# frozen_string_literal: true
module Analyze
module Graph
class ParentsBySocioEconomicStatus
def to_s
"Parents by Socio-Economic Status"
end
def slug
"parents-by-socio-economic-status"
end
def columns
[].tap do |array|
array << Analyze::Graph::Column::Parent::SocioEconomicStatus.new(socio_economic_status: 0, label: ["No Advantage"], show_irrelevancy_message: false)
array << Analyze::Graph::Column::Parent::SocioEconomicStatus.new(socio_economic_status: 1, label: ["Low Advantage"], show_irrelevancy_message: false)
array << Analyze::Graph::Column::Parent::SocioEconomicStatus.new(socio_economic_status: 2, label: ["Mediumn Advantage"], show_irrelevancy_message: false)
array << Analyze::Graph::Column::Parent::SocioEconomicStatus.new(socio_economic_status: 3, label: ["High Advantage"], show_irrelevancy_message: false)
array << Analyze::Graph::Column::Parent::SocioEconomicStatus.new(socio_economic_status: [0, 1, 2, 3, nil], label: ["All Students"], show_irrelevancy_message: true)
end
end
def source
Analyze::Source::SurveyData.new(slices: nil, graph: self)
end
def slice
Analyze::Slice::ParentsByGroup.new(graph: self)
end
def group
Analyze::Group::Base.new(name: "Parents By Socio-Economic Status", slug: "parents-by-socio-economic-status", graph: self)
end
end
end
end

@ -167,7 +167,8 @@ module Analyze
"students-by-ell" => Analyze::Graph::StudentsByEll.new(ells: selected_ells),
"parents-by-race" => Analyze::Graph::ParentsByRace.new,
"parents-by-language" => Analyze::Graph::ParentsByLanguage.new,
"parents-by-gender" => Analyze::Graph::ParentsByGender.new }
"parents-by-gender" => Analyze::Graph::ParentsByGender.new,
"parents-by-socio-economic-status" => Analyze::Graph::ParentsBySocioEconomicStatus.new }
end
# The last item will per slice type will be selected as the default slice
@ -185,7 +186,9 @@ module Analyze
"students-by-ell" => nil,
"parents-by-race" => Analyze::Graph::ParentsByRace.new,
"parents-by-language" => Analyze::Graph::ParentsByLanguage.new,
"parents-by-gender" => Analyze::Graph::ParentsByGender.new }
"parents-by-gender" => Analyze::Graph::ParentsByGender.new,
"parents-by-socio-economic-status" => Analyze::Graph::ParentsBySocioEconomicStatus.new }
end
def graphs

@ -52,6 +52,13 @@ class SurveyResponsesDataLoader
SurveyItemResponse.import(survey_item_responses.compact.flatten, batch_size:, on_duplicate_key_update: :all)
end
def socio_economic_score(education, benefits, employment)
employment_points = employment.map(&:points).sum.clamp(0, 1)
ed_points = education&.points || 0
benefits_points = benefits&.points || 0
ed_points + benefits_points + employment_points
end
private
def schools
@ -141,7 +148,9 @@ class SurveyResponsesDataLoader
tmp_employments = row.employments.map { |employment| employments[employment] }.reject(&:nil?)
parent.employments.concat(tmp_employments)
parent.socio_economic_status = socio_economic_score(educations[row.education], benefits[row.benefits], tmp_employments)
parent.housing = housings[row.housing] if row.housing.present?
parent.save
end

@ -0,0 +1,5 @@
class AddSocioEconomicStatusToParent < ActiveRecord::Migration[8.0]
def change
add_column :parents, :socio_economic_status, :integer, default: nil
end
end

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_06_24_230522) do
ActiveRecord::Schema[8.0].define(version: 2025_06_25_201425) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
@ -399,6 +399,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_06_24_230522) do
t.bigint "housing_id"
t.bigint "education_id"
t.bigint "benefits_id"
t.integer "socio_economic_status"
t.index ["benefits_id"], name: "index_parents_on_benefits_id"
t.index ["education_id"], name: "index_parents_on_education_id"
t.index ["housing_id"], name: "index_parents_on_housing_id"

@ -341,6 +341,34 @@ describe SurveyResponsesDataLoader do
end
end
end
describe ".socio_economic_score" do
it "returns 0 when none of the rubrics meet the standard for higher advantage" do
score = SurveyResponsesDataLoader.new.socio_economic_score(Education.new(designation: "No formal schooling completed"), Benefit.new(designation: "No"), [Employment.new(designation: "No full-time or part-time employment")])
expect(score).to eq 0
score = SurveyResponsesDataLoader.new.socio_economic_score(Education.new(designation: "Unknown"), Benefit.new(designation: "Unknown"), [Employment.new(designation: "Unknown")])
expect(score).to eq 0
end
it "returns 1 when one of the rubrics meets the standard for higher advantage" do
score = SurveyResponsesDataLoader.new.socio_economic_score(Education.new(designation: "Associates Degree"), Benefit.new(designation: "No"), [Employment.new(designation: "No full-time or part-time employment")])
expect(score).to eq 1
end
it "returns 2 when two of the rubrics meet the standard for higher advantage" do
score = SurveyResponsesDataLoader.new.socio_economic_score(Education.new(designation: "Associates Degree"), Benefit.new(designation: "Yes"), [Employment.new(designation: "No full-time or part-time employment")])
expect(score).to eq 2
end
it "returns 3 when all three of the rubrics meet the standard for higher advantage" do
score = SurveyResponsesDataLoader.new.socio_economic_score(Education.new(designation: "Associates Degree"), Benefit.new(designation: "Yes"), [Employment.new(designation: "Two adults with full-time employment")])
expect(score).to eq 3
score = SurveyResponsesDataLoader.new.socio_economic_score(Education.new(designation: "Associates Degree"), Benefit.new(designation: "Yes"), [Employment.new(designation: "One adult with full-time employment"), Employment.new(designation: "Two adults with full-time employment")])
expect(score).to eq 3
end
end
end
def assigns_academic_year_to_survey_item_responses

Loading…
Cancel
Save