Skip to content

Commit

Permalink
feat: adds case contact topics
Browse files Browse the repository at this point in the history
feat: adds case contact topics model
- shoulda matcher validations

feat: adds default topics
- adds default topics in yml file
- adds checks to only allow certain keys

feat: adds tests for case contact methods
- tests generation for casa orgs
- tests creation of dupes

feat: add contact topics seeding

feat: tests for form controller
- case_contact form_controller update step only updates correct values
- case contact controller create step creates default topics from org on
  case contact

feat: adds tests for casa admin
Tests that when a admin creates a casa org the default contact topics are created.
  • Loading branch information
elasticspoon committed Feb 9, 2024
1 parent bb9e9e7 commit 50c304a
Show file tree
Hide file tree
Showing 20 changed files with 411 additions and 51 deletions.
2 changes: 1 addition & 1 deletion app/controllers/all_casa_admins/casa_orgs_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def create
@casa_org = CasaOrg.new(casa_org_params)

if @casa_org.save
@casa_org.generate_contact_types_and_hearing_types
@casa_org.generate_defaults
respond_to do |format|
format.html do
redirect_to all_casa_admins_casa_org_path(@casa_org),
Expand Down
4 changes: 4 additions & 0 deletions app/controllers/case_contacts/form_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ def create_additional_case_contacts(case_contact)
other_expenses_describe: ae.other_expenses_describe
)
end
case_contact.case_contact_topics.each do |cct|
new_case_contact.case_contact_topics << cct.dup
end

new_case_contact.save!
end
end
Expand Down
1 change: 1 addition & 0 deletions app/controllers/case_contacts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def new
end

@case_contact = CaseContact.create(creator: current_user, draft_case_ids: draft_case_ids)
@case_contact.create_court_topics(current_organization)
redirect_to case_contact_form_path(CaseContact::FORM_STEPS.first, case_contact_id: @case_contact.id)
end

Expand Down
5 changes: 4 additions & 1 deletion app/models/casa_org.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CasaOrg < ApplicationRecord
has_many :case_groups, dependent: :destroy
has_one_attached :logo
has_one_attached :court_report_template
has_many :case_contact_topics

encrypts :twilio_account_sid
encrypts :twilio_api_key_sid
Expand Down Expand Up @@ -85,10 +86,12 @@ def set_slug
self.slug = name.parameterize
end

def generate_contact_types_and_hearing_types
# generates default: contact types, hearing types, contact topics
def generate_defaults
ActiveRecord::Base.transaction do
ContactTypeGroup.generate_for_org!(self)
HearingType.generate_for_org!(self)
CaseContactTopic.generate_for_org!(self)
end
end

Expand Down
10 changes: 10 additions & 0 deletions app/models/case_contact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class CaseContact < ApplicationRecord
}, primary_key: :creator_id, foreign_key: :volunteer_id
has_one :supervisor, through: :creator
has_many :followups
has_many :case_contact_topics, dependent: :destroy

# Draft support requires the casa_case to be nil if the contact is in_progress
belongs_to :casa_case, optional: true
Expand Down Expand Up @@ -49,6 +50,7 @@ def active_or_expenses?

accepts_nested_attributes_for :case_contact_contact_type
accepts_nested_attributes_for :casa_case
accepts_nested_attributes_for :case_contact_topics, update_only: true, reject_if: :all_blank

scope :supervisors, ->(supervisor_ids = nil) {
joins(:supervisor_volunteer).where(supervisor_volunteers: {supervisor_id: supervisor_ids}) if supervisor_ids.present?
Expand Down Expand Up @@ -282,6 +284,14 @@ def self.case_hash_from_cases(cases)
contact_made_desc: "Contact made ('yes' first)"
}
end

def create_court_topics(casa_org)
casa_org.case_contact_topics.each do |topic|
case_contact_topics << topic.dup
end

save!
end
end

# == Schema Information
Expand Down
44 changes: 44 additions & 0 deletions app/models/case_contact_topic.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
class CaseContactTopic < ApplicationRecord
CASA_DEFAULT_COURT_TOPICS = Rails.root.join("data", "default_contact_topics.yml")
REQUIRED_ATTRS = %w[title details].freeze

belongs_to :casa_org
belongs_to :case_contact, optional: true

validates :title, :details, presence: true

class << self
def generate_for_org!(casa_org)
default_contact_topics.each do |topic|
filtered_topic = topic.select { |k, _| REQUIRED_ATTRS.include?(k) }
find_or_create_by!(casa_org:, **filtered_topic)
end
end

private

def default_contact_topics
YAML.load_file(CASA_DEFAULT_COURT_TOPICS)
end
end
end

# == Schema Information
#
# Table name: case_contact_topics
#
# id :bigint not null, primary key
# active :boolean default(FALSE)
# answer :string
# details :string
# title :string
# created_at :datetime not null
# updated_at :datetime not null
# casa_org_id :bigint not null
# case_contact_id :bigint
#
# Indexes
#
# index_case_contact_topics_on_casa_org_id (casa_org_id)
# index_case_contact_topics_on_case_contact_id (case_contact_id)
#
3 changes: 2 additions & 1 deletion app/values/case_contact_parameters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ def initialize(params)
:volunteer_address,
draft_case_ids: [],
case_contact_contact_type_attributes: [:contact_type_id],
additional_expenses_attributes: [:id, :other_expense_amount, :other_expenses_describe]
case_contact_topics_attributes: %i[case_contact_topic_id id answer active],
additional_expenses_attributes: %i[id other_expense_amount other_expenses_describe]
)
if params.dig(:case_contact, :duration_minutes)
new_params[:duration_minutes] = convert_duration_minutes(params)
Expand Down
36 changes: 36 additions & 0 deletions data/default_contact_topics.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
- title: "Background information"
details:
"a) When did the family first come into contact with the Department of Social Services or Department of Juvenile Justice – how many times?
b) Tell the history of their involvement with the department and any facts about their life that could help determine the need for placement and/or services.
c) Discuss the child’s history – behavior problems, educational history, medical history, psychological history (any hospitalizations, previous counseling, etc.)
d) If child has been placed previously give a history of the child’s placements (placed with different parents, relatives, DSS, etc)."
- title: "Current situation"
details:
"a) When did the family first come into contact with the Department of Social Services or Department of Juvenile Justice – how many times?
b) Tell the history of their involvement with the department and any facts about their life that could help determine the need for placement and/or services.
c) Discuss the child’s history – behavior problems, educational history, medical history, psychological history (any hospitalizations, previous counseling, etc.)
d) If child has been placed previously give a history of the child’s placements (placed with different parents, relatives, DSS, etc)."
- title: "Education, vocation, or daycare"
details:
"a) When did the family first come into contact with the Department of Social Services or Department of Juvenile Justice – how many times?
b) Tell the history of their involvement with the department and any facts about their life that could help determine the need for placement and/or services.
c) Discuss the child’s history – behavior problems, educational history, medical history, psychological history (any hospitalizations, previous counseling, etc.)
d) If child has been placed previously give a history of the child’s placements (placed with different parents, relatives, DSS, etc)."
- title: "Health and mental health"
details:
"a) When did the family first come into contact with the Department of Social Services or Department of Juvenile Justice – how many times?
b) Tell the history of their involvement with the department and any facts about their life that could help determine the need for placement and/or services.
c) Discuss the child’s history – behavior problems, educational history, medical history, psychological history (any hospitalizations, previous counseling, etc.)
d) If child has been placed previously give a history of the child’s placements (placed with different parents, relatives, DSS, etc)."
- title: "Family and community connections"
details:
"a) When did the family first come into contact with the Department of Social Services or Department of Juvenile Justice – how many times?
b) Tell the history of their involvement with the department and any facts about their life that could help determine the need for placement and/or services.
c) Discuss the child’s history – behavior problems, educational history, medical history, psychological history (any hospitalizations, previous counseling, etc.)
d) If child has been placed previously give a history of the child’s placements (placed with different parents, relatives, DSS, etc)."
- title: "Child’s strengths"
details:
"a) When did the family first come into contact with the Department of Social Services or Department of Juvenile Justice – how many times?
b) Tell the history of their involvement with the department and any facts about their life that could help determine the need for placement and/or services.
c) Discuss the child’s history – behavior problems, educational history, medical history, psychological history (any hospitalizations, previous counseling, etc.)
d) If child has been placed previously give a history of the child’s placements (placed with different parents, relatives, DSS, etc)."
14 changes: 14 additions & 0 deletions db/migrate/20240128015203_create_case_contact_topics.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class CreateCaseContactTopics < ActiveRecord::Migration[7.0]
def change
create_table :case_contact_topics do |t|
t.string :title
t.string :details
t.string :answer
t.boolean :active, default: false
t.references :casa_org, null: false
t.references :case_contact, null: true

t.timestamps
end
end
end
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.0].define(version: 2023_11_25_150721) do
ActiveRecord::Schema[7.1].define(version: 2024_01_28_015203) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

Expand Down Expand Up @@ -184,6 +184,19 @@
t.index ["contact_type_id"], name: "index_case_contact_contact_types_on_contact_type_id"
end

create_table "case_contact_topics", force: :cascade do |t|
t.string "title"
t.string "details"
t.string "answer"
t.boolean "active", default: false
t.bigint "casa_org_id", null: false
t.bigint "case_contact_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["casa_org_id"], name: "index_case_contact_topics_on_casa_org_id"
t.index ["case_contact_id"], name: "index_case_contact_topics_on_case_contact_id"
end

create_table "case_contacts", force: :cascade do |t|
t.bigint "creator_id", null: false
t.bigint "casa_case_id"
Expand Down Expand Up @@ -395,6 +408,7 @@

create_table "learning_hours", force: :cascade do |t|
t.bigint "user_id", null: false
t.integer "learning_type", default: 5
t.string "name", null: false
t.integer "duration_minutes", null: false
t.integer "duration_hours", null: false
Expand Down
4 changes: 3 additions & 1 deletion db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
require_relative "../lib/tasks/data_post_processors/case_contact_populator"
require_relative "../lib/tasks/data_post_processors/contact_type_populator"
require_relative "../lib/tasks/data_post_processors/sms_notification_event_populator"
require_relative "../lib/tasks/data_post_processors/contact_topic_populator"

class SeederMain
attr_reader :db_populator, :rng
Expand Down Expand Up @@ -76,6 +77,7 @@ def active_record_classes
def post_process_data
ContactTypePopulator.populate
CaseContactPopulator.populate
ContactTopicPopulator.populate
end

def get_seed_specification
Expand All @@ -97,7 +99,7 @@ def get_seed_specification
def report_object_counts
log "\nRecords written to the DB:\n\nCount Class Name\n----- ----------\n\n"
active_record_classes.each do |klass|
log "%5d %s" % [klass.count, klass.name]
log format("%5d %s", klass.count, klass.name)
end
log "\n\nVolunteers, Supervisors and CasaAdmins are types of Users"
end
Expand Down
7 changes: 7 additions & 0 deletions lib/tasks/data_post_processors/contact_topic_populator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module ContactTopicPopulator
def self.populate
CasaOrg.all.each do |casa_org|
CaseContactTopic.generate_for_org!(casa_org)
end
end
end
8 changes: 8 additions & 0 deletions spec/factories/case_contact_topics.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FactoryBot.define do
factory :case_contact_topic do
title { Faker::Lorem.sentence }
details { Faker::Lorem.paragraph }
casa_org
case_contact
end
end
95 changes: 55 additions & 40 deletions spec/models/casa_org_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
it { is_expected.to have_many(:case_assignments).through(:users) }
it { is_expected.to have_one_attached(:logo) }
it { is_expected.to have_one_attached(:court_report_template) }
it { is_expected.to have_many(:case_contact_topics) }

it "has unique name" do
org = create(:casa_org)
Expand Down Expand Up @@ -86,10 +87,15 @@
it { is_expected.to eq 15 }
end

describe "generate_contact_types_and_hearing_types" do
describe "generate_defaults" do
let(:org) { create(:casa_org) }
let(:fake_topics) { [{"title" => "Test Title", "details" => "Test Details"}] }

before { org.generate_contact_types_and_hearing_types }
before do
default_topics_file = Rails.root.join("data", "default_contact_topics.yml")
allow(YAML).to receive(:load_file).with(default_topics_file).and_return(fake_topics)
org.generate_defaults
end

describe "generates default contact type groups" do
let(:groups) { ContactTypeGroup.where(casa_org: org).joins(:contact_types).pluck(:name, "contact_types.name").sort }
Expand Down Expand Up @@ -128,52 +134,61 @@
end
end

describe "mileage rate for a given date" do
let(:casa_org) { build(:casa_org) }
describe "generates default contact types" do
let(:contact_topics) { CaseContactTopic.where(casa_org: org).pluck(:title) }

describe "with a casa org with no rates" do
it "is nil" do
expect(casa_org.mileage_rate_for_given_date(Date.today)).to be_nil
end
it "matches default contact topics" do
expected = fake_topics.map { |topic| topic["title"] }
expect(contact_topics).to include(*expected)
end
end
end

describe "with a casa org with inactive dates" do
let!(:mileage_rates) do
[
create(:mileage_rate, casa_org: casa_org, effective_date: 10.days.ago, is_active: false),
create(:mileage_rate, casa_org: casa_org, effective_date: 3.days.ago, is_active: false)
]
end

it "is nil" do
expect(casa_org.mileage_rates.count).to eq 2
expect(casa_org.mileage_rate_for_given_date(Date.today)).to be_nil
end
describe "mileage rate for a given date" do
let(:casa_org) { build(:casa_org) }

describe "with a casa org with no rates" do
it "is nil" do
expect(casa_org.mileage_rate_for_given_date(Date.today)).to be_nil
end
end

describe "with active dates in the future" do
let!(:mileage_rate) { create(:mileage_rate, casa_org: casa_org, effective_date: 3.days.from_now) }
describe "with a casa org with inactive dates" do
let!(:mileage_rates) do
[
create(:mileage_rate, casa_org:, effective_date: 10.days.ago, is_active: false),
create(:mileage_rate, casa_org:, effective_date: 3.days.ago, is_active: false)
]
end

it "is nil" do
expect(casa_org.mileage_rates.count).to eq 2
expect(casa_org.mileage_rate_for_given_date(Date.today)).to be_nil
end
end

describe "with active dates in the future" do
let!(:mileage_rate) { create(:mileage_rate, casa_org:, effective_date: 3.days.from_now) }

it "is nil" do
expect(casa_org.mileage_rates.count).to eq 1
expect(casa_org.mileage_rate_for_given_date(Date.today)).to be_nil
end
end

it "is nil" do
expect(casa_org.mileage_rates.count).to eq 1
expect(casa_org.mileage_rate_for_given_date(Date.today)).to be_nil
end
describe "with active dates in the past" do
let!(:mileage_rates) do
[
create(:mileage_rate, casa_org:, amount: 4.50, effective_date: 20.days.ago),
create(:mileage_rate, casa_org:, amount: 5.50, effective_date: 10.days.ago),
create(:mileage_rate, casa_org:, amount: 6.50, effective_date: 3.days.ago)
]
end

describe "with active dates in the past" do
let!(:mileage_rates) do
[
create(:mileage_rate, casa_org: casa_org, amount: 4.50, effective_date: 20.days.ago),
create(:mileage_rate, casa_org: casa_org, amount: 5.50, effective_date: 10.days.ago),
create(:mileage_rate, casa_org: casa_org, amount: 6.50, effective_date: 3.days.ago)
]
end

it "uses the most recent date" do
expect(casa_org.mileage_rate_for_given_date(12.days.ago.to_date)).to eq 4.50
expect(casa_org.mileage_rate_for_given_date(5.days.ago.to_date)).to eq 5.50
expect(casa_org.mileage_rate_for_given_date(Date.today)).to eq 6.50
end
it "uses the most recent date" do
expect(casa_org.mileage_rate_for_given_date(12.days.ago.to_date)).to eq 4.50
expect(casa_org.mileage_rate_for_given_date(5.days.ago.to_date)).to eq 5.50
expect(casa_org.mileage_rate_for_given_date(Date.today)).to eq 6.50
end
end
end
Expand Down
Loading

0 comments on commit 50c304a

Please sign in to comment.