sqm-dashboards/app/presenters/response_rate_presenter.rb
Nelson Jovel 33da0859b9 Split academic year into seasons if the academic year's range is
initialized with a season, i.e. "2024-25 Fall".  Update scapers for
admin data, enrollment and staffing to use the new range standard
correctly.   Update the loaders for admin data, enrollment and staffing
so that it populates all seasons in a given year.  So admin data for
2024-25 gets loaded into "2024-25 Fall" and "2024-25 Spring".  Add tests
for the new range format.  Set the default cutoff for the start of Spring season will be the last Sunday in February
2024-04-25 09:21:04 -07:00

108 lines
3.1 KiB
Ruby

class ResponseRatePresenter
attr_reader :focus, :academic_year, :school, :survey_items
def initialize(focus:, academic_year:, school:)
@focus = focus
@academic_year = academic_year
@school = school
if focus == :student
@survey_items = Measure.all.flat_map do |measure|
measure.student_survey_items_with_sufficient_responses(school:, academic_year:)
end
end
@survey_items = SurveyItem.teacher_survey_items if focus == :teacher
end
def date
SurveyItemResponse.where(survey_item: survey_items, school:,
academic_year:).order(recorded_date: :DESC).first&.recorded_date
end
def percentage
return 0 if respondents_count.nil? || respondents_count.zero?
cap_at_100(actual_count.to_f / respondents_count.to_f * 100).round
end
def color
percentage > 75 ? "purple" : "gold"
end
def date_message
return "" if date.nil?
"Response rate as of #{date.to_date.strftime('%m/%d/%y')}"
end
def hover_message
return "" if date.nil?
"Percentages based on #{actual_count} out of #{respondents_count.round} #{focus}s completing at least 25% of the survey."
end
private
def cap_at_100(value)
value > 100 ? 100 : value
end
def actual_count
if focus == :teacher
response_count_for_survey_items(survey_items:)
else
non_early_ed_items = survey_items - SurveyItem.early_education_survey_items
non_early_ed_count = response_count_for_survey_items(survey_items: non_early_ed_items)
early_ed_items = survey_items & SurveyItem.early_education_survey_items
early_ed_count = SurveyItemResponse.where(school:, academic_year:,
survey_item: early_ed_items)
.group(:survey_item)
.select(:response_id)
.distinct
.count
.reduce(0) do |largest, row|
count = row[1]
if count > largest
count
else
largest
end
end
non_early_ed_count + early_ed_count
end
end
def response_count_for_survey_items(survey_items:)
SurveyItemResponse.where(school:, academic_year:,
survey_item: survey_items).select(:response_id).distinct.count || 0
end
def respondents_count
return 0 if respondents.nil?
count = enrollment if focus == :student
count = respondents.total_teachers if focus == :teacher
count
end
def enrollment
SurveyItemResponse.where(school:, academic_year:, grade: grades,
survey_item: SurveyItem.student_survey_items)
.select(:grade)
.distinct
.pluck(:grade)
.reject(&:nil?)
.map do |grade|
respondents.enrollment_by_grade[grade]
end.sum.to_f
end
def respondents
@respondents ||= Respondent.by_school_and_year(school:, academic_year:)
end
def grades
respondents.enrollment_by_grade.keys
end
end