generated from DFE-Digital/govuk-rails-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CPDLP-3933] Importers::CreateMentorCallOffContract service
- Loading branch information
Showing
8 changed files
with
289 additions
and
5 deletions.
There are no files selected for viewing
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
108 changes: 108 additions & 0 deletions
108
app/services/importers/create_mentor_call_off_contract.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,108 @@ | ||
# frozen_string_literal: true | ||
|
||
require "csv" | ||
|
||
module Importers | ||
class CreateMentorCallOffContract | ||
def call | ||
logger.info "CreateMentorCallOffContract: Started!" | ||
|
||
if path_to_csv.present? | ||
create_mentor_call_off_contract_from_csv | ||
else | ||
create_default_mentor_call_off_contracts | ||
end | ||
|
||
logger.info "CreateMentorCallOffContract: Finished!" | ||
end | ||
|
||
private | ||
|
||
attr_reader :path_to_csv, :logger | ||
|
||
def initialize(path_to_csv: nil, logger: Rails.logger) | ||
@path_to_csv = path_to_csv | ||
@logger = logger | ||
end | ||
|
||
def create_default_mentor_call_off_contracts | ||
raise "Do not seed default Mentor Call Off Contracts in Production!" if Rails.env.production? | ||
|
||
LeadProvider.find_each do |lead_provider| | ||
[cohort_current, cohort_previous, cohort_next].each do |cohort| | ||
create_mentor_call_off_contract(lead_provider:, cohort:, contract_data: example_contract_data) | ||
end | ||
end | ||
end | ||
|
||
def create_mentor_call_off_contract_from_csv | ||
check_headers! | ||
|
||
ActiveRecord::Base.transaction do | ||
rows.each do |row| | ||
cohort = Cohort.find_by!(start_year: row["cohort-start-year"].to_i) | ||
lead_provider = LeadProvider.joins(:cohorts).find_by!(name: row["lead-provider-name"], cohorts: { start_year: row["cohort-start-year"].to_i }) | ||
|
||
mentor_call_off_contract = MentorCallOffContract.find_by( | ||
lead_provider:, | ||
cohort:, | ||
) | ||
|
||
next if mentor_call_off_contract | ||
|
||
contract_data = build_contract_data(row) | ||
create_mentor_call_off_contract(lead_provider:, cohort:, contract_data:) | ||
end | ||
end | ||
end | ||
|
||
def create_mentor_call_off_contract(lead_provider:, cohort:, contract_data:) | ||
logger.info "CreateMentorCallOffContract: Adding Mentor Call Off Contract for Lead Provider: #{lead_provider.name} in cohort: #{cohort.start_year}" | ||
|
||
MentorCallOffContract.create!( | ||
lead_provider:, | ||
cohort:, | ||
recruitment_target: contract_data[:recruitment_target], | ||
payment_per_participant: contract_data[:payment_per_participant], | ||
) | ||
|
||
logger.info "CreateMentorCallOffContract: Added Mentor Call Off Contract for Lead Provider: #{lead_provider.name} in cohort: #{cohort.start_year} successfully!" | ||
end | ||
|
||
def check_headers! | ||
unless %w[lead-provider-name cohort-start-year recruitment-target payment-per-participant].all? { |header| rows.headers.include?(header) } | ||
raise NameError, "Invalid headers" | ||
end | ||
end | ||
|
||
def rows | ||
@rows ||= CSV.read(path_to_csv, headers: true) | ||
end | ||
|
||
def cohort_current | ||
@cohort_current ||= Cohort.current || FactoryBot.create(:cohort, :current) | ||
end | ||
|
||
def cohort_previous | ||
@cohort_previous ||= Cohort.previous || FactoryBot.create(:cohort, :previous) | ||
end | ||
|
||
def cohort_next | ||
@cohort_next ||= Cohort.next || FactoryBot.create(:cohort, :next) | ||
end | ||
|
||
def example_contract_data | ||
@example_contract_data ||= { | ||
recruitment_target: 4500, | ||
payment_per_participant: 1000.0, | ||
} | ||
end | ||
|
||
def build_contract_data(row) | ||
{ | ||
recruitment_target: row["recruitment-target"], | ||
payment_per_participant: row["payment-per-participant"], | ||
} | ||
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
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 |
---|---|---|
@@ -1,3 +1,4 @@ | ||
# frozen_string_literal: true | ||
|
||
Importers::CreateCallOffContract.new.call | ||
Importers::CreateMentorCallOffContract.new.call |
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 |
---|---|---|
|
@@ -7,6 +7,6 @@ | |
|
||
recruitment_target { 6000 } | ||
payment_per_participant { 1000.0 } | ||
version { "0.0.1" } | ||
version { "1.0" } | ||
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
147 changes: 147 additions & 0 deletions
147
spec/services/importers/create_mentor_call_off_contract_spec.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,147 @@ | ||
# frozen_string_literal: true | ||
|
||
require "tempfile" | ||
|
||
RSpec.describe Importers::CreateMentorCallOffContract do | ||
let(:csv) { Tempfile.new("data.csv") } | ||
let(:path_to_csv) { csv.path } | ||
|
||
subject(:importer) { described_class.new(path_to_csv:) } | ||
|
||
describe "#call" do | ||
context "when no csv given" do | ||
let(:path_to_csv) {} | ||
let!(:lead_provider_1) { create(:lead_provider, name: "Penguin Institute") } | ||
let!(:lead_provider_2) { create(:lead_provider, name: "Apples") } | ||
|
||
it "creates seed mentor call off contracts for all lead providers in three cohorts" do | ||
expect { importer.call }.to change(MentorCallOffContract, :count).by(6) | ||
end | ||
|
||
context "when in production env" do | ||
before do | ||
allow(Rails).to receive(:env).and_return ActiveSupport::EnvironmentInquirer.new("production") | ||
end | ||
|
||
it "raises an error and does not create records" do | ||
expect { importer.call }.to raise_error(RuntimeError, /do not seed default mentor call off contracts in production/i) | ||
expect(MentorCallOffContract.count).to be_zero | ||
end | ||
end | ||
end | ||
|
||
context "when csv given" do | ||
context "when csv headers invalid" do | ||
before do | ||
csv.write "some-other-column,cohort-start-year" | ||
csv.write "\n" | ||
csv.write "Arctic Wolf Institute,2021" | ||
csv.write "\n" | ||
csv.close | ||
end | ||
|
||
it "raises an error" do | ||
expect { importer.call }.to raise_error(NameError) | ||
end | ||
end | ||
|
||
context "when lead provider does not exist" do | ||
let!(:cohort_2021) { create(:cohort, start_year: 2021) } | ||
before do | ||
csv.write "lead-provider-name,cohort-start-year,recruitment-target,payment-per-participant" | ||
csv.write "\n" | ||
csv.write "Aardvark Institute,2021,9999,333.0" | ||
csv.write "\n" | ||
csv.close | ||
end | ||
|
||
it "raises an error" do | ||
expect { importer.call }.to raise_error(ActiveRecord::RecordNotFound) | ||
end | ||
end | ||
|
||
context "when cohort does not exist" do | ||
let(:year_without_cohort) { Cohort.ordered_by_start_year.last.start_year + 2000 } | ||
let!(:lead_provider) { create(:lead_provider, name: "Koala Institute") } | ||
before do | ||
csv.write "lead-provider-name,cohort-start-year,recruitment-target,payment-per-participant" | ||
csv.write "\n" | ||
csv.write "#{lead_provider.name},#{year_without_cohort},2021,9999,333.0" | ||
csv.write "\n" | ||
csv.close | ||
end | ||
|
||
it "raises an error" do | ||
expect { importer.call }.to raise_error(ActiveRecord::RecordNotFound) | ||
end | ||
end | ||
|
||
context "when lead provider does not belong in supplied cohort" do | ||
let!(:lead_provider) { create(:lead_provider, name: "Kangaroo Institute", cohorts: []) } | ||
let!(:cohort) { create :cohort } | ||
before do | ||
csv.write "lead-provider-name,cohort-start-year,recruitment-target,payment-per-participant" | ||
csv.write "\n" | ||
csv.write "#{lead_provider.name},#{cohort.start_year},9999,333.0" | ||
csv.write "\n" | ||
csv.close | ||
end | ||
|
||
it "raises an error" do | ||
expect { importer.call }.to raise_error(ActiveRecord::RecordNotFound) | ||
end | ||
end | ||
|
||
context "when the lead provider has an existing mentor call off contract in the cohort" do | ||
let!(:cohort) { create :seed_cohort } | ||
let!(:lead_provider) { create(:lead_provider, name: "Whale Institute", cohorts: [cohort]) } | ||
let!(:mentor_call_off_contract) { create(:mentor_call_off_contract, cohort:, lead_provider:) } | ||
before do | ||
csv.write "lead-provider-name,cohort-start-year,recruitment-target,payment-per-participant" | ||
csv.write "\n" | ||
csv.write "#{lead_provider.name},#{cohort.start_year},9999,333.0" | ||
csv.write "\n" | ||
csv.close | ||
end | ||
|
||
it "does not create a new call off contract" do | ||
expect { importer.call }.to not_change(MentorCallOffContract, :count) | ||
end | ||
|
||
it "does not create participant bands" do | ||
expect { importer.call }.to not_change(ParticipantBand, :count) | ||
end | ||
end | ||
|
||
context "when no mentor call off contract exists for lead provider" do | ||
let!(:cohort) { create :cohort } | ||
let!(:lead_provider) { create(:lead_provider, name: "Butterfly Institute", cohorts: [cohort]) } | ||
before do | ||
csv.write "lead-provider-name,cohort-start-year,recruitment-target,payment-per-participant" | ||
csv.write "\n" | ||
csv.write "#{lead_provider.name},#{cohort.start_year},9999,333.0" | ||
csv.write "\n" | ||
csv.close | ||
end | ||
|
||
it "creates a new mentor call off contract" do | ||
expect { importer.call }.to change(MentorCallOffContract, :count).by(1) | ||
end | ||
|
||
it "sets the mentor call off contract version" do | ||
importer.call | ||
expect(lead_provider.mentor_call_off_contracts.first.version).to eq("0.0.1") | ||
end | ||
|
||
it "sets the correct values on the mentor call off contract" do | ||
importer.call | ||
expect(lead_provider.mentor_call_off_contracts.first).to have_attributes( | ||
cohort:, | ||
recruitment_target: 9999, | ||
payment_per_participant: 333.0, | ||
) | ||
end | ||
end | ||
end | ||
end | ||
end |