-
-
Notifications
You must be signed in to change notification settings - Fork 503
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dashboard! #3788
Dashboard! #3788
Changes from 16 commits
e7f43d3
64a5d6e
e815d25
30279cb
cd08a7b
a7e46c6
3052d09
c302248
dd0265f
5c77138
7a4b9d0
73deb2f
251f09c
59a5cfb
914881a
d4e67fa
802505c
54e9f13
be3f641
8bba60e
d85cce4
0a5b57d
357df3a
94f12c0
b8df3a5
020b4bb
1ca53e7
77fda90
fe27dbe
27b0309
72fa881
1a34dd7
0dc6632
48d0ebb
5268b42
5ed4e7e
c6b0625
ab21419
60a0515
d3098fe
39af23b
1dd2d53
d4e6ec2
79ddf74
2f75591
a6e84ce
ae90f1a
4b0dc7a
1010cdc
b2df7b1
0834a0d
955d9b9
41aac22
3b42cf0
f726ba9
ef0b294
9f2ac37
f5bc55a
5a73788
7ec14dc
304e2a3
1bcc0ff
1d38d58
97369e3
4ada1e5
19ebe3b
13d164a
547d4ba
9e92a98
17aa91c
b25e320
6b890b7
7cc0763
88a53cb
756f294
8220e00
75cd62e
a6b4849
517d0fb
afd8c64
c20401c
6e0b771
872f4ea
96f245b
0919c22
90389b2
dbff0af
a216b66
444aa49
e3a5e71
9c738a2
0868441
831d4b0
e8e546c
36c0704
b272b91
e2d1c22
f44e444
c8b5131
bab467f
df0d759
55d36e4
a6371f7
b5dcff0
128ff44
f40cbce
cacb59a
a6428bf
e5341eb
2db7d1d
407f738
33ce9e4
81b1247
8e89364
80fc8ff
ecdd904
8e4eb71
49821c9
e483637
4c5bbeb
db4d441
993778a
f8ca6e0
31bf22a
cefe205
922ec32
bce1288
2826843
d7757c5
ffef79b
1f9c68b
f3647c4
971697a
0ebe7cf
258005d
123e8ca
c2638fe
2de9bcb
6fd2f10
7287c11
df48642
7c5f900
5802818
982f322
fc3ea3a
44b3978
4919505
d888831
3049b6c
f4202a9
b4c1cbd
debb351
3b274a7
ec47ef6
8354477
0b3cbc0
aba16d1
b63d998
fadfd71
6273aa3
94c0ebd
5bf83f8
9ab87d7
5026b95
72b1904
312d881
4ce6300
f49a357
b698b05
2392f4f
a52a7d0
189dc89
a43b405
befd4fe
d27aa81
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,51 @@ | ||
class LowInventoryQuery | ||
def self.call(organization) | ||
sql_query = <<-SQL | ||
SELECT | ||
items.id, | ||
items.name, | ||
items.on_hand_minimum_quantity, | ||
items.on_hand_recommended_quantity, | ||
sum(inventory_items.quantity) as total_quantity | ||
FROM inventory_items | ||
JOIN items ON items.id = inventory_items.item_id | ||
JOIN storage_locations ON storage_locations.id = inventory_items.storage_location_id | ||
WHERE storage_locations.organization_id = ? | ||
GROUP BY items.id, items.name, items.on_hand_minimum_quantity, items.on_hand_recommended_quantity | ||
HAVING sum(inventory_items.quantity) < items.on_hand_minimum_quantity | ||
OR sum(inventory_items.quantity) < items.on_hand_recommended_quantity | ||
ORDER BY items.name | ||
SQL | ||
if Event.read_events?(organization) | ||
inventory = InventoryAggregate.inventory_for(organization.id) | ||
|
||
sanitized_sql = ActiveRecord::Base.send(:sanitize_sql_array, [sql_query, organization.id]) | ||
ActiveRecord::Base.connection.execute(sanitized_sql).to_a | ||
items = {} | ||
inventory.storage_locations.values.each do |storage_location| | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dorner this is the adaptation of the SQL query -> an in-memory rollup. Is there a preferred way to do this? I tested it on moms-for-moms, which has quite a few items, and it is fast with our dataset. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @awwaiid take a look at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated to use View::Inventory! |
||
storage_location.items.values.each do |item| | ||
items[item.item_id] = items[item.item_id].to_i + item.quantity | ||
end | ||
end | ||
|
||
low_inventory_items = [] | ||
items.each do |item_id, quantity| | ||
item = Item.find(item_id) | ||
if quantity < item.on_hand_minimum_quantity.to_i || quantity < item.on_hand_recommended_quantity.to_i | ||
low_inventory_items.push(OpenStruct.new( | ||
id: item.id, | ||
name: item.name, | ||
on_hand_minimum_quantity: item.on_hand_minimum_quantity, | ||
on_hand_recommended_quantity: item.on_hand_recommended_quantity, | ||
total_quantity: quantity | ||
)) | ||
end | ||
end | ||
|
||
low_inventory_items.sort_by { |item| item[:name] } | ||
|
||
else | ||
sql_query = <<-SQL | ||
SELECT | ||
items.id, | ||
items.name, | ||
items.on_hand_minimum_quantity, | ||
items.on_hand_recommended_quantity, | ||
sum(inventory_items.quantity) as total_quantity | ||
FROM inventory_items | ||
JOIN items ON items.id = inventory_items.item_id | ||
JOIN storage_locations ON storage_locations.id = inventory_items.storage_location_id | ||
WHERE storage_locations.organization_id = ? | ||
GROUP BY items.id, items.name, items.on_hand_minimum_quantity, items.on_hand_recommended_quantity | ||
HAVING sum(inventory_items.quantity) < items.on_hand_minimum_quantity | ||
OR sum(inventory_items.quantity) < items.on_hand_recommended_quantity | ||
ORDER BY items.name | ||
SQL | ||
|
||
sanitized_sql = ActiveRecord::Base.send(:sanitize_sql_array, [sql_query, organization.id]) | ||
ActiveRecord::Base.connection.execute(sanitized_sql).to_a | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<% if @broadcast_announcements.any? %> | ||
<div class="shared/card" id="distributions"> | ||
<div class="card-header border-0 bg-gradient-warning"> | ||
<h3 class="card-title">Announcements | ||
<small>from Human Essentials</small></h3> | ||
<div class="card-tools"> | ||
<button type="button" class="btn btn-tool" data-card-widget="collapse"> | ||
<i class="fas fa-minus"></i> | ||
</button> | ||
</div> | ||
</div> | ||
<div class="card-body"> | ||
<ul class="list-group list-group-flush"> | ||
<% @broadcast_announcements.each do |announcement| %> | ||
<li class="list-group-item"> | ||
<strong><%= if announcement.created_at.strftime("%Y") == DateTime.now.strftime("%Y") | ||
announcement.created_at.strftime("%B %d") | ||
else | ||
announcement.created_at.strftime("%B %d %Y") | ||
end %></strong> | ||
<br> | ||
<%= announcement.message %> | ||
<% unless announcement.link == '' %> | ||
<br> | ||
<a href="<%= announcement.link %>" class="btn btn-primary">more info</a> | ||
<% end %> | ||
</li> | ||
<% end %> | ||
</ul> | ||
</div> | ||
</div> | ||
<% end %> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
|
||
<%= render( | ||
"shared/card", | ||
id: "low_inventory", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,35 @@ | ||
<table class="table table-hover striped"> | ||
<thead> | ||
<tr> | ||
<th>Date</th> | ||
<th>Partner</th> | ||
<th>Requestor</th> | ||
<th>Comments</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<% outstanding_requests.each do |item| %> | ||
<tr> | ||
<td class="date"><%= link_to item.created_at.strftime("%m/%d/%Y"), item %></td> | ||
<td><%= item.partner.name %></td> | ||
<td><%= item.partner_user&.formatted_email %></td> | ||
<td><%= item.comments %></td> | ||
</tr> | ||
<% end %> | ||
</tbody> | ||
</table> | ||
<%= | ||
render( | ||
"shared/card", | ||
id: "outstanding", | ||
gradient: "warning", | ||
title: "Outstanding Requests", | ||
footer: link_to("View all requests", requests_path), | ||
footer_options: { class: "text-center" }, | ||
) do | ||
%> | ||
<% if @outstanding_requests.empty? %> | ||
No outstanding requests! | ||
<% else %> | ||
<table class="table table-hover striped"> | ||
<thead> | ||
<tr> | ||
<th>Date</th> | ||
<th>Partner</th> | ||
<th>Requestor</th> | ||
<th>Comments</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<% @outstanding_requests.take(25).each do |item| %> | ||
<tr> | ||
<td class="date"><%= link_to item.created_at.strftime("%m/%d/%Y"), item %></td> | ||
<td><%= item.partner.name %></td> | ||
<td><%= item.partner_user&.formatted_email %></td> | ||
<td><%= item.comments %></td> | ||
</tr> | ||
<% end %> | ||
</tbody> | ||
</table> | ||
<% end %> | ||
<% end %> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<%= render( | ||
"shared/card", | ||
id: "partner_approvals", | ||
title: "Partner Approvals", | ||
class: "wide-table", | ||
type: @partners_awaiting_review.blank? ? :box : :table | ||
) do %> | ||
<% if @partners_awaiting_review.present? %> | ||
<table class="table table-striped"> | ||
<thead> | ||
<tr> | ||
<th>Partner Name</th> | ||
<th>Primary Contact Name</th> | ||
<th>Primary Contact Email</th> | ||
<th>Review Requested</th> | ||
<th>Action</th> | ||
</tr> | ||
</thead> | ||
<% @partners_awaiting_review.each do |partner| %> | ||
<tr> | ||
<td><%= partner.name %></td> | ||
<td><%= partner.profile.primary_contact_name %></td> | ||
<td><%= partner.profile.primary_contact_email %></td> | ||
<td><%= partner.updated_at.strftime("%B %d %Y") %></td> | ||
<td> | ||
<%= view_button_to partner_path(partner) + "#partner-information", { text: "Review Application", icon: "check", type: "warning", class: 'badge' } %> | ||
</td> | ||
</tr> | ||
<% end %> | ||
</table> | ||
<% else %> | ||
No partners waiting for approval | ||
<% end %> | ||
<% end %> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be done more cleanly by using
params[:controller]
and (if necessary)params[:action]
. We shouldn't be doing any kind of string munging of the path.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. It might look similar, but now you can specify the controller name and optionally the action name.