diff --git a/app/controllers/partners/children_controller.rb b/app/controllers/partners/children_controller.rb
index b0e6047557..74b842f7bd 100644
--- a/app/controllers/partners/children_controller.rb
+++ b/app/controllers/partners/children_controller.rb
@@ -82,11 +82,11 @@ def child_params
:first_name,
:gender,
:health_insurance,
- :item_needed_diaperid,
:last_name,
:race,
:archived,
- child_lives_with: []
+ child_lives_with: [],
+ requested_item_ids: []
)
end
diff --git a/app/controllers/partners/family_requests_controller.rb b/app/controllers/partners/family_requests_controller.rb
index ff91b4b9bc..6b8dc44051 100644
--- a/app/controllers/partners/family_requests_controller.rb
+++ b/app/controllers/partners/family_requests_controller.rb
@@ -23,9 +23,9 @@ def create
end
end
- children = current_partner.children.active.where(id: children_ids).where.not(item_needed_diaperid: [nil, 0])
+ children = current_partner.children.active.where(id: children_ids).joins(:requested_items).select('children.*', :item_id)
- children_grouped_by_item_id = children.group_by(&:item_needed_diaperid)
+ children_grouped_by_item_id = children.group_by(&:item_id)
family_requests_attributes = children_grouped_by_item_id.map do |item_id, item_requested_children|
{ item_id: item_id, person_count: item_requested_children.size, children: item_requested_children }
end
diff --git a/app/helpers/partners_helper.rb b/app/helpers/partners_helper.rb
index 6a8e8b87b3..fcf9f498c9 100644
--- a/app/helpers/partners_helper.rb
+++ b/app/helpers/partners_helper.rb
@@ -1,5 +1,12 @@
# Encapsulates methods that need some business logic
module PartnersHelper
+ def display_requested_items(partner, child)
+ ids = child.requested_item_ids
+ ids.map do |item_id|
+ partner.organization.item_id_to_display_string_map[item_id]
+ end.join(', ')
+ end
+
def show_header_column_class(partner, additional_classes: "")
if partner.quota.present?
"col-sm-3 col-3 #{additional_classes}"
diff --git a/app/models/partners/child.rb b/app/models/partners/child.rb
index 1421bd47a1..c64eba620c 100644
--- a/app/models/partners/child.rb
+++ b/app/models/partners/child.rb
@@ -25,6 +25,7 @@ class Child < Base
serialize :child_lives_with, Array
belongs_to :family
has_many :child_item_requests, dependent: :destroy
+ has_and_belongs_to_many :requested_items, class_name: 'Item'
include Filterable
include Exportable
@@ -88,7 +89,7 @@ def display_name
def self.csv_export_headers
%w[
id first_name last_name date_of_birth gender child_lives_with race agency_child_id
- health_insurance comments created_at updated_at family_id item_needed_diaperid active archived
+ health_insurance comments created_at updated_at family_id requested_item_ids active archived
].freeze
end
@@ -107,7 +108,7 @@ def csv_export_attributes
created_at,
updated_at,
family_id,
- item_needed_diaperid,
+ requested_item_ids,
active,
archived
]
diff --git a/app/views/partners/children/_child.json.jbuilder b/app/views/partners/children/_child.json.jbuilder
index 63ae89cc65..98be8b3f55 100644
--- a/app/views/partners/children/_child.json.jbuilder
+++ b/app/views/partners/children/_child.json.jbuilder
@@ -1,2 +1,2 @@
-json.extract! child, :id, :first_name, :last_name, :date_of_birth, :gender, :child_lives_with, :race, :agency_child_id, :health_insurance, :item_needed_diaperid, :comments, :created_at, :updated_at
+json.extract! child, :id, :first_name, :last_name, :date_of_birth, :gender, :child_lives_with, :race, :agency_child_id, :health_insurance, :requested_item_ids, :comments, :created_at, :updated_at
json.url child_url(child, format: :json)
diff --git a/app/views/partners/children/_form.html.erb b/app/views/partners/children/_form.html.erb
index 8bd2ac2725..3f11457e9f 100644
--- a/app/views/partners/children/_form.html.erb
+++ b/app/views/partners/children/_form.html.erb
@@ -16,11 +16,22 @@
<%= form.label :last_name, "Last Name" %>
<%= form.text_field :last_name, class: "form-control" %>
- <%= form.label :item_needed, "Diaper/Item Used" %>
- <%= form.select :item_needed_diaperid, @requestable_items,
- {include_blank: 'Select an item'},
- {class: 'form-control'} %>
+ <%= @requestable_items.map(&:last).intersect?(child.requested_item_ids) %>
+
+ <%= form.label :item_needed, "Item(s) Requested" %>
+ <%= form.select(
+ :requested_item_ids,
+ @requestable_items,
+ { include_hidden: true },
+ {
+ multiple: true,
+ class: "form-control custom-select",
+ "data-controller": "select2",
+ "data-select2-config-value": "{}",
+ },
+ ) %>
+
<%= form.input :date_of_birth, as: :date, start_year: 20.years.ago.year, end_year: Time.current.year, label: "Date of Birth" %>
<%= form.input :gender, collection: ["Male", "Female"], class: "form-control" %>
@@ -53,16 +64,15 @@
<%= form.label "Archived?" %>
<%= form.check_box :archived %>
-
-
<% end %>
-
-
+
+
-
-
-
+
+
+
+
diff --git a/app/views/partners/children/show.html.erb b/app/views/partners/children/show.html.erb
index 45e28aa0ed..3b5eb21949 100644
--- a/app/views/partners/children/show.html.erb
+++ b/app/views/partners/children/show.html.erb
@@ -58,8 +58,8 @@
Health insurance:
<%= @child.health_insurance %>
- Item needed:
- <%= current_partner.organization.item_id_to_display_string_map[@child.item_needed_diaperid] %>
+ Item(s) needed:
+ <%= display_requested_items(current_partner, @child) %>
Comments:
<%= @child.comments %>
diff --git a/app/views/partners/family_requests/_list.html.erb b/app/views/partners/family_requests/_list.html.erb
index 2b350f25b1..9be1448a55 100644
--- a/app/views/partners/family_requests/_list.html.erb
+++ b/app/views/partners/family_requests/_list.html.erb
@@ -18,15 +18,15 @@
<%= child.first_name %> <%= child.last_name %>
- <% if child.item_needed_diaperid %>
- <%= current_partner.organization.item_id_to_display_string_map[child.item_needed_diaperid] %>
+ <% if child.requested_item_ids.any? %>
+ <%= display_requested_items(current_partner, child) %>
<% else %>
<%= "N/A" %>
<% end %>
|
- <% if child.item_needed_diaperid %>
+ <% if child.requested_item_ids.any? %>
<%= check_box_tag "child-#{child.id}", child.active, child.active,
class: "custom-control-input",
id: "child-#{child.id}" %>
diff --git a/db/migrate/20240703174254_create_join_table_children_items.rb b/db/migrate/20240703174254_create_join_table_children_items.rb
new file mode 100644
index 0000000000..6250f20a04
--- /dev/null
+++ b/db/migrate/20240703174254_create_join_table_children_items.rb
@@ -0,0 +1,8 @@
+class CreateJoinTableChildrenItems < ActiveRecord::Migration[7.1]
+ def change
+ create_join_table :children, :items do |t|
+ t.index [:child_id, :item_id], unique: true
+ t.index [:item_id, :child_id], unique: true
+ end
+ end
+end
diff --git a/db/migrate/20240704214509_backfill_partner_child_requested_items.rb b/db/migrate/20240704214509_backfill_partner_child_requested_items.rb
new file mode 100644
index 0000000000..9e4cdba70d
--- /dev/null
+++ b/db/migrate/20240704214509_backfill_partner_child_requested_items.rb
@@ -0,0 +1,7 @@
+class BackfillPartnerChildRequestedItems < ActiveRecord::Migration[7.1]
+ def change
+ Partners::Child.unscoped.where.not(item_needed_diaperid: nil).each do |child|
+ child.requested_items << Item.find_by(id: child.item_needed_diaperid)
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index bcbb2930f3..8cf2594a08 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.1].define(version: 2024_06_24_185108) do
+ActiveRecord::Schema[7.1].define(version: 2024_07_04_214509) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -188,6 +188,13 @@
t.index ["family_id"], name: "index_children_on_family_id"
end
+ create_table "children_items", id: false, force: :cascade do |t|
+ t.bigint "child_id", null: false
+ t.bigint "item_id", null: false
+ t.index ["child_id", "item_id"], name: "index_children_items_on_child_id_and_item_id", unique: true
+ t.index ["item_id", "child_id"], name: "index_children_items_on_item_id_and_child_id", unique: true
+ end
+
create_table "counties", force: :cascade do |t|
t.string "name"
t.string "region"
diff --git a/db/seeds.rb b/db/seeds.rb
index 0a138b6301..e5ab8f6030 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -292,6 +292,8 @@ def random_record_for_org(org, klass)
)
end
+ requestable_items = PartnerFetchRequestableItemsService.new(partner_id: p.id).call.map(&:last)
+
families.each do |family|
Partners::AuthorizedFamilyMember.create!(
first_name: Faker::Name.first_name,
@@ -316,7 +318,7 @@ def random_record_for_org(org, klass)
comments: Faker::Lorem.paragraph,
active: Faker::Boolean.boolean,
archived: false,
- item_needed_diaperid: p.organization.item_id_to_display_string_map.key(Partners::Child::CHILD_ITEMS.sample)
+ requested_item_ids: requestable_items.sample(rand(4))
)
end
@@ -334,7 +336,7 @@ def random_record_for_org(org, klass)
comments: Faker::Lorem.paragraph,
active: Faker::Boolean.boolean,
archived: false,
- item_needed_diaperid: p.organization.item_id_to_display_string_map.key(Partners::Child::CHILD_ITEMS.sample)
+ requested_item_ids: requestable_items.sample(rand(4))
)
end
end
diff --git a/spec/factories/partners/child.rb b/spec/factories/partners/child.rb
index cf6a20204f..ea035bf620 100644
--- a/spec/factories/partners/child.rb
+++ b/spec/factories/partners/child.rb
@@ -9,7 +9,6 @@
first_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
gender { Faker::Gender.binary_type }
- # TODO: change when closing #4199
- item_needed_diaperid { Item.all.sample&.id || create(:item, organization: family.partner.organization).id }
+ requested_item_ids { [create(:item, organization: family.partner.organization).id] }
end
end
diff --git a/spec/models/partners/child_spec.rb b/spec/models/partners/child_spec.rb
index 3e58946bb1..c95bec16de 100644
--- a/spec/models/partners/child_spec.rb
+++ b/spec/models/partners/child_spec.rb
@@ -25,6 +25,7 @@
describe 'associations' do
it { should belong_to(:family) }
it { should have_many(:child_item_requests).dependent(:destroy) }
+ it { should have_and_belong_to_many(:requested_items).class_name('Item') }
end
describe "#display_name" do
diff --git a/spec/requests/partners/children_requests_spec.rb b/spec/requests/partners/children_requests_spec.rb
index ca42e7386a..3deb22b3cf 100644
--- a/spec/requests/partners/children_requests_spec.rb
+++ b/spec/requests/partners/children_requests_spec.rb
@@ -4,6 +4,8 @@
let(:partner_user) { partner.primary_user }
let(:partner) { create(:partner) }
let(:family) { create(:partners_family, partner: partner) }
+ let(:item1) { create(:item, organization: partner.organization) }
+ let(:item2) { create(:item, organization: partner.organization) }
let!(:child1) do
create(:partners_child,
first_name: "John",
@@ -15,7 +17,7 @@
agency_child_id: "Agency McAgence",
health_insurance: "Private insurance",
comments: "Some comment",
- item_needed_diaperid: nil,
+ requested_item_ids: nil,
active: true,
archived: false,
family: family)
@@ -31,9 +33,9 @@
agency_child_id: "Agency McAgence",
health_insurance: "Private insurance",
comments: "Some comment",
- item_needed_diaperid: nil,
active: true,
archived: false,
+ requested_item_ids: [item1.id, item2.id],
family: family)
end
@@ -51,9 +53,9 @@
headers = {"Accept" => "text/csv", "Content-Type" => "text/csv"}
get partners_children_path, headers: headers
csv = <<~CSV
- id,first_name,last_name,date_of_birth,gender,child_lives_with,race,agency_child_id,health_insurance,comments,created_at,updated_at,family_id,item_needed_diaperid,active,archived
+ id,first_name,last_name,date_of_birth,gender,child_lives_with,race,agency_child_id,health_insurance,comments,created_at,updated_at,family_id,requested_item_ids,active,archived
#{child1.id},John,Smith,2019-01-01,Male,"mother,grandfather",Other,Agency McAgence,Private insurance,Some comment,#{child1.created_at},#{child1.updated_at},#{family.id},"",true,false
- #{child2.id},Jane,Smith,2018-01-01,Female,father,Hispanic,Agency McAgence,Private insurance,Some comment,#{child2.created_at},#{child2.updated_at},#{family.id},"",true,false
+ #{child2.id},Jane,Smith,2018-01-01,Female,father,Hispanic,Agency McAgence,Private insurance,Some comment,#{child2.created_at},#{child2.updated_at},#{family.id},"#{item1.id},#{item2.id}",true,false
CSV
expect(response.body).to eq(csv)
end
diff --git a/spec/requests/partners/family_requests_controller_spec.rb b/spec/requests/partners/family_requests_controller_spec.rb
index 04b17f75f2..47e9c603ed 100644
--- a/spec/requests/partners/family_requests_controller_spec.rb
+++ b/spec/requests/partners/family_requests_controller_spec.rb
@@ -34,7 +34,7 @@
# Set one child as deactivated and the other as active but
# without a item_needed_diaperid
children[0].update(active: false)
- children[1].update(item_needed_diaperid: nil)
+ children[1].update(requested_item_ids: [])
end
subject { post partners_family_requests_path, params: params }
diff --git a/spec/system/partners/children_system_spec.rb b/spec/system/partners/children_system_spec.rb
new file mode 100644
index 0000000000..25b2531138
--- /dev/null
+++ b/spec/system/partners/children_system_spec.rb
@@ -0,0 +1,36 @@
+RSpec.describe "Creating a parner child", type: :system, js: true do
+ let(:organization) { create(:organization) }
+ let(:partner) { FactoryBot.create(:partner, organization: organization) }
+ let(:partner_user) { partner.primary_user }
+ let(:family) { create(:partners_family, guardian_first_name: "Main", guardian_last_name: "Family", partner: partner) }
+
+ before do
+ partner.update(status: :approved)
+ login_as(partner_user)
+ create(:item, name: "Item 1", organization: organization)
+ create(:item, name: "Item 2", organization: organization)
+ end
+
+ describe "creating a child for a family" do
+ it "creates a child with correct info" do
+ visit new_partners_child_path(family_id: family.id)
+ fill_in "First Name", with: "Child First Name"
+ fill_in "Last Name", with: "Child Last Name"
+ select "Other", from: "Race"
+ fill_in "Agency Child ID", with: "01234"
+ fill_in "Comments", with: "Some Comment"
+
+ select2(page, "requestable-items-container", "Item 2")
+ select2(page, "requestable-items-container", "Item 1")
+
+ click_button "Create Child"
+
+ expect(page).to have_text("Child was successfully created.")
+ expect(page).to have_text("Child First Name")
+ expect(page).to have_text("Child Last Name")
+ expect(page).to have_text("01234")
+ expect(page).to have_text("Some Comment")
+ expect(page).to have_text("Item 1, Item 2")
+ end
+ end
+end
diff --git a/spec/system/partners/family_requests_system_spec.rb b/spec/system/partners/family_requests_system_spec.rb
index e1030f284a..08b416506c 100644
--- a/spec/system/partners/family_requests_system_spec.rb
+++ b/spec/system/partners/family_requests_system_spec.rb
@@ -1,8 +1,8 @@
RSpec.describe "Family requests", type: :system, js: true do
let(:partner) { FactoryBot.create(:partner) }
let(:partner_user) { partner.primary_user }
- let(:family) { create(:partners_family, guardian_last_name: "Morales", partner: partner) }
- let(:other_family) { create(:partners_family, partner: partner) }
+ let(:family) { create(:partners_family, guardian_first_name: "Main", guardian_last_name: "Family", partner: partner) }
+ let(:other_family) { create(:partners_family, partner: partner, guardian_first_name: "Other", guardian_last_name: "Family") }
before do
partner.update(status: :approved)
@@ -10,26 +10,56 @@
end
describe "for children with different items, from different families" do
- let(:item_id) { Item.all.sample.id }
- let!(:children) do
- [
- create(:partners_child, family: family),
- create(:partners_child, family: family, item_needed_diaperid: item_id),
- create(:partners_child, family: family, item_needed_diaperid: item_id),
- create(:partners_child, family: other_family, item_needed_diaperid: item_id),
- create(:partners_child, family: other_family)
- ]
+ let(:item1) { create(:item, name: "Item 1") }
+ let(:item2) { create(:item, name: "Item 2") }
+ let(:item3) { create(:item, name: "Item 3") }
+
+ before do
+ create(:partners_child, family: family, first_name: "Main", last_name: "No Items", requested_item_ids: nil)
+ create(:partners_child, family: family, first_name: "Main", last_name: "Items1", requested_item_ids: [item1.id, item2.id])
+ create(:partners_child, family: family, first_name: "Main", last_name: "Items2", requested_item_ids: [item2.id, item3.id])
+ create(:partners_child, first_name: "Other", last_name: "Items", family: other_family, requested_item_ids: [item1.id, item2.id])
+ create(:partners_child, first_name: "Other", last_name: "No Items", family: other_family, requested_item_ids: nil)
end
scenario "it creates family requests" do
visit partners_requests_path
find('a[aria-label="Create a request for a child or family"]').click
+
+ within("table tbody tr", text: "Main Items1") do |row|
+ expect(row).to have_css("td", text: "Main Family")
+ expect(row).to have_css("td", text: "Main Items1")
+ expect(row).to have_css("td", text: "Item 1, Item 2")
+ end
+
+ within("table tbody tr", text: "Main Items2") do |row|
+ expect(row).to have_css("td", text: "Main Family")
+ expect(row).to have_css("td", text: "Main Items2")
+ expect(row).to have_css("td", text: "Item 2, Item 3")
+ end
+
+ within("table tbody tr", text: "Main No Items") do |row|
+ expect(row).to have_css("td", text: "Main Family")
+ expect(row).to have_css("td", text: "Main No Items")
+ expect(row).to have_css("td", text: "N/A")
+ end
+
+ within("table tbody tr", text: "Other Items") do |row|
+ expect(row).to have_css("td", text: "Other Family")
+ expect(row).to have_css("td", text: "Other Items")
+ expect(row).to have_css("td", text: "Item 1, Item 2")
+ end
+
+ within("table tbody tr", text: "Other No Items") do |row|
+ expect(row).to have_css("td", text: "Other Family")
+ expect(row).to have_css("td", text: "Other No Items")
+ expect(row).to have_css("td", text: "N/A")
+ end
+
find('input[type="submit"]').click
expect(page).to have_text("Request Details")
click_link "Your Previous Requests"
expect(page).to have_text("Request History")
- expect(Partners::ChildItemRequest.pluck(:child_id)).to match_array(children.pluck(:id))
- expect(Partners::ItemRequest.pluck(:item_id)).to match_array(children.pluck(:item_needed_diaperid).uniq)
end
end
@@ -53,7 +83,7 @@
visit partners_requests_path
find('a[aria-label="Create a request for a child or family"]').click
expect(page).to have_css("table tbody tr", count: 3)
- fill_in "Search By Guardian Name", with: "Morales"
+ fill_in "Search By Guardian Name", with: "Main Family"
expect(page).to have_text("Zeno")
expect(page).to have_text("Arthur")
expect(page).to_not have_text("Louis")
|