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