Skip to content

Commit 53eaa68

Browse files
author
Olexii Kasianenko
committed
Add Inventory Flow tab with quantity tracking and date filtering
1 parent 3e45d92 commit 53eaa68

17 files changed

+207
-329
lines changed

.rubocop_todo.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,6 @@ Layout/ExtraSpacing:
8686
- 'Guardfile'
8787
- 'app/models/barcode_item.rb'
8888
- 'app/queries/items_by_storage_collection_query.rb'
89-
- 'app/queries/items_in_query.rb'
90-
- 'app/queries/items_in_total_query.rb'
91-
- 'app/queries/items_out_query.rb'
92-
- 'app/queries/items_out_total_query.rb'
9389
- 'config/environments/development.rb'
9490
- 'config/environments/test.rb'
9591
- 'config/puma.rb'
@@ -169,10 +165,6 @@ Layout/MultilineMethodCallIndentation:
169165
- 'app/models/partner_distribution.rb'
170166
- 'app/models/storage_location.rb'
171167
- 'app/queries/items_by_storage_collection_query.rb'
172-
- 'app/queries/items_in_query.rb'
173-
- 'app/queries/items_in_total_query.rb'
174-
- 'app/queries/items_out_query.rb'
175-
- 'app/queries/items_out_total_query.rb'
176168
- 'app/services/reports/acquisition_report_service.rb'
177169
- 'app/services/reports/adult_incontinence_report_service.rb'
178170
- 'app/services/reports/children_served_report_service.rb'

app/controllers/storage_locations_controller.rb

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ def edit
5454
@storage_location = current_organization.storage_locations.find(params[:id])
5555
end
5656

57-
# TODO: Move these queries to Query Object
5857
def show
58+
setup_date_range_picker
5959
@storage_location = current_organization.storage_locations.find(params[:id])
6060
version_date = params[:version_date].presence&.to_date
61-
# TODO: Find a way to do these with less hard SQL. These queries have to be manually updated because they're not in-sync with the Model
62-
@items_out = ItemsOutQuery.new(organization: current_organization, storage_location: @storage_location).call
63-
@items_out_total = ItemsOutTotalQuery.new(organization: current_organization, storage_location: @storage_location).call
64-
@items_in = ItemsInQuery.new(organization: current_organization, storage_location: @storage_location).call
65-
@items_in_total = ItemsInTotalQuery.new(organization: current_organization, storage_location: @storage_location).call
61+
@items = current_organization.items.order(:name)
62+
@items = @items.created_between(*date_range) if filter_params[:date_range].present?
63+
@total_quantity_in = @items.sum { |item| item.quantity_in_storage(@storage_location.id) }
64+
@total_quantity_out = @items.sum { |item| item.quantity_out_storage(@storage_location.id) }
65+
@total_quantity_change = @total_quantity_in - @total_quantity_out
6666
if View::Inventory.within_snapshot?(current_organization.id, version_date)
6767
@inventory = View::Inventory.new(current_organization.id, event_time: version_date)
6868
else
@@ -157,9 +157,16 @@ def include_omitted_items(existing_item_ids = [])
157157
end
158158

159159
helper_method \
160-
def filter_params
160+
def filter_params
161161
return {} unless params.key?(:filters)
162162

163-
params.require(:filters).permit(:containing)
163+
params.require(:filters).permit(:containing, :date_range, :date_range_label)
164+
end
165+
166+
def date_range
167+
date_range = filter_params[:date_range].split(" - ")
168+
start_date = Date.parse(date_range[0])
169+
end_date = Date.parse(date_range[1])
170+
[start_date, end_date]
164171
end
165172
end

app/models/item.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class Item < ApplicationRecord
6969
scope :period_supplies, -> {
7070
where(reporting_category: [:pads, :tampons, :period_liners, :period_underwear, :period_other])
7171
}
72-
72+
scope :created_between, ->(start_date, end_date) { where(created_at: start_date..end_date) }
7373
enum :reporting_category, {
7474
adult_incontinence: "adult_incontinence",
7575
cloth_diapers: "cloth_diapers",
@@ -193,6 +193,18 @@ def sync_request_units!(unit_ids)
193193
end
194194
end
195195

196+
def quantity_in_storage(storage_location_id)
197+
line_items.inventory_in_storage(storage_location_id).sum(:quantity)
198+
end
199+
200+
def quantity_out_storage(storage_location_id)
201+
line_items.inventory_out_storage(storage_location_id).sum(:quantity)
202+
end
203+
204+
def quantity_change(storage_location_id)
205+
quantity_in_storage(storage_location_id) - quantity_out_storage(storage_location_id)
206+
end
207+
196208
private
197209

198210
def set_default_distribution_quantity

app/models/line_item.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,28 @@ class LineItem < ApplicationRecord
2525

2626
scope :active, -> { joins(:item).where(items: { active: true }) }
2727

28+
scope :inventory_in_storage, ->(storage_location_id) do
29+
joins("
30+
LEFT OUTER JOIN donations ON donations.id = line_items.itemizable_id AND line_items.itemizable_type = 'Donation'
31+
LEFT OUTER JOIN purchases ON purchases.id = line_items.itemizable_id AND line_items.itemizable_type = 'Purchase'
32+
LEFT OUTER JOIN adjustments ON adjustments.id = line_items.itemizable_id AND line_items.itemizable_type = 'Adjustment'
33+
LEFT OUTER JOIN transfers ON transfers.id = line_items.itemizable_id AND line_items.itemizable_type = 'Transfer'")
34+
.where("donations.storage_location_id = :storage_location_id OR
35+
purchases.storage_location_id = :storage_location_id OR
36+
(adjustments.storage_location_id = :storage_location_id and line_items.quantity < 0) OR
37+
transfers.to_id = :storage_location_id", storage_location_id: storage_location_id)
38+
end
39+
40+
scope :inventory_out_storage, ->(storage_location_id) do
41+
joins("
42+
LEFT OUTER JOIN distributions ON distributions.id = line_items.itemizable_id AND line_items.itemizable_type = 'Distribution'
43+
LEFT OUTER JOIN adjustments ON adjustments.id = line_items.itemizable_id AND line_items.itemizable_type = 'Adjustment'
44+
LEFT OUTER JOIN transfers ON transfers.id = line_items.itemizable_id AND line_items.itemizable_type = 'Transfer'")
45+
.where("distributions.storage_location_id = :storage_location_id OR
46+
(adjustments.storage_location_id = :storage_location_id and line_items.quantity > 0) OR
47+
transfers.from_id = :storage_location_id", storage_location_id: storage_location_id)
48+
end
49+
2850
delegate :name, to: :item
2951

3052
# Used in a distribution that was initialized from a request. The `item_request` will be

app/queries/items_in_query.rb

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

app/queries/items_in_total_query.rb

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

app/queries/items_out_query.rb

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

app/queries/items_out_total_query.rb

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<% css_class = item_row.quantity_change(@storage_location.id).negative? ? 'modal-body-warning-text' : '' %>
2+
<tr id="<%= item_row.id %>">
3+
<td><%= link_to item_row.name, item_path(item_row.id) %></td>
4+
<td><%= item_row.quantity_in_storage(@storage_location.id) %></td>
5+
<td><%= item_row.quantity_out_storage(@storage_location.id) %></td>
6+
<td class="<%= css_class %>"><%= item_row.quantity_change(@storage_location.id) %></td>
7+
</tr>

app/views/storage_locations/show.html.erb

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,11 @@
6868
<div class="card card-primary card-outline card-outline-tabs">
6969
<div class="card-header p-0 border-bottom-0">
7070
<ul class="nav nav-tabs" id="custom-tabs-three-tab" role="tablist">
71-
<li class="nav-item" class="active">
71+
<li class="nav-item active">
7272
<a class="nav-link active" id="custom-tabs-inventory-tab" data-bs-toggle="pill" href="#custom-tabs-inventory" role="tab" aria-controls="custom-tabs-one-home-tab" aria-selected="true">Inventory</a>
7373
</li>
7474
<li class="nav-item">
75-
<a class="nav-link" id="custom-tabs-inventory-in-tab" data-bs-toggle="pill" href="#custom-tabs-inventory-in" role="tab" aria-controls="custom-tabs-two-home-tab" aria-selected="false">Inventory Coming In</a>
76-
</li>
77-
<li class="nav-item">
78-
<a class="nav-link" id="custom-tabs-inventory-out-tab" data-bs-toggle="pill" href="#custom-tabs-inventory-out" role="tab" aria-controls="custom-tabs-three-home-tab" aria-selected="false">Inventory Going Out</a>
75+
<a class="nav-link" id="custom-tabs-inventory-flow-tab" data-bs-toggle="pill" href="#custom-tabs-inventory-flow" role="tab" aria-controls="custom-tabs-two-home-tab" aria-selected="false">Inventory Flow</a>
7976
</li>
8077
</ul>
8178
</div>
@@ -131,41 +128,39 @@
131128
</table>
132129
</div><!-- /.box-body.table-responsive -->
133130

134-
<div class="tab-pane fade show" id="custom-tabs-inventory-in" role="tabpanel" aria-labelledby="custom-two-home-tab">
135-
<table class="table">
136-
<thead>
137-
<tr>
138-
<th>Item</th>
139-
<th>Quantity</th>
140-
</tr>
141-
</thead>
142-
<tbody>
143-
<%= render partial: "line_item_row", collection: @items_in %>
144-
</tbody>
145-
<tfoot>
146-
<tr>
147-
<td>Total</td>
148-
<td><%= @items_in_total %></td>
149-
</tr>
150-
</tfoot>
151-
</table>
152-
</div><!-- /.box-body.table-responsive -->
153-
154-
<div class="tab-pane fade show" id="custom-tabs-inventory-out" role="tabpanel" aria-labelledby="custom-tabs-three-home-tab">
131+
<div class="tab-pane fade show" id="custom-tabs-inventory-flow" role="tabpanel" aria-labelledby="custom-two-home-tab">
132+
<%= form_for @storage_location, method: :get do %>
133+
<%= label_tag "Date Range" %>
134+
<div class="row">
135+
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
136+
<%= render partial: "shared/date_range_picker", locals: {css_class: "form-control"} %>
137+
</div>
138+
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
139+
<%= filter_button %>
140+
<%= clear_filter_button %>
141+
</div>
142+
</div>
143+
<% end %>
144+
<br><br>
155145
<table class="table">
156146
<thead>
157147
<tr>
158148
<th>Item</th>
159-
<th>Quantity</th>
149+
<th>Quantity In</th>
150+
<th>Quantity Out</th>
151+
<th>Change</th>
160152
</tr>
161153
</thead>
162154
<tbody>
163-
<%= render partial: "line_item_row", collection: @items_out %>
155+
<%= render partial: "item_row", collection: @items %>
164156
</tbody>
165157
<tfoot>
166158
<tr>
167159
<td>Total</td>
168-
<td><%= @items_out_total %></td>
160+
<td><%= @total_quantity_in %></td>
161+
<td><%= @total_quantity_out %></td>
162+
<% css_class = @total_quantity_change.negative? ? 'modal-body-warning-text' : '' %>
163+
<td class="<%= css_class %>"><%= @total_quantity_change %></td>
169164
</tr>
170165
</tfoot>
171166
</table>

0 commit comments

Comments
 (0)