Skip to content

Commit 407b128

Browse files
Implement partner groups (#2131)
* PartnerGroup and PartnerGroupMembership models - migrations - factories - validation specs * Basic CRUD for PartnerGroups TODO: add tests TODO: need to be able to add partners * Add partner to group via modal with dropdown change partners display in group Implement remove partner from partner group * Implement tagging items with partner groups * Implement PartnerRequestableItemsService - if the partner is not in any groups, return all items in organization - if the partner is a member in some groups, returns items tagged by those groups * Update migrations to utilize different data structure * Add associations and specs to verify them * Update controller actions to fetch requestable items on partner frontend * Be able to associate Partner to PartnerGroup * Get the tabs to render properly based on URL * WIP * Got the functionality to work * Add basic CRUD for partner group system specs * Add partner association to group spec * Remove unused code * Fix broken specs * Fix rubocop complaints * Fix rubocop errors * Fix broken spec * Update * Update items association on partners to indicate purpose Co-authored-by: Edwin Mak <edwinthinks@gmail.com>
1 parent d5e0be7 commit 407b128

42 files changed

Lines changed: 810 additions & 113 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.rubocop.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ AllCops:
1111
Exclude:
1212
- "vendor/**/*"
1313
- "db/schema.rb"
14+
- "db/partners_schema.rb"
1415
- "db/seeds.rb"
1516
- "db/migrate/*"
1617
- "bin/*"
@@ -440,5 +441,8 @@ Rails/WhereExists:
440441
Enabled: false
441442
Rails/WhereNot:
442443
Enabled: false
444+
Rails/HasAndBelongsToMany:
445+
Enabled: false
443446
Lint/EnsureReturn: # The service objects return self in an ensure block. Not using an explicit return does not do correct behavior
444447
Enabled: false
448+

app/assets/javascripts/application.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ function load_quagga() {
124124
};
125125
$(document).on('turbolinks:load', load_quagga);
126126

127+
/**
128+
* Handle loading on specified tab in the URL parameter. In case we would like
129+
* to direct a user to a specific tab on a page rather than the default.
130+
*/
127131

128132
$(document).ready(function () {
129133
var hash = location.hash.replace(/^#/, ''); // ^ means starting, meaning only match the first hash
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
class PartnerGroupsController < ApplicationController
2+
def index
3+
@partner_groups = current_organization.partner_groups
4+
5+
respond_to do |format|
6+
format.html
7+
end
8+
end
9+
10+
def new
11+
@partner_group = current_organization.partner_groups.new
12+
@item_categories = current_organization.item_categories
13+
end
14+
15+
def create
16+
@partner_group = current_organization.partner_groups.new(partner_group_params)
17+
if @partner_group.save
18+
# Redirect to groups tab in Partner page.
19+
redirect_to partners_path + "#nav-partner-groups", notice: "Partner group added!"
20+
else
21+
flash[:error] = "Something didn't work quite right -- try again?"
22+
render action: :new
23+
end
24+
end
25+
26+
def edit
27+
@partner_group = current_organization.partner_groups.find(params[:id])
28+
@item_categories = current_organization.item_categories
29+
end
30+
31+
def update
32+
@partner_group = current_organization.partner_groups.find(params[:id])
33+
if @partner_group.update(partner_group_params)
34+
redirect_to partners_path + "#nav-partner-groups", notice: "Partner group edited!"
35+
else
36+
flash[:error] = "Something didn't work quite right -- try again?"
37+
render action: :edit
38+
end
39+
end
40+
41+
private
42+
43+
def partner_group_params
44+
params.require(:partner_group).permit(:name, item_category_ids: [])
45+
end
46+
end

app/controllers/partners/children_controller.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ def show
3535
def new
3636
family = current_partner.families.find_by!(id: params[:family_id])
3737
@child = family.children.new
38+
39+
requestable_items = PartnerFetchRequestableItemsService.new(partner_id: current_partner.partner.id).call
40+
@formatted_requestable_items = requestable_items.map do |rt|
41+
[rt.name, rt.id]
42+
end
3843
end
3944

4045
def active
@@ -45,6 +50,10 @@ def active
4550

4651
def edit
4752
@child = current_partner.children.find_by(id: params[:id])
53+
requestable_items = PartnerFetchRequestableItemsService.new(partner_id: current_partner.partner.id).call
54+
@formatted_requestable_items = requestable_items.map do |rt|
55+
[rt.name, rt.id]
56+
end
4857
end
4958

5059
def create
@@ -107,4 +116,4 @@ def fetch_valid_item_name(id)
107116
@valid_items.find { |vi| vi[:id] == id }&.fetch(:name)
108117
end
109118
end
110-
end
119+
end

app/controllers/partners/individuals_requests_controller.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ module Partners
22
class IndividualsRequestsController < BaseController
33
def new
44
@request = FamilyRequest.new({}, initial_items: 1)
5-
@requestable_items = Organization.find(current_partner.diaper_bank_id).valid_items.map do |item|
6-
[item[:name], item[:id]]
7-
end.sort
5+
6+
requestable_items = PartnerFetchRequestableItemsService.new(partner_id: current_partner.partner.id).call
7+
@formatted_requestable_items = requestable_items.map do |rt|
8+
[rt.name, rt.id]
9+
end
810
end
911

1012
def create

app/controllers/partners/requests_controller.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ def new
1111
@partner_request = Partners::Request.new
1212
@partner_request.item_requests.build
1313

14-
# Fetch the valid items
15-
@requestable_items = Organization.find(current_partner.diaper_bank_id).valid_items.map do |item|
16-
[item[:name], item[:id]]
17-
end.sort
14+
requestable_items = PartnerFetchRequestableItemsService.new(partner_id: current_partner.partner.id).call
15+
@formatted_requestable_items = requestable_items.map do |rt|
16+
[rt.name, rt.id]
17+
end
1818
end
1919

2020
def show
@@ -35,7 +35,7 @@ def create
3535
else
3636
@partner_request = create_service.partner_request
3737
@errors = create_service.errors
38-
@requestable_items = Organization.find(current_partner.diaper_bank_id).valid_items.map do |item|
38+
@formatted_requestable_items = Organization.find(current_partner.diaper_bank_id).valid_items.map do |item|
3939
[item[:name], item[:id]]
4040
end.sort
4141

app/controllers/partners_controller.rb

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

77
def index
88
@unfiltered_partners_for_statuses = Partner.where(organization: current_organization)
9-
@partners = Partner.where(organization: current_organization).class_filter(filter_params).alphabetized
9+
@partners = Partner.includes(:partner_group).where(organization: current_organization).class_filter(filter_params).alphabetized
10+
@partner_groups = PartnerGroup.includes(:partners, :item_categories).where(organization: current_organization)
1011

1112
respond_to do |format|
1213
format.html
@@ -57,10 +58,12 @@ def show
5758

5859
def new
5960
@partner = current_organization.partners.new
61+
@partner_groups = current_organization.partner_groups
6062
end
6163

6264
def edit
6365
@partner = current_organization.partners.find(params[:id])
66+
@partner_groups = PartnerGroup.where(organization: current_organization)
6467
end
6568

6669
def update
@@ -153,7 +156,7 @@ def reactivate
153156
private
154157

155158
def partner_params
156-
params.require(:partner).permit(:name, :email, :send_reminders, :quota, :notes, documents: [])
159+
params.require(:partner).permit(:name, :email, :send_reminders, :quota, :notes, :partner_group_id, documents: [])
157160
end
158161

159162
helper_method \

app/models/item_category.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
# id :bigint not null, primary key
66
# description :text
7-
# name :string
7+
# name :string not null
88
# created_at :datetime not null
99
# updated_at :datetime not null
1010
# organization_id :integer not null
@@ -16,4 +16,5 @@ class ItemCategory < ApplicationRecord
1616

1717
belongs_to :organization
1818
has_many :items, -> { order(name: :asc) }, inverse_of: :item_category
19+
has_many :partner_groups, dependent: :nullify
1920
end

app/models/organization.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class Organization < ApplicationRecord
4545
has_many :donations
4646
has_many :manufacturers
4747
has_many :partners
48+
has_many :partner_groups
4849
has_many :purchases
4950
has_many :requests
5051
has_many :storage_locations

app/models/partner.rb

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22
#
33
# Table name: partners
44
#
5-
# id :integer not null, primary key
6-
# email :string
7-
# name :string
8-
# notes :text
9-
# quota :integer
10-
# send_reminders :boolean default(FALSE), not null
11-
# status :integer default("uninvited")
12-
# created_at :datetime not null
13-
# updated_at :datetime not null
14-
# organization_id :integer
5+
# id :integer not null, primary key
6+
# email :string
7+
# name :string
8+
# notes :text
9+
# quota :integer
10+
# send_reminders :boolean default(FALSE), not null
11+
# status :integer default("uninvited")
12+
# created_at :datetime not null
13+
# updated_at :datetime not null
14+
# organization_id :integer
15+
# partner_group_id :bigint
1516
#
1617

1718
class Partner < ApplicationRecord
@@ -26,8 +27,11 @@ class Partner < ApplicationRecord
2627
enum status: { uninvited: 0, invited: 1, awaiting_review: 2, approved: 3, error: 4, recertification_required: 5, deactivated: 6 }
2728

2829
belongs_to :organization
29-
has_many :distributions, dependent: :destroy
30+
belongs_to :partner_group, optional: true
31+
has_many :item_categories, through: :partner_group
32+
has_many :requestable_items, through: :item_categories, source: :items
3033

34+
has_many :distributions, dependent: :destroy
3135
has_many :requests, dependent: :destroy
3236

3337
has_many_attached :documents

0 commit comments

Comments
 (0)