diff --git a/app/controllers/partners/children_controller.rb b/app/controllers/partners/children_controller.rb index 64b8033934..0c2c42ae28 100644 --- a/app/controllers/partners/children_controller.rb +++ b/app/controllers/partners/children_controller.rb @@ -88,11 +88,11 @@ def child_params :first_name, :gender, :health_insurance, - :item_needed_diaperid, :last_name, :race, :archived, - child_lives_with: [] + child_lives_with: [], + needed_item_ids: [] ) end diff --git a/app/controllers/partners/family_requests_controller.rb b/app/controllers/partners/family_requests_controller.rb index ff91b4b9bc..fdcd0a5493 100644 --- a/app/controllers/partners/family_requests_controller.rb +++ b/app/controllers/partners/family_requests_controller.rb @@ -23,9 +23,12 @@ 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(:needed_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/models/partners/child.rb b/app/models/partners/child.rb index 1421bd47a1..e0899d29a9 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 :needed_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 needed_item_ids active archived ].freeze end @@ -107,7 +108,7 @@ def csv_export_attributes created_at, updated_at, family_id, - item_needed_diaperid, + needed_item_ids, active, archived ] @@ -115,3 +116,4 @@ def csv_export_attributes end end +# TODO: drop item_needed_diaperid after issue #3797 released to prod diff --git a/app/views/partners/children/_child.json.jbuilder b/app/views/partners/children/_child.json.jbuilder index 63ae89cc65..7368b28458 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, :needed_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 5a8795941b..7cfc9747b7 100644 --- a/app/views/partners/children/_form.html.erb +++ b/app/views/partners/children/_form.html.erb @@ -17,10 +17,10 @@ <%= form.text_field :last_name, class: "form-control" %> <%= form.label :item_needed, "Diaper/Item Used" %> - <%= form.select :item_needed_diaperid, @formatted_requestable_items, - {include_blank: 'Select an item'}, - {class: 'form-control'} %> -
+ (select multiple by holding `ctrl`) + <%= form.select :needed_item_ids, @formatted_requestable_items, + {include_blank: false, include_hidden: false, selected: child.needed_item_ids}, + {class: 'form-control', multiple: true} %> <%= 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" %> diff --git a/app/views/partners/children/show.html.erb b/app/views/partners/children/show.html.erb index 45e28aa0ed..75019c664f 100644 --- a/app/views/partners/children/show.html.erb +++ b/app/views/partners/children/show.html.erb @@ -59,7 +59,11 @@
<%= @child.health_insurance %>
Item needed:
-
<%= current_partner.organization.item_id_to_display_string_map[@child.item_needed_diaperid] %>
+
+ <%= @child.needed_item_ids.map{|item_id| + current_partner.organization.item_id_to_display_string_map[item_id] + }.join(', ') %> +
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..26067ffc08 100644 --- a/app/views/partners/family_requests/_list.html.erb +++ b/app/views/partners/family_requests/_list.html.erb @@ -18,15 +18,17 @@ <%= 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.needed_item_ids.present? %> + <%= child.needed_item_ids.map{|item_id| + current_partner.organization.item_id_to_display_string_map[item_id] + }.join(', ') %> <% else %> <%= "N/A" %> <% end %>
- <% if child.item_needed_diaperid %> + <% if child.needed_item_ids.present? %> <%= check_box_tag "child-#{child.id}", child.active, child.active, class: "custom-control-input", id: "child-#{child.id}" %> diff --git a/db/migrate/20240221072117_create_join_table_child_item.rb b/db/migrate/20240221072117_create_join_table_child_item.rb new file mode 100644 index 0000000000..5be9339cfc --- /dev/null +++ b/db/migrate/20240221072117_create_join_table_child_item.rb @@ -0,0 +1,12 @@ +class CreateJoinTableChildItem < ActiveRecord::Migration[7.0] + def change + create_table :children_items do |t| + t.references :child, null: false, foreign_key: true + t.references :item, null: false, foreign_key: true + + t.timestamps + end + + add_index :children_items, [:child_id, :item_id], unique: true + end +end diff --git a/db/migrate/20240221072118_populate_needed_items.rb b/db/migrate/20240221072118_populate_needed_items.rb new file mode 100644 index 0000000000..1282600cc3 --- /dev/null +++ b/db/migrate/20240221072118_populate_needed_items.rb @@ -0,0 +1,7 @@ +class PopulateNeededItems < ActiveRecord::Migration[7.0] + def change + Partners::Child.find_each do |child| + child.needed_item_ids = [child.item_needed_diaperid] if child.item_needed_diaperid.present? + end + end +end diff --git a/db/schema.rb b/db/schema.rb index ec0fb34d6a..af530fefd2 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.0].define(version: 2024_02_07_202431) do +ActiveRecord::Schema[7.0].define(version: 2024_02_21_072118) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -188,6 +188,16 @@ t.index ["family_id"], name: "index_children_on_family_id" end + create_table "children_items", force: :cascade do |t| + t.bigint "child_id", null: false + t.bigint "item_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["child_id", "item_id"], name: "index_children_items_on_child_id_and_item_id", unique: true + t.index ["child_id"], name: "index_children_items_on_child_id" + t.index ["item_id"], name: "index_children_items_on_item_id" + end + create_table "counties", force: :cascade do |t| t.string "name" t.string "region" @@ -861,6 +871,8 @@ add_foreign_key "child_item_requests", "children" add_foreign_key "child_item_requests", "item_requests" add_foreign_key "children", "families" + add_foreign_key "children_items", "children" + add_foreign_key "children_items", "items" add_foreign_key "distributions", "partners" add_foreign_key "distributions", "storage_locations" add_foreign_key "donations", "manufacturers" diff --git a/db/seeds.rb b/db/seeds.rb index 7da24334b8..f51f19896c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -304,7 +304,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) + needed_item_ids: [p.organization.item_id_to_display_string_map.key(Partners::Child::CHILD_ITEMS.sample)] ) end @@ -322,7 +322,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) + needed_item_ids: [p.organization.item_id_to_display_string_map.key(Partners::Child::CHILD_ITEMS.sample)] ) end end diff --git a/spec/factories/partners/child.rb b/spec/factories/partners/child.rb index 6b4b60b43c..8b4339aeaa 100644 --- a/spec/factories/partners/child.rb +++ b/spec/factories/partners/child.rb @@ -9,6 +9,6 @@ first_name { Faker::Name.first_name } last_name { Faker::Name.last_name } gender { Faker::Gender.binary_type } - item_needed_diaperid { Item.all.sample.id } + needed_item_ids { [Item.all.sample.id] } end end diff --git a/spec/models/partners/child_spec.rb b/spec/models/partners/child_spec.rb index c8ace29762..ce6bdcd82b 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(:needed_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..cd3dcf1e75 100644 --- a/spec/requests/partners/children_requests_spec.rb +++ b/spec/requests/partners/children_requests_spec.rb @@ -15,7 +15,7 @@ agency_child_id: "Agency McAgence", health_insurance: "Private insurance", comments: "Some comment", - item_needed_diaperid: nil, + needed_item_ids: nil, active: true, archived: false, family: family) @@ -31,7 +31,7 @@ agency_child_id: "Agency McAgence", health_insurance: "Private insurance", comments: "Some comment", - item_needed_diaperid: nil, + needed_item_ids: nil, active: true, archived: false, family: family) @@ -51,7 +51,7 @@ 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,needed_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 CSV diff --git a/spec/requests/partners/family_requests_controller_spec.rb b/spec/requests/partners/family_requests_controller_spec.rb index 04b17f75f2..a2d3a103de 100644 --- a/spec/requests/partners/family_requests_controller_spec.rb +++ b/spec/requests/partners/family_requests_controller_spec.rb @@ -32,9 +32,9 @@ describe 'POST #create' do before do # Set one child as deactivated and the other as active but - # without a item_needed_diaperid + # without a needed items children[0].update(active: false) - children[1].update(item_needed_diaperid: nil) + children[1].needed_item_ids = [] end subject { post partners_family_requests_path, params: params } diff --git a/spec/system/partners/family_requests_system_spec.rb b/spec/system/partners/family_requests_system_spec.rb index e1030f284a..8775eba7bc 100644 --- a/spec/system/partners/family_requests_system_spec.rb +++ b/spec/system/partners/family_requests_system_spec.rb @@ -10,13 +10,13 @@ end describe "for children with different items, from different families" do - let(:item_id) { Item.all.sample.id } + let(:item_ids) { Item.pluck(:id).sample(2).sort } 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: family, needed_item_ids: item_ids), + create(:partners_child, family: family, needed_item_ids: item_ids), + create(:partners_child, family: other_family, needed_item_ids: item_ids), create(:partners_child, family: other_family) ] end @@ -28,8 +28,16 @@ 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) + + expect(children[0].child_item_requests.size).to eq(1) + expect(children[1].child_item_requests.size).to eq(2) + expect(children[2].child_item_requests.size).to eq(2) + expect(children[3].child_item_requests.size).to eq(2) + expect(children[4].child_item_requests.size).to eq(1) + expect(children[1].child_item_requests.map(&:item_request).map(&:item_id).sort).to eq(item_ids) + expect(children[2].child_item_requests.map(&:item_request).map(&:item_id).sort).to eq(item_ids) + expect(children[3].child_item_requests.map(&:item_request).map(&:item_id).sort).to eq(item_ids) + expect(Partners::ItemRequest.pluck(:item_id)).to match_array(children.map(&:needed_item_ids).flatten.uniq) end end