Skip to content

Commit 3dfb654

Browse files
authored
821 Create manufacturers on new donations (#1013) (#1020)
Merges the development branch
1 parent c775181 commit 3dfb654

34 files changed

+716
-30
lines changed

app/assets/javascripts/donations.coffee.erb

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,62 @@
44

55
$ ->
66
control_id = "#donation_source"
7+
78
diaper_drive_participant_id = "#donation_diaper_drive_participant_id"
9+
manufacturer_id = "#donation_manufacturer_id"
10+
11+
donation_site_container_id = "div.donation_donation_site"
12+
diaper_drive_participant_container_id = "div.donation_diaper_drive_participant"
13+
manufacturer_container_id = "div.donation_manufacturer"
14+
815
diaper_drive_participant_text = "<%= Donation::SOURCES[:diaper_drive] %>"
16+
manufacturer_text = "<%= Donation::SOURCES[:manufacturer] %>"
917
donation_site_text = "<%= Donation::SOURCES[:donation_site] %>"
10-
diaper_drive_participant_container_id = "div.donation_diaper_drive_participant"
11-
donation_site_container_id = "div.donation_donation_site"
18+
1219
$(diaper_drive_participant_container_id).hide()
20+
$(manufacturer_container_id).hide()
1321
$(donation_site_container_id).hide()
22+
1423
create_new_diaper_drive_text = "---Create new diaper drive---"
24+
create_new_manufacturer_text = "---Create new Manufacturer---"
25+
1526
$(diaper_drive_participant_id).
16-
append('<option value="">---Create new diaper drive---</option>')
27+
append('<option value="">' + create_new_diaper_drive_text + '</option>')
28+
29+
$(manufacturer_id).
30+
append('<option value="">' + create_new_manufacturer_text + '</option>')
1731

1832
$(document).on "change", diaper_drive_participant_id, (evt) ->
1933
selection = $(diaper_drive_participant_id + " option").
2034
filter(':selected').text()
2135
if (selection is create_new_diaper_drive_text)
2236
$("#new_diaper_drive").click()
2337

38+
$(document).on "change", manufacturer_id, (evt) ->
39+
selection = $(manufacturer_id + " option").
40+
filter(':selected').text()
41+
if (selection is create_new_manufacturer_text)
42+
$("#new_manufacturer").click()
43+
2444
$(document).on "change", control_id, (evt) ->
2545
selection = $(control_id + " option").filter(':selected').text()
2646

2747
if (selection is diaper_drive_participant_text)
2848
$(diaper_drive_participant_container_id).show()
2949
$(donation_site_container_id).hide()
50+
$(manufacturer_container_id).hide()
51+
else if (selection is manufacturer_text)
52+
$(manufacturer_container_id).show()
53+
$(diaper_drive_participant_container_id).hide()
54+
$(donation_site_container_id).hide()
3055
else if (selection is donation_site_text)
3156
$(diaper_drive_participant_container_id).hide()
3257
$(donation_site_container_id).show()
58+
$(manufacturer_container_id).hide()
3359
else
3460
$(diaper_drive_participant_container_id).hide()
3561
$(donation_site_container_id).hide()
62+
$(manufacturer_container_id).hide()
3663

3764
$(control_id).change()
3865

app/controllers/dashboard_controller.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,10 @@ def index
99
@total_inventory = current_organization.total_inventory
1010

1111
@org_stats = OrganizationStats.new(current_organization)
12+
13+
# calling .recent on recent donations by manufacturers will only count the last 3 donations
14+
# which may not make sense when calculating total count using a date range
15+
@recent_donations_from_manufacturers = current_organization.donations.includes(:line_items).during(helpers.selected_range).by_source(:manufacturer)
16+
@top_manufacturers = current_organization.manufacturers.by_donation_count
1217
end
1318
end

app/controllers/donations_controller.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class DonationsController < ApplicationController
66

77
def index
88
@donations = current_organization.donations
9-
.includes(:line_items, :storage_location, :donation_site, :diaper_drive_participant)
9+
.includes(:line_items, :storage_location, :donation_site, :diaper_drive_participant, :manufacturer)
1010
.order(created_at: :desc)
1111
.class_filter(filter_params)
1212
# Are these going to be inefficient with large datasets?
@@ -22,8 +22,10 @@ def index
2222
@diaper_drives = @donations.collect do |d|
2323
d.source == Donation::SOURCES[:diaper_drive] ? d.diaper_drive_participant : nil
2424
end.compact.uniq
25-
2625
@selected_diaper_drive = filter_params[:by_diaper_drive_participant]
26+
@manufacturers = @donations.collect(&:manufacturer).compact.uniq
27+
@selected_manufacturer = filter_params[:from_manufacturer]
28+
2729
@selected_date = date_filter
2830
end
2931

@@ -102,13 +104,14 @@ def load_form_collections
102104
@storage_locations = current_organization.storage_locations
103105
@donation_sites = current_organization.donation_sites
104106
@diaper_drive_participants = current_organization.diaper_drive_participants
107+
@manufacturers = current_organization.manufacturers
105108
@items = current_organization.items.alphabetized
106109
end
107110

108111
def donation_params
109112
strip_unnecessary_params
110113
params = compact_line_items
111-
params.require(:donation).permit(:source, :comment, :storage_location_id, :money_raised, :issued_at, :donation_site_id, :diaper_drive_participant_id, line_items_attributes: %i(id item_id quantity _destroy)).merge(organization: current_organization)
114+
params.require(:donation).permit(:source, :comment, :storage_location_id, :money_raised, :issued_at, :donation_site_id, :diaper_drive_participant_id, :manufacturer_id, line_items_attributes: %i(id item_id quantity _destroy)).merge(organization: current_organization)
112115
end
113116

114117
def donation_item_params
@@ -118,7 +121,7 @@ def donation_item_params
118121
def filter_params
119122
return {} unless params.key?(:filters)
120123

121-
fp = params.require(:filters).slice(:at_storage_location, :by_source, :from_donation_site, :by_diaper_drive_participant)
124+
fp = params.require(:filters).slice(:at_storage_location, :by_source, :from_donation_site, :by_diaper_drive_participant, :from_manufacturer)
122125
fp.merge(by_issued_at: date_filter)
123126
end
124127

@@ -136,6 +139,7 @@ def date_filter
136139
# Omits donation_site_id or diaper_drive_participant_id if those aren't selected as source
137140
def strip_unnecessary_params
138141
params[:donation].delete(:donation_site_id) unless params[:donation][:source] == Donation::SOURCES[:donation_site]
142+
params[:donation].delete(:manufacturer_id) unless params[:donation][:source] == Donation::SOURCES[:manufacturer]
139143
params[:donation].delete(:diaper_drive_participant_id) unless params[:donation][:source] == Donation::SOURCES[:diaper_drive]
140144
params
141145
end
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
class ManufacturersController < ApplicationController
2+
def index
3+
@manufacturers = current_organization.manufacturers.includes(:donations).all.order(:name)
4+
end
5+
6+
def create
7+
@manufacturer = current_organization.manufacturers.new(manufacturer_params.merge(organization: current_organization))
8+
respond_to do |format|
9+
if @manufacturer.save
10+
format.html { redirect_to manufacturers_path, notice: "New Manufacturer added!" }
11+
format.js
12+
else
13+
flash[:error] = "Something didn't work quite right -- try again?"
14+
format.html { render action: :new }
15+
format.js { render template: "manufacturers/new_modal.js.erb" }
16+
end
17+
end
18+
end
19+
20+
def new
21+
@manufacturer = current_organization.manufacturers.new
22+
if request.xhr?
23+
respond_to do |format|
24+
format.js { render template: "manufacturers/new_modal.js.erb" }
25+
end
26+
end
27+
end
28+
29+
def edit
30+
@manufacturer = current_organization.manufacturers.find(params[:id])
31+
end
32+
33+
def show
34+
@manufacturer = current_organization.manufacturers.includes(:donations).find(params[:id])
35+
end
36+
37+
def update
38+
@manufacturer = current_organization.manufacturers.find(params[:id])
39+
if @manufacturer.update(manufacturer_params)
40+
redirect_to manufacturers_path, notice: "#{@manufacturer.name} updated!"
41+
42+
else
43+
flash[:error] = "Something didn't work quite right -- try again?"
44+
render action: :edit
45+
end
46+
end
47+
48+
private
49+
50+
def manufacturer_params
51+
params.require(:manufacturer)
52+
.permit(:name)
53+
end
54+
end

app/models/donation.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,20 @@
1313
# diaper_drive_participant_id :integer
1414
# issued_at :datetime
1515
# money_raised :integer
16+
# manufacturer_id :bigint(8)
1617
#
1718

1819
class Donation < ApplicationRecord
1920
SOURCES = { diaper_drive: "Diaper Drive",
21+
manufacturer: "Manufacturer",
2022
donation_site: "Donation Site",
2123
misc: "Misc. Donation" }.freeze
2224

2325
belongs_to :organization
2426

2527
belongs_to :donation_site, optional: true # Validation is conditionally handled below.
2628
belongs_to :diaper_drive_participant, optional: proc { |d| d.from_diaper_drive? } # Validation is conditionally handled below.
29+
belongs_to :manufacturer, optional: proc { |d| d.from_manufacturer? } # Validation is conditionally handled below.
2730
belongs_to :storage_location
2831
include Itemizable
2932

@@ -36,6 +39,9 @@ class Donation < ApplicationRecord
3639
scope :by_diaper_drive_participant, ->(diaper_drive_participant_id) {
3740
where(diaper_drive_participant_id: diaper_drive_participant_id)
3841
}
42+
scope :from_manufacturer, ->(manufacturer_id) {
43+
where(manufacturer_id: manufacturer_id)
44+
}
3945
scope :for_csv_export, ->(organization) {
4046
where(organization: organization)
4147
.includes(:line_items, :storage_location, :donation_site)
@@ -50,6 +56,9 @@ class Donation < ApplicationRecord
5056
validates :diaper_drive_participant, presence:
5157
{ message: "must be specified since you chose '#{SOURCES[:diaper_drive]}'" },
5258
if: :from_diaper_drive?
59+
validates :manufacturer, presence:
60+
{ message: "must be specified since you chose '#{SOURCES[:manufacturer]}'" },
61+
if: :from_manufacturer?
5362
validates :source, presence: true, inclusion: { in: SOURCES.values,
5463
message: "Must be a valid source." }
5564

@@ -66,6 +75,10 @@ def from_diaper_drive?
6675
source == SOURCES[:diaper_drive]
6776
end
6877

78+
def from_manufacturer?
79+
source == SOURCES[:manufacturer]
80+
end
81+
6982
def from_donation_site?
7083
source == SOURCES[:donation_site]
7184
end

app/models/manufacturer.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# == Schema Information
2+
#
3+
# Table name: manufacturers
4+
#
5+
# id :bigint(8) not null, primary key
6+
# name :string
7+
# organization_id :bigint(8)
8+
# created_at :datetime not null
9+
# updated_at :datetime not null
10+
#
11+
12+
class Manufacturer < ApplicationRecord
13+
belongs_to :organization
14+
15+
has_many :donations, inverse_of: :manufacturer, dependent: :destroy
16+
17+
has_many :line_items, through: :donations
18+
19+
validates :name, presence: true, uniqueness: { scope: :organization, message: 'Manufacturer already exists' }
20+
21+
def volume
22+
# returns 0 instead of nil when Manufacturer exists without any donations
23+
donations.map { |d| d.line_items.total }.reduce(:+) || 0
24+
end
25+
26+
def self.by_donation_count(count = 10)
27+
# selects manufacturers that have donation qty > 0
28+
# and sorts them by highest volume of donation
29+
select { |m| m.volume.positive? }.sort.reverse.first(count)
30+
end
31+
32+
private
33+
34+
def exists_in_org?
35+
organization.manufacturers.where(name: name).exists?
36+
end
37+
end

app/models/organization.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def all
4040
has_many :purchases, dependent: :destroy
4141
has_many :donation_sites, dependent: :destroy
4242
has_many :diaper_drive_participants, dependent: :destroy
43+
has_many :manufacturers, dependent: :destroy
4344
has_many :vendors, dependent: :destroy
4445
has_many :storage_locations, dependent: :destroy
4546
has_many :inventory_items, through: :storage_locations
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<div class="row manufacturer">
2+
<div class="pull-left">
3+
<%= link_to manufacturer do %>
4+
<%= manufacturer.name %> (<%= number_with_delimiter(manufacturer.volume) %>)
5+
<% end %>
6+
</div>
7+
</div>

app/views/dashboard/index.html.erb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,31 @@
155155
}) %>
156156
</div>
157157
</div>
158+
<div class="box box-success">
159+
<div class="box-header with-border">
160+
<h3 class="box-title">Manufacturer Donations</h3>
161+
<div class="box-tools pull-right">
162+
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i>
163+
</button>
164+
<button type="button" class="btn btn-box-tool" data-widget="remove"><i class="fa fa-times"></i></button>
165+
</div>
166+
</div>
167+
<div class="box-body text-center float-center">
168+
<h3 class="text-center"><%= number_with_delimiter(@recent_donations_from_manufacturers.sum { |d| d.line_items.total }) %> items donated <%= display_interval %> by <%= pluralize(@recent_donations_from_manufacturers.group_by(&:manufacturer).count, 'Manufacturer') %></h3>
169+
</div>
170+
<div class="box-body">
171+
<div class="box-body text-center float-center">
172+
<h4>Top Manufacturer Donations</h4>
173+
<%= render partial: "manufacturer", collection: @top_manufacturers, as: :manufacturer %>
174+
</div>
175+
</div>
176+
<div class="box-footer text-center">
177+
<%= link_to "See more...", donations_path(
178+
filters: {
179+
by_source: "Manufacturer"
180+
}) %>
181+
</div>
182+
</div>
158183
<div class="box box-info">
159184
<div class="box-header with-border">
160185
<h3 class="box-title">Purchases</h3>

app/views/donations/_donation_form.html.erb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@
3232
</div>
3333
</div>
3434

35+
<div class="row">
36+
<div class="col-xs-8 col-md-6 col-lg-3">
37+
<%= f.association :manufacturer,
38+
collection: @manufacturers,
39+
prompt: "Choose one...",
40+
label_method: :name,
41+
label: "Manufacturer",
42+
error: "Which Manufacturer was this from?",
43+
wrapper: :vertical_input_group %>
44+
</div>
45+
</div>
46+
3547
<div class="row">
3648
<div class="col-xs-8 col-md-6 col-lg-3">
3749
<%= f.association :storage_location,

0 commit comments

Comments
 (0)