Skip to content

Commit

Permalink
[7827] - Encapsulate Withdrawal (#4826)
Browse files Browse the repository at this point in the history
  • Loading branch information
d-a-v-e authored Nov 25, 2024
1 parent d822133 commit 6bc2f75
Show file tree
Hide file tree
Showing 13 changed files with 208 additions and 8 deletions.
3 changes: 2 additions & 1 deletion app/models/bulk_update/row_error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
#
# Indexes
#
# index_bulk_update_row_errors_on_error_type (error_type)
# idx_on_errored_on_id_errored_on_type_492045ed60 (errored_on_id,errored_on_type)
# index_bulk_update_row_errors_on_error_type (error_type)
#
class BulkUpdate::RowError < ApplicationRecord
belongs_to :errored_on, polymorphic: true
Expand Down
1 change: 1 addition & 0 deletions app/models/trainee.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ class Trainee < ApplicationRecord

has_many :trainee_withdrawal_reasons, inverse_of: :trainee
has_many :withdrawal_reasons, through: :trainee_withdrawal_reasons
has_many :trainee_withdrawals, dependent: :destroy

has_many :potential_duplicate_trainees, dependent: :destroy

Expand Down
32 changes: 32 additions & 0 deletions app/models/trainee_withdrawal.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: trainee_withdrawals
#
# id :bigint not null, primary key
# another_reason :string
# date :date
# discarded_at :datetime
# future_interest :enum
# trigger :enum
# created_at :datetime not null
# updated_at :datetime not null
# trainee_id :bigint not null
#
# Indexes
#
# index_trainee_withdrawals_on_discarded_at (discarded_at)
# index_trainee_withdrawals_on_trainee_id (trainee_id)
#
# Foreign Keys
#
# fk_rails_... (trainee_id => trainees.id)
#
class TraineeWithdrawal < ApplicationRecord
belongs_to :trainee
has_many :trainee_withdrawal_reasons, dependent: :destroy

enum :trigger, { provider: "provider", trainee: "trainee" }, prefix: :triggered_by
enum :future_interest, { yes: "yes", no: "no", unknown: "unknown" }, suffix: true
end
14 changes: 9 additions & 5 deletions app/models/trainee_withdrawal_reason.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,30 @@
#
# Table name: trainee_withdrawal_reasons
#
# id :bigint not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
# trainee_id :bigint not null
# withdrawal_reason_id :bigint not null
# id :bigint not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
# trainee_id :bigint not null
# trainee_withdrawal_id :bigint
# withdrawal_reason_id :bigint not null
#
# Indexes
#
# index_trainee_withdrawal_reasons_on_trainee_id (trainee_id)
# index_trainee_withdrawal_reasons_on_withdrawal_reason_id (withdrawal_reason_id)
# uniq_idx_trainee_withdawal_reasons (trainee_id,withdrawal_reason_id) UNIQUE
# uniq_idx_trainee_withdrawal_id_withdrawal_reason_id (trainee_withdrawal_id,withdrawal_reason_id) UNIQUE
#
# Foreign Keys
#
# fk_rails_... (trainee_id => trainees.id)
# fk_rails_... (trainee_withdrawal_id => trainee_withdrawals.id)
# fk_rails_... (withdrawal_reason_id => withdrawal_reasons.id)
#
class TraineeWithdrawalReason < ApplicationRecord
belongs_to :trainee, touch: true
belongs_to :withdrawal_reason
belongs_to :trainee_withdrawal, optional: true

audited associated_with: :trainee
end
11 changes: 11 additions & 0 deletions config/analytics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,20 @@ shared:
- created_at
- updated_at
- name
:trainee_withdrawals:
- id
- trainee_id
- date
- trigger
- another_reason
- future_interest
- discarded_at
- created_at
- updated_at
:trainee_withdrawal_reasons:
- id
- trainee_id
- withdrawal_reason_id
- trainee_withdrawal_id
- created_at
- updated_at
25 changes: 25 additions & 0 deletions db/data/20241120205446_migrate_withdrawal_data_to_withdrawals.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

class MigrateWithdrawalDataToWithdrawals < ActiveRecord::Migration[7.2]
def up
safety_assured do
execute <<~SQL
WITH new_withdrawals AS (
INSERT INTO trainee_withdrawals (trainee_id, date, created_at, updated_at)
SELECT id, withdraw_date, NOW(), NOW()
FROM trainees
WHERE state = 4
RETURNING trainee_id, id
)
UPDATE trainee_withdrawal_reasons twr
SET trainee_withdrawal_id = nw.id
FROM new_withdrawals nw
WHERE twr.trainee_id = nw.trainee_id;
SQL
end
end

def down
raise ActiveRecord::IrreversibleMigration
end
end
36 changes: 36 additions & 0 deletions db/migrate/20241118160942_create_trainee_withdrawals.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

class CreateTraineeWithdrawals < ActiveRecord::Migration[7.2]
def up
safety_assured {
execute <<-SQL
CREATE TYPE trigger_type AS ENUM ('provider', 'trainee');
CREATE TYPE future_interest_type AS ENUM ('yes', 'no', 'unknown');
SQL
}

create_table :trainee_withdrawals do |t|
t.belongs_to :trainee, null: false, foreign_key: true
t.date :date
t.column :trigger, :trigger_type
t.string :another_reason
t.column :future_interest, :future_interest_type
t.datetime :discarded_at

t.timestamps
end

add_index :trainee_withdrawals, :discarded_at
end

def down
drop_table :trainee_withdrawals

safety_assured {
execute <<-SQL
DROP TYPE trigger_type;
DROP TYPE future_interest_type;
SQL
}
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

class AssociateWithdrawalWithTraineeWithdrawalReason < ActiveRecord::Migration[7.2]
disable_ddl_transaction!

def up
# Add the withdrawal_id column
add_column :trainee_withdrawal_reasons, :trainee_withdrawal_id, :bigint

# Add the foreign key without validation
add_foreign_key :trainee_withdrawal_reasons, :trainee_withdrawals, column: :trainee_withdrawal_id, validate: false

# Add the index concurrently
add_index :trainee_withdrawal_reasons, %i[trainee_withdrawal_id withdrawal_reason_id],
unique: true,
name: "uniq_idx_trainee_withdrawal_id_withdrawal_reason_id",
algorithm: :concurrently
end

def down
# Remove the index
remove_index :trainee_withdrawal_reasons, name: "uniq_idx_trainee_withdrawal_id_withdrawal_reason_id"

# Remove the foreign key
remove_foreign_key :trainee_withdrawal_reasons, column: :trainee_withdrawal_id

# Remove the trainee_withdrawal_id column
remove_column :trainee_withdrawal_reasons, :trainee_withdrawal_id
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class ValidateAssociateWithdrawalWithTraineeWithdrawalReason < ActiveRecord::Migration[7.2]
def change
validate_foreign_key :trainee_withdrawal_reasons, :trainee_withdrawals
end
end
26 changes: 24 additions & 2 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,19 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.2].define(version: 2024_11_14_153414) do
ActiveRecord::Schema[7.2].define(version: 2024_11_20_205445) do
# These are extensions that must be enabled in order to support this database
enable_extension "btree_gist"
enable_extension "citext"
enable_extension "pg_trgm"
enable_extension "pgcrypto"
enable_extension "plpgsql"

# Custom types defined in this database.
# Note that some types may not work with other database engines. Be careful if changing database.
create_enum "future_interest_type", ["yes", "no", "unknown"]
create_enum "trigger_type", ["provider", "trainee"]

create_table "academic_cycles", force: :cascade do |t|
t.date "start_date", null: false
t.date "end_date", null: false
Expand Down Expand Up @@ -669,10 +674,10 @@
t.string "surname16"
t.string "ttcid"
t.string "hesa_committed_at"
t.string "previous_hesa_id"
t.string "application_choice_id"
t.string "itt_start_date"
t.string "trainee_start_date"
t.string "previous_hesa_id"
t.string "provider_trainee_id"
t.string "lead_partner_urn"
t.index ["hesa_id", "rec_id"], name: "index_hesa_students_on_hesa_id_and_rec_id", unique: true
Expand Down Expand Up @@ -867,11 +872,26 @@
t.bigint "withdrawal_reason_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "trainee_withdrawal_id"
t.index ["trainee_id", "withdrawal_reason_id"], name: "uniq_idx_trainee_withdawal_reasons", unique: true
t.index ["trainee_id"], name: "index_trainee_withdrawal_reasons_on_trainee_id"
t.index ["trainee_withdrawal_id", "withdrawal_reason_id"], name: "uniq_idx_trainee_withdrawal_id_withdrawal_reason_id", unique: true
t.index ["withdrawal_reason_id"], name: "index_trainee_withdrawal_reasons_on_withdrawal_reason_id"
end

create_table "trainee_withdrawals", force: :cascade do |t|
t.bigint "trainee_id", null: false
t.date "date"
t.enum "trigger", enum_type: "trigger_type"
t.string "another_reason"
t.enum "future_interest", enum_type: "future_interest_type"
t.datetime "discarded_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["discarded_at"], name: "index_trainee_withdrawals_on_discarded_at"
t.index ["trainee_id"], name: "index_trainee_withdrawals_on_trainee_id"
end

create_table "trainees", force: :cascade do |t|
t.text "first_names"
t.text "last_name"
Expand Down Expand Up @@ -1048,8 +1068,10 @@
add_foreign_key "subject_specialisms", "allocation_subjects"
add_foreign_key "trainee_disabilities", "disabilities"
add_foreign_key "trainee_disabilities", "trainees"
add_foreign_key "trainee_withdrawal_reasons", "trainee_withdrawals"
add_foreign_key "trainee_withdrawal_reasons", "trainees"
add_foreign_key "trainee_withdrawal_reasons", "withdrawal_reasons"
add_foreign_key "trainee_withdrawals", "trainees"
add_foreign_key "trainees", "academic_cycles", column: "end_academic_cycle_id"
add_foreign_key "trainees", "academic_cycles", column: "start_academic_cycle_id"
add_foreign_key "trainees", "allocation_subjects", column: "course_allocation_subject_id"
Expand Down
Binary file modified docs/database-diagram.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions spec/factories/trainee_withdrawals.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

FactoryBot.define do
factory :trainee_withdrawal, class: "TraineeWithdrawal" do
trainee
date { "2024-11-18" }
trigger { :provider }
another_reason { "Not enough coffee" }
future_interest { :yes }
end
end
20 changes: 20 additions & 0 deletions spec/models/trainee_withdrawal_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe TraineeWithdrawal do
describe "associations" do
it { is_expected.to belong_to(:trainee) }
it { is_expected.to have_many(:trainee_withdrawal_reasons).dependent(:destroy) }
end

describe "enums" do
it "defines the correct values for trigger enum" do
expect(described_class.triggers).to eq("provider" => "provider", "trainee" => "trainee")
end

it "defines the correct values for future_interest enum" do
expect(described_class.future_interests).to eq("yes" => "yes", "no" => "no", "unknown" => "unknown")
end
end
end

0 comments on commit 6bc2f75

Please sign in to comment.