diff --git a/app/services/staffing_loader.rb b/app/services/staffing_loader.rb new file mode 100644 index 00000000..b2d126d7 --- /dev/null +++ b/app/services/staffing_loader.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +# TODO +require 'csv' + +class StaffingLoader + def self.load_data(filepath:) + schools = [] + respondents = [] + CSV.parse(File.read(filepath), headers: true) do |row| + row = StaffingRowValues.new(row:) + next unless row.school.present? && row.academic_year.present? + + schools << row.school + + respondents << create_staffing_entry(row:) + end + + Respondent.import respondents, batch_size: 1000, on_duplicate_key_update: [:total_teachers] + Respondent.where.not(school: schools).destroy_all + end + + def self.clone_previous_year_data + years = AcademicYear.order(:range).last(2) + previous_year = years.first + current_year = years.last + respondents = [] + School.all.each do |school| + Respondent.where(school:, academic_year: previous_year).each do |respondent| + current_respondent = Respondent.find_or_initialize_by(school:, academic_year: current_year) + current_respondent.total_teachers = respondent.total_teachers + respondents << current_respondent + end + end + Respondent.import respondents, batch_size: 1000, on_duplicate_key_update: [:total_teachers] + end + + private + + def self.create_staffing_entry(row:) + respondent = Respondent.find_or_initialize_by(school: row.school, academic_year: row.academic_year) + respondent.total_teachers = row.fte_count + respondent + end + + private_class_method :create_staffing_entry +end + +class StaffingRowValues + attr_reader :row + + def initialize(row:) + @row = row + end + + def school + @school ||= begin + dese_id = row['DESE ID'].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 fte_count + row['FTE Count'] + end +end diff --git a/spec/services/staffing_loader_spec.rb b/spec/services/staffing_loader_spec.rb new file mode 100644 index 00000000..cea86417 --- /dev/null +++ b/spec/services/staffing_loader_spec.rb @@ -0,0 +1,49 @@ +require 'rails_helper' + +describe StaffingLoader do + let(:path_to_staffing_data) { Rails.root.join('spec', 'fixtures', 'sample_staffing_data.csv') } + let(:ay_2022_23) { create(:academic_year, range: '2022-23') } + let(:ay_2021_22) { create(:academic_year, range: '2021-22') } + 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 + ay_2021_22 + attleboro + beachmont + winchester + StaffingLoader.load_data filepath: path_to_staffing_data + StaffingLoader.clone_previous_year_data + end + + after :each do + DatabaseCleaner.clean + end + + context 'self.load_data' do + it 'loads the correct staffing numbers' do + academic_year = ay_2021_22 + expect(Respondent.find_by(school: attleboro, academic_year:).total_teachers).to eq 197.5 + + expect(Respondent.find_by(school: beachmont, academic_year:).total_teachers).to eq 56.4 + + expect(Respondent.find_by(school: winchester, academic_year:).total_teachers).to eq 149.8 + end + + context 'when the staffing data is missing a school' do + after :each do + DatabaseCleaner.clean + end + it 'fills in empty staffing numbers with the previous years data' do + academic_year = ay_2022_23 + expect(Respondent.find_by(school: attleboro, academic_year:).total_teachers).to eq 197.5 + + expect(Respondent.find_by(school: beachmont, academic_year:).total_teachers).to eq 56.4 + + expect(Respondent.find_by(school: winchester, academic_year:).total_teachers).to eq 149.8 + end + end + end +end