Skip to content

Commit

Permalink
feat: Item Inventory for Banks with many locations (#3784)
Browse files Browse the repository at this point in the history
* Add new table with collapsible locations for banks with many locations

The "Items, Quantity, and Location" table has a nasty horizontal scroll
if the bank has many locations, which can be common for banks that allow
volunteers to take inventory back to their residences to package into
kits. This is very unwieldly for them, but other banks with few
locations have a great scannable view of where their inventory is. We're
reproducing this table with the locations collapsed under a heading for
banks with many locations in a new tab to preserve the experience for
banks with few locations.

ExpandableTable from AdminLTE is being used to handle the expansion.
Location is being stored slightly differently in the query to make it
easier to access.

* Add new styling for expandable tabes to hint that they can be expanded when clicked.

* Location name could be duplicated, so use id to identify the location instead.

Resolves #3776
  • Loading branch information
ChaelCodes authored Jul 30, 2023
1 parent 33ceb9f commit 14dcb6a
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 7 deletions.
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
@import 'progress_stepper';
@import 'audits';
@import 'modal-dialog';
@import 'expandable_table';
@import 'custom';

.modal-dialog {
Expand Down
22 changes: 22 additions & 0 deletions app/assets/stylesheets/expandable_table.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Customized Styling for Exandable Tables - provided by AdminLTE
* ExpandableTable - https://adminlte.io/docs/3.1/javascript/expandable-tables.html
*/

/*
* Default Expanded table has no indicator that the row is clickable. This styles an expand/collapse icon.
* Expanded=true is minus, Expanded=false is plus
*/
[data-widget="expandable-table"] {
&[aria-expanded="true"] {
td > .fa::before{
content: "\f068";
}
}

&[aria-expanded="false"] {
td > .fa::before{
content: "\f067";
}
}
}
15 changes: 12 additions & 3 deletions app/queries/items_by_storage_collection_and_quantity_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,24 @@ def call
@items_by_storage_collection.each do |row|
unless @items_by_storage_collection_and_quantity.key?(row.id)
@items_by_storage_collection_and_quantity[row.id] = {
item_id: row.id,
item_name: row.name,
item_on_hand_minimum_quantity: row.on_hand_minimum_quantity,
item_on_hand_recommended_quantity: row.on_hand_recommended_quantity,
item_value: row.value_in_cents,
item_barcode_count: row.barcode_count
item_barcode_count: row.barcode_count,
locations: [],
quantity: 0
}
end

if row.storage_id
@items_by_storage_collection_and_quantity[row.id][:locations] << {
id: row.storage_id,
name: row.storage_name,
quantity: row.quantity
}
end
@items_by_storage_collection_and_quantity[row.id][row.storage_id] = row.quantity
@items_by_storage_collection_and_quantity[row.id][:quantity] ||= 0
@items_by_storage_collection_and_quantity[row.id][:quantity] += row.quantity || 0
end

Expand Down
18 changes: 18 additions & 0 deletions app/views/items/_item_row_inventory.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<% row_item = row.last %>
<tr data-widget="expandable-table" aria-expanded="false">
<td><i class="fa" /></td>
<td><%= link_to(row_item[:item_name], item_url(row_item[:item_id])) %></td>
<td class="numeric"><%= row_item[:quantity] %></td>
<td class="numeric"><%= row_item[:item_on_hand_minimum_quantity] %></td>
<td class="numeric"><%= row_item[:item_on_hand_recommended_quantity] %></td>
</tr>
<tr class="expandable-body">
<td colspan="5">
<p>
<% row_item[:locations].each do |location| %>
<%= link_to(location[:name], storage_location_url(location[:id])) %>
<%= " - #{location[:quantity]} units" %><br>
<% end %>
</p>
</td>
</tr>
6 changes: 4 additions & 2 deletions app/views/items/_item_row_quantity_and_storages.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<% row_item = row.last %>
<tr>
<td><%= row_item[:item_name] %></td>
<td><%= link_to(row_item[:item_name], item_url(row_item[:item_id])) %></td>
<% @storages.each do |storage| %>
<td class="numeric"><%= row_item[storage.id] || "0" %></td>
<td class="numeric">
<%= row_item[:locations].find { |location| location[:id] == storage.id }&.dig(:quantity) || "0" %>
</td>
<% end %>
<td class="numeric"><%= row_item[:item_on_hand_minimum_quantity] %></td>
<td class="numeric"><%= row_item[:item_on_hand_recommended_quantity] %></td>
Expand Down
21 changes: 21 additions & 0 deletions app/views/items/_items_inventory.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div class="tab-pane fade" id="custom-tabs-three-inventory" role="tabpanel" aria-labelledby="custom-tabs-three-inventory-tab">
<div class='flex justify-end mb-4'>
<%= new_button_to new_item_path(organization_id: current_organization), {text: "New Item"} %>
</div>

<table class="table table-items-location">
<thead>
<tr>
<th></th>
<th>Name</th>
<th class="numeric">Quantity</th>
<th class="numeric">Minimum Quantity</th>
<th class="numeric">Recommended Quantity</th>
</tr>
</thead>
<tbody>
<%= render partial: "item_row_inventory", collection: @items_by_storage_collection_and_quantity, as: :row %>
</tbody>
</table>
</div><!-- /.box-body.table-responsive -->

7 changes: 6 additions & 1 deletion app/views/items/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,16 @@
</li>
</li>
<li class="nav-item">
<a class="nav-link" id="custom-tabs-three-profile-tab" data-toggle="pill" href="#custom-tabs-three-categories" role="tab" aria-controls="custom-tabs-three-categories" aria-selected="false">Item Categories</a>
<a class="nav-link" id="custom-tabs-three-categories-tab" data-toggle="pill" href="#custom-tabs-three-categories" role="tab" aria-controls="custom-tabs-three-categories" aria-selected="false">Item Categories</a>
</li>
<li class="nav-item">
<a class="nav-link" id="custom-tabs-three-profile-tab" data-toggle="pill" href="#custom-tabs-three-profile" role="tab" aria-controls="custom-tabs-three-profile" aria-selected="false">Items,
Quantity, and Location</a>
</li>
<li class="nav-item">
<a class="nav-link" id="custom-tabs-three-inventory-tab" data-toggle="pill" href="#custom-tabs-three-inventory" role="tab" aria-controls="custom-tabs-three-inventory" aria-selected="false">
Item Inventory</a>
</li>
<li class="nav-item">
<a class="nav-link" id="custom-tabs-three-kits-tab" data-toggle="pill" href="#custom-tabs-three-kits" role="tab" aria-controls="custom-tabs-three-kits" aria-selected="false">Kits</a>
</li>
Expand All @@ -92,6 +96,7 @@
<%= render partial: 'item_list', locals: { items: @items } %>
<%= render partial: 'item_categories', locals: { item_categories: @item_categories } %>
<%= render partial: 'items_quantity_and_location' %>
<%= render partial: 'items_inventory' %>
<%= render partial: 'kits' %>
</div>
</div>
Expand Down
23 changes: 22 additions & 1 deletion spec/system/item_system_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
let(:storage) { create(:storage_location, :with_items, item: item_pullups, item_quantity: num_pullups_in_donation, name: storage_name) }
let!(:aux_storage) { create(:storage_location, :with_items, item: item_pullups, item_quantity: num_pullups_second_donation, name: "a secret secondary location") }
let(:num_pullups_in_donation) { 666 }
let(:num_pullups_second_donation) { 1 }
let(:num_pullups_second_donation) { 15 }
let(:num_tampons_in_donation) { 42 }
let(:num_tampons_second_donation) { 17 }
let!(:donation_tampons) { create(:donation, :with_items, storage_location: storage, item_quantity: num_tampons_in_donation, item: item_tampons) }
Expand Down Expand Up @@ -189,6 +189,27 @@
expect(tab_items_quantity_location_text).to have_content item_pullups.name
expect(tab_items_quantity_location_text).to have_content item_tampons.name
end

it "should display an Item Inventory table", js: true do
click_link "Item Inventory" # href="#sectionD"
tab_items_quantity_location_text = page.find(".table-items-location", visible: true).text
expect(tab_items_quantity_location_text).to have_content "Quantity"
expect(tab_items_quantity_location_text).to have_content item_pullups.name
expect(tab_items_quantity_location_text).to have_content item_tampons.name
expect(tab_items_quantity_location_text).to have_content num_pullups_in_donation + num_pullups_second_donation
expect(tab_items_quantity_location_text).to have_content num_tampons_in_donation + num_tampons_second_donation
expect(tab_items_quantity_location_text).not_to have_content storage_name
expect(tab_items_quantity_location_text).not_to have_content num_pullups_in_donation
expect(tab_items_quantity_location_text).not_to have_content num_pullups_second_donation
expect(tab_items_quantity_location_text).not_to have_content num_tampons_in_donation
expect(tab_items_quantity_location_text).not_to have_content num_tampons_second_donation
expandable_row = find("td", text: item_tampons.name).find(:xpath, "..")
expandable_row.click
expanded_row = find(".expandable-body", visible: true).text
expect(find(".expandable-body", visible: true)).to have_link storage_name
expect(expanded_row).to have_content num_tampons_in_donation
expect(expanded_row).to have_content num_tampons_second_donation
end
end

describe 'Item Category Management' do
Expand Down

0 comments on commit 14dcb6a

Please sign in to comment.