Skip to content

Commit b67d30d

Browse files
coalestcielf
andauthored
Add viewing/editing/filtering of item reporting category (#5209)
* Add viewing/editing/filtering of item reporting category * Put other reporting_category at end of dropdown * Remove no longer needed system spec * Rename to NDBN Reporting Category * Add NDBN reporting category filtering to user guide * Add field description for NDBN Reporting Category * Fix NoMethodError for items without a reporting_category * Disable NDBN reporting category for items housing a kit * Remove connection to base_item from item * Remove partner_key validation on request items * Fix failing specs * Fix failing spec * Remove base item from items csv export * Fix failing spec * Removing "menstrual" from ndbn reporting categories (it is a super-category that should not be selectable) * Adding informational text to reporting category if the item represents a kit * rubocop happiness --------- Co-authored-by: CL Fisher <[email protected]>
1 parent a95a278 commit b67d30d

File tree

19 files changed

+167
-102
lines changed

19 files changed

+167
-102
lines changed

app/controllers/items_controller.rb

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class ItemsController < ApplicationController
44
def index
55
@items = current_organization
66
.items
7-
.includes(:base_item, :kit, :line_items, :request_units, :item_category)
7+
.includes(:kit, :line_items, :request_units, :item_category)
88
.alphabetized
99
.class_filter(filter_params)
1010
.group('items.id')
@@ -15,7 +15,7 @@ def index
1515
@storages = current_organization.storage_locations.active.order(id: :asc)
1616

1717
@include_inactive_items = params[:include_inactive_items]
18-
@selected_base_item = filter_params[:by_base_item]
18+
@selected_reporting_category = filter_params[:by_reporting_category]
1919

2020
@paginated_items = @items.page(params[:page])
2121

@@ -41,7 +41,6 @@ def create
4141
if result.success?
4242
redirect_to items_path, notice: "#{result.value.name} added!"
4343
else
44-
@base_items = BaseItem.without_kit.alphabetized
4544
# Define a @item to be used in the `new` action to be rendered with
4645
# the provided parameters. This is required to render the page again
4746
# with the error + the invalid parameters.
@@ -53,15 +52,14 @@ def create
5352
end
5453

5554
def new
56-
@base_items = BaseItem.without_kit.alphabetized
5755
@item_categories = current_organization.item_categories
5856
@item = current_organization.items.new
5957
end
6058

6159
def edit
62-
@base_items = BaseItem.without_kit.alphabetized
6360
@item_categories = current_organization.item_categories
6461
@item = current_organization.items.find(params[:id])
62+
@reporting_category_hint = reporting_category_hint
6563
end
6664

6765
def show
@@ -70,14 +68,14 @@ def show
7068
storage_location_ids = @inventory.storage_locations_for_item(@item.id)
7169
@storage_locations_containing = StorageLocation.find(storage_location_ids)
7270
@barcodes_for = BarcodeItem.where(barcodeable_id: @item.id)
71+
@reporting_category_hint = reporting_category_hint
7372
end
7473

7574
def update
7675
@item = current_organization.items.find(params[:id])
7776
@item.attributes = item_params
7877
deactivated = @item.active_changed? && !@item.active
7978
if deactivated && !@item.can_deactivate?
80-
@base_items = BaseItem.without_kit.alphabetized
8179
flash.now[:error] = "Can't deactivate this item - it is currently assigned to either an active kit or a storage location!"
8280
render action: :edit
8381
return
@@ -86,7 +84,6 @@ def update
8684
if update_item
8785
redirect_to items_path, notice: "#{@item.name} updated!"
8886
else
89-
@base_items = BaseItem.without_kit.alphabetized
9087
flash.now[:error] = "Something didn't work quite right -- try again? #{@item.errors.map { |error| "#{error.attribute}: #{error.message}" }}"
9188
render action: :edit
9289
end
@@ -140,6 +137,13 @@ def remove_category
140137

141138
private
142139

140+
def reporting_category_hint
141+
item = current_organization.items.find(params[:id])
142+
if item.kit_id
143+
"Kits are reported based on their contents."
144+
end
145+
end
146+
143147
def clean_item_value_in_cents
144148
return unless params[:item][:value_in_cents]
145149

@@ -164,6 +168,7 @@ def item_params
164168
@item_params = params.require(:item).permit(
165169
:name,
166170
:item_category_id,
171+
:reporting_category,
167172
:partner_key,
168173
:value_in_cents,
169174
:package_size,
@@ -205,6 +210,6 @@ def update_item_and_request_units
205210
def filter_params(_parameters = nil)
206211
return {} unless params.key?(:filters)
207212

208-
params.require(:filters).permit(:by_base_item, :include_inactive_items)
213+
params.require(:filters).permit(:by_reporting_category, :include_inactive_items)
209214
end
210215
end

app/models/base_item.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class BaseItem < ApplicationRecord
8080
}.freeze
8181

8282
def to_h
83-
{ partner_key: partner_key, name: name }
83+
{ partner_key: partner_key, name: name, reporting_category: reporting_category }
8484
end
8585

8686
private

app/models/item.rb

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,10 @@ class Item < ApplicationRecord
3030

3131
after_initialize :set_default_distribution_quantity, if: :new_record?
3232
after_update :update_associated_kit_name, if: -> { kit.present? }
33-
before_create :set_reporting_category
3433
before_destroy :validate_destroy, prepend: true
3534

3635
belongs_to :organization # If these are universal this isn't necessary
37-
belongs_to :base_item, counter_cache: :item_count, primary_key: :partner_key, foreign_key: :partner_key, inverse_of: :items
36+
belongs_to :base_item, counter_cache: :item_count, primary_key: :partner_key, foreign_key: :partner_key, inverse_of: :items, optional: true
3837
belongs_to :kit, optional: true
3938
belongs_to :item_category, optional: true
4039

@@ -45,6 +44,7 @@ class Item < ApplicationRecord
4544
validates :on_hand_recommended_quantity, numericality: { greater_than_or_equal_to: 0 }, allow_blank: true
4645
validates :on_hand_minimum_quantity, numericality: { greater_than_or_equal_to: 0 }
4746
validates :package_size, numericality: { greater_than_or_equal_to: 0 }, allow_blank: true
47+
validates :reporting_category, presence: true, unless: proc { |i| i.kit }
4848

4949
has_many :line_items, dependent: :destroy
5050
has_many :inventory_items, dependent: :destroy
@@ -63,10 +63,9 @@ class Item < ApplicationRecord
6363
scope :visible, -> { where(visible_to_partners: true) }
6464
scope :alphabetized, -> { order(:name) }
6565
scope :by_base_item, ->(base_item) { where(base_item: base_item) }
66+
scope :by_reporting_category, ->(reporting_category) { where(reporting_category: reporting_category) }
6667
scope :by_partner_key, ->(partner_key) { where(partner_key: partner_key) }
6768

68-
scope :by_size, ->(size) { joins(:base_item).where(base_items: { size: size }) }
69-
7069
scope :period_supplies, -> {
7170
where(reporting_category: [:pads, :tampons, :period_liners, :period_underwear, :period_other])
7271
}
@@ -75,14 +74,19 @@ class Item < ApplicationRecord
7574
adult_incontinence: "adult_incontinence",
7675
cloth_diapers: "cloth_diapers",
7776
disposable_diapers: "disposable_diapers",
78-
menstrual: "menstrual",
79-
other_categories: "other",
8077
pads: "pads",
8178
period_liners: "period_liners",
8279
period_other: "period_other",
8380
period_underwear: "period_underwear",
84-
tampons: "tampons"
85-
}, instance_methods: false
81+
tampons: "tampons",
82+
other_categories: "other"
83+
}, instance_methods: false, validate: { allow_nil: true }
84+
85+
def self.reporting_categories_for_select
86+
reporting_categories.map do |key, value|
87+
Option.new(id: key, name: value.titleize)
88+
end
89+
end
8690

8791
def self.reactivate(item_ids)
8892
item_ids = Array.wrap(item_ids)
@@ -141,6 +145,11 @@ def deactivate!
141145
end
142146
end
143147

148+
# @return [String]
149+
def reporting_category_humanized
150+
Item.reporting_categories[reporting_category].to_s.titleize
151+
end
152+
144153
def other?
145154
partner_key == "other"
146155
end
@@ -156,7 +165,7 @@ def to_h
156165
end
157166

158167
def self.csv_export_headers
159-
["Name", "Barcodes", "Base Item", "Quantity"]
168+
["Name", "Barcodes", "Quantity"]
160169
end
161170

162171
# @param items [Array<Item>]
@@ -166,7 +175,7 @@ def self.generate_csv_from_inventory(items, inventory)
166175
item_quantities = items.to_h { |i| [i.id, inventory.quantity_for(item_id: i.id)] }
167176
CSV.generate(headers: true) do |csv|
168177
csv_data = items.map do |item|
169-
attributes = [item.name, item.barcode_count, item.base_item.name, item_quantities[item.id]]
178+
attributes = [item.name, item.barcode_count, item_quantities[item.id]]
170179
attributes.map { |attr| normalize_csv_attribute(attr) }
171180
end
172181
([csv_export_headers] + csv_data).each { |row| csv << row }
@@ -186,14 +195,6 @@ def sync_request_units!(unit_ids)
186195

187196
private
188197

189-
# Sets reporting_category according to reporting_category of base item.
190-
# TODO: Remove once items can be created with a reporting category.
191-
def set_reporting_category
192-
return unless reporting_category.blank?
193-
194-
self.reporting_category = base_item.reporting_category if base_item.reporting_category
195-
end
196-
197198
def set_default_distribution_quantity
198199
self.distribution_quantity ||= kit_id.present? ? 1 : 50
199200
end

app/models/partners/item_request.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ class ItemRequest < Base
2424
validates :quantity, presence: true
2525
validates :quantity, numericality: { only_integer: true, greater_than_or_equal_to: 1 }
2626
validates :name, presence: true
27-
validates :partner_key, presence: true
2827
validate :request_unit_is_supported
2928

3029
def request_unit_is_supported

app/views/base_items/_dropdown.html.erb

Lines changed: 0 additions & 6 deletions
This file was deleted.

app/views/items/_form.html.erb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@
99
<!-- /.card-header -->
1010
<!-- form start -->
1111
<div class="card-body">
12-
<% if @item.kit.blank? %>
13-
<%= render partial: "base_items/dropdown", object: f %>
14-
<% end %>
1512
<%= f.input :name, label: "Name", wrapper: :input_group do %>
1613
<span class="input-group-text"><i class="fa fa-tag"></i></span>
1714
<%= f.input_field :name, class: "form-control" %>
@@ -20,6 +17,10 @@
2017
<div class='w-1/4'>
2118
<%= f.input :item_category_id, label: 'Category', collection: @item_categories, hint: 'Categories can help organize and identify items' %>
2219
</div>
20+
<div class='w-1/4'>
21+
22+
<%= f.input :reporting_category, label: 'NDBN Reporting Category', collection: Item.reporting_categories_for_select, disabled: !!@item.kit_id, required: !@item.kit_id, hint: @reporting_category_hint %>
23+
</div>
2324

2425
<%= f.input :name, label: "Value per item", wrapper: :input_group do %>
2526
<span class="input-group-text"><i class="fa fa-money"></i></span>

app/views/items/_item_list.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<tr>
99
<th>Category</th>
1010
<th>Name</th>
11+
<th>NDBN Reporting Category</th>
1112
<th>Add. Info</th>
1213
<th class="text-right">Quantity Per Individual</th>
1314
<th class="text-right">Fair Market Value (per item)</th>

app/views/items/_item_row.html.erb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<tr data-item-id="<%= item_row.id %>">
22
<td><%= item_row.item_category && link_to(item_row.item_category&.name, item_category_path(item_row.item_category), class: 'text-blue-500') %></td>
33
<td><%= item_row.name %></td>
4+
<td><%= item_row.reporting_category_humanized %></td>
45
<td><%= truncate item_row.additional_info, length: 25 %></td>
56
<td class="text-right"> <%= item_row.distribution_quantity %></td>
67
<td class="numeric"><%= dollar_value(item_row.value_in_cents) %></td>
78
<% if Flipper.enabled?(:enable_packs) %>
8-
<% unless current_organization.request_units.empty? %>
9+
<% unless current_organization.request_units.blank? %>
910
<td><%= item_row.request_units.pluck(:name).join(', ') %></td>
1011
<% end %>
1112
<% end %>

app/views/items/index.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
<%= form_tag(items_path, method: :get) do |f| %>
3838
<div class="row">
3939
<div class="form-group col-lg-3 col-md-4 col-sm-6 col-xs-12">
40-
<%= filter_select(scope: :by_base_item, collection: BaseItem.alphabetized, key: :partner_key, selected: @selected_base_item) %>
40+
<%= filter_select(scope: :by_reporting_category, label: "Filter by NDBN Reporting Category", collection: Item.reporting_categories_for_select, selected: @selected_reporting_category) %>
4141
</div>
4242
</div>
4343
<div class="row">

app/views/items/show.html.erb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@
3131
<div class="card-body p-0">
3232
<table class="table">
3333
<tbody>
34-
<tr>
35-
<th>Base Item</th>
36-
<td><%= @item.base_item.name %></td>
37-
</tr>
3834
<tr>
3935
<th>Name</th>
4036
<td><%= @item.name %></td>
@@ -43,6 +39,10 @@
4339
<th>Category</th>
4440
<td><%= @item&.item_category&.name %></td>
4541
</tr>
42+
<tr>
43+
<th>NDBN Reporting Category</th>
44+
<td><%= @item.reporting_category_humanized %><%= @reporting_category_hint %></td>
45+
</tr>
4646
<tr>
4747
<th>Value Per Item</th>
4848
<td>$<%= @item.value_in_dollars || 0 %></td>

0 commit comments

Comments
 (0)