Skip to content

Commit

Permalink
Merge pull request #5442 from DFE-Digital/3933-add-mentor-call-off-co…
Browse files Browse the repository at this point in the history
…ntract-to-ecf-2

[CPDLP-3933] Add Mentor call off contract to ECF
  • Loading branch information
mooktakim authored Jan 17, 2025
2 parents c0df760 + 2b4fb47 commit c8811d2
Show file tree
Hide file tree
Showing 18 changed files with 368 additions and 8 deletions.
8 changes: 8 additions & 0 deletions app/models/finance/statement/ecf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ def contract
)
end

def mentor_contract
MentorCallOffContract.find_by!(
version: contract_version,
cohort:,
lead_provider:,
)
end

def payable!
update!(type: "Finance::Statement::ECF::Payable")
end
Expand Down
1 change: 1 addition & 0 deletions app/models/lead_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class LeadProvider < ApplicationRecord
has_many :partnership_csv_uploads
has_many :lead_provider_api_tokens
has_one :call_off_contract
has_many :mentor_call_off_contracts

has_many :statements, through: :cpd_lead_provider, class_name: "Finance::Statement::ECF", source: :ecf_statements
validates :name, presence: { message: "Enter a name" }
Expand Down
6 changes: 6 additions & 0 deletions app/models/mentor_call_off_contract.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

class MentorCallOffContract < ApplicationRecord
belongs_to :lead_provider
belongs_to :cohort
end
108 changes: 108 additions & 0 deletions app/services/importers/create_mentor_call_off_contract.rb
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
8 changes: 6 additions & 2 deletions app/services/importers/create_new_ecf_cohort.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ def call

private

attr_reader :cohort_csv, :cohort_lead_provider_csv, :contract_csv, :schedule_csv, :statement_csv, :logger
attr_reader :cohort_csv, :cohort_lead_provider_csv, :contract_csv, :mentor_contract_csv, :schedule_csv, :statement_csv, :logger

def initialize(cohort_csv:, cohort_lead_provider_csv:, contract_csv:, schedule_csv:, statement_csv:, logger: Rails.logger)
def initialize(cohort_csv:, cohort_lead_provider_csv:, contract_csv:, mentor_contract_csv:, schedule_csv:, statement_csv:, logger: Rails.logger)
@cohort_csv = cohort_csv
@cohort_lead_provider_csv = cohort_lead_provider_csv
@contract_csv = contract_csv
@mentor_contract_csv = mentor_contract_csv
@schedule_csv = schedule_csv
@statement_csv = statement_csv
@logger = logger
Expand All @@ -39,6 +40,9 @@ def run_ecf_cohort_scripts
logger.info "CreateNewECFCohort: Running CreateCallOffContract with: '#{contract_csv}'"
CreateCallOffContract.new(path_to_csv: contract_csv).call

logger.info "CreateNewECFCohort: Running CreateMentorCallOffContract with: '#{mentor_contract_csv}'"
CreateMentorCallOffContract.new(path_to_csv: mentor_contract_csv).call

logger.info "CreateNewECFCohort: Running CreateSchedule with: '#{schedule_csv}'"
CreateSchedule.new(path_to_csv: schedule_csv).call

Expand Down
9 changes: 9 additions & 0 deletions config/analytics_blocklist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,15 @@
- revised_target
- cohort_id
- monthly_service_fee
:mentor_call_off_contracts:
- id
- lead_provider_id
- cohort_id
- version
- recruitment_target
- payment_per_participant
- created_at
- updated_at
:appropriate_body_profiles:
- id
- user_id
Expand Down
1 change: 1 addition & 0 deletions db/legacy_seeds/test_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -598,4 +598,5 @@ def create_participant_with_eligibility(urn, name, participant_class, options =
end

Importers::CreateCallOffContract.new.call
Importers::CreateMentorCallOffContract.new.call
Importers::CreateStatement.new(path_to_csv: Rails.root.join("db/data/statements/statements.csv")).call
16 changes: 16 additions & 0 deletions db/migrate/20250114144917_create_mentor_call_off_contracts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

class CreateMentorCallOffContracts < ActiveRecord::Migration[7.1]
def change
create_table :mentor_call_off_contracts do |t|
t.belongs_to :lead_provider, null: false, foreign_key: true, type: :uuid, index: true
t.belongs_to :cohort, null: false, foreign_key: true, type: :uuid, index: true

t.string :version, null: false, default: "0.0.1"
t.integer :recruitment_target
t.decimal :payment_per_participant, default: 1000.00, null: false

t.timestamps
end
end
end
1 change: 1 addition & 0 deletions db/new_seeds/base/add_contracts.rb
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
16 changes: 15 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2025_01_10_125608) do
ActiveRecord::Schema[7.1].define(version: 2025_01_14_144917) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "fuzzystrmatch"
Expand Down Expand Up @@ -650,6 +650,18 @@
t.index ["code"], name: "index_local_authority_districts_on_code", unique: true
end

create_table "mentor_call_off_contracts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "lead_provider_id", null: false
t.uuid "cohort_id", null: false
t.string "version", default: "0.0.1", null: false
t.integer "recruitment_target"
t.decimal "payment_per_participant", default: "1000.0", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["cohort_id"], name: "index_mentor_call_off_contracts_on_cohort_id"
t.index ["lead_provider_id"], name: "index_mentor_call_off_contracts_on_lead_provider_id"
end

create_table "milestones", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.text "name", null: false
t.date "milestone_date"
Expand Down Expand Up @@ -1216,6 +1228,8 @@
add_foreign_key "lead_provider_profiles", "lead_providers"
add_foreign_key "lead_provider_profiles", "users"
add_foreign_key "lead_providers", "cpd_lead_providers"
add_foreign_key "mentor_call_off_contracts", "cohorts"
add_foreign_key "mentor_call_off_contracts", "lead_providers"
add_foreign_key "milestones", "schedules"
add_foreign_key "nomination_emails", "partnership_notification_emails"
add_foreign_key "nomination_emails", "schools"
Expand Down
12 changes: 12 additions & 0 deletions spec/factories/mentor_call_off_contracts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

FactoryBot.define do
factory :mentor_call_off_contract do
lead_provider { build(:lead_provider, cpd_lead_provider: build(:cpd_lead_provider)) }
cohort { Cohort.current || create(:cohort, :current) }

recruitment_target { 6000 }
payment_per_participant { 1000.0 }
version { "1.0" }
end
end
2 changes: 2 additions & 0 deletions spec/fixtures/files/importers/mentor_contract_csv_data.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
lead-provider-name,cohort-start-year,recruitment-target,payment-per-participant
Ambition Institute,2026,4600,1000.0
1 change: 1 addition & 0 deletions spec/models/call_off_contract_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

describe "associations" do
it { is_expected.to belong_to(:cohort) }
it { is_expected.to belong_to(:lead_provider) }
it { is_expected.to have_many(:participant_bands) }

it "is expected to have band_a with the lowest minimum value" do
Expand Down
26 changes: 22 additions & 4 deletions spec/models/finance/statement/ecf_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@
require "rails_helper"

RSpec.describe Finance::Statement::ECF do
let(:call_off_contract) { create(:call_off_contract) }
let(:ecf_lead_provider) { create(:lead_provider, call_off_contract:) }
let(:cpd_lead_provider) { create(:cpd_lead_provider, lead_provider: ecf_lead_provider) }
subject { create(:ecf_statement, cpd_lead_provider:) }
let(:cohort) { Cohort.current || create(:cohort, :current) }
let(:cpd_lead_provider) { create(:cpd_lead_provider, :with_lead_provider) }
let(:lead_provider) { cpd_lead_provider.lead_provider }

let(:contract_version) { "0.0.2" }

let!(:call_off_contract) { create(:call_off_contract, cohort:, lead_provider:, version: contract_version) }
let!(:mentor_call_off_contract) { create(:mentor_call_off_contract, cohort:, lead_provider:, version: contract_version) }

subject { create(:ecf_statement, cpd_lead_provider:, cohort:, contract_version:) }

describe "#payable!" do
it "transitions the statement to payable" do
Expand All @@ -15,4 +21,16 @@
}.to change(subject, :type).from("Finance::Statement::ECF").to("Finance::Statement::ECF::Payable")
end
end

describe "#contract" do
it "returns call_off_contract" do
expect(subject.contract).to eq(call_off_contract)
end
end

describe "#mentor_contract" do
it "returns mentor_call_off_contract" do
expect(subject.mentor_contract).to eq(mentor_call_off_contract)
end
end
end
1 change: 1 addition & 0 deletions spec/models/lead_provider_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
it { is_expected.to have_many(:delivery_partners).through(:provider_relationships) }
it { is_expected.to have_many(:partnership_csv_uploads) }
it { is_expected.to have_one(:call_off_contract) }
it { is_expected.to have_many(:mentor_call_off_contracts) }
it { is_expected.to have_many(:statements).through(:cpd_lead_provider).class_name("Finance::Statement::ECF").source(:ecf_statements) }

describe "active_partnerships" do
Expand Down
12 changes: 12 additions & 0 deletions spec/models/mentor_call_off_contract_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe MentorCallOffContract, type: :model do
let(:mentor_call_off_contract) { create(:mentor_call_off_contract) }

describe "associations" do
it { is_expected.to belong_to(:cohort) }
it { is_expected.to belong_to(:lead_provider) }
end
end
Loading

0 comments on commit c8811d2

Please sign in to comment.