Skip to content

Commit

Permalink
Merge pull request #10201 from DFE-Digital/426-withdrawal-reasons-mig…
Browse files Browse the repository at this point in the history
…rations

426 Part 1 New withdrawal reasons, migrations and tables
  • Loading branch information
elceebee authored Jan 2, 2025
2 parents b9e5112 + bc306cb commit c30f81b
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 1 deletion.
2 changes: 2 additions & 0 deletions app/models/application_choice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class ApplicationChoice < ApplicationRecord

has_many :notes, dependent: :destroy
has_many :interviews, dependent: :destroy
has_many :withdrawal_reasons, dependent: :destroy
has_many :draft_withdrawal_reasons, -> { draft }, class_name: 'WithdrawalReason', dependent: :destroy

has_many :work_experiences, as: :experienceable, class_name: 'ApplicationWorkExperience'
has_many :volunteering_experiences, as: :experienceable, class_name: 'ApplicationVolunteeringExperience'
Expand Down
28 changes: 28 additions & 0 deletions app/models/withdrawal_reason.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class WithdrawalReason < ApplicationRecord
belongs_to :application_choice
validates :reason, presence: true

PERSONAL_CIRCUMSTANCES_KEY = 'personal-circumstances-have-changed'.freeze
CONFIG_PATH = 'config/candidate_withdrawal_reasons.yml'.freeze

enum :status, {
draft: 'draft',
published: 'published',
}

def publish!
update!(status: 'published')
end

def self.selectable_reasons
YAML.load_file(CONFIG_PATH).fetch('candidate-withdrawal-reasons')
end

def self.find_reason_options(reason = '')
if reason.empty?
selectable_reasons
else
selectable_reasons.dig(*reason.split('.'))
end
end
end
8 changes: 8 additions & 0 deletions config/analytics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -508,3 +508,11 @@ shared:
- provider_id
- response_headers
- created_at
:withdrawal_reasons:
- id
- reason
- comment
- application_choice_id
- created_at
- updated_at
- status
36 changes: 36 additions & 0 deletions config/candidate_withdrawal_reasons.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
candidate-withdrawal-reasons:
applying-to-another-provider:
accepted-another-offer: {}
seen-a-course-that-suits-me-better: {}
provider-has-not-replied-to-me: {}
location-is-too-far-away: {}
personal-circumstances-have-changed:
concerns-about-cost-of-doing-course: {}
concerns-about-having-enough-time-to-train: {}
concerns-about-training-with-a-disability-or-health-condition: {}
other: {}
course-no-longer-available: {}
other: {}
change-or-update-application-with-this-provider:
update-my-application-correct-an-error-or-add-information: {}
change-study-pattern: {}
apply-for-a-different-subject-with-the-same-provider: {}
other: {}
apply-in-the-future:
personal-circumstances-have-changed:
concerns-about-cost-of-doing-course: {}
concerns-about-having-enough-time-to-train: {}
concerns-about-training-with-a-disability-or-health-condition: {}
other: {}
gain-more-experience: {}
improve-qualifications: {}
other: {}
do-not-want-to-train-anymore:
personal-circumstances-have-changed:
concerns-about-cost-of-doing-course: {}
concerns-about-having-enough-time-to-train: {}
concerns-about-training-with-a-disability-or-health-condition: {}
other: {}
another-career-path-or-accepted-a-job-offer: {}
other: {}
other: {}
12 changes: 12 additions & 0 deletions db/migrate/20241209145628_create_withdrawal_reasons.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateWithdrawalReasons < ActiveRecord::Migration[8.0]
def change
create_table :withdrawal_reasons do |t|
t.string :reason, index: true
t.text :comment
t.string :status, default: 'draft'
t.references :application_choice, null: false, foreign_key: { on_delete: :cascade }

t.timestamps
end
end
end
14 changes: 13 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[8.0].define(version: 2024_12_05_101639) do
ActiveRecord::Schema[8.0].define(version: 2024_12_09_145628) do
create_sequence "qualifications_public_id_seq", start: 120000

# These are extensions that must be enabled in order to support this database
Expand Down Expand Up @@ -906,6 +906,17 @@
t.index ["name"], name: "index_vendors_on_name", unique: true
end

create_table "withdrawal_reasons", force: :cascade do |t|
t.string "reason"
t.text "comment"
t.string "status", default: "draft"
t.bigint "application_choice_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["application_choice_id"], name: "index_withdrawal_reasons_on_application_choice_id"
t.index ["reason"], name: "index_withdrawal_reasons_on_reason"
end

add_foreign_key "account_recovery_request_codes", "account_recovery_requests", on_delete: :cascade
add_foreign_key "account_recovery_requests", "candidates", on_delete: :cascade
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
Expand Down Expand Up @@ -941,4 +952,5 @@
add_foreign_key "rejection_feedbacks", "application_choices", on_delete: :cascade
add_foreign_key "sites", "providers"
add_foreign_key "vendor_api_tokens", "providers", on_delete: :cascade
add_foreign_key "withdrawal_reasons", "application_choices", on_delete: :cascade
end
Binary file modified docs/domain-model.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions spec/models/application_choice_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
it { is_expected.to have_many(:work_experiences).class_name('ApplicationWorkExperience') }
it { is_expected.to have_many(:volunteering_experiences).class_name('ApplicationVolunteeringExperience') }
it { is_expected.to have_many(:work_history_breaks).class_name('ApplicationWorkHistoryBreak') }
it { is_expected.to have_many(:withdrawal_reasons).dependent(:destroy) }
it { is_expected.to have_many(:draft_withdrawal_reasons).dependent(:destroy) }

describe 'auditing', :with_audited do
it 'creates audit entries' do
Expand Down
90 changes: 90 additions & 0 deletions spec/models/withdrawal_reason_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
require 'rails_helper'

RSpec.describe WithdrawalReason do
describe 'validations' do
it { is_expected.to validate_presence_of(:reason) }
end

describe 'associations' do
it { is_expected.to belong_to(:application_choice) }
end

describe '#selectable_reasons' do
it 'returns a hash of selectable reasons' do
expect(described_class.selectable_reasons).to eq(selectable_reasons)
end
end

describe '#find_reason_options' do
context 'without a reason_id' do
it 'returns all selectable reasons' do
expect(described_class.find_reason_options).to eq(selectable_reasons)
end
end

context 'with primary reason id' do
it 'returns all the reasons under that id' do
expect(
described_class.find_reason_options('applying-to-another-provider'),
).to eq(selectable_reasons['applying-to-another-provider'])
end
end

context 'with nested reason id' do
it 'returns all secondary reasons when there are any' do
expect(
described_class.find_reason_options('applying-to-another-provider.personal-circumstances-have-changed'),
).to eq({ 'concerns-about-cost-of-doing-course' => {},
'concerns-about-having-enough-time-to-train' => {},
'concerns-about-training-with-a-disability-or-health-condition' => {},
'other' => {} })
end

it 'returns an empty hash when there are none' do
expect(
described_class.find_reason_options('applying-to-another-provider.location-is-too-far-away'),
).to eq({})
end
end
end

private

def selectable_reasons
{ 'applying-to-another-provider' =>
{ 'accepted-another-offer' => {},
'seen-a-course-that-suits-me-better' => {},
'provider-has-not-replied-to-me' => {},
'location-is-too-far-away' => {},
'personal-circumstances-have-changed' =>
{ 'concerns-about-cost-of-doing-course' => {},
'concerns-about-having-enough-time-to-train' => {},
'concerns-about-training-with-a-disability-or-health-condition' => {},
'other' => {} },
'course-no-longer-available' => {},
'other' => {} },
'change-or-update-application-with-this-provider' =>
{ 'update-my-application-correct-an-error-or-add-information' => {},
'change-study-pattern' => {},
'apply-for-a-different-subject-with-the-same-provider' => {},
'other' => {} },
'apply-in-the-future' =>
{ 'personal-circumstances-have-changed' =>
{ 'concerns-about-cost-of-doing-course' => {},
'concerns-about-having-enough-time-to-train' => {},
'concerns-about-training-with-a-disability-or-health-condition' => {},
'other' => {} },
'gain-more-experience' => {},
'improve-qualifications' => {},
'other' => {} },
'do-not-want-to-train-anymore' =>
{ 'personal-circumstances-have-changed' =>
{ 'concerns-about-cost-of-doing-course' => {},
'concerns-about-having-enough-time-to-train' => {},
'concerns-about-training-with-a-disability-or-health-condition' => {},
'other' => {} },
'another-career-path-or-accepted-a-job-offer' => {},
'other' => {} },
'other' => {} }
end
end

0 comments on commit c30f81b

Please sign in to comment.