sqm-dashboards/app/models/report/measure.rb
rebuilt 058cbb0f6e fix: ECP-124 Update grade range to be the union of grades found in the database and the enrollment of the school. "Subcategory - School & District"
# Fixed reported grades
	     # Runs faster
      "Measure - District only"
	      # Should only be run per district
	      # Runs faster
	      # Fixed reported grades
      "Measure - School & District"
	      # Reports the grades that took the survey for that school+year; not the grades that responded to the measure
	      # Runs faster
	      # Fixed reported grades
      "Beyond Learning Loss"
      		# Runs faster
      "Beyond Learning Loss - Response Rate"
      		# Fixed reported grades
      "Survey Item - By Item"
	      # may be able to speed it up by getting all averages in a single request
	      # Fixed reported grades
      "Survey Item - By Grade"
      		# Fixed reported grades
	      #may be able to speed it up by getting all averages in a single request
      "Survey Entries - by Measure"
      		# No changes
2025-04-29 11:06:38 -07:00

126 lines
4.9 KiB
Ruby

module Report
class Measure
def self.create_report(schools: School.all.includes(:district), academic_years: AcademicYear.all, measures: ::Measure.all, filename: "measure_report.csv")
data = to_csv(schools, academic_years:, measures:)
FileUtils.mkdir_p Rails.root.join("tmp", "reports")
filepath = Rails.root.join("tmp", "reports", filename)
write_csv(data:, filepath:)
data
end
def self.to_csv(schools:, academic_years:, measures:)
data = []
mutex = Thread::Mutex.new
data << ["Measure Name", "Measure ID", "District", "School", "School Code", "Academic Year", "Recorded Date Range", "Grades", "Student Score", "Student Zone", "Teacher Score",
"Teacher Zone", "Admin Score", "Admin Zone", "All Score (Average)", "All Score Zone"]
pool_size = 2
jobs = Queue.new
schools.each { |school| jobs << school }
workers = pool_size.times.map do
Thread.new do
while school = jobs.pop(true)
academic_years.each do |academic_year|
respondents = Respondent.by_school_and_year(school:, academic_year:)
next if respondents.nil?
begin_date = ::SurveyItemResponse.where(school:,
academic_year:).where.not(recorded_date: nil).order(:recorded_date).first&.recorded_date&.to_date
end_date = ::SurveyItemResponse.where(school:,
academic_year:).where.not(recorded_date: nil).order(:recorded_date).last&.recorded_date&.to_date
date_range = "#{begin_date} - #{end_date}"
all_grades = Respondent.grades_that_responded_to_survey(academic_year: academic_year, school: school)
grades = "#{all_grades.first}-#{all_grades.last}"
measures.each do |measure|
score = measure.score(school:, academic_year:)
zone = measure.zone(school:, academic_year:).type.to_s.capitalize
response_rate = measure.subcategory.response_rate(school:, academic_year:)
next unless response_rate.meets_student_threshold? || response_rate.meets_teacher_threshold?
row = [response_rate, measure, school, academic_year]
mutex.synchronize do
data << [measure.name,
measure.measure_id,
school.district.name,
school.name,
school.dese_id,
academic_year.range,
date_range,
grades,
student_score(row:),
student_zone(row:),
teacher_score(row:),
teacher_zone(row:),
admin_score(row:),
admin_zone(row:),
score.average,
zone]
end
end
end
end
rescue ThreadError
end
end
workers.each(&:join)
csv = CSV.generate do |csv|
data.each do |row|
csv << row
end
end
end
def self.write_csv(data:, filepath:)
File.write(filepath, csv)
end
def self.student_score(row:)
row in [response_rate, measure, school, academic_year]
student_score = measure.student_score(school:, academic_year:).average if response_rate.meets_student_threshold?
student_score || "N/A"
end
def self.student_zone(row:)
row in [response_rate, measure, school, academic_year]
if response_rate.meets_student_threshold?
student_zone = measure.student_zone(school:,
academic_year:).type.to_s.capitalize
end
student_zone || "N/A"
end
def self.teacher_score(row:)
row in [response_rate, measure, school, academic_year]
teacher_score = measure.teacher_score(school:, academic_year:).average if response_rate.meets_teacher_threshold?
teacher_score || "N/A"
end
def self.teacher_zone(row:)
row in [response_rate, measure, school, academic_year]
if response_rate.meets_teacher_threshold?
teacher_zone = measure.teacher_zone(school:, academic_year:).type.to_s.capitalize
end
teacher_zone || "N/A"
end
def self.admin_score(row:)
row in [response_rate, measure, school, academic_year]
admin_score = measure.admin_score(school:, academic_year:).average
admin_score = "N/A" unless admin_score.present? && admin_score >= 0
admin_score
end
def self.admin_zone(row:)
row in [response_rate, measure, school, academic_year]
tmp_zone = measure.admin_zone(school:, academic_year:).type
tmp_zone == :insufficient_data ? "N/A" : tmp_zone.to_s.capitalize
end
end
end