Skip to content

Commit

Permalink
Merge pull request #4806 from DFE-Digital/3061-identity-participants-…
Browse files Browse the repository at this point in the history
…for-archiving

Add methods to identify archivable participants
  • Loading branch information
ethax-ross authored May 22, 2024
2 parents f4643e0 + c8a2d7c commit 267a1ef
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 1 deletion.
28 changes: 28 additions & 0 deletions app/models/participant_profile/ecf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,39 @@ def self.eligible_to_change_cohort_and_continue_training(in_cohort_start_year:,
query
end

def self.archivable(for_cohort_start_year:, restrict_to_participant_ids: [])
latest_cohort = Cohort.order(start_year: :desc).first
return none unless for_cohort_start_year <= latest_cohort.start_year - Cohort::OPEN_COHORTS_COUNT

unbillable_states = %i[ineligible voided submitted].freeze

# Find all participants that have no FIP induction records (as finding those with only FIP is more complicated).
not_fip_induction_records = InductionRecord.left_joins(:induction_programme).where.not(induction_programme: { training_programme: :full_induction_programme })
not_fip_induction_records = not_fip_induction_records.where(participant_profile_id: restrict_to_participant_ids) if restrict_to_participant_ids.any?

query = left_joins(:participant_declarations, schedule: :cohort)
# Exclude participants that have any induction records that are not FIP.
.where.not(id: not_fip_induction_records.select(:participant_profile_id))
.where(cohorts: { start_year: for_cohort_start_year })
# Exclude participants that have any billable/submitted declarations, but
# retain participants that have no declarations at all.
.where.not("participant_declarations.id IS NOT NULL AND participant_declarations.state NOT IN (?)", unbillable_states)
.distinct

query = query.where(id: restrict_to_participant_ids) if restrict_to_participant_ids.any?

query
end

# Instance Methods
def eligible_to_change_cohort_and_continue_training?(in_cohort_start_year:)
self.class.eligible_to_change_cohort_and_continue_training(in_cohort_start_year:, restrict_to_participant_ids: [id]).exists?
end

def archivable?(for_cohort_start_year:)
self.class.archivable(for_cohort_start_year:, restrict_to_participant_ids: [id]).exists?
end

def completed_induction?
induction_completion_date.present?
end
Expand Down
8 changes: 8 additions & 0 deletions app/models/participant_profile/ect.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ class ParticipantProfile::ECT < ParticipantProfile::ECF
where(induction_start_date: nil).joins(:ecf_participant_eligibility).merge(ECFParticipantEligibility.waiting_for_induction)
}

def self.archivable(for_cohort_start_year:, restrict_to_participant_ids: [])
latest_induction_start_date = Date.new(for_cohort_start_year, 9, 1)

super(for_cohort_start_year:, restrict_to_participant_ids:)
.where(induction_completion_date: nil)
.where("induction_start_date IS NULL OR induction_start_date < ?", latest_induction_start_date)
end

def ect?
true
end
Expand Down
6 changes: 6 additions & 0 deletions app/models/participant_profile/mentor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ class ParticipantProfile::Mentor < ParticipantProfile::ECF
started_not_completed: "started_not_completed",
}

def self.archivable(for_cohort_start_year:, restrict_to_participant_ids: [])
super(for_cohort_start_year:, restrict_to_participant_ids:)
.where(mentor_completion_date: nil)
.where.not(id: InductionRecord.where.not(mentor_profile_id: nil).select(:mentor_profile_id).distinct)
end

def complete_training!(completion_date:, completion_reason:)
self.mentor_completion_date = completion_date
self.mentor_completion_reason = completion_reason
Expand Down
3 changes: 2 additions & 1 deletion spec/factories/services/mentors/create.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
lead_provider { create(:cpd_lead_provider, :with_lead_provider).lead_provider }
uplifts { [] }
trn { user.teacher_profile&.trn || sprintf("%07i", Random.random_number(9_999_999)) }
cohort { Cohort.current || create(:cohort, :current) }
end

user { create(:user) }
school_cohort { create(:school_cohort, :fip, :with_induction_programme, *uplifts, lead_provider:) }
school_cohort { create(:school_cohort, :fip, :with_induction_programme, *uplifts, lead_provider:, cohort:) }
full_name { user.full_name }
email { user.email }

Expand Down
23 changes: 23 additions & 0 deletions spec/models/participant_profile/ect_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,27 @@
end

include_context "can change cohort and continue training", :ect, :mentor, :induction_completion_date

include_context "can archive participant profile", :mentor, :induction_completion_date do
def create_declaration(attrs = {})
create(:ect_participant_declaration, attrs)
end

def create_profile(attrs = {})
create(:ect_participant_profile, attrs)
end

describe ".archivable" do
subject { described_class.archivable(for_cohort_start_year:) }

it "does not include participants where the induction_start_date is 1/9/<for_cohort_start_year> or later" do
build_profile(cohort: eligible_cohort, induction_start_date: Date.new(for_cohort_start_year, 9, 1))
build_profile(cohort: eligible_cohort, induction_start_date: Date.new(for_cohort_start_year + 1, 3, 1))

eligible_participant = build_profile(cohort: eligible_cohort)

is_expected.to contain_exactly(eligible_participant)
end
end
end
end
24 changes: 24 additions & 0 deletions spec/models/participant_profile/mentor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,28 @@
end

include_context "can change cohort and continue training", :mentor, :ect, :mentor_completion_date

include_context "can archive participant profile", :ect, :mentor_completion_date do
def create_declaration(attrs = {})
create(:mentor_participant_declaration, attrs)
end

def create_profile(attrs = {})
create(:mentor_participant_profile, attrs)
end

describe ".archivable" do
subject { described_class.archivable(for_cohort_start_year:) }

it "does not include participants that have mentees" do
build_profile(cohort: eligible_cohort).tap do |mentor_profile|
create(:induction_record, :ect, mentor_profile:)
end

eligible_participant = build_profile(cohort: eligible_cohort)

is_expected.to contain_exactly(eligible_participant)
end
end
end
end
85 changes: 85 additions & 0 deletions spec/support/shared_examples/archivable_support.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# frozen_string_literal: true

RSpec.shared_examples "can archive participant profile" do |other_participant_type, completed_training_at_attribute|
let(:for_cohort_start_year) { latest_cohort.start_year - Cohort::OPEN_COHORTS_COUNT }
let(:eligible_cohort) { create(:cohort, start_year: for_cohort_start_year) }
let(:latest_cohort) { create(:cohort, :current) }

def build_profile(attrs = {})
create_profile(attrs).tap do |participant_profile|
create(:induction_record, participant_profile:, induction_programme: create(:induction_programme, :fip))
end
end

def build_declaration(attrs = {})
create_declaration(attrs) do |declaration|
participant_profile = declaration.participant_profile
create(:induction_record, participant_profile:, induction_programme: create(:induction_programme, :fip))
end
end

describe ".archivable" do
let(:restrict_to_participant_ids) { [] }
let(:eligible_no_declarations) { build_profile(cohort: eligible_cohort) }
let(:eligible_only_unbillable_declarations) { build_declaration(state: :voided, cohort: eligible_cohort).participant_profile }

before do
# Participant not in an eligible cohort.
build_profile(cohort: latest_cohort)

# Participant with billable declarations.
build_declaration(state: :paid, cohort: eligible_cohort)

# Other participant type.
create("#{other_participant_type}_participant_profile", cohort: eligible_cohort)

# Ineligible due to having the completed_training_at_attribute populated.
build_declaration(state: :ineligible, cohort: eligible_cohort).participant_profile.update!("#{completed_training_at_attribute}": 1.month.ago)

# Participant with CIP induction record.
build_profile(cohort: eligible_cohort).tap do |participant_profile|
create(:induction_record, participant_profile:, induction_programme: create(:induction_programme, :cip))
end
end

subject { described_class.archivable(for_cohort_start_year:, restrict_to_participant_ids:) }

it { is_expected.to contain_exactly(eligible_no_declarations, eligible_only_unbillable_declarations) }

context "when restricted to a set of participant IDs" do
let(:restrict_to_participant_ids) { [eligible_no_declarations.id] }

it { is_expected.to contain_exactly(eligible_no_declarations) }
end
end

describe "archivable?" do
it "returns true if the participant is in an eligible cohort and has no declarations" do
participant_profile = build_profile(cohort: eligible_cohort)
expect(participant_profile).to be_archivable(for_cohort_start_year:)
end

%i[ineligible voided submitted].each do |unbillable_state|
it "returns true if the participant is in an eligible cohort and the participant has only #{unbillable_state} declarations" do
participant_profile = build_declaration(state: unbillable_state, cohort: eligible_cohort).participant_profile
expect(participant_profile).to be_archivable(for_cohort_start_year:)
end
end

it "returns false if the participant is not in an eligible cohort" do
participant_profile = build_profile(cohort: latest_cohort)
expect(participant_profile).not_to be_archivable(for_cohort_start_year:)
end

it "returns false if the participant has billable declarations" do
participant_profile = build_declaration(state: :paid, cohort: eligible_cohort).participant_profile
expect(participant_profile).not_to be_archivable(for_cohort_start_year:)
end

it "returns false if the participant has a CIP induction record" do
participant_profile = build_profile(cohort: latest_cohort)
create(:induction_record, participant_profile:, induction_programme: create(:induction_programme, :cip))
expect(participant_profile).not_to be_archivable(for_cohort_start_year:)
end
end
end

0 comments on commit 267a1ef

Please sign in to comment.