Skip to content

Commit

Permalink
Merge pull request #4306 from rubyforgood/4096-packs-models
Browse files Browse the repository at this point in the history
Add models to support request units
  • Loading branch information
cielf authored May 24, 2024
2 parents 58cbea9 + e2fe2a3 commit b8e9ea0
Show file tree
Hide file tree
Showing 14 changed files with 211 additions and 5 deletions.
1 change: 1 addition & 0 deletions app/models/item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class Item < ApplicationRecord
has_many :storage_locations, through: :inventory_items
has_many :donations, through: :line_items, source: :itemizable, source_type: "::Donation"
has_many :distributions, through: :line_items, source: :itemizable, source_type: "::Distribution"
has_many :request_units, class_name: "ItemUnit", dependent: :destroy

scope :active, -> { where(active: true) }

Expand Down
20 changes: 20 additions & 0 deletions app/models/item_unit.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# == Schema Information
#
# Table name: item_units
#
# id :bigint not null, primary key
# name :string not null
# created_at :datetime not null
# updated_at :datetime not null
# item_id :bigint
#
class ItemUnit < ApplicationRecord
belongs_to :item

validate do
names = item.organization.request_units.map(&:name)
unless names.include?(name)
errors.add(:name, "is not supported by the organization")
end
end
end
1 change: 1 addition & 0 deletions app/models/organization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class Organization < ApplicationRecord
has_many :transfers
has_many :users, -> { distinct }, through: :roles
has_many :vendors
has_many :request_units, class_name: 'Unit'
end

has_many :items, dependent: :destroy do
Expand Down
12 changes: 12 additions & 0 deletions app/models/partners/item_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# name :string
# partner_key :string
# quantity :string
# request_unit :string
# created_at :datetime not null
# updated_at :datetime not null
# item_id :integer
Expand All @@ -16,12 +17,23 @@ module Partners
class ItemRequest < Base
has_paper_trail
belongs_to :request, class_name: '::Request', foreign_key: :partner_request_id, inverse_of: :item_requests
belongs_to :item
has_many :child_item_requests, dependent: :destroy
has_many :children, through: :child_item_requests

validates :quantity, presence: true
validates :quantity, numericality: { only_integer: true, greater_than_or_equal_to: 1 }
validates :name, presence: true
validates :partner_key, presence: true
validate :request_unit_is_supported

def request_unit_is_supported
return if request_unit.blank?

names = item.request_units.map(&:name)
unless names.include?(request_unit)
errors.add(:request_unit, "is not supported")
end
end
end
end
13 changes: 13 additions & 0 deletions app/models/unit.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# == Schema Information
#
# Table name: units
#
# id :bigint not null, primary key
# name :string not null
# created_at :datetime not null
# updated_at :datetime not null
# organization_id :bigint
#
class Unit < ApplicationRecord
belongs_to :organization
end
16 changes: 16 additions & 0 deletions db/migrate/20240426135118_add_pack_models.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class AddPackModels < ActiveRecord::Migration[7.0]
def change
create_table :units do |t|
t.string :name, null: false
t.references :organization, foreign_key: true
t.timestamps
end

create_table :item_units do |t|
t.string :name, null: false
t.references :item, foreign_key: true
t.timestamps
end

end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddRequestUnitsToItemRequests < ActiveRecord::Migration[7.0]
def change
add_column :item_requests, :request_unit, :string
end
end
21 changes: 20 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,8 @@
t.integer "organization_id"
t.datetime "issued_at", precision: nil
t.string "agency_rep"
t.boolean "reminder_email_enabled", default: false, null: false
t.integer "state", default: 5, null: false
t.boolean "reminder_email_enabled", default: false, null: false
t.integer "delivery_method", default: 0, null: false
t.decimal "shipping_cost", precision: 8, scale: 2
t.index ["organization_id"], name: "index_distributions_on_organization_id"
Expand Down Expand Up @@ -381,10 +381,19 @@
t.string "partner_key"
t.integer "item_id"
t.integer "old_partner_request_id"
t.string "request_unit"
t.index ["item_id"], name: "index_item_requests_on_item_id"
t.index ["partner_request_id"], name: "index_item_requests_on_partner_request_id"
end

create_table "item_units", force: :cascade do |t|
t.string "name", null: false
t.bigint "item_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["item_id"], name: "index_item_units_on_item_id"
end

create_table "items", id: :serial, force: :cascade do |t|
t.string "name"
t.string "category"
Expand Down Expand Up @@ -782,6 +791,14 @@
t.index ["organization_id"], name: "index_transfers_on_organization_id"
end

create_table "units", force: :cascade do |t|
t.string "name", null: false
t.bigint "organization_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["organization_id"], name: "index_units_on_organization_id"
end

create_table "users", id: :serial, force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
Expand Down Expand Up @@ -880,6 +897,7 @@
add_foreign_key "item_categories", "organizations"
add_foreign_key "item_categories_partner_groups", "item_categories"
add_foreign_key "item_categories_partner_groups", "partner_groups"
add_foreign_key "item_units", "items"
add_foreign_key "items", "item_categories"
add_foreign_key "items", "kits"
add_foreign_key "kit_allocations", "kits"
Expand All @@ -898,5 +916,6 @@
add_foreign_key "requests", "distributions"
add_foreign_key "requests", "organizations"
add_foreign_key "requests", "partners"
add_foreign_key "units", "organizations"
add_foreign_key "users", "users_roles", column: "last_role_id", on_delete: :nullify
end
38 changes: 34 additions & 4 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
return
end

# Activate all feature flags
Flipper.enable(:onebase)

# ----------------------------------------------------------------------------
# Random Record Generators
# ----------------------------------------------------------------------------
Expand Down Expand Up @@ -80,6 +77,26 @@ def random_record_for_org(org, klass)
end
end

# ----------------------------------------------------------------------------
# Request Units
# ----------------------------------------------------------------------------

%w(pack box flat).each do |name|
Unit.create!(organization: pdx_org, name: name)
end

pdx_org.items.each_with_index do |item, i|
if item.name == 'Pads'
%w(box pack).each { |name| item.request_units.create!(name: name) }
elsif item.name == 'Wipes (Baby)'
item.request_units.create!(name: 'pack')
elsif item.name == 'Kids Pull-Ups (5T-6T)'
%w(pack flat).each do |name|
item.request_units.create!(name: name)
end
end
end

# ----------------------------------------------------------------------------
# Item Categories
# ----------------------------------------------------------------------------
Expand Down Expand Up @@ -337,7 +354,20 @@ def random_record_for_org(org, klass)
)

item_requests = []
Array.new(Faker::Number.within(range: 5..15)) do
pads = p.organization.items.find_by(name: 'Pads')
new_item_request = Partners::ItemRequest.new(
item_id: pads.id,
quantity: Faker::Number.within(range: 10..30),
children: [],
name: pads.name,
partner_key: pads.partner_key,
created_at: date,
updated_at: date,
request_unit: 'pack'
)
partner_request.item_requests << new_item_request

Array.new(Faker::Number.within(range: 4..14)) do
item = p.organization.items.sample
new_item_request = Partners::ItemRequest.new(
item_id: item.id,
Expand Down
20 changes: 20 additions & 0 deletions spec/factories/item_units.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# == Schema Information
#
# Table name: item_units
#
# id :bigint not null, primary key
# name :string not null
# created_at :datetime not null
# updated_at :datetime not null
# item_id :bigint
#
FactoryBot.define do
factory :item_unit do
sequence(:name) { |n| "Unit #{n}" }
item

before(:create) do |unit, _|
unit.item.organization.request_units.find_or_create_by(name: unit.name)
end
end
end
9 changes: 9 additions & 0 deletions spec/factories/partners/item_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FactoryBot.define do
factory :item_request, class: Partners::ItemRequest do
item
request { build(:request, organization: item.organization) }
quantity { 5 }
sequence(:name) { |n| "Item Request #{n}" }
sequence(:partner_key) { |n| "partner_key#{n}" }
end
end
16 changes: 16 additions & 0 deletions spec/factories/units.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# == Schema Information
#
# Table name: units
#
# id :bigint not null, primary key
# name :string not null
# created_at :datetime not null
# updated_at :datetime not null
# organization_id :bigint
#
FactoryBot.define do
factory :unit do
sequence(:name) { |n| "Unit #{n}" }
organization
end
end
25 changes: 25 additions & 0 deletions spec/models/item_unit_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: item_request_units
#
# id :bigint not null, primary key
# name :string not null
# created_at :datetime not null
# updated_at :datetime not null
# item_id :bigint
#
RSpec.describe ItemUnit, type: :model do
context "Validations >" do
let(:organization) { create(:organization) }
let(:item) { create(:item, organization: organization) }
it "should only be valid if the organization has a corresponding unit" do
item_unit = build(:item_unit, item: item, name: "pack")
expect(item_unit.valid?).to eq(false)
expect(item_unit.errors.full_messages).to eq(["Name is not supported by the organization"])

create(:unit, organization: organization, name: "pack")
organization.reload
expect(item_unit.valid?).to eq(true)
end
end
end
19 changes: 19 additions & 0 deletions spec/models/partners/item_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# name :string
# partner_key :string
# quantity :string
# request_unit :string
# created_at :datetime not null
# updated_at :datetime not null
# item_id :integer
Expand All @@ -15,6 +16,7 @@
require "rails_helper"

RSpec.describe Partners::ItemRequest, type: :model do
let(:organization) { create(:organization) }
describe 'associations' do
it { should belong_to(:request).class_name('::Request').with_foreign_key(:partner_request_id) }
it { should have_many(:child_item_requests).dependent(:destroy) }
Expand All @@ -26,6 +28,23 @@
it { should validate_numericality_of(:quantity).only_integer.is_greater_than_or_equal_to(1) }
it { should validate_presence_of(:name) }
it { should validate_presence_of(:partner_key) }

it "should only be able to use item's request units" do
create(:unit, organization: organization, name: 'pack')
create(:unit, organization: organization, name: 'flat')
item = create(:item, organization: organization)
item_unit = create(:item_unit, name: 'pack', item: item)
request = build(:request, organization: organization)

item_request = build(:item_request, request_unit: "flat", request: request, item: item)

expect(item_request.valid?).to eq(false)
expect(item_request.errors.full_messages).to eq(["Request unit is not supported"])

item_unit.update!(name: 'flat')
item.reload
expect(item_request.valid?).to eq(true)
end
end

describe "versioning" do
Expand Down

0 comments on commit b8e9ea0

Please sign in to comment.