From d272e48adcb36dac0ea95067391518dd21c11f65 Mon Sep 17 00:00:00 2001 From: rebuilt Date: Wed, 8 Mar 2023 04:48:25 -0800 Subject: [PATCH] load total students and batch importing records --- app/services/enrollment_loader.rb | 131 ++++++++++++++++++++++++ spec/services/enrollment_loader_spec.rb | 40 ++++++++ 2 files changed, 171 insertions(+) create mode 100644 app/services/enrollment_loader.rb create mode 100644 spec/services/enrollment_loader_spec.rb diff --git a/app/services/enrollment_loader.rb b/app/services/enrollment_loader.rb new file mode 100644 index 00000000..29f11ecd --- /dev/null +++ b/app/services/enrollment_loader.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +require 'csv' + +class EnrollmentLoader + def self.load_data(filepath:) + schools = [] + enrollments = [] + CSV.parse(File.read(filepath), headers: true) do |row| + row = EnrollmentRowValues.new(row:) + + next unless row.school.present? && row.academic_year.present? + + schools << row.school + + enrollments << create_enrollment_entry(row:) + end + + # It's possible that instead of updating all columns on duplicate key, we could just update the student columns and leave total_teachers alone. Right now enrollment data loads before staffing data so it works correctly. + Respondent.import enrollments, batch_size: 1000, + on_duplicate_key_update: %i[pk k one two three four five six seven eight nine ten eleven twelve total_students] + + Respondent.where.not(school: schools).destroy_all + end + + private + + def self.create_enrollment_entry(row:) + respondent = Respondent.find_or_initialize_by(school: row.school, academic_year: row.academic_year) + respondent.pk = row.pk + respondent.k = row.k + respondent.one = row.one + respondent.two = row.two + respondent.three = row.three + respondent.four = row.four + respondent.five = row.five + respondent.six = row.six + respondent.seven = row.seven + respondent.eight = row.eight + respondent.nine = row.nine + respondent.ten = row.ten + respondent.eleven = row.eleven + respondent.twelve = row.twelve + respondent.total_students = row.total_students + respondent + end + + private_class_method :create_enrollment_entry +end + +class EnrollmentRowValues + attr_reader :row + + def initialize(row:) + @row = row + end + + def school + @school ||= begin + dese_id = row['DESE ID'].try(:strip).to_i + School.find_by_dese_id(dese_id) + end + end + + def academic_year + @academic_year ||= begin + year = row['Academic Year'] + AcademicYear.find_by_range(year) + end + end + + def pk + row['PK'] || row['pk'] + end + + def k + row['K'] || row['k'] + end + + def one + row['1'] + end + + def two + row['2'] + end + + def three + row['3'] + end + + def four + row['4'] + end + + def five + row['5'] + end + + def six + row['6'] + end + + def seven + row['7'] + end + + def eight + row['8'] + end + + def nine + row['9'] + end + + def ten + row['10'] + end + + def eleven + row['11'] + end + + def twelve + row['12'] + end + + def total_students + row['Total'].gsub(',', '').to_i + end +end diff --git a/spec/services/enrollment_loader_spec.rb b/spec/services/enrollment_loader_spec.rb new file mode 100644 index 00000000..b947d3ae --- /dev/null +++ b/spec/services/enrollment_loader_spec.rb @@ -0,0 +1,40 @@ +require 'rails_helper' + +describe EnrollmentLoader do + let(:path_to_enrollment_data) { Rails.root.join('spec', 'fixtures', 'sample_enrollment_data.csv') } + let(:ay_2022_23) { create(:academic_year, range: '2022-23') } + + let(:attleboro) { School.find_or_create_by(name: 'Attleboro', dese_id: 160_505) } + let(:beachmont) { School.find_or_create_by(name: 'Beachmont', dese_id: 2_480_013) } + let(:winchester) { School.find_or_create_by(name: 'Winchester', dese_id: 3_440_505) } + before :each do + ay_2022_23 + attleboro + beachmont + winchester + EnrollmentLoader.load_data filepath: path_to_enrollment_data + end + + after :each do + DatabaseCleaner.clean + end + + context 'self.load_data' do + it 'loads the correct enrollment numbers' do + academic_year = ay_2022_23 + expect(Respondent.find_by(school: attleboro, academic_year:).nine).to eq 506 + # expect(Respondent.find_by(school: attleboro, academic_year:).total_students).to eq 1844 + + expect(Respondent.find_by(school: beachmont, academic_year:).pk).to eq 34 + expect(Respondent.find_by(school: beachmont, academic_year:).k).to eq 64 + expect(Respondent.find_by(school: beachmont, academic_year:).one).to eq 58 + expect(Respondent.find_by(school: beachmont, academic_year:).total_students).to eq 336 + + expect(Respondent.find_by(school: winchester, academic_year:).nine).to eq 361 + expect(Respondent.find_by(school: winchester, academic_year:).ten).to eq 331 + expect(Respondent.find_by(school: winchester, academic_year:).eleven).to eq 339 + expect(Respondent.find_by(school: winchester, academic_year:).twelve).to eq 352 + expect(Respondent.find_by(school: winchester, academic_year:).total_students).to eq 1383 + end + end +end