diff --git a/app/controllers/contact_topics_controller.rb b/app/controllers/contact_topics_controller.rb
index 3667fb69c2..805cfd5103 100644
--- a/app/controllers/contact_topics_controller.rb
+++ b/app/controllers/contact_topics_controller.rb
@@ -56,6 +56,6 @@ def set_contact_topic
# Only allow a list of trusted parameters through.
def contact_topic_params
- params.require(:contact_topic).permit(:casa_org_id, :question, :details, :active)
+ params.require(:contact_topic).permit(:casa_org_id, :question, :details, :active, :exclude_from_court_report)
end
end
diff --git a/app/models/case_court_report_context.rb b/app/models/case_court_report_context.rb
index c0fa3b2b6d..870064955b 100644
--- a/app/models/case_court_report_context.rb
+++ b/app/models/case_court_report_context.rb
@@ -108,6 +108,7 @@ def org_address(path_to_template)
def court_topics
topics = ContactTopic
.joins(contact_topic_answers: {case_contact: [:casa_case, :contact_types]}).distinct
+ .where(contact_topics: {exclude_from_court_report: false})
.where("casa_cases.id": @casa_case.id)
.where("case_contacts.occurred_at": @date_range)
.order(:occurred_at, :value)
diff --git a/app/models/contact_topic.rb b/app/models/contact_topic.rb
index 8088574980..2da133a5b3 100644
--- a/app/models/contact_topic.rb
+++ b/app/models/contact_topic.rb
@@ -42,14 +42,15 @@ def default_contact_topics
#
# Table name: contact_topics
#
-# id :bigint not null, primary key
-# active :boolean default(TRUE), not null
-# details :text
-# question :string
-# soft_delete :boolean default(FALSE), not null
-# created_at :datetime not null
-# updated_at :datetime not null
-# casa_org_id :bigint not null
+# id :bigint not null, primary key
+# active :boolean default(TRUE), not null
+# details :text
+# exclude_from_court_report :boolean default(FALSE), not null
+# question :string
+# soft_delete :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# casa_org_id :bigint not null
#
# Foreign Keys
#
diff --git a/app/models/user.rb b/app/models/user.rb
index 179a1f14e2..99c3f24e98 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -121,7 +121,7 @@ def no_attempt_for_two_weeks
if volunteer.supervisor.active? &&
volunteer.case_assignments.any? { |assignment| assignment.active? } &&
(volunteer.case_contacts.none? ||
- volunteer.case_contacts.maximum(:created_at) < (14.days.ago))
+ volunteer.case_contacts.maximum(:created_at) < 14.days.ago)
no_attempt_count += 1
end
diff --git a/app/views/contact_topics/_form.html.erb b/app/views/contact_topics/_form.html.erb
index 8d93894422..b513dd297c 100644
--- a/app/views/contact_topics/_form.html.erb
+++ b/app/views/contact_topics/_form.html.erb
@@ -29,6 +29,10 @@
<%= form.check_box :active, class: 'form-check-input' %>
<%= form.label :active, "Active?", class: 'form-check-label' %>
+
+ <%= form.check_box :exclude_from_court_report, class: 'form-check-input' %>
+ <%= form.label :exclude_from_court_report, "Exclude from Court Report?", class: 'form-check-label' %>
+
<%= button_tag(type: "submit", class: "btn-sm main-btn primary-btn btn-hover") do %>
Submit
diff --git a/db/migrate/20250702142004_add_exclude_from_court_report_to_contact_topics.rb b/db/migrate/20250702142004_add_exclude_from_court_report_to_contact_topics.rb
new file mode 100644
index 0000000000..575a298a40
--- /dev/null
+++ b/db/migrate/20250702142004_add_exclude_from_court_report_to_contact_topics.rb
@@ -0,0 +1,5 @@
+class AddExcludeFromCourtReportToContactTopics < ActiveRecord::Migration[7.2]
+ def change
+ add_column :contact_topics, :exclude_from_court_report, :boolean, default: false, null: false
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index af59159f47..be89070502 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.2].define(version: 2025_05_28_092341) do
+ActiveRecord::Schema[7.2].define(version: 2025_07_02_142004) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -270,6 +270,7 @@
t.string "question"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.boolean "exclude_from_court_report", default: false, null: false
end
create_table "contact_type_groups", force: :cascade do |t|
diff --git a/lib/tasks/no_contact_made_reminder.rb b/lib/tasks/no_contact_made_reminder.rb
index eab4ef0dea..412b85b391 100644
--- a/lib/tasks/no_contact_made_reminder.rb
+++ b/lib/tasks/no_contact_made_reminder.rb
@@ -40,7 +40,7 @@ def get_contact_types_in_past_2_weeks(volunteer, contact_made)
def valid_past_reminders(volunteer)
reminder = UserReminderTime.find_by(user_id: volunteer.id)
- if reminder&.case_contact_types && reminder.case_contact_types.today?
+ if reminder&.case_contact_types&.today?
return false
end
diff --git a/spec/models/case_court_report_context_spec.rb b/spec/models/case_court_report_context_spec.rb
index ee90369bc7..23b683f370 100644
--- a/spec/models/case_court_report_context_spec.rb
+++ b/spec/models/case_court_report_context_spec.rb
@@ -193,23 +193,9 @@
])
end
end
- # let(:contacts) { create_list(:case_contact, 4, casa_case: casa_case, occurred_at: 1.month.ago) }
context "when given data" do
- # Add some values that should get filtered out
before do
- contact_one = create(:case_contact, casa_case: casa_case, medium_type: "in-person", occurred_at: 1.day.ago)
- create_list(:contact_topic_answer, 2, case_contact: contact_one, contact_topic: topics[0], value: "Not included")
-
- contact_two = create(:case_contact, casa_case: casa_case, medium_type: "in-person", occurred_at: 50.day.ago)
- create_list(:contact_topic_answer, 2, case_contact: contact_two, contact_topic: topics[0], value: "Not included")
-
- other_case = create(:casa_case, casa_org: org)
- contact_three = create(:case_contact, casa_case: other_case, medium_type: "in-person", occurred_at: 50.day.ago)
- create_list(:contact_topic_answer, 2, case_contact: contact_three, contact_topic: topics[0], value: "Not included")
- end
-
- it "generates correctly shaped data" do
# Contact 1 Answers
create(:contact_topic_answer, case_contact: contacts[0], contact_topic: topics[0], value: "Answer 1")
create(:contact_topic_answer, case_contact: contacts[0], contact_topic: topics[1], value: "Answer 2")
@@ -222,27 +208,64 @@
create(:contact_topic_answer, case_contact: contacts[2], contact_topic: topics[1], value: "Answer 5")
create(:contact_topic_answer, case_contact: contacts[2], contact_topic: topics[2], value: "")
- # Contact 4 Answers
- # No Answers
-
- expected_topics = {
- "Question 1" => {topic: "Question 1", details: "Details 1", answers: [
- {date: "12/02/20", medium: "Type A1, Type B1", value: "Answer 1"},
- {date: "12/03/20", medium: "Type A2, Type B2", value: "Answer 3"}
- ]},
- "Question 2" => {topic: "Question 2", details: "Details 2", answers: [
- {date: "12/02/20", medium: "Type A1, Type B1", value: "Answer 2"},
- {date: "12/04/20", medium: "Type A3, Type B3", value: "Answer 5"}
- ]},
- "Question 3" => {topic: "Question 3", details: "Details 3", answers: [
- {date: "12/03/20", medium: "Type A2, Type B2", value: "No Answer Provided"},
- {date: "12/04/20", medium: "Type A3, Type B3", value: "No Answer Provided"}
- ]}
- }
+ # Contacts that will be filtered
+ one_day_ago_contact = create(:case_contact, casa_case: casa_case, medium_type: "in-person", occurred_at: 1.day.ago)
+ create_list(:contact_topic_answer, 2, case_contact: one_day_ago_contact, contact_topic: topics[0], value: "Answer From One Day Ago")
- court_report_context = build(:case_court_report_context, start_date: 45.day.ago.to_s, end_date: 5.day.ago.to_s, casa_case: casa_case)
+ one_year_ago_contact = create(:case_contact, casa_case: casa_case, medium_type: "in-person", occurred_at: 1.year.ago)
+ create_list(:contact_topic_answer, 2, case_contact: one_year_ago_contact, contact_topic: topics[0], value: "Answer From One Year Ago")
+
+ other_case = create(:casa_case, casa_org: org)
+ other_case_contact = create(:case_contact, casa_case: other_case, medium_type: "in-person", occurred_at: 1.month.ago)
+ create_list(:contact_topic_answer, 2, case_contact: other_case_contact, contact_topic: topics[0], value: "Answer From Another Case")
+ end
+
+ it "returns a hash of topics with the correct shape" do
+ court_topics = build(:case_court_report_context, casa_case: casa_case).court_topics
+
+ expect(court_topics).to be_a(Hash)
+
+ expect(court_topics.keys).to all(a_kind_of(String))
+ expect(court_topics.values).to all(
+ a_hash_including(
+ topic: a_kind_of(String),
+ details: a_kind_of(String),
+ answers: all(
+ a_hash_including(
+ date: a_string_matching(/\d{2}\/\d{2}\/\d{2}/),
+ medium: a_kind_of(String),
+ value: a_kind_of(String)
+ )
+ )
+ )
+ )
+ end
+
+ it "returns topics related to the case" do
+ court_topics = build(:case_court_report_context, casa_case: casa_case).court_topics
+
+ expect(court_topics.keys).to match_array(["Question 1", "Question 2", "Question 3"])
+ expect(court_topics["Question 1"][:answers].map { |a| a[:value] }).to match_array(
+ ["Answer From One Year Ago", "Answer 1", "Answer 3", "Answer From One Day Ago"]
+ )
+ expect(court_topics["Question 2"][:answers].map { |a| a[:value] }).to match_array(["Answer 2", "Answer 5"])
+ expect(court_topics["Question 3"][:answers].map { |a| a[:value] }).to match_array(["No Answer Provided", "No Answer Provided"])
+ end
+
+ it "filters by date range" do
+ court_topics = build(:case_court_report_context, start_date: 45.day.ago.to_s, end_date: 5.day.ago.to_s, casa_case: casa_case).court_topics
+
+ expect(court_topics.keys).to match_array(["Question 1", "Question 2", "Question 3"])
+ expect(court_topics["Question 1"][:answers].map { |a| a[:value] }).to match_array(["Answer 1", "Answer 3"])
+ end
+
+ it "filters answers from topics set be excluded from court report" do
+ topics[0].update(exclude_from_court_report: true)
+
+ court_topics = build(:case_court_report_context, casa_case: casa_case).court_topics
- expect(court_report_context.court_topics).to eq(expected_topics)
+ expect(court_topics.keys).not_to include("Question 1")
+ expect(court_topics.keys).to include("Question 2", "Question 3")
end
end
diff --git a/spec/requests/contact_topics_spec.rb b/spec/requests/contact_topics_spec.rb
index 341349942f..5160c044f1 100644
--- a/spec/requests/contact_topics_spec.rb
+++ b/spec/requests/contact_topics_spec.rb
@@ -53,6 +53,17 @@
post contact_topics_url, params: {contact_topic: attributes}
expect(response).to redirect_to(edit_casa_org_path(casa_org))
end
+
+ it "can set exclude_from_court_report attribute" do
+ attributes[:exclude_from_court_report] = true
+
+ expect do
+ post contact_topics_url, params: {contact_topic: attributes}
+ end.to change(ContactTopic, :count).by(1)
+
+ topic = ContactTopic.last
+ expect(topic.exclude_from_court_report).to be true
+ end
end
context "with invalid parameters" do
@@ -107,6 +118,14 @@
patch contact_topic_url(contact_topic), params: {contact_topic: new_attributes}
expect(response).to redirect_to(edit_casa_org_path(casa_org))
end
+
+ it "can change exclude_from_court_report" do
+ new_attributes = {exclude_from_court_report: true}
+
+ expect {
+ patch contact_topic_url(contact_topic), params: {contact_topic: new_attributes}
+ }.to change { contact_topic.reload.exclude_from_court_report }.from(false).to(true)
+ end
end
context "with invalid parameters" do