-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
305 additions
and
1 deletion.
There are no files selected for viewing
25 changes: 25 additions & 0 deletions
25
app/controllers/admin/early_years_data_uploads_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
module Admin | ||
class EarlyYearsDataUploadsController < BaseAdminController | ||
before_action :ensure_service_operator | ||
|
||
def new | ||
end | ||
|
||
def create | ||
file = params[:file] | ||
@importer = EarlyYearsDataImporter.new(file) | ||
|
||
if @importer.errors.any? | ||
render :new | ||
else | ||
file_upload = FileUpload.create(uploaded_by: admin_user, body: File.read(file)) | ||
ImportEarlyYearsDataJob.perform_later(file_upload.id) | ||
|
||
redirect_to admin_claims_path, notice: "EY file uploaded and queued to be imported" | ||
end | ||
rescue => e | ||
Rollbar.error(e) | ||
redirect_to new_admin_early_years_data_upload_path, alert: "There was a problem, please try again" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
class ImportEarlyYearsDataJob < FileImporterJob | ||
import_with EarlyYearsDataImporter do | ||
Rails.logger.info "EY data imported" | ||
end | ||
rescue_with -> { EarlyYearsData.delete_all } | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
class EarlyYearsData < ApplicationRecord | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
class EarlyYearsDataImporter < CsvImporter::Base | ||
import_options( | ||
target_data_model: EarlyYearsData, | ||
transform_rows_with: :row_to_hash, | ||
skip_row_if: :skip_row_conditions?, | ||
mandatory_headers: [ | ||
"Nursery Name", | ||
"EYURN / Ofsted URN", | ||
"LA Code", | ||
"Nursery Address", | ||
"Primary Key Contact Email Address", | ||
"Secondary Contact Email Address (Optional)" | ||
] | ||
) | ||
|
||
private | ||
|
||
def skip_row_conditions?(row) | ||
row.fetch("EYURN / Ofsted URN").blank? || row.fetch("Primary Key Contact Email Address").blank? | ||
end | ||
|
||
def row_to_hash(row) | ||
{ | ||
nursery_name: row.fetch("Nursery Name"), | ||
urn: row.fetch("EYURN / Ofsted URN"), | ||
local_authority_id: LocalAuthority.find_by(code: row.fetch("LA Code")).try(:id), | ||
nursery_address: row.fetch("Nursery Address"), | ||
primary_key_contact_email_address: row.fetch("Primary Key Contact Email Address"), | ||
secondary_contact_email_address: row.fetch("Secondary Contact Email Address (Optional)") | ||
} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<div class="govuk-grid-row"> | ||
<div class="govuk-grid-column-two-thirds"> | ||
<h1 class="govuk-heading-xl"> | ||
Upload Early Years data | ||
</h1> | ||
|
||
<p class="govuk-body">You are uploading a list of eligible nurseries and whitelisted email addresses for the EY Policy.</p> | ||
|
||
<p class="govuk-body"> | ||
Before uploading please note the following: | ||
</p> | ||
|
||
<ul class="govuk-list govuk-list--bullet"> | ||
<li>All previously uploaded EY data will be wiped.</li> | ||
<li>Previously uploaded data will remain wiped if there are any errors processing the uploaded file.</li> | ||
<li>You can wipe all data by uploading a CSV file with just the header row and no data rows.</li> | ||
</ul> | ||
|
||
<%= form_with url: admin_early_years_data_uploads_path, multipart: true do |f| %> | ||
<div class="govuk-form-group"> | ||
<%= f.label "file", "Upload a CSV file", class: "govuk-label" %> | ||
|
||
<% @importer && @importer.errors.each do |error| %> | ||
<span class="govuk-error-message"> | ||
<span class="govuk-visually-hidden">Error:</span> <%= error %> | ||
</span> | ||
<% end %> | ||
|
||
<%= f.file_field "file", class: "govuk-file-upload" %> | ||
</div> | ||
<%= f.submit "Upload", class: "govuk-button", data: {module: "govuk-button"} %> | ||
<% end %> | ||
</div> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
class CreateEarlyYearsData < ActiveRecord::Migration[7.0] | ||
def change | ||
create_table :early_years_data, id: :uuid do |t| | ||
t.string :nursery_name | ||
t.string :urn | ||
t.references :local_authority, null: false, foreign_key: true, type: :uuid | ||
t.string :nursery_address | ||
t.string :primary_key_contact_email_address | ||
t.string :secondary_contact_email_address | ||
|
||
t.timestamps | ||
end | ||
add_index :early_years_data, :urn | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
require "rails_helper" | ||
|
||
RSpec.describe ImportEarlyYearsDataJob do | ||
describe "#perform" do | ||
subject(:upload) { described_class.new.perform(file_upload.id) } | ||
let(:file_upload) { create(:file_upload, body: csv) } | ||
let!(:local_authority) { create(:local_authority, code: "101") } | ||
let(:csv) do | ||
<<~CSV | ||
Nursery Name,EYURN / Ofsted URN,LA Code,Nursery Address,Primary Key Contact Email Address,Secondary Contact Email Address (Optional) | ||
Test Nursery,1234567,101,"123 Test Street, Test Town, TE1 5TT",[email protected],[email protected] | ||
Other Nursery,9876543,101,"321 Test Street, Test Town, TE1 5TT",[email protected], | ||
CSV | ||
end | ||
|
||
context "csv data processes successfully" do | ||
it "imports early years data" do | ||
expect { upload }.to change(EarlyYearsData, :count).by(2) | ||
end | ||
|
||
it "deletes the file upload" do | ||
upload | ||
|
||
expect(FileUpload.find_by_id(file_upload.id)).to be_nil | ||
end | ||
|
||
it "associates local authourity correctly" do | ||
upload | ||
|
||
expect(EarlyYearsData.first.nursery_name).to eq("Test Nursery") | ||
expect(EarlyYearsData.first.local_authority).to eq(local_authority) | ||
end | ||
end | ||
|
||
context "csv data encounters an error" do | ||
before do | ||
allow(EarlyYearsData).to receive(:insert_all).and_raise(ActiveRecord::RecordInvalid) | ||
end | ||
|
||
it "does not import early years data" do | ||
expect { upload }.not_to change(EarlyYearsData, :count) | ||
end | ||
|
||
it "keeps the file upload" do | ||
upload | ||
|
||
expect(FileUpload.find_by_id(file_upload.id)).to be_present | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
require "rails_helper" | ||
|
||
RSpec.describe "EY (Early Years) data upload " do | ||
# TODO: Set up EY journeys/check service open as required | ||
let!(:journey_configuration_tslr) { create(:journey_configuration, :student_loans) } | ||
let!(:journey_configuration_ecp_lupp) { create(:journey_configuration, :additional_payments) } | ||
let!(:local_authority) { create(:local_authority, code: "101") } | ||
|
||
before { @signed_in_user = sign_in_as_service_operator } | ||
|
||
describe "#new" do | ||
it "shows the upload form" do | ||
get new_admin_early_years_data_upload_path | ||
expect(response.body).to include("You are uploading a list of eligible nurseries and whitelisted email addresses") | ||
end | ||
end | ||
|
||
describe "#create" do | ||
let(:file) { Rack::Test::UploadedFile.new(StringIO.new(csv), "text/csv", original_filename: "ey_data.csv") } | ||
|
||
context "when an invalid CSV is uploaded" do | ||
let(:csv) { "Malformed CSV File\"," } | ||
|
||
it "displays an error" do | ||
post admin_early_years_data_uploads_path, params: {file: file} | ||
|
||
expect(response.body).to include("The selected file must be a CSV") | ||
end | ||
end | ||
|
||
context "when no CSV file is uploaded" do | ||
it "displays an error" do | ||
post admin_early_years_data_uploads_path | ||
|
||
expect(response.body).to include("Select a file") | ||
end | ||
end | ||
|
||
[DfeSignIn::User::SUPPORT_AGENT_DFE_SIGN_IN_ROLE_CODE, DfeSignIn::User::PAYROLL_OPERATOR_DFE_SIGN_IN_ROLE_CODE].each do |role| | ||
it "returns a unauthorized response for #{role} users" do | ||
sign_in_to_admin_with_role(role) | ||
|
||
post admin_early_years_data_uploads_path | ||
|
||
expect(response).to have_http_status(:unauthorized) | ||
end | ||
end | ||
|
||
context "when a valid CSV is uploaded" do | ||
subject(:upload) do | ||
post admin_early_years_data_uploads_path, params: {file: file} | ||
end | ||
|
||
let(:csv) do | ||
<<~CSV | ||
Nursery Name,EYURN / Ofsted URN,LA Code,Nursery Address,Primary Key Contact Email Address,Secondary Contact Email Address (Optional) | ||
#{rows[0].values.join(",")} | ||
#{rows[1].values.join(",")} | ||
CSV | ||
end | ||
|
||
let(:rows) do | ||
[ | ||
{ | ||
nursery_name: "Test Nursery", | ||
urn: "1234567", | ||
local_authority_id: "101", | ||
nursery_address: "123 Test Street, Test Town, TE1 5ST", | ||
primary_key_contact_email_address: "[email protected]", | ||
secondary_contact_email_address: "[email protected]" | ||
}, | ||
{ | ||
nursery_name: "Other Nursery", | ||
urn: "9876543", | ||
local_authority_id: "101", | ||
nursery_address: "321 Test Street, Test Town, TE1 5ST", | ||
primary_key_contact_email_address: "[email protected]", | ||
secondary_contact_email_address: "" | ||
} | ||
] | ||
end | ||
|
||
let(:expected_records) do | ||
rows.map do |row| | ||
expected_row = row.dup | ||
expected_row[:local_authourity] = local_authourity | ||
expected_row.delete :local_authority_id | ||
expected_row | ||
end | ||
end | ||
|
||
it "enqueues a job to import the file asynchronously" do | ||
expect { upload }.to have_enqueued_job(ImportEarlyYearsDataJob) | ||
end | ||
|
||
it "parses the rows and saves them as early years data records" do | ||
aggregate_failures do | ||
expect { perform_enqueued_jobs { upload } }.to change(EarlyYearsData, :count).by(2) | ||
expect(EarlyYearsData.find(urn: "1234567")).to have_attributes(expected_records[0]) | ||
expect(EarlyYearsData.find(urn: "9876543")).to have_attributes(expected_records[1]) | ||
end | ||
end | ||
|
||
shared_examples :no_upload do | ||
it "does not upload the rows" do | ||
expect { perform_enqueued_jobs { upload } }.not_to change(EarlyYearsData, :count) | ||
end | ||
end | ||
|
||
context "with rows with blank 'URN'" do | ||
let(:rows) { super().map { |row| row.merge(urn: "") } } | ||
|
||
include_examples :no_upload | ||
end | ||
|
||
context "with rows with invalid primary email" do | ||
let(:rows) { super().map { |row| row.merge(primary_key_contact_email_address: "") } } | ||
|
||
include_examples :no_upload | ||
end | ||
end | ||
end | ||
end |