From b4544cd83b257609961495741ee6bb52f68016f6 Mon Sep 17 00:00:00 2001 From: Albert Chae Date: Wed, 30 Dec 2020 15:42:51 -0800 Subject: [PATCH 01/21] PartnerGroup and PartnerGroupMembership models - migrations - factories - validation specs --- .../api/v1/partner_requests_controller.rb | 1 + app/models/organization.rb | 1 + app/models/partner_group.rb | 18 ++++++++++ app/models/partner_group_membership.rb | 30 ++++++++++++++++ .../20201230233305_create_partner_groups.rb | 10 ++++++ ...233349_create_partner_group_memberships.rb | 10 ++++++ db/schema.rb | 21 +++++++++++ spec/factories/partner_group_memberships.rb | 17 +++++++++ spec/factories/partner_groups.rb | 17 +++++++++ spec/models/partner_group_membership_spec.rb | 36 +++++++++++++++++++ spec/models/partner_group_spec.rb | 28 +++++++++++++++ 11 files changed, 189 insertions(+) create mode 100644 app/models/partner_group.rb create mode 100644 app/models/partner_group_membership.rb create mode 100644 db/migrate/20201230233305_create_partner_groups.rb create mode 100644 db/migrate/20201230233349_create_partner_group_memberships.rb create mode 100644 spec/factories/partner_group_memberships.rb create mode 100644 spec/factories/partner_groups.rb create mode 100644 spec/models/partner_group_membership_spec.rb create mode 100644 spec/models/partner_group_spec.rb diff --git a/app/controllers/api/v1/partner_requests_controller.rb b/app/controllers/api/v1/partner_requests_controller.rb index b79be2463f..096f574cd4 100644 --- a/app/controllers/api/v1/partner_requests_controller.rb +++ b/app/controllers/api/v1/partner_requests_controller.rb @@ -22,6 +22,7 @@ def show return head :forbidden unless api_key_valid? organization = Organization.find(params[:id]) + # replace this with items from partner group render json: organization.valid_items, status: :ok rescue ActiveRecord::RecordNotFound => e render json: { error: e.message }, status: :bad_request diff --git a/app/models/organization.rb b/app/models/organization.rb index eb957faac5..fdacbdab06 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -45,6 +45,7 @@ class Organization < ApplicationRecord has_many :donations has_many :manufacturers has_many :partners + has_many :partner_groups has_many :purchases has_many :requests has_many :storage_locations diff --git a/app/models/partner_group.rb b/app/models/partner_group.rb new file mode 100644 index 0000000000..b1e0e3e51e --- /dev/null +++ b/app/models/partner_group.rb @@ -0,0 +1,18 @@ +# == Schema Information +# +# Table name: partner_groups +# +# id :bigint not null, primary key +# name :string +# created_at :datetime not null +# updated_at :datetime not null +# organization_id :bigint +# +class PartnerGroup < ApplicationRecord + belongs_to :organization + has_many :partner_group_memberships + has_many :partners, through: :partner_group_memberships + + validates :organization, presence: true + validates :name, presence: true, uniqueness: { scope: :organization } +end diff --git a/app/models/partner_group_membership.rb b/app/models/partner_group_membership.rb new file mode 100644 index 0000000000..da4b802535 --- /dev/null +++ b/app/models/partner_group_membership.rb @@ -0,0 +1,30 @@ +# == Schema Information +# +# Table name: partner_group_memberships +# +# id :bigint not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# partner_group_id :bigint +# partner_id :bigint +# +class PartnerGroupMembership < ApplicationRecord + belongs_to :partner_group + belongs_to :partner + has_one :organization, through: :partner_group + + validates :partner_group, presence: true + validates :partner, presence: true, uniqueness: { scope: :partner_group } + + validate :partner_belongs_to_partner_group_organization + + private + + def partner_belongs_to_partner_group_organization + return if organization.nil? + + unless organization == partner.organization + errors.add :partner, "partner must belong to same organization as partner_group" + end + end +end diff --git a/db/migrate/20201230233305_create_partner_groups.rb b/db/migrate/20201230233305_create_partner_groups.rb new file mode 100644 index 0000000000..61f1350370 --- /dev/null +++ b/db/migrate/20201230233305_create_partner_groups.rb @@ -0,0 +1,10 @@ +class CreatePartnerGroups < ActiveRecord::Migration[6.0] + def change + create_table :partner_groups do |t| + t.references :organization, foreign_key: true + t.string :name + + t.timestamps + end + end +end diff --git a/db/migrate/20201230233349_create_partner_group_memberships.rb b/db/migrate/20201230233349_create_partner_group_memberships.rb new file mode 100644 index 0000000000..aa4f3dd64d --- /dev/null +++ b/db/migrate/20201230233349_create_partner_group_memberships.rb @@ -0,0 +1,10 @@ +class CreatePartnerGroupMemberships < ActiveRecord::Migration[6.0] + def change + create_table :partner_group_memberships do |t| + t.references :partner_group, foreign_key: true + t.references :partner, foreign_key: true + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 516c2483ab..78cf8c0a12 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,6 +11,7 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema.define(version: 20_210_107_175_100) do + # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -289,6 +290,23 @@ t.index ["short_name"], name: "index_organizations_on_short_name" end + create_table "partner_group_memberships", force: :cascade do |t| + t.bigint "partner_group_id" + t.bigint "partner_id" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["partner_group_id"], name: "index_partner_group_memberships_on_partner_group_id" + t.index ["partner_id"], name: "index_partner_group_memberships_on_partner_id" + end + + create_table "partner_groups", force: :cascade do |t| + t.bigint "organization_id" + t.string "name" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["organization_id"], name: "index_partner_groups_on_organization_id" + end + create_table "partners", id: :serial, force: :cascade do |t| t.string "name" t.string "email" @@ -418,6 +436,9 @@ add_foreign_key "kits", "organizations" add_foreign_key "manufacturers", "organizations" add_foreign_key "organizations", "account_requests" + add_foreign_key "partner_group_memberships", "partner_groups" + add_foreign_key "partner_group_memberships", "partners" + add_foreign_key "partner_groups", "organizations" add_foreign_key "requests", "organizations" add_foreign_key "requests", "partners" end diff --git a/spec/factories/partner_group_memberships.rb b/spec/factories/partner_group_memberships.rb new file mode 100644 index 0000000000..028a68b72d --- /dev/null +++ b/spec/factories/partner_group_memberships.rb @@ -0,0 +1,17 @@ +# == Schema Information +# +# Table name: partner_group_memberships +# +# id :bigint not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# partner_group_id :bigint +# partner_id :bigint +# + +FactoryBot.define do + factory :partner_group_membership do + partner_group + partner + end +end diff --git a/spec/factories/partner_groups.rb b/spec/factories/partner_groups.rb new file mode 100644 index 0000000000..bdf52b9fad --- /dev/null +++ b/spec/factories/partner_groups.rb @@ -0,0 +1,17 @@ +# == Schema Information +# +# Table name: partner_groups +# +# id :bigint not null, primary key +# name :string +# created_at :datetime not null +# updated_at :datetime not null +# organization_id :bigint +# + +FactoryBot.define do + factory :partner_group do + sequence(:name) { |n| "Group #{n}" } + organization { Organization.try(:first) || create(:organization) } + end +end diff --git a/spec/models/partner_group_membership_spec.rb b/spec/models/partner_group_membership_spec.rb new file mode 100644 index 0000000000..bc53474833 --- /dev/null +++ b/spec/models/partner_group_membership_spec.rb @@ -0,0 +1,36 @@ +# == Schema Information +# +# Table name: partner_group_memberships +# +# id :bigint not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# partner_group_id :bigint +# partner_id :bigint +# +RSpec.describe PartnerGroupMembership, type: :model do + context "Validations >" do + it "must belong to a partner_group" do + expect(build(:partner_group_membership, partner_group_id: nil)).not_to be_valid + end + + it "must belong to a partner" do + expect(build(:partner_group_membership, partner_id: nil)).not_to be_valid + end + + it "a partner can only be a member of a partner_group once" do + membership = create(:partner_group_membership) + expect(build(:partner_group_membership, + partner_group: membership.partner_group, + partner: membership.partner)).not_to be_valid + end + + it "a partner must belong to the same organization as the partner_group" do + partner_group = create(:partner_group, organization: create(:organization)) + partner = create(:partner, organization: create(:organization)) + expect(build(:partner_group_membership, + partner_group: partner_group, + partner: partner)).not_to be_valid + end + end +end diff --git a/spec/models/partner_group_spec.rb b/spec/models/partner_group_spec.rb new file mode 100644 index 0000000000..8ce9cbf937 --- /dev/null +++ b/spec/models/partner_group_spec.rb @@ -0,0 +1,28 @@ +# == Schema Information +# +# Table name: partner_groups +# +# id :bigint not null, primary key +# name :string +# created_at :datetime not null +# updated_at :datetime not null +# organization_id :bigint +# +RSpec.describe PartnerGroup, type: :model do + context "Validations >" do + it "must belong to an organization" do + expect(build(:partner_group, organization_id: nil)).not_to be_valid + end + + it "requires a unique name within an organization" do + expect(build(:partner_group, name: nil)).not_to be_valid + create(:partner_group, name: "Foo") + expect(build(:partner_group, name: "Foo")).not_to be_valid + end + + it "does not require a unique name between organizations" do + create(:partner, name: "Foo") + expect(build(:partner, name: "Foo", organization: build(:organization))).to be_valid + end + end +end From bc90be3fcc4a79be0c7222510a9ebf4f99e93e27 Mon Sep 17 00:00:00 2001 From: Albert Chae Date: Wed, 30 Dec 2020 22:46:39 -0800 Subject: [PATCH 02/21] Basic CRUD for PartnerGroups TODO: add tests TODO: need to be able to add partners --- app/controllers/partner_groups_controller.rb | 56 +++++++++++++++ app/views/layouts/_lte_sidebar.html.erb | 7 ++ app/views/partner_groups/_form.html.erb | 29 ++++++++ app/views/partner_groups/edit.html.erb | 25 +++++++ app/views/partner_groups/index.html.erb | 67 ++++++++++++++++++ app/views/partner_groups/new.html.erb | 25 +++++++ app/views/partner_groups/show.html.erb | 71 ++++++++++++++++++++ config/routes.rb | 3 + 8 files changed, 283 insertions(+) create mode 100644 app/controllers/partner_groups_controller.rb create mode 100644 app/views/partner_groups/_form.html.erb create mode 100644 app/views/partner_groups/edit.html.erb create mode 100644 app/views/partner_groups/index.html.erb create mode 100644 app/views/partner_groups/new.html.erb create mode 100644 app/views/partner_groups/show.html.erb diff --git a/app/controllers/partner_groups_controller.rb b/app/controllers/partner_groups_controller.rb new file mode 100644 index 0000000000..c6a83c5c58 --- /dev/null +++ b/app/controllers/partner_groups_controller.rb @@ -0,0 +1,56 @@ +class PartnerGroupsController < ApplicationController + def index + @partner_groups = current_organization.partner_groups + + respond_to do |format| + format.html + end + end + + def show + @partner_group = current_organization.partner_groups.find(params[:id]) + + respond_to do |format| + format.html + end + end + + def new + @partner_group = current_organization.partner_groups.new + end + + def create + @partner_group = current_organization.partner_groups.new(partner_group_params) + if @partner_group.save + redirect_to partner_groups_path, notice: "Partner group added!" + else + flash[:error] = "Something didn't work quite right -- try again?" + render action: :new + end + end + + def edit + @partner_group = current_organization.partner_groups.find(params[:id]) + end + + def update + @partner_group = current_organization.partner_groups.find(params[:id]) + if @partner_group.update(partner_group_params) + redirect_to partner_group_path(@partner_group), notice: "#{@partner_group.name} updated!" + else + flash[:error] = "Something didn't work quite right -- try again?" + render action: :edit + end + end + + def destroy + current_organization.partner_groups.find(params[:id]).destroy + redirect_to partner_groups_path + end + + private + + def partner_group_params + params.require(:partner_group).permit(:name) + end +end diff --git a/app/views/layouts/_lte_sidebar.html.erb b/app/views/layouts/_lte_sidebar.html.erb index f885165b87..29319cf12d 100644 --- a/app/views/layouts/_lte_sidebar.html.erb +++ b/app/views/layouts/_lte_sidebar.html.erb @@ -96,6 +96,13 @@ <% end %> + + -