Skip to content

Commit 8e2ab73

Browse files
author
Olexii Kasianenko
committed
Add Inventory Flow tab with quantity tracking and date filtering
1 parent 3e76a21 commit 8e2ab73

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
@@ -70,7 +70,7 @@ class Item < ApplicationRecord
7070
scope :period_supplies, -> {
7171
where(reporting_category: [:pads, :tampons, :period_liners, :period_underwear, :period_other])
7272
}
73-
73+
scope :created_between, ->(start_date, end_date) { where(created_at: start_date..end_date) }
7474
enum :reporting_category, {
7575
adult_incontinence: "adult_incontinence",
7676
cloth_diapers: "cloth_diapers",
@@ -184,6 +184,18 @@ def sync_request_units!(unit_ids)
184184
end
185185
end
186186

187+
def quantity_in_storage(storage_location_id)
188+
line_items.inventory_in_storage(storage_location_id).sum(:quantity)
189+
end
190+
191+
def quantity_out_storage(storage_location_id)
192+
line_items.inventory_out_storage(storage_location_id).sum(:quantity)
193+
end
194+
195+
def quantity_change(storage_location_id)
196+
quantity_in_storage(storage_location_id) - quantity_out_storage(storage_location_id)
197+
end
198+
187199
private
188200

189201
# Sets reporting_category according to reporting_category of base item.

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
@@ -66,14 +66,11 @@
6666
<div class="card card-primary card-outline card-outline-tabs">
6767
<div class="card-header p-0 border-bottom-0">
6868
<ul class="nav nav-tabs" id="custom-tabs-three-tab" role="tablist">
69-
<li class="nav-item" class="active">
69+
<li class="nav-item active">
7070
<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>
7171
</li>
7272
<li class="nav-item">
73-
<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>
74-
</li>
75-
<li class="nav-item">
76-
<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>
73+
<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>
7774
</li>
7875
</ul>
7976
</div>
@@ -129,41 +126,39 @@
129126
</table>
130127
</div><!-- /.box-body.table-responsive -->
131128

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

0 commit comments

Comments
 (0)