Skip to content

Commit

Permalink
Updating contract data, fixes 2350 data request (#2066)
Browse files Browse the repository at this point in the history
  • Loading branch information
slawosz authored Dec 11, 2024
1 parent cfb54cf commit b19ea73
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 0 deletions.
16 changes: 16 additions & 0 deletions app/models/contract_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,20 @@ class ContractTemplate < ApplicationRecord
greater_than: 0,
}
validates :ecf_id, uniqueness: { case_sensitive: false }, allow_nil: true

def new_from_existing(attributes_to_override)
new_attributes = {
special_course: special_course,
per_participant: per_participant,
output_payment_percentage: output_payment_percentage,
number_of_payment_periods: number_of_payment_periods,
service_fee_percentage: service_fee_percentage,
service_fee_installments: service_fee_installments,
recruitment_target: recruitment_target,
monthly_service_fee: monthly_service_fee,
targeted_delivery_funding_per_participant: targeted_delivery_funding_per_participant,
}.merge(attributes_to_override)

ContractTemplate.new(new_attributes)
end
end
30 changes: 30 additions & 0 deletions app/services/one_off/update_contracts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module OneOff
class UpdateContracts
def self.call(year:, month:, cohort_year:, csv_path:)
csv_file = CSV.read(csv_path, headers: true)

ActiveRecord::Base.transaction do
csv_file.each do |row|
lead_provider = LeadProvider.find_by!(name: row["provider_name"])
cohort = Cohort.find_by!(start_year: cohort_year)
course = Course.find_by!(identifier: row["course_identifier"])

statements = Statement.where(year:, month:, cohort: cohort, lead_provider: lead_provider)
raise "There should be only one statement present (#{row.to_h})" if statements.count != 1

contracts = statements.first.contracts.where(course: course)
raise "There should be only one contract present (#{row.to_h})" if contracts.count != 1

contract = contracts.first
old_template = contract.contract_template
new_template = old_template.new_from_existing(per_participant: row["per_participant"])
new_template.save!

contract.contract_template = new_template
contract.save!
Rails.logger.info("[UpdateContract] Contract #{contract.id} got template updated: #{old_template.id} to #{new_template.id}")
end
end
end
end
end
6 changes: 6 additions & 0 deletions lib/tasks/one_off/update_contracts_2350.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace :one_off do
desc "One off task for ticket 2350 to update contracts"
task :update_contracts, %i[file_path] => :environment do |_t, args|
OneOff::UpdateContracts.call(year: 2024, month: 12, cohort_year: 2024, csv_path: args[:file_path])
end
end
19 changes: 19 additions & 0 deletions spec/models/contract_template_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,23 @@
it { is_expected.to validate_numericality_of(:recruitment_target).only_integer.is_greater_than(0).with_message("Must be an integer greater than zero") }
it { is_expected.to validate_uniqueness_of(:ecf_id).case_insensitive.with_message("ECF ID must be unique").allow_nil }
end

describe "#new_from_existing" do
let(:contract_template) { create(:contract_template, per_participant: 123.0) }

let(:new_contract_template) { contract_template.new_from_existing(per_participant: 321.0) }

it "is not persisted" do
expect(new_contract_template).not_to be_persisted
end

it "overrides attributes" do
expect(new_contract_template.per_participant).to eq(321.0)
end

it "is copying attributes if not specified" do
new_attributes = contract_template.new_from_existing({})
expect(new_attributes.attributes.except("created_at", "updated_at", "id", "ecf_id")).to eq(contract_template.attributes.except("created_at", "updated_at", "id", "ecf_id"))
end
end
end
94 changes: 94 additions & 0 deletions spec/services/one_off/update_contracts_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
require "rails_helper"

RSpec.describe OneOff::UpdateContracts do
describe ".call" do
let(:year) { 2024 }
let(:month) { 12 }
let(:cohort_year) { 2024 }
let(:csv_file) { Tempfile.new }
let(:csv_path) { csv_file.path }
let(:csv_content) do
<<~CSV
provider_name,course_identifier,per_participant
Provider 1,#{Course::NPQ_SENCO},1000
Provider 2,#{Course::NPQ_HEADSHIP},2000
CSV
end

let(:lead_provider_1) { create(:lead_provider, name: "Provider 1") }
let(:lead_provider_2) { create(:lead_provider, name: "Provider 2") }
let(:cohort) { create(:cohort, start_year: cohort_year) }
let(:course_1) { create(:course, :senco) }
let(:course_2) { create(:course, :headship) }
let(:statement_1) { create(:statement, year: year, month: month, cohort: cohort, lead_provider: lead_provider_1) }
let(:statement_2) { create(:statement, year: year, month: month, cohort: cohort, lead_provider: lead_provider_2) }
let(:contract_template_1) { create(:contract_template, per_participant: 100) }
let(:contract_template_2) { create(:contract_template, per_participant: 200) }
let!(:contract_1) { create(:contract, contract_template: contract_template_1, statement: statement_1, course: course_1) }
let!(:contract_2) { create(:contract, contract_template: contract_template_2, statement: statement_2, course: course_2) }

before do
csv_file.write(csv_content)
csv_file.rewind
end

context "when operation is successful" do
it "changes the contract templates" do
OneOff::UpdateContracts.call(year: 2024, month: 12, cohort_year: 2024, csv_path:)

expect(contract_1.reload.contract_template).not_to eq(contract_template_1)
expect(contract_2.reload.contract_template).not_to eq(contract_template_2)

expect(contract_1.reload.contract_template.per_participant).to eq(1000.0)
expect(contract_2.reload.contract_template.per_participant).to eq(2000.0)
end

describe "logs" do
let(:csv_content) do
<<~CSV
provider_name,course_identifier,per_participant
Provider 1,#{Course::NPQ_SENCO},1000
CSV
end

let(:expected_message) do
from_id = contract_template_1.id
to_id = contract_1.reload.contract_template.id

"[UpdateContract] Contract #{contract_1.id} got template updated: #{from_id} to #{to_id}"
end

it "has proper output" do
allow(Rails.logger).to receive(:info)

OneOff::UpdateContracts.call(year: 2024, month: 12, cohort_year: 2024, csv_path:)

expect(Rails.logger)
.to have_received(:info).with(expected_message)
end
end
end

context "when record is missing from the file" do
let(:csv_content) do
<<~CSV
provider_name,course_identifier,per_participant
Provider 1,#{Course::NPQ_SENCO},1000
Provider 2,#{Course::NPQ_HEADSHIP},2000
Provider 3,#{Course::NPQ_HEADSHIP},2000
CSV
end

it "makes the whole process unsuccessful" do
expect(contract_1.reload.contract_template.per_participant).not_to eq(1000.0)
expect(contract_2.reload.contract_template.per_participant).not_to eq(2000.0)
end

it "raises the exception" do
expect {
OneOff::UpdateContracts.call(year: 2024, month: 12, cohort_year: 2024, csv_path:)
}.to raise_error(ActiveRecord::RecordNotFound)
end
end
end
end

0 comments on commit b19ea73

Please sign in to comment.