diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 7c8bba423e..1a837ba719 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -11,7 +11,7 @@ def index @items = @items.active unless params[:include_inactive_items] @item_categories = current_organization.item_categories.includes(:items).order('name ASC') - @kits = current_organization.kits.includes(item: {line_items: :item}) + @kits = current_organization.kits.includes(kit_item: {line_items: :item}) @storages = current_organization.storage_locations.active.order(id: :asc) @include_inactive_items = params[:include_inactive_items] diff --git a/app/controllers/kits_controller.rb b/app/controllers/kits_controller.rb index d1d43918b0..1e3d81eed5 100644 --- a/app/controllers/kits_controller.rb +++ b/app/controllers/kits_controller.rb @@ -4,7 +4,7 @@ def show end def index - @kits = current_organization.kits.includes(item: {line_items: :item}).class_filter(filter_params) + @kits = current_organization.kits.includes(kit_item: {line_items: :item}).class_filter(filter_params) @inventory = View::Inventory.new(current_organization.id) unless params[:include_inactive_items] @kits = @kits.active @@ -16,8 +16,8 @@ def new load_form_collections @kit = current_organization.kits.new - @kit.item = current_organization.items.new - @kit.item.line_items.build + @kit.kit_item = current_organization.items.new + @kit.kit_item.line_items.build end def create @@ -36,8 +36,8 @@ def create kit_only_params = kit_params.except(:line_items_attributes) @kit = Kit.new(kit_only_params) load_form_collections - @kit.item ||= current_organization.items.new(kit_params.slice(:line_items_attributes)) - @kit.item.line_items.build if @kit.item.line_items.empty? + @kit.kit_item ||= current_organization.items.new(kit_params.slice(:line_items_attributes)) + @kit.kit_item.line_items.build if @kit.kit_item.line_items.empty? render :new end diff --git a/app/events/kit_allocate_event.rb b/app/events/kit_allocate_event.rb index a71a11aeb7..46160a83a0 100644 --- a/app/events/kit_allocate_event.rb +++ b/app/events/kit_allocate_event.rb @@ -1,6 +1,6 @@ class KitAllocateEvent < Event def self.event_line_items(kit, storage_location, quantity) - items = kit.item.line_items.map do |item| + items = kit.kit_item.line_items.map do |item| EventTypes::EventLineItem.new( quantity: item.quantity * quantity, item_id: item.item_id, @@ -11,8 +11,8 @@ def self.event_line_items(kit, storage_location, quantity) end items.push(EventTypes::EventLineItem.new( quantity: quantity, - item_id: kit.item.id, - item_value_in_cents: kit.item.value_in_cents, + item_id: kit.kit_item.id, + item_value_in_cents: kit.kit_item.value_in_cents, to_storage_location: storage_location, from_storage_location: nil )) diff --git a/app/events/kit_deallocate_event.rb b/app/events/kit_deallocate_event.rb index 5ddc7366a4..26a41a387d 100644 --- a/app/events/kit_deallocate_event.rb +++ b/app/events/kit_deallocate_event.rb @@ -1,6 +1,6 @@ class KitDeallocateEvent < Event def self.event_line_items(kit, storage_location, quantity) - items = kit.item.line_items.map do |item| + items = kit.kit_item.line_items.map do |item| EventTypes::EventLineItem.new( quantity: item.quantity * quantity, item_id: item.item_id, @@ -11,8 +11,8 @@ def self.event_line_items(kit, storage_location, quantity) end items.push(EventTypes::EventLineItem.new( quantity: quantity, - item_id: kit.item.id, - item_value_in_cents: kit.item.value_in_cents, + item_id: kit.kit_item.id, + item_value_in_cents: kit.kit_item.value_in_cents, from_storage_location: storage_location, to_storage_location: nil )) diff --git a/app/models/concrete_item.rb b/app/models/concrete_item.rb new file mode 100644 index 0000000000..7a56d8f80f --- /dev/null +++ b/app/models/concrete_item.rb @@ -0,0 +1,26 @@ +# == Schema Information +# +# Table name: items +# +# id :integer not null, primary key +# active :boolean default(TRUE) +# additional_info :text +# barcode_count :integer +# distribution_quantity :integer +# name :string +# on_hand_minimum_quantity :integer default(0), not null +# on_hand_recommended_quantity :integer +# package_size :integer +# partner_key :string +# reporting_category :string +# type :string default("ConcreteItem"), not null +# value_in_cents :integer default(0) +# visible_to_partners :boolean default(TRUE), not null +# created_at :datetime not null +# updated_at :datetime not null +# item_category_id :integer +# kit_id :integer +# organization_id :integer +# +class ConcreteItem < Item +end diff --git a/app/models/item.rb b/app/models/item.rb index 12adb66f18..e9776300a6 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -13,6 +13,7 @@ # package_size :integer # partner_key :string # reporting_category :string +# type :string default("ConcreteItem"), not null # value_in_cents :integer default(0) # visible_to_partners :boolean default(TRUE), not null # created_at :datetime not null @@ -105,11 +106,11 @@ def in_request? def is_in_kit?(kits = nil) if kits - kits.any? { |k| k.item.line_items.map(&:item_id).include?(id) } + kits.any? { |k| k.kit_item.line_items.map(&:item_id).include?(id) } else organization.kits .active - .joins(item: :line_items) + .joins(kit_item: :line_items) .where(line_items: { item_id: id}).any? end end diff --git a/app/models/kit.rb b/app/models/kit.rb index 4f571b9e85..bc014c5d0a 100644 --- a/app/models/kit.rb +++ b/app/models/kit.rb @@ -17,7 +17,7 @@ class Kit < ApplicationRecord include Valuable belongs_to :organization - has_one :item, dependent: :restrict_with_exception + has_one :kit_item, dependent: :restrict_with_exception scope :active, -> { where(active: true) } scope :alphabetized, -> { order(:name) } @@ -30,23 +30,23 @@ class Kit < ApplicationRecord # @return [Boolean] def can_deactivate?(inventory = nil) inventory ||= View::Inventory.new(organization_id) - inventory.quantity_for(item_id: item.id).zero? + inventory.quantity_for(item_id: kit_item.id).zero? end def deactivate update!(active: false) - item.update!(active: false) + kit_item.update!(active: false) end # Kits can't reactivate if they have any inactive items, because now whenever they are allocated # or deallocated, we are changing inventory for inactive items (which we don't allow). # @return [Boolean] def can_reactivate? - item.line_items.joins(:item).where(items: { active: false }).none? + kit_item.line_items.joins(:kit_item).where(items: { active: false }).none? end def reactivate update!(active: true) - item.update!(active: true) + kit_item.update!(active: true) end end diff --git a/app/models/kit_item.rb b/app/models/kit_item.rb new file mode 100644 index 0000000000..9081efd30e --- /dev/null +++ b/app/models/kit_item.rb @@ -0,0 +1,29 @@ +# == Schema Information +# +# Table name: items +# +# id :integer not null, primary key +# active :boolean default(TRUE) +# additional_info :text +# barcode_count :integer +# distribution_quantity :integer +# name :string +# on_hand_minimum_quantity :integer default(0), not null +# on_hand_recommended_quantity :integer +# package_size :integer +# partner_key :string +# reporting_category :string +# type :string default("ConcreteItem"), not null +# value_in_cents :integer default(0) +# visible_to_partners :boolean default(TRUE), not null +# created_at :datetime not null +# updated_at :datetime not null +# item_category_id :integer +# kit_id :integer +# organization_id :integer +# +class KitItem < Item + # for now. Technically not optional, but since we will be changing this to be standalone (no kit), + # there isn't really a reason to enforce this at the moment. + belongs_to :kit, optional: true +end diff --git a/app/services/kit_create_service.rb b/app/services/kit_create_service.rb index 34fecebbcd..5be5670788 100644 --- a/app/services/kit_create_service.rb +++ b/app/services/kit_create_service.rb @@ -38,6 +38,7 @@ def call item_creation = ItemCreateService.new( organization_id: organization.id, item_params: { + type: 'KitItem', line_items_attributes: line_items, name: kit.name, partner_key: item_housing_a_kit_base_item.partner_key, diff --git a/app/services/reports/adult_incontinence_report_service.rb b/app/services/reports/adult_incontinence_report_service.rb index bb3f4efaae..ef77136aae 100644 --- a/app/services/reports/adult_incontinence_report_service.rb +++ b/app/services/reports/adult_incontinence_report_service.rb @@ -144,7 +144,7 @@ def distributed_kits_for_year def total_distributed_kits_containing_adult_incontinence_items_per_month kits = Kit.where(id: distributed_kits_for_year).select do |kit| - kit.item.items.adult_incontinence.exists? + kit.kit_item.items.adult_incontinence.exists? end total_assisted_adults = kits.sum do |kit| diff --git a/app/services/reports/children_served_report_service.rb b/app/services/reports/children_served_report_service.rb index 386b8edb2a..f3f818d5af 100644 --- a/app/services/reports/children_served_report_service.rb +++ b/app/services/reports/children_served_report_service.rb @@ -52,7 +52,7 @@ def children_served_with_kits_containing_disposables kits_subquery = organization .distributions .for_year(year) - .joins(line_items: { item: { kit: { item: { line_items: :item} } }}) + .joins(line_items: { item: { kit: { kit_item: { line_items: :item} } }}) .where("items_line_items.reporting_category = 'disposable_diapers'") .select("DISTINCT ON (distributions.id, line_items.id, kits.id) line_items.quantity, items.distribution_quantity") .to_sql diff --git a/app/views/kits/_form.html.erb b/app/views/kits/_form.html.erb index e5fe5ccac3..f4da7936f7 100644 --- a/app/views/kits/_form.html.erb +++ b/app/views/kits/_form.html.erb @@ -19,7 +19,7 @@ <%= f.input_field :value_in_dollars, class: "form-control", min: 0 %> <% end %> - <%= fields_for @kit.item do |ff| %> + <%= fields_for @kit.kit_item do |ff| %>
Items in this Kit
diff --git a/app/views/kits/_table.html.erb b/app/views/kits/_table.html.erb index 119ef0986f..271914d90a 100644 --- a/app/views/kits/_table.html.erb +++ b/app/views/kits/_table.html.erb @@ -13,7 +13,7 @@ <%= kit.name %> @@ -26,7 +26,7 @@ Quantity - <% @inventory.all_items.select { |i| i.item_id == kit.item.id}.each do |item| %> + <% @inventory.all_items.select { |i| i.item_id == kit.kit_item.id}.each do |item| %> <%= @inventory.storage_location_name(item.storage_location_id) %> <%= item.quantity %> diff --git a/app/views/kits/allocations.html.erb b/app/views/kits/allocations.html.erb index 7b1f943331..6d58205a03 100644 --- a/app/views/kits/allocations.html.erb +++ b/app/views/kits/allocations.html.erb @@ -51,7 +51,7 @@ <% if @inventory %> - <% @inventory.all_items.select { |i| i.item_id == @kit.item.id }.each do |ii| %> + <% @inventory.all_items.select { |i| i.item_id == @kit.kit_item.id }.each do |ii| %> <%= @inventory.storage_location_name(ii.storage_location_id) %> @@ -100,7 +100,7 @@ <%= @kit.name %> - <% @kit.item.line_items.each do |li| %> + <% @kit.kit_item.line_items.each do |li| %> <%= li.item.name %> diff --git a/db/migrate/20260313201123_add_type_to_items.rb b/db/migrate/20260313201123_add_type_to_items.rb new file mode 100644 index 0000000000..0c5dde71c6 --- /dev/null +++ b/db/migrate/20260313201123_add_type_to_items.rb @@ -0,0 +1,11 @@ +class AddTypeToItems < ActiveRecord::Migration[8.0] + def up + add_column :items, :type, :string, default: 'ConcreteItem', null: false + Item.where.not(kit_id: nil).update_all(type: 'KitItem', updated_at: Time.zone.now) + end + + def down + add_column :items, :type, :string, default: 'ConcreteItem', null: false + end + +end diff --git a/db/schema.rb b/db/schema.rb index b1ce1c0540..6763e951c6 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[8.0].define(version: 2025_10_07_141240) do +ActiveRecord::Schema[8.0].define(version: 2026_03_13_201123) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" @@ -231,21 +231,6 @@ t.index ["user_id"], name: "index_deprecated_feedback_messages_on_user_id" end - create_table "diaper_drive_participants", id: :serial, force: :cascade do |t| - t.string "contact_name" - t.string "email" - t.string "phone" - t.string "comment" - t.integer "organization_id" - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.string "address" - t.string "business_name" - t.float "latitude" - t.float "longitude" - t.index ["latitude", "longitude"], name: "index_diaper_drive_participants_on_latitude_and_longitude" - end - create_table "distributions", id: :serial, force: :cascade do |t| t.text "comment" t.datetime "created_at", precision: nil, null: false @@ -341,16 +326,6 @@ t.index ["partner_id"], name: "index_families_on_partner_id" end - create_table "feedback_messages", force: :cascade do |t| - t.bigint "user_id" - t.string "message" - t.string "path" - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.boolean "resolved" - t.index ["user_id"], name: "index_feedback_messages_on_user_id" - end - create_table "flipper_features", force: :cascade do |t| t.string "key", null: false t.datetime "created_at", precision: nil, null: false @@ -433,6 +408,7 @@ t.integer "item_category_id" t.text "additional_info" t.string "reporting_category" + t.string "type", default: "ConcreteItem", null: false t.index ["kit_id"], name: "index_items_on_kit_id" t.index ["organization_id"], name: "index_items_on_organization_id" t.index ["partner_key"], name: "index_items_on_partner_key" @@ -519,9 +495,9 @@ t.boolean "signature_for_distribution_pdf", default: false t.boolean "receive_email_on_requests", default: false, null: false t.boolean "include_in_kind_values_in_exported_files", default: false, null: false + t.boolean "bank_is_set_up", default: false, null: false t.string "reminder_schedule_definition" t.boolean "include_packages_in_distribution_export", default: false, null: false - t.boolean "bank_is_set_up", default: false, null: false t.index ["latitude", "longitude"], name: "index_organizations_on_latitude_and_longitude" end @@ -543,10 +519,11 @@ t.string "reminder_schedule_definition" t.index ["name", "organization_id"], name: "index_partner_groups_on_name_and_organization_id", unique: true t.index ["organization_id"], name: "index_partner_groups_on_organization_id" - t.check_constraint "deadline_day <= 28", name: "deadline_day_of_month_check" - t.check_constraint "reminder_day <= 28", name: "reminder_day_of_month_check" end + add_check_constraint "partner_groups", "deadline_day <= 28", name: "deadline_day_of_month_check", validate: false + add_check_constraint "partner_groups", "reminder_day <= 28", name: "reminder_day_of_month_check", validate: false + create_table "partner_profiles", force: :cascade do |t| t.bigint "essentials_bank_id" t.integer "partner_id" diff --git a/db/seeds.rb b/db/seeds.rb index 1afec0ea4b..41f81c0a9c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -855,12 +855,12 @@ def seed_quantity(item_name, organization, storage_location, quantity) complete_orgs.each do |org| org.storage_locations.active.each do |storage_location| org.kits.active.each do |kit| - next unless kit.item # Ensure kit has an associated item + next unless kit.kit_item # Ensure kit has an associated item # Create inventory for each kit InventoryItem.create!( storage_location: storage_location, - item: kit.item, + item: kit.kit_item, quantity: Faker::Number.within(range: 10..50) ) end diff --git a/spec/events/inventory_aggregate_spec.rb b/spec/events/inventory_aggregate_spec.rb index d1f683c09a..1c2df363fb 100644 --- a/spec/events/inventory_aggregate_spec.rb +++ b/spec/events/inventory_aggregate_spec.rb @@ -404,7 +404,7 @@ item1.id => EventTypes::EventItem.new(item_id: item1.id, quantity: 10, storage_location_id: storage_location1.id), item2.id => EventTypes::EventItem.new(item_id: item2.id, quantity: 4, storage_location_id: storage_location1.id), item3.id => EventTypes::EventItem.new(item_id: item3.id, quantity: 40, storage_location_id: storage_location1.id), - kit.item.id => EventTypes::EventItem.new(item_id: kit.item.id, quantity: 2, storage_location_id: storage_location1.id) + kit.kit_item.id => EventTypes::EventItem.new(item_id: kit.kit_item.id, quantity: 2, storage_location_id: storage_location1.id) } ), storage_location2.id => EventTypes::EventStorageLocation.new( @@ -430,7 +430,7 @@ item1.id => 30, item2.id => 10, item3.id => 40, - kit.item.id => 3 + kit.kit_item.id => 3 }, storage_location2.id => { item2.id => 10, @@ -439,9 +439,9 @@ }) inventory = InventoryAggregate.inventory_for(organization.id) # reload - kit.item.line_items = [] - kit.item.line_items << build(:line_item, quantity: 20, item: item1, itemizable: kit.item) - kit.item.line_items << build(:line_item, quantity: 5, item: item2, itemizable: kit.item) + kit.kit_item.line_items = [] + kit.kit_item.line_items << build(:line_item, quantity: 20, item: item1, itemizable: kit.kit_item) + kit.kit_item.line_items << build(:line_item, quantity: 5, item: item2, itemizable: kit.kit_item) KitDeallocateEvent.publish(kit, storage_location1.id, 2) # 30 + (20*2) = 70, 10 + (5*2) = 20 @@ -456,7 +456,7 @@ item1.id => EventTypes::EventItem.new(item_id: item1.id, quantity: 70, storage_location_id: storage_location1.id), item2.id => EventTypes::EventItem.new(item_id: item2.id, quantity: 20, storage_location_id: storage_location1.id), item3.id => EventTypes::EventItem.new(item_id: item3.id, quantity: 40, storage_location_id: storage_location1.id), - kit.item.id => EventTypes::EventItem.new(item_id: kit.item.id, quantity: 1, storage_location_id: storage_location1.id) + kit.kit_item.id => EventTypes::EventItem.new(item_id: kit.kit_item.id, quantity: 1, storage_location_id: storage_location1.id) } ), storage_location2.id => EventTypes::EventStorageLocation.new( diff --git a/spec/factories/items.rb b/spec/factories/items.rb index 1f87ad94ea..853697300e 100644 --- a/spec/factories/items.rb +++ b/spec/factories/items.rb @@ -13,6 +13,7 @@ # package_size :integer # partner_key :string # reporting_category :string +# type :string default("ConcreteItem"), not null # value_in_cents :integer default(0) # visible_to_partners :boolean default(TRUE), not null # created_at :datetime not null diff --git a/spec/factories/kit_items.rb b/spec/factories/kit_items.rb new file mode 100644 index 0000000000..dcf652ad7a --- /dev/null +++ b/spec/factories/kit_items.rb @@ -0,0 +1,15 @@ +FactoryBot.define do + factory :kit_item do + sequence(:name) { |n| "#{n} - Dont test this" } + partner_key { nil } + reporting_category { kit ? nil : "disposable_diapers" } + organization + + # Once we start using this directly, we should start adding line items by default same as kit + # after(:build) do |instance, _| + # if instance.line_items.blank? + # instance.line_items << build(:line_item, item: create(:item, organization: instance.organization), itemizable: nil) + # end + # end + end +end diff --git a/spec/factories/kits.rb b/spec/factories/kits.rb index 2530e2e735..5047ad9e2d 100644 --- a/spec/factories/kits.rb +++ b/spec/factories/kits.rb @@ -17,9 +17,9 @@ organization after(:build) do |instance, _| - instance.item ||= build(:item, organization: instance.organization) - if instance.item.line_items.blank? - instance.item.line_items << build(:line_item, item: create(:item, organization: instance.organization), itemizable: nil) + instance.kit_item ||= build(:kit_item, organization: instance.organization) + if instance.kit_item.line_items.blank? + instance.kit_item.line_items << build(:line_item, item: create(:item, organization: instance.organization), itemizable: nil) end end diff --git a/spec/models/item_spec.rb b/spec/models/item_spec.rb index 5f9e28e485..be3a877c1e 100644 --- a/spec/models/item_spec.rb +++ b/spec/models/item_spec.rb @@ -13,6 +13,7 @@ # package_size :integer # partner_key :string # reporting_category :string +# type :string default("ConcreteItem"), not null # value_in_cents :integer default(0) # visible_to_partners :boolean default(TRUE), not null # created_at :datetime not null @@ -42,6 +43,9 @@ it { should validate_numericality_of(:on_hand_recommended_quantity).is_greater_than_or_equal_to(0) } it { should validate_length_of(:additional_info).is_at_most(500) } it { should validate_numericality_of(:package_size).is_greater_than_or_equal_to(0) } + it 'should be a concrete item by default' do + expect(build(:item)).to be_a_kind_of(ConcreteItem) + end end context "Filtering >" do @@ -308,7 +312,7 @@ it 'deactivates the kit if it exists' do kit = create(:kit) - item = create(:item, kit: kit) + item = create(:kit_item, kit: kit) expect(kit).to be_active item.deactivate! expect(item).not_to be_active @@ -339,7 +343,7 @@ it "should not succeed" do allow(item).to receive(:can_delete?).and_return(false) expect { item.destroy! } - .to raise_error(/Failed to destroy Item/) + .to raise_error(/Failed to destroy ConcreteItem/) .and not_change { Item.count } expect(item.errors.full_messages).to eq(["Cannot delete item - it has already been used!"]) end @@ -479,7 +483,7 @@ let(:organization) { create(:organization) } let(:base_item) { create(:base_item, name: "Kit") } let(:kit) { create(:kit, organization: organization) } - let(:kit_item) { create(:item, kit: kit, organization: organization, base_item: base_item) } + let(:kit_item) { create(:kit_item, kit: kit, organization: organization, base_item: base_item) } let(:regular_item) { create(:item, organization: organization) } it "has no reporting category" do diff --git a/spec/models/kit_spec.rb b/spec/models/kit_spec.rb index a1593be354..770ff664e8 100644 --- a/spec/models/kit_spec.rb +++ b/spec/models/kit_spec.rb @@ -32,18 +32,18 @@ end it "ensures the associated line_items are invalid with a nil quantity" do - kit.item.line_items << build(:line_item, quantity: nil) - expect(kit.item).not_to be_valid + kit.kit_item.line_items << build(:line_item, quantity: nil) + expect(kit.kit_item).not_to be_valid end it "ensures the associated line_items are invalid with a zero quantity" do - kit.item.line_items << build(:line_item, quantity: 0) - expect(kit.item).not_to be_valid + kit.kit_item.line_items << build(:line_item, quantity: 0) + expect(kit.kit_item).not_to be_valid end it "ensures the associated line_items are valid with a one quantity" do - kit.item.line_items << build(:line_item, quantity: 1) - expect(kit.item).to be_valid + kit.kit_item.line_items << build(:line_item, quantity: 1) + expect(kit.kit_item).to be_valid end end @@ -69,11 +69,11 @@ context "Value >" do describe ".value_per_itemizable" do it "calculates values from associated items" do - kit.item.line_items = [ + kit.kit_item.line_items = [ create(:line_item, quantity: 1, item: create(:item, value_in_cents: 100)), create(:line_item, quantity: 1, item: create(:item, value_in_cents: 90)) ] - expect(kit.item.value_per_itemizable).to eq(190) + expect(kit.kit_item.value_per_itemizable).to eq(190) end end @@ -99,7 +99,7 @@ TestInventory.create_inventory(organization, { storage_location.id => { - kit.item.id => 10 + kit.kit_item.id => 10 } }) expect(kit.reload.can_deactivate?).to eq(false) @@ -116,13 +116,13 @@ specify 'deactivate and reactivate' do kit = create_kit(organization: organization) expect(kit.active).to eq(true) - expect(kit.item.active).to eq(true) + expect(kit.kit_item.active).to eq(true) kit.deactivate expect(kit.active).to eq(false) - expect(kit.item.active).to eq(false) + expect(kit.kit_item.active).to eq(false) kit.reactivate expect(kit.active).to eq(true) - expect(kit.item.active).to eq(true) + expect(kit.kit_item.active).to eq(true) end describe "versioning" do diff --git a/spec/requests/kit_requests_spec.rb b/spec/requests/kit_requests_spec.rb index b2ab7da695..fc99c50345 100644 --- a/spec/requests/kit_requests_spec.rb +++ b/spec/requests/kit_requests_spec.rb @@ -40,7 +40,7 @@ storage_location = create(:storage_location) TestInventory.create_inventory(kit.organization, { storage_location.id => { - kit.item.id => 10 + kit.kit_item.id => 10 } }) get kits_url @@ -83,7 +83,7 @@ it "cannot reactivate if it has an inactive item" do kit.deactivate expect(kit).not_to be_active - kit.item.line_items.first.item.update!(active: false) + kit.kit_item.line_items.first.kit_item.update!(active: false) put reactivate_kit_url(kit) expect(kit.reload).not_to be_active diff --git a/spec/services/kit_create_service_spec.rb b/spec/services/kit_create_service_spec.rb index 7eed75e08a..ff2a589904 100644 --- a/spec/services/kit_create_service_spec.rb +++ b/spec/services/kit_create_service_spec.rb @@ -33,11 +33,12 @@ it 'should create a new Kit' do expect { subject }.to change { Kit.all.count }.by(1) kit = Kit.last - expect(kit.item.line_items.count).to eq(3) + expect(kit.kit_item.line_items.count).to eq(3) end it 'should create a new Item' do - expect { subject }.to change { Item.all.count }.by(1) + expect { subject }.to change { KitItem.all.count }.by(1) + expect(KitItem.last.kit).to eq(Kit.last) end it 'should create the new Item associated with the Kit' do @@ -55,7 +56,7 @@ end it 'should not create a Item' do - expect { subject }.not_to change { Item.all.count } + expect { subject }.not_to change { KitItem.all.count } end it 'should have an error that includes the raised error' do @@ -76,7 +77,7 @@ end it 'should not create a Item' do - expect { subject }.not_to change { Item.all.count } + expect { subject }.not_to change { KitItem.all.count } end it 'should have an error that includes the error' do diff --git a/spec/services/reports/adult_incontinence_report_service_spec.rb b/spec/services/reports/adult_incontinence_report_service_spec.rb index 557c90bb71..64bc9a7e73 100644 --- a/spec/services/reports/adult_incontinence_report_service_spec.rb +++ b/spec/services/reports/adult_incontinence_report_service_spec.rb @@ -33,29 +33,46 @@ end describe 'with values' do - before(:each) do - within_time = Time.zone.parse("2020-05-31 14:00:00") - outside_time = Time.zone.parse("2019-05-31 14:00:00") + let(:within_time) { Time.zone.parse("2020-05-31 14:00:00") } + let(:outside_time) { Time.zone.parse("2019-05-31 14:00:00") } + + # Concrete items that go inside kits + let!(:ai_concrete_1) { create(:item, name: "Adult Briefs (Medium)", reporting_category: "adult_incontinence", organization: organization) } + let!(:ai_concrete_2) { create(:item, name: "Adult Briefs (Large)", reporting_category: "adult_incontinence", organization: organization) } + let!(:ai_concrete_3) { create(:item, name: "Adult Briefs (Small)", reporting_category: "adult_incontinence", organization: organization) } + let!(:non_ai_concrete) { create(:item, name: "Baby Wipes", reporting_category: "other", organization: organization) } + + # Create kits and configure their kit_items with concrete items + let!(:kit_1) do + kit = create(:kit, organization: organization) + kit.kit_item.update!(distribution_quantity: 1) + kit.kit_item.line_items = [create(:line_item, item: ai_concrete_1, quantity: 5)] + kit + end - adult_incontinence_item = organization.items.adult_incontinence.first - non_adult_incontinence_item = organization.items.where.not(id: organization.items.adult_incontinence).first + let!(:kit_2) do + kit = create(:kit, organization: organization) + kit.kit_item.update!(distribution_quantity: 1) + kit.kit_item.line_items = [create(:line_item, item: ai_concrete_2, quantity: 5)] + kit + end - # kit items (each item represents a kit and contains itself as a component) - adult_incontinence_kit_item_1 = create(:item, name: "Adult Briefs (Medium)", reporting_category: "adult_incontinence", distribution_quantity: 1, organization: organization) - adult_incontinence_kit_item_2 = create(:item, name: "Adult Briefs (Large)", reporting_category: "adult_incontinence", distribution_quantity: 1, organization: organization) - adult_incontinence_kit_item_3 = create(:item, name: "Adult Briefs (Small)", reporting_category: "adult_incontinence", distribution_quantity: 1, organization: organization) - non_adult_incontinence_kit_item = create(:item, name: "Baby Wipes", reporting_category: "other", organization: organization) + let!(:kit_4) do + kit = create(:kit, organization: organization) + kit.kit_item.update!(distribution_quantity: 1) + kit.kit_item.line_items = [create(:line_item, item: ai_concrete_3, quantity: 5)] + kit + end - # Add component line items to each kit item - adult_incontinence_kit_item_1.line_items.create!(item: adult_incontinence_kit_item_1, quantity: 5) - adult_incontinence_kit_item_2.line_items.create!(item: adult_incontinence_kit_item_2, quantity: 5) - adult_incontinence_kit_item_3.line_items.create!(item: adult_incontinence_kit_item_3, quantity: 5) - non_adult_incontinence_kit_item.line_items.create!(item: non_adult_incontinence_kit_item, quantity: 5) + let!(:kit_3) do + kit = create(:kit, organization: organization) + kit.kit_item.line_items = [create(:line_item, item: non_ai_concrete, quantity: 5)] + kit + end - @kit_1 = create(:kit, organization: organization, item: adult_incontinence_kit_item_1) - @kit_2 = create(:kit, organization: organization, item: adult_incontinence_kit_item_2) - @kit_4 = create(:kit, organization: organization, item: adult_incontinence_kit_item_3) - @kit_3 = create(:kit, organization: organization, item: non_adult_incontinence_kit_item) + before(:each) do + adult_incontinence_item = organization.items.adult_incontinence.first + non_adult_incontinence_item = organization.items.where.not(id: organization.items.adult_incontinence).first # kit distributions kit_distribution_1 = create(:distribution, organization: organization, issued_at: within_time) @@ -64,11 +81,11 @@ # wipes distribution kit_distribution_3 = create(:distribution, organization: organization, issued_at: within_time) - create(:line_item, :distribution, quantity: 100, item: @kit_1.item, itemizable: kit_distribution_1) - create(:line_item, :distribution, quantity: 100, item: @kit_2.item, itemizable: kit_distribution_2) - create(:line_item, :distribution, quantity: 100, item: @kit_4.item, itemizable: kit_distribution_4) + create(:line_item, :distribution, quantity: 100, item: kit_1.kit_item, itemizable: kit_distribution_1) + create(:line_item, :distribution, quantity: 100, item: kit_2.kit_item, itemizable: kit_distribution_2) + create(:line_item, :distribution, quantity: 100, item: kit_4.kit_item, itemizable: kit_distribution_4) # wipes kit no ai items - create(:line_item, :distribution, quantity: 100, item: @kit_3.item, itemizable: kit_distribution_3) + create(:line_item, :distribution, quantity: 100, item: kit_3.kit_item, itemizable: kit_distribution_3) # We will create data both within and outside our date range, and both adult_incontinence and non adult_incontinence. # Spec will ensure that only the required data is included. @@ -141,7 +158,7 @@ it "should return the kits distributed within a specific year" do result = report.distributed_kits_for_year - expect(result.to_a).to match_array([@kit_1.id, @kit_2.id, @kit_3.id, @kit_4.id]) + expect(result.to_a).to match_array([kit_1.id, kit_2.id, kit_3.id, kit_4.id]) end it 'should report normal values' do @@ -151,8 +168,8 @@ "% adult incontinence bought" => "60%", "% adult incontinence supplies donated" => "40%", "Adults Assisted Per Month" => 233.33, - "Adult incontinence supplies distributed" => "51,800", - "Adult incontinence supplies per adult per month" => 18.5, + "Adult incontinence supplies distributed" => "51,500", + "Adult incontinence supplies per adult per month" => 18.39, "Money spent purchasing adult incontinence supplies" => "$30.00" })) expect(report.report[:entries]['Adult incontinence supplies'].split(', ')) @@ -178,9 +195,9 @@ expect(report.report[:entries]).to match(hash_including({ "% adult incontinence bought" => "60%", "% adult incontinence supplies donated" => "40%", - "Adult incontinence supplies distributed" => "51,800", + "Adult incontinence supplies distributed" => "51,500", "Adults Assisted Per Month" => 108.33, - "Adult incontinence supplies per adult per month" => 39.85, + "Adult incontinence supplies per adult per month" => 39.62, "Money spent purchasing adult incontinence supplies" => "$30.00" })) expect(report.report[:entries]['Adult incontinence supplies'].split(', ')) diff --git a/spec/services/reports/children_served_report_service_spec.rb b/spec/services/reports/children_served_report_service_spec.rb index c715282780..90976349d6 100644 --- a/spec/services/reports/children_served_report_service_spec.rb +++ b/spec/services/reports/children_served_report_service_spec.rb @@ -30,19 +30,19 @@ infant_disposable_kit_item = create(:item, name: "Infant Disposable Diapers", reporting_category: :disposable_diapers) kit_1 = create(:kit, organization: organization) - kit_1.item.line_items = [ + kit_1.kit_item.line_items = [ create(:line_item, item: toddler_disposable_kit_item), create(:line_item, item: infant_disposable_kit_item) ] kit_2 = create(:kit, organization: organization) - kit_2.item.line_items = [ + kit_2.kit_item.line_items = [ create(:line_item, item: toddler_disposable_kit_item), create(:line_item, item: infant_disposable_kit_item) ] - create(:item, name: "Kit 1", kit: kit_1, organization:, distribution_quantity: 1) - create(:item, name: "Kit 2", kit: kit_2, organization:, distribution_quantity: 1) + create(:kit_item, name: "Kit 1", kit: kit_1, organization:, distribution_quantity: 1) + create(:kit_item, name: "Kit 2", kit: kit_2, organization:, distribution_quantity: 1) # Distributions distributions = create_list(:distribution, 2, issued_at: within_time, organization: organization) @@ -55,10 +55,10 @@ infant_distribution = create(:distribution, organization: organization, issued_at: within_time) toddler_distribution = create(:distribution, organization: organization, issued_at: within_time) - create(:line_item, quantity: 5, item: kit_1.item, itemizable: infant_distribution) - create(:line_item, quantity: 5, item: kit_1.item, itemizable: toddler_distribution) - create(:line_item, quantity: 5, item: kit_2.item, itemizable: infant_distribution) - create(:line_item, quantity: 5, item: kit_2.item, itemizable: toddler_distribution) + create(:line_item, quantity: 5, item: kit_1.kit_item, itemizable: infant_distribution) + create(:line_item, quantity: 5, item: kit_1.kit_item, itemizable: toddler_distribution) + create(:line_item, quantity: 5, item: kit_2.kit_item, itemizable: infant_distribution) + create(:line_item, quantity: 5, item: kit_2.kit_item, itemizable: toddler_distribution) report = described_class.new(organization: organization, year: within_time.year).report expect(report).to eq({ @@ -86,12 +86,12 @@ infant_disposable_kit_item = create(:item, name: "Infant Disposable Diapers", reporting_category: :disposable_diapers) kit = create(:kit, organization: organization) - kit.item.line_items = [ + kit.kit_item.line_items = [ create(:line_item, item: toddler_disposable_kit_item), create(:line_item, item: infant_disposable_kit_item) ] - create(:item, name: "Kit 1", kit:, organization:, distribution_quantity: 1) + create(:kit_item, name: "Kit 1", kit:, organization:, distribution_quantity: 1) # Distributions distributions = create_list(:distribution, 2, issued_at: within_time, organization: organization) @@ -104,8 +104,8 @@ infant_distribution = create(:distribution, organization: organization, issued_at: within_time) toddler_distribution = create(:distribution, organization: organization, issued_at: within_time) - create(:line_item, quantity: 10, item: kit.item, itemizable: infant_distribution) - create(:line_item, quantity: 10, item: kit.item, itemizable: toddler_distribution) + create(:line_item, quantity: 10, item: kit.kit_item, itemizable: infant_distribution) + create(:line_item, quantity: 10, item: kit.kit_item, itemizable: toddler_distribution) report = described_class.new(organization: organization, year: within_time.year).report expect(report).to eq({ @@ -128,20 +128,20 @@ # this quantity shouldn't matter so I'm setting it to a high number to ensure it isn't used kit = create(:kit, organization: organization) - kit.item.line_items = [ + kit.kit_item.line_items = [ create(:line_item, quantity: 1000, item: toddler_disposable_kit_item), create(:line_item, quantity: 1000, item: infant_disposable_kit_item), create(:line_item, quantity: 1000, item: not_disposable_kit_item) ] - create(:item, name: "Kit 1", kit:, organization:, distribution_quantity: 3) + create(:kit_item, name: "Kit 1", kit:, organization:, distribution_quantity: 3) # Distributions toddler_distribution = create(:distribution, organization: organization, issued_at: within_time) infant_distribution = create(:distribution, organization: organization, issued_at: within_time) [toddler_distribution, infant_distribution].each do |distribution| - create(:line_item, quantity: 2, item: kit.item, itemizable: distribution) + create(:line_item, quantity: 2, item: kit.kit_item, itemizable: distribution) end report = described_class.new(organization: organization, year: within_time.year).report diff --git a/spec/services/reports/diaper_report_service_spec.rb b/spec/services/reports/diaper_report_service_spec.rb index 17cd564b38..186d00c542 100644 --- a/spec/services/reports/diaper_report_service_spec.rb +++ b/spec/services/reports/diaper_report_service_spec.rb @@ -23,8 +23,8 @@ disposable_kit_item_distribution = create(:distribution, organization: organization, issued_at: within_time) another_disposable_kit_item_distribution = create(:distribution, organization: organization, issued_at: within_time) - create(:line_item, :distribution, quantity: 10, item: disposable_kit.item, itemizable: disposable_kit_item_distribution) - create(:line_item, :distribution, quantity: 10, item: another_disposable_kit.item, itemizable: another_disposable_kit_item_distribution) + create(:line_item, :distribution, quantity: 10, item: disposable_kit.kit_item, itemizable: disposable_kit_item_distribution) + create(:line_item, :distribution, quantity: 10, item: another_disposable_kit.kit_item, itemizable: another_disposable_kit_item_distribution) # Total disposable items distributed so far: 5*10 + 5*10 = 100 # create disposable and non disposable items diff --git a/spec/services/reports/period_supply_report_service_spec.rb b/spec/services/reports/period_supply_report_service_spec.rb index b5ac34f4b1..10fd1a7326 100644 --- a/spec/services/reports/period_supply_report_service_spec.rb +++ b/spec/services/reports/period_supply_report_service_spec.rb @@ -44,13 +44,13 @@ another_period_supplies_kit_item = create(:item, name: "Adult Tampons", reporting_category: :tampons, organization:) purchased_period_supplies_kit_item = create(:item, name: "Liners", reporting_category: :period_liners, organization:) - period_supplies_kit.item.line_items.first.update!(item_id: period_supplies_kit_item.id, quantity: 5) - another_period_supply_kit.item.line_items.first.update!(item_id: another_period_supplies_kit_item.id, quantity: 5) - donated_period_supply_kit.item.line_items.first.update!(item_id: another_period_supplies_kit_item.id, quantity: 5) - purchased_period_supply_kit.item.line_items.first.update!(item_id: purchased_period_supplies_kit_item.id, quantity: 5) + period_supplies_kit.kit_item.line_items.first.update!(item_id: period_supplies_kit_item.id, quantity: 5) + another_period_supply_kit.kit_item.line_items.first.update!(item_id: another_period_supplies_kit_item.id, quantity: 5) + donated_period_supply_kit.kit_item.line_items.first.update!(item_id: another_period_supplies_kit_item.id, quantity: 5) + purchased_period_supply_kit.kit_item.line_items.first.update!(item_id: purchased_period_supplies_kit_item.id, quantity: 5) - pad_and_tampon_kit.item.line_items.first.update!(item_id: period_supplies_kit_item.id, quantity: 10) - pad_and_tampon_kit.item.line_items.first.update!(item_id: another_period_supplies_kit_item.id, quantity: 10) + pad_and_tampon_kit.kit_item.line_items.first.update!(item_id: period_supplies_kit_item.id, quantity: 10) + pad_and_tampon_kit.kit_item.line_items.first.update!(item_id: another_period_supplies_kit_item.id, quantity: 10) period_supplies_kit_distribution = create(:distribution, organization: organization, issued_at: within_time) another_period_supplies_kit_distribution = create(:distribution, organization: organization, issued_at: within_time) @@ -63,15 +63,15 @@ create(:line_item, :purchase, item: purchased_period_supplies_kit_item, quantity: 5) ]) - create(:line_item, :distribution, quantity: 10, item: period_supplies_kit.item, itemizable: period_supplies_kit_distribution) - create(:line_item, :distribution, quantity: 10, item: another_period_supply_kit.item, itemizable: another_period_supplies_kit_distribution) + create(:line_item, :distribution, quantity: 10, item: period_supplies_kit.kit_item, itemizable: period_supplies_kit_distribution) + create(:line_item, :distribution, quantity: 10, item: another_period_supply_kit.kit_item, itemizable: another_period_supplies_kit_distribution) - create(:line_item, :distribution, quantity: 10, item: pad_and_tampon_kit.item, itemizable: pad_and_tampon_kit_distribution) - create(:line_item, :distribution, quantity: 10, item: pad_and_tampon_kit.item, itemizable: pad_and_tampon_kit_distribution) + create(:line_item, :distribution, quantity: 10, item: pad_and_tampon_kit.kit_item, itemizable: pad_and_tampon_kit_distribution) + create(:line_item, :distribution, quantity: 10, item: pad_and_tampon_kit.kit_item, itemizable: pad_and_tampon_kit_distribution) - create(:line_item, :donation, quantity: 10, item: donated_period_supply_kit.item, itemizable: kit_donation) + create(:line_item, :donation, quantity: 10, item: donated_period_supply_kit.kit_item, itemizable: kit_donation) - create(:line_item, :purchase, quantity: 30, item: purchased_period_supply_kit.item, itemizable: kit_purchase) + create(:line_item, :purchase, quantity: 30, item: purchased_period_supply_kit.kit_item, itemizable: kit_purchase) # Distributions distributions = create_list(:distribution, 2, issued_at: within_time, organization: organization) diff --git a/spec/system/kit_system_spec.rb b/spec/system/kit_system_spec.rb index 840d8df3cb..11c292f8ab 100644 --- a/spec/system/kit_system_spec.rb +++ b/spec/system/kit_system_spec.rb @@ -84,7 +84,7 @@ click_on 'Modify Allocation' inventory = View::Inventory.new(organization.id) - original_kit_count = inventory.quantity_for(item_id: existing_kit.item.id, storage_location: storage_location.id) + original_kit_count = inventory.quantity_for(item_id: existing_kit.kit_item.id, storage_location: storage_location.id) original_item_1_count = inventory.quantity_for(item_id: existing_kit_item_1.id, storage_location: storage_location.id) original_item_2_count = inventory.quantity_for(item_id: existing_kit_item_2.id, storage_location: storage_location.id) @@ -102,7 +102,7 @@ inventory.reload # Check that the kit quantity increased by the expected amount - expect(inventory.quantity_for(item_id: existing_kit.item.id, storage_location: storage_location.id)).to eq(2) + expect(inventory.quantity_for(item_id: existing_kit.kit_item.id, storage_location: storage_location.id)).to eq(2) # Ensure each of the contained items decrease the correct amount expect(inventory.quantity_for(item_id: existing_kit_item_1.id, storage_location: storage_location.id)).to eq(40) @@ -116,7 +116,7 @@ click_on 'Save' inventory.reload - expect(inventory.quantity_for(item_id: existing_kit.item.id, storage_location: storage_location.id)).to eq(0) + expect(inventory.quantity_for(item_id: existing_kit.kit_item.id, storage_location: storage_location.id)).to eq(0) expect(inventory.quantity_for(item_id: existing_kit_item_1.id, storage_location: storage_location.id)).to eq(50) expect(inventory.quantity_for(item_id: existing_kit_item_2.id, storage_location: storage_location.id)).to eq(50) end @@ -145,7 +145,7 @@ click_on 'Modify Allocation' inventory = View::Inventory.new(organization.id) - original_kit_count = inventory.quantity_for(item_id: existing_kit.item.id, storage_location: storage_location.id) + original_kit_count = inventory.quantity_for(item_id: existing_kit.kit_item.id, storage_location: storage_location.id) original_item_1_count = inventory.quantity_for(item_id: existing_kit_item_1.id, storage_location: storage_location.id) original_item_2_count = inventory.quantity_for(item_id: existing_kit_item_2.id, storage_location: storage_location.id) @@ -161,7 +161,7 @@ click_on 'Save' inventory.reload - expect(inventory.quantity_for(item_id: existing_kit.item.id, storage_location: storage_location.id)).to eq(0) + expect(inventory.quantity_for(item_id: existing_kit.kit_item.id, storage_location: storage_location.id)).to eq(0) expect(inventory.quantity_for(item_id: existing_kit_item_1.id, storage_location: storage_location.id)).to eq(0) expect(inventory.quantity_for(item_id: existing_kit_item_2.id, storage_location: storage_location.id)).to eq(0) end @@ -172,7 +172,7 @@ # Force there to be no kit quantity available TestInventory.create_inventory(organization, { storage_location.id => { - existing_kit.item.id => 0, + existing_kit.kit_item.id => 0, existing_kit_item_1.id => 50, existing_kit_item_2.id => 50 } @@ -185,7 +185,7 @@ click_on 'Modify Allocation' inventory = View::Inventory.new(organization.id) - original_kit_count = inventory.quantity_for(item_id: existing_kit.item.id, storage_location: storage_location.id) + original_kit_count = inventory.quantity_for(item_id: existing_kit.kit_item.id, storage_location: storage_location.id) original_item_1_count = inventory.quantity_for(item_id: existing_kit_item_1.id, storage_location: storage_location.id) original_item_2_count = inventory.quantity_for(item_id: existing_kit_item_2.id, storage_location: storage_location.id) @@ -201,7 +201,7 @@ click_on 'Save' inventory.reload - expect(inventory.quantity_for(item_id: existing_kit.item.id, storage_location: storage_location.id)).to eq(0) + expect(inventory.quantity_for(item_id: existing_kit.kit_item.id, storage_location: storage_location.id)).to eq(0) expect(inventory.quantity_for(item_id: existing_kit_item_1.id, storage_location: storage_location.id)).to eq(50) expect(inventory.quantity_for(item_id: existing_kit_item_2.id, storage_location: storage_location.id)).to eq(50) end