From 109dfb177d4ecfc1985dc92df5a725edd29bb76a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 06:35:24 +0000 Subject: [PATCH 1/9] Initial plan From 4882fdf383e91040f8bb7af0aa94d9405e6f1c8d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 06:42:06 +0000 Subject: [PATCH 2/9] Rename organization_people to affiliations - models, controllers, routes, factories, specs Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com> --- app/controllers/affiliations_controller.rb | 36 +++++++++++++++++++ app/controllers/application_controller.rb | 4 +-- .../organization_people_controller.rb | 36 ------------------- app/controllers/organizations_controller.rb | 20 +++++------ app/controllers/people_controller.rb | 30 ++++++++-------- app/controllers/users_controller.rb | 4 +-- ...{organization_person.rb => affiliation.rb} | 10 +++--- app/models/organization.rb | 10 +++--- app/models/person.rb | 26 ++++++-------- ....html.erb => _affiliation_fields.html.erb} | 0 ....html.erb => _affiliation_fields.html.erb} | 0 app/views/people/_form.html.erb | 12 +++---- .../people/sections/_affiliations.html.erb | 14 ++++++++ .../sections/_organization_people.html.erb | 16 --------- app/views/people/show.html.erb | 2 +- ....html.erb => _affiliation_fields.html.erb} | 0 config/routes.rb | 2 +- ...ame_organization_people_to_affiliations.rb | 5 +++ ...organization_people.rb => affiliations.rb} | 2 +- ...ion_person_spec.rb => affiliation_spec.rb} | 14 ++++---- 20 files changed, 121 insertions(+), 122 deletions(-) create mode 100644 app/controllers/affiliations_controller.rb delete mode 100644 app/controllers/organization_people_controller.rb rename app/models/{organization_person.rb => affiliation.rb} (88%) rename app/views/organizations/{_organization_person_fields.html.erb => _affiliation_fields.html.erb} (100%) rename app/views/people/{_organization_person_fields.html.erb => _affiliation_fields.html.erb} (100%) create mode 100644 app/views/people/sections/_affiliations.html.erb delete mode 100644 app/views/people/sections/_organization_people.html.erb rename app/views/users/{_organization_person_fields.html.erb => _affiliation_fields.html.erb} (100%) create mode 100644 db/migrate/20260215063711_rename_organization_people_to_affiliations.rb rename spec/factories/{organization_people.rb => affiliations.rb} (76%) rename spec/models/{organization_person_spec.rb => affiliation_spec.rb} (75%) diff --git a/app/controllers/affiliations_controller.rb b/app/controllers/affiliations_controller.rb new file mode 100644 index 000000000..b4e3a9ddc --- /dev/null +++ b/app/controllers/affiliations_controller.rb @@ -0,0 +1,36 @@ +class AffiliationsController < ApplicationController + before_action :set_affiliation, only: %i[ destroy ] + + def destroy + authorize! @affiliation, to: :destroy? + affiliation = Affiliation.find(params[:id]) + person = affiliation.person + destroyed = affiliation.destroy + + if destroyed + flash.now[:notice] = "Person has been removed from the organization." + else + flash.now[:alert] = "Unable to remove affiliation. Please contact AWBW." + end + + respond_to do |format| + format.turbo_stream do + if destroyed + render turbo_stream: turbo_stream.remove("affiliation_#{affiliation.id}") + else + render turbo_stream: turbo_stream.replace("flash_now", partial: "shared/flash_messages"), + status: :unprocessable_entity + end + end + format.html do + redirect_to generate_facilitator_user_path(person.user) + end + end + end + + private + + def set_affiliation + @affiliation = Affiliation.find(params[:id]) + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e3ed1feb4..878e793ad 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -69,8 +69,8 @@ def flush_lifecycle_events def preload_current_user_associations return unless current_user&.person - @current_user_active_org_people = current_user.person - .organization_people + @current_user_active_affiliations = current_user.person + .affiliations .active .includes(:organization) .load diff --git a/app/controllers/organization_people_controller.rb b/app/controllers/organization_people_controller.rb deleted file mode 100644 index 7671e7095..000000000 --- a/app/controllers/organization_people_controller.rb +++ /dev/null @@ -1,36 +0,0 @@ -class OrganizationPeopleController < ApplicationController - before_action :set_organization_person, only: %i[ destroy ] - - def destroy - authorize! @organization_person, to: :destroy? - organization_person = OrganizationPerson.find(params[:id]) - person = organization_person.person - destroyed = organization_person.destroy - - if destroyed - flash.now[:notice] = "Person has been removed from the organization." - else - flash.now[:alert] = "Unable to remove organization person. Please contact AWBW." - end - - respond_to do |format| - format.turbo_stream do - if destroyed - render turbo_stream: turbo_stream.remove("organization_person_#{organization_person.id}") - else - render turbo_stream: turbo_stream.replace("flash_now", partial: "shared/flash_messages"), - status: :unprocessable_entity - end - end - format.html do - redirect_to generate_facilitator_user_path(person.user) - end - end - end - - private - - def set_organization_person - @organization_person = OrganizationPerson.find(params[:id]) - end -end diff --git a/app/controllers/organizations_controller.rb b/app/controllers/organizations_controller.rb index 4eb8d5288..765d8c39d 100644 --- a/app/controllers/organizations_controller.rb +++ b/app/controllers/organizations_controller.rb @@ -101,16 +101,16 @@ def set_form_variables .map { |fn, ln, id| [ "#{fn} #{ln}", id ] } if @organization.persisted? && @organization.errors.empty? - org_people = @organization.organization_people - org_people = org_people.includes(:person) unless org_people.loaded? - sorted = org_people.to_a - .sort_by { |op| - expired = op.inactive? || (op.end_date.present? && op.end_date < Date.current) + affiliations = @organization.affiliations + affiliations = affiliations.includes(:person) unless affiliations.loaded? + sorted = affiliations.to_a + .sort_by { |affiliation| + expired = affiliation.inactive? || (affiliation.end_date.present? && affiliation.end_date < Date.current) [ expired ? 1 : 0, - op.person&.first_name.to_s.downcase, - op.person&.last_name.to_s.downcase ] + affiliation.person&.first_name.to_s.downcase, + affiliation.person&.last_name.to_s.downcase ] } - @organization.organization_people.proxy_association.target.replace(sorted) + @organization.affiliations.proxy_association.target.replace(sorted) end end @@ -137,7 +137,7 @@ def set_organization @organization = Organization.includes( :organization_status, :windows_type, :addresses, { sectorable_items: :sector }, - organization_people: :person + affiliations: :person ).find(params[:id]) end @@ -155,7 +155,7 @@ def organization_params :sector_id, :_destroy ], - organization_people_attributes: [ + affiliations_attributes: [ :id, :person_id, :inactive, diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 62d0c63f6..6eb541f14 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -9,7 +9,7 @@ def index :avatar_attachment, :user, sectorable_items: :sector, - organization_people: :organization + affiliations: :organization ).references(:user)) filtered = base_scope.search_by_params(params.to_unsafe_h) .order(:first_name, :last_name) @@ -57,9 +57,9 @@ def show when "workshop_variation_ideas" @workshop_variation_ideas = @person.user&.workshop_variation_ideas_creator&.order(created_at: :desc)&.paginate(page: params[:page], per_page: per_page) || [] render partial: "people/sections/workshop_variation_ideas", locals: { person: @person, workshop_variation_ideas: @workshop_variation_ideas } - when "organization_people" - @organization_people = @person.organization_people.active.includes(organization: :logo_attachment).paginate(page: params[:page], per_page: per_page) - render partial: "people/sections/organization_people", locals: { person: @person, organization_people: @organization_people } + when "affiliations" + @affiliations = @person.affiliations.active.includes(organization: :logo_attachment).paginate(page: params[:page], per_page: per_page) + render partial: "people/sections/affiliations", locals: { person: @person, affiliations: @affiliations } end end end @@ -79,7 +79,7 @@ def edit { avatar_attachment: :blob }, { comments: [ :created_by, :updated_by ] }, { sectorable_items: :sector }, - organization_people: { organization: :logo_attachment } + affiliations: { organization: :logo_attachment } ).find(params[:id]).decorate authorize! @person set_form_variables @@ -175,18 +175,18 @@ def set_form_variables set_user # @person.build_user if @person.user.blank? # Build a fresh one if missing if @person.persisted? && @person.errors.empty? - org_people = @person.organization_people - org_people = org_people.includes(:organization) unless org_people.loaded? - sorted = org_people.to_a - .sort_by { |op| - expired = op.inactive? || (op.end_date.present? && op.end_date < Date.current) + affiliations = @person.affiliations + affiliations = affiliations.includes(:organization) unless affiliations.loaded? + sorted = affiliations.to_a + .sort_by { |affiliation| + expired = affiliation.inactive? || (affiliation.end_date.present? && affiliation.end_date < Date.current) [ expired ? 1 : 0, - op.start_date || Date.new(9999), - op.organization&.name.to_s.downcase ] + affiliation.start_date || Date.new(9999), + affiliation.organization&.name.to_s.downcase ] } - @person.organization_people.proxy_association.target.replace(sorted) + @person.affiliations.proxy_association.target.replace(sorted) end - @person.organization_people.build if @person.organization_people.empty? + @person.affiliations.build if @person.affiliations.empty? @all_sectors = Sector.published.order(:name) @sectors_collection = @all_sectors.pluck(:name, :id) @@ -372,7 +372,7 @@ def person_params :zip2, :notes ], - organization_people_attributes: [ + affiliations_attributes: [ :id, :organization_id, :position, diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 252e6bf74..6d47ddc22 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -267,7 +267,7 @@ def set_person def set_form_variables set_person - @user.person.organization_people.first || @user.person.organization_people.build if @user.person + @user.person.affiliations.first || @user.person.affiliations.build if @user.person organizations = authorized_scope(Organization.all) @organizations_array = organizations.order(:name).pluck(:name, :id) end @@ -333,8 +333,8 @@ def user_params :phone, :phone2, :phone3, :birthday, :best_time_to_call, :notes, # legacy to remove later ##### - organization_people_attributes: [ :id, :organization_id, :position, :title, :inactive, :primary_contact, :start_date, :end_date, :_destroy ], comments_attributes: [ :id, :body ], + affiliations_attributes: [ :id, :organization_id, :position, :title, :inactive, :primary_contact, :start_date, :end_date, :_destroy ], ) end end diff --git a/app/models/organization_person.rb b/app/models/affiliation.rb similarity index 88% rename from app/models/organization_person.rb rename to app/models/affiliation.rb index c1a0e3f6c..4cb45c248 100644 --- a/app/models/organization_person.rb +++ b/app/models/affiliation.rb @@ -1,4 +1,4 @@ -class OrganizationPerson < ApplicationRecord +class Affiliation < ApplicationRecord belongs_to :organization belongs_to :person, touch: true @@ -28,7 +28,7 @@ def name private def skip_if_duplicate - scope = OrganizationPerson.where( + scope = Affiliation.where( organization_id: organization_id, person_id: person_id, start_date: start_date, @@ -49,7 +49,7 @@ def set_inactive_from_dates def sync_organization_affiliation_dates org = organization - affiliations = org.organization_people.where.not(id: destroyed_by_association ? id : nil) + affiliations = org.affiliations.where.not(id: destroyed_by_association ? id : nil) earliest_start = affiliations.minimum(:start_date) has_active = affiliations.active.exists? @@ -67,7 +67,7 @@ def sync_organization_affiliation_dates end def deactivate_organization_if_no_active_people - return if organization.organization_people.active.exists? + return if organization.affiliations.active.exists? inactive_status = OrganizationStatus.find_by(name: "Inactive") return unless inactive_status @@ -81,7 +81,7 @@ def deactivate_organization_if_no_active_people resource_id: organization.id, resource_title: organization.name, change: "status_set_to_inactive", - reason: "no_active_organization_people" + reason: "no_active_affiliations" ) end end diff --git a/app/models/organization.rb b/app/models/organization.rb index bc4f5a677..fc79a0c91 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -6,8 +6,8 @@ class Organization < ApplicationRecord belongs_to :windows_type, optional: true has_many :addresses, as: :addressable, dependent: :destroy has_many :bookmarks, as: :bookmarkable, dependent: :destroy - has_many :organization_people, dependent: :restrict_with_error - has_many :people, through: :organization_people + has_many :affiliations, dependent: :restrict_with_error + has_many :people, through: :affiliations has_many :users, through: :people has_many :reports has_many :workshop_logs @@ -35,7 +35,7 @@ class Organization < ApplicationRecord validates :organization_status_id, presence: true validates :email, format: { with: URI::MailTo::EMAIL_REGEXP, message: "must be a valid email address" }, allow_blank: true validates :website_url, format: { with: /\Ahttps?:\/\/\S+\z/i, message: "must start with http:// or https://" }, allow_blank: true - validate :affiliation_dates_locked, if: -> { organization_people.any? && !Current.user&.super_user? } + validate :affiliation_dates_locked, if: -> { affiliations.any? && !Current.user&.super_user? } # Nested attributes accepts_nested_attributes_for :addresses, allow_destroy: true, @@ -43,7 +43,7 @@ class Organization < ApplicationRecord accepts_nested_attributes_for :sectorable_items, allow_destroy: true, reject_if: proc { |attrs| attrs["sector_id"].blank? } after_save :remove_duplicate_sectorable_items - accepts_nested_attributes_for :organization_people, allow_destroy: true, + accepts_nested_attributes_for :affiliations, allow_destroy: true, reject_if: proc { |attrs| attrs["person_id"].blank? } # SearchCop @@ -149,7 +149,7 @@ def affiliation_dates_locked end def leader - organization_people.find_by(position: 2) + affiliations.find_by(position: 2) end def remove_duplicate_sectorable_items diff --git a/app/models/person.rb b/app/models/person.rb index 598dc3d44..90e43da50 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -5,8 +5,8 @@ class Person < ApplicationRecord belongs_to :updated_by, class_name: "User" has_one :user, inverse_of: :person, dependent: :nullify - has_many :organization_people, dependent: :destroy - has_many :organizations, through: :organization_people + has_many :affiliations, dependent: :destroy + has_many :organizations, through: :affiliations has_many :communal_reports, through: :organizations, source: :reports has_many :windows_types, through: :organizations @@ -58,7 +58,7 @@ class Person < ApplicationRecord accepts_nested_attributes_for :sectorable_items, allow_destroy: true, reject_if: proc { |attrs| attrs["sector_id"].blank? } accepts_nested_attributes_for :user, update_only: true - accepts_nested_attributes_for :organization_people, allow_destroy: true, + accepts_nested_attributes_for :affiliations, allow_destroy: true, reject_if: proc { |attrs| attrs["organization_id"].blank? } accepts_nested_attributes_for :comments, reject_if: proc { |attrs| attrs["body"].blank? } @@ -76,18 +76,18 @@ class Person < ApplicationRecord scope :published, -> { searchable.with_active_affiliations } scope :searchable, ->(searchable = nil) { searchable ? where(profile_is_searchable: searchable) : where(profile_is_searchable: true) } scope :with_active_affiliations, -> { - joins(:organization_people) - .merge(OrganizationPerson.active) + joins(:affiliations) + .merge(Affiliation.active) .distinct } scope :organization_name, ->(organization_name) { return all if organization_name.blank? - left_joins(organization_people: :organization) + left_joins(affiliations: :organization) .where("organizations.name LIKE ?", "%#{sanitize_sql_like(organization_name)}%") .distinct } scope :organization_id, ->(organization_id) { - joins(:organization_people) - .where(organization_people: { organization_id: organization_id }) + joins(:affiliations) + .where(affiliations: { organization_id: organization_id }) .distinct } def self.search_by_params(params) @@ -102,7 +102,7 @@ def self.search_by_params(params) end def published? - profile_is_searchable? && organization_people.active.exists? + profile_is_searchable? && affiliations.active.exists? end def sector_list @@ -139,15 +139,11 @@ def phone_number end def has_liasion_position_for?(organization_id) - !organization_people.where(organization_id: organization_id, position: 1).first.nil? - end - - def published? - profile_is_searchable? && organization_people.active.exists? + !affiliations.where(organization_id: organization_id, position: 1).first.nil? end def primary_organization - organization_people + affiliations .active .order(updated_at: :desc) .first&.organization diff --git a/app/views/organizations/_organization_person_fields.html.erb b/app/views/organizations/_affiliation_fields.html.erb similarity index 100% rename from app/views/organizations/_organization_person_fields.html.erb rename to app/views/organizations/_affiliation_fields.html.erb diff --git a/app/views/people/_organization_person_fields.html.erb b/app/views/people/_affiliation_fields.html.erb similarity index 100% rename from app/views/people/_organization_person_fields.html.erb rename to app/views/people/_affiliation_fields.html.erb diff --git a/app/views/people/_form.html.erb b/app/views/people/_form.html.erb index 6060fdbeb..eff9a0c93 100644 --- a/app/views/people/_form.html.erb +++ b/app/views/people/_form.html.erb @@ -174,23 +174,23 @@
<% if allowed_to?(:manage?, Person) %>
- <%= f.fields_for :organization_people do |organization_person_form| %> + <%= f.fields_for :affiliations do |affiliation_form| %>
- <%= render "organization_person_fields", - f: organization_person_form %> + <%= render "affiliation_fields", + f: affiliation_form %>
<% end %>
<%= link_to_add_association "➕ Add Affiliation", f, - :organization_people, + :affiliations, class: "btn btn-secondary-outline" %>
<% else %> - <% f.object.organization_people.each do |ou| %> + <% f.object.affiliations.each do |affiliation| %>
-
  • <%= ou.title || ou.position %> - <%= ou.persisted? ? (link_to ou.organization&.name, organization_path(ou.organization), class: "underline") : ou.organization&.name %>
  • +
  • <%= affiliation.title || affiliation.position %> - <%= affiliation.persisted? ? (link_to affiliation.organization&.name, organization_path(affiliation.organization), class: "underline") : affiliation.organization&.name %>
  • <% end %> <% end %> diff --git a/app/views/people/sections/_affiliations.html.erb b/app/views/people/sections/_affiliations.html.erb new file mode 100644 index 000000000..4acc7c164 --- /dev/null +++ b/app/views/people/sections/_affiliations.html.erb @@ -0,0 +1,14 @@ +<%= turbo_frame_tag "person_affiliations_section" do %> + <% if affiliations.any? %> +
    + <% affiliations.each do |affiliation| %> + <%= organization_profile_button(affiliation.organization) %> + <% end %> +
    +
    + <%= tailwind_paginate affiliations, params: { section: "affiliations" } %> +
    + <% else %> +

    No affiliations listed.

    + <% end %> +<% end %> diff --git a/app/views/people/sections/_organization_people.html.erb b/app/views/people/sections/_organization_people.html.erb deleted file mode 100644 index e51e02cce..000000000 --- a/app/views/people/sections/_organization_people.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -<%= turbo_frame_tag "person_organization_people_section" do %> - <% if organization_people.any? %> -
    - <% organization_people.each do |op| %> - <% if op.organization.present? %> - <%= organization_profile_button(op.organization) %> - <% end %> - <% end %> -
    -
    - <%= tailwind_paginate organization_people, params: { section: "organization_people" } %> -
    - <% else %> -

    No affiliations listed.

    - <% end %> -<% end %> diff --git a/app/views/people/show.html.erb b/app/views/people/show.html.erb index 1b95244dd..b5d216741 100644 --- a/app/views/people/show.html.erb +++ b/app/views/people/show.html.erb @@ -100,7 +100,7 @@ <% if @person.profile_show_affiliations? %>

    Affiliations

    - <%= turbo_frame_tag "person_organization_people_section", src: person_path(@person, section: "organization_people"), loading: :lazy do %> + <%= turbo_frame_tag "person_affiliations_section", src: person_path(@person, section: "affiliations"), loading: :lazy do %>

    Loading affiliations...

    <% end %>
    diff --git a/app/views/users/_organization_person_fields.html.erb b/app/views/users/_affiliation_fields.html.erb similarity index 100% rename from app/views/users/_organization_person_fields.html.erb rename to app/views/users/_affiliation_fields.html.erb diff --git a/config/routes.rb b/config/routes.rb index 092da4660..cee6cc7f5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -107,7 +107,7 @@ end end resources :organization_statuses - resources :organization_people + resources :affiliations resources :quotes resources :monthly_reports diff --git a/db/migrate/20260215063711_rename_organization_people_to_affiliations.rb b/db/migrate/20260215063711_rename_organization_people_to_affiliations.rb new file mode 100644 index 000000000..3b3844a77 --- /dev/null +++ b/db/migrate/20260215063711_rename_organization_people_to_affiliations.rb @@ -0,0 +1,5 @@ +class RenameOrganizationPeopleToAffiliations < ActiveRecord::Migration[8.1] + def change + rename_table :organization_people, :affiliations + end +end diff --git a/spec/factories/organization_people.rb b/spec/factories/affiliations.rb similarity index 76% rename from spec/factories/organization_people.rb rename to spec/factories/affiliations.rb index 4f8ea8cb4..c13dada51 100644 --- a/spec/factories/organization_people.rb +++ b/spec/factories/affiliations.rb @@ -1,5 +1,5 @@ FactoryBot.define do - factory :organization_person do + factory :affiliation do association :organization association :person diff --git a/spec/models/organization_person_spec.rb b/spec/models/affiliation_spec.rb similarity index 75% rename from spec/models/organization_person_spec.rb rename to spec/models/affiliation_spec.rb index 017295d91..5f62cf6cf 100644 --- a/spec/models/organization_person_spec.rb +++ b/spec/models/affiliation_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -RSpec.describe OrganizationPerson do +RSpec.describe Affiliation do describe 'associations' do it { should belong_to(:organization) } it { should belong_to(:person) } @@ -8,7 +8,7 @@ describe 'validations' do subject do - build(:organization_person, organization: create(:organization), person: create(:person)) + build(:affiliation, organization: create(:organization), person: create(:person)) end it { should validate_presence_of(:organization_id) } end @@ -18,10 +18,10 @@ end describe '.active' do - let!(:active_op) { create(:organization_person, inactive: false, end_date: nil) } - let!(:active_with_future_end) { create(:organization_person, inactive: false, end_date: 1.month.from_now) } - let!(:inactive_by_flag) { create(:organization_person, inactive: true, end_date: nil) } - let!(:inactive_by_end_date) { create(:organization_person, inactive: false, end_date: 1.day.ago) } + let!(:active_op) { create(:affiliation, inactive: false, end_date: nil) } + let!(:active_with_future_end) { create(:affiliation, inactive: false, end_date: 1.month.from_now) } + let!(:inactive_by_flag) { create(:affiliation, inactive: true, end_date: nil) } + let!(:inactive_by_end_date) { create(:affiliation, inactive: false, end_date: 1.day.ago) } it 'includes records with inactive: false and no end date' do expect(described_class.active).to include(active_op) @@ -41,7 +41,7 @@ end describe '#set_inactive_from_dates' do - let(:op) { create(:organization_person, inactive: false, end_date: nil) } + let(:op) { create(:affiliation, inactive: false, end_date: nil) } it 'sets inactive to true when end_date is set to a past date' do op.update!(end_date: 1.day.ago) From d180b37eddee11876f55aa0c96a45830727d1ac5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 06:46:57 +0000 Subject: [PATCH 3/9] Complete view, policy, decorator, rake task, and spec updates for affiliations rename Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com> --- app/controllers/organizations_controller.rb | 6 +-- ..._decorator.rb => affiliation_decorator.rb} | 2 +- app/decorators/organization_decorator.rb | 2 +- app/decorators/person_decorator.rb | 4 +- ...person_policy.rb => affiliation_policy.rb} | 2 +- app/policies/monthly_report_policy.rb | 2 +- app/policies/organization_policy.rb | 6 +-- app/policies/person_policy.rb | 2 +- app/policies/user_policy.rb | 2 +- app/views/organizations/_form.html.erb | 14 +++--- app/views/organizations/show.html.erb | 12 ++--- app/views/people/index.html.erb | 2 +- app/views/story_ideas/_form.html.erb | 4 +- app/views/workshop_logs/_form.html.erb | 4 +- .../workshop_variation_ideas/_form.html.erb | 2 +- lib/tasks/migrate_affiliations.rake | 45 +++++++++++++++++++ lib/tasks/migrate_organization_people.rake | 45 ------------------- spec/models/organization_spec.rb | 2 +- spec/models/person_spec.rb | 4 +- spec/policies/person_policy_spec.rb | 4 +- 20 files changed, 83 insertions(+), 83 deletions(-) rename app/decorators/{organization_person_decorator.rb => affiliation_decorator.rb} (67%) rename app/policies/{organization_person_policy.rb => affiliation_policy.rb} (87%) create mode 100644 lib/tasks/migrate_affiliations.rake delete mode 100644 lib/tasks/migrate_organization_people.rake diff --git a/app/controllers/organizations_controller.rb b/app/controllers/organizations_controller.rb index 765d8c39d..350309fc7 100644 --- a/app/controllers/organizations_controller.rb +++ b/app/controllers/organizations_controller.rb @@ -8,13 +8,13 @@ def index base_scope = authorized_scope(Organization.includes(:windows_type, :organization_status, :sectors, :addresses, logo_attachment: :blob)) filtered = base_scope.search_by_params(params).order(:name) @organizations_count = filtered.count - @active_people_count = OrganizationPerson.active.where(organization_id: filtered.select(:id)).count("DISTINCT person_id, organization_id") + @active_people_count = Affiliation.active.where(organization_id: filtered.select(:id)).count("DISTINCT person_id, organization_id") @organizations = filtered.paginate(page: params[:page], per_page: per_page) org_ids = @organizations.map(&:id) - @affiliated_since = OrganizationPerson.where(organization_id: org_ids) + @affiliated_since = Affiliation.where(organization_id: org_ids) .group(:organization_id) .minimum(:start_date) - @active_people_counts = OrganizationPerson.active + @active_people_counts = Affiliation.active .where(organization_id: org_ids) .group(:organization_id) .distinct diff --git a/app/decorators/organization_person_decorator.rb b/app/decorators/affiliation_decorator.rb similarity index 67% rename from app/decorators/organization_person_decorator.rb rename to app/decorators/affiliation_decorator.rb index c110346d0..86f3f24dc 100644 --- a/app/decorators/organization_person_decorator.rb +++ b/app/decorators/affiliation_decorator.rb @@ -1,4 +1,4 @@ -class OrganizationPersonDecorator < ApplicationDecorator +class AffiliationDecorator < ApplicationDecorator def detail(length: nil) "#{person.full_name}: #{title.presence || position} - #{organization.name}" end diff --git a/app/decorators/organization_decorator.rb b/app/decorators/organization_decorator.rb index 1a821611e..163388f0d 100644 --- a/app/decorators/organization_decorator.rb +++ b/app/decorators/organization_decorator.rb @@ -13,7 +13,7 @@ def title end def badges - earliest = organization_people.minimum(:start_date) || start_date + earliest = affiliations.minimum(:start_date) || start_date years = earliest ? (Time.zone.now.year - earliest.year) : nil badges = [] badges << badge("Legacy Organization (10+ years)", :legacy_facilitator) if years && years >= 10 diff --git a/app/decorators/person_decorator.rb b/app/decorators/person_decorator.rb index ae760db8b..82b867eb0 100644 --- a/app/decorators/person_decorator.rb +++ b/app/decorators/person_decorator.rb @@ -4,7 +4,7 @@ def title end def detail(length: nil) - text = organization_people.active.map { |op| "#{op.title.presence || op.position}, #{op.organization.name}" }.join(", ") + text = affiliations.active.map { |affiliation| "#{affiliation.title.presence || affiliation.position}, #{affiliation.organization.name}" }.join(", ") length ? text&.truncate(length) : text end @@ -30,7 +30,7 @@ def member_since_year end def badges - earliest = organization_people.minimum(:start_date) || member_since + earliest = affiliations.minimum(:start_date) || member_since years = earliest ? (Time.zone.now.year - earliest.year) : nil badges = [] badges << badge("Legacy Facilitator (10+ years)", :legacy_facilitator) if years && years >= 10 diff --git a/app/policies/organization_person_policy.rb b/app/policies/affiliation_policy.rb similarity index 87% rename from app/policies/organization_person_policy.rb rename to app/policies/affiliation_policy.rb index 740ed79a1..1f99ba949 100644 --- a/app/policies/organization_person_policy.rb +++ b/app/policies/affiliation_policy.rb @@ -1,4 +1,4 @@ -class OrganizationPersonPolicy < ApplicationPolicy +class AffiliationPolicy < ApplicationPolicy # See https://actionpolicy.evilmartians.io/#/writing_policies # def destroy? diff --git a/app/policies/monthly_report_policy.rb b/app/policies/monthly_report_policy.rb index 6caea8943..933873843 100644 --- a/app/policies/monthly_report_policy.rb +++ b/app/policies/monthly_report_policy.rb @@ -21,7 +21,7 @@ def member? @member ||= begin return false unless authenticated? return false unless record.organization - record.organization.organization_people.exists?(person_id: user.person_id) + record.organization.affiliations.exists?(person_id: user.person_id) end end diff --git a/app/policies/organization_policy.rb b/app/policies/organization_policy.rb index 80b266383..11d15c430 100644 --- a/app/policies/organization_policy.rb +++ b/app/policies/organization_policy.rb @@ -26,8 +26,8 @@ def show_workshop_logs? next relation.active if admin? next relation.none unless user&.person_id - relation.joins(:organization_people) - .where(organization_people: { person_id: user.person_id }) + relation.joins(:affiliations) + .where(affiliations: { person_id: user.person_id }) end private @@ -35,7 +35,7 @@ def show_workshop_logs? def member? @member ||= begin return false unless user&.person_id - record.organization_people.exists?(person_id: user.person_id) + record.affiliations.exists?(person_id: user.person_id) end end end diff --git a/app/policies/person_policy.rb b/app/policies/person_policy.rb index 0f8b9fc44..a01414d30 100644 --- a/app/policies/person_policy.rb +++ b/app/policies/person_policy.rb @@ -38,7 +38,7 @@ def owner? def has_associated_data? record.user.present? || - record.organization_people.exists? || + record.affiliations.exists? || record.stories_as_spotlighted_facilitator.exists? end end diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index 719a4c484..85a776ee3 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -22,7 +22,7 @@ def update_password? = authenticated? relation_scope(:colleagues) do |relation| next relation.has_access if admin? - colleague_person_ids = OrganizationPerson.where( + colleague_person_ids = Affiliation.where( organization_id: user.organization_ids ).select(:person_id) relation.where(person_id: colleague_person_ids).or(relation.where(id: user.id)) diff --git a/app/views/organizations/_form.html.erb b/app/views/organizations/_form.html.erb index ccdf31b7d..98ae16150 100644 --- a/app/views/organizations/_form.html.erb +++ b/app/views/organizations/_form.html.erb @@ -1,6 +1,6 @@ <%= simple_form_for(@organization) do |f| %> <%= render 'shared/errors', resource: @organization if @organization.errors.any? %> - <% has_affiliations = f.object.persisted? && f.object.organization_people.any? %> + <% has_affiliations = f.object.persisted? && f.object.affiliations.any? %> <% automanaged_notice = "Auto-managed by affiliations" %>
    @@ -254,23 +254,23 @@
    <% if allowed_to?(:manage?, Organization) %>
    - <%= f.fields_for :organization_people do |organization_person_form| %> + <%= f.fields_for :affiliations do |affiliation_form| %>
    - <%= render "organization_person_fields", - f: organization_person_form %> + <%= render "affiliation_fields", + f: affiliation_form %>
    <% end %>
    <%= link_to_add_association "➕ Add Affiliation", f, - :organization_people, + :affiliations, class: "btn btn-secondary-outline" %>
    <% else %> - <% f.object.user&.person&.organization_people&.each do |pu| %> + <% f.object.user&.person&.affiliations&.each do |affiliation| %>
    -
  • <%= pu.title || pu.position %> - <%= person_profile_button(pu.user.person) if pu.persisted? && pu.user.person %>
  • +
  • <%= affiliation.title || affiliation.position %> - <%= person_profile_button(affiliation.user.person) if affiliation.persisted? && affiliation.user.person %>
  • <% end %> <% end %> diff --git a/app/views/organizations/show.html.erb b/app/views/organizations/show.html.erb index b98d10982..79063bca9 100644 --- a/app/views/organizations/show.html.erb +++ b/app/views/organizations/show.html.erb @@ -116,14 +116,14 @@

    Affiliations

    - <% active_ops = @organization.organization_people - .select { |op| !op.inactive? && (op.end_date.nil? || op.end_date >= Date.current) && op.person.present? } - .sort_by { |op| [op.person.first_name.to_s.downcase, op.person.last_name.to_s.downcase] } %> - <% if active_ops.any? %> + <% active_affiliations = @organization.affiliations + .select { |affiliation| !affiliation.inactive? && (affiliation.end_date.nil? || affiliation.end_date >= Date.current) && affiliation.person.present? } + .sort_by { |affiliation| [affiliation.person.first_name.to_s.downcase, affiliation.person.last_name.to_s.downcase] } %> + <% if active_affiliations.any? %>
    - <% active_ops.each do |pu| %> + <% active_affiliations.each do |affiliation| %>
    - <%= person_profile_button(pu.person, subtitle: pu.title.presence) %> + <%= person_profile_button(affiliation.person, subtitle: affiliation.title.presence) %>
    <% end %>
    diff --git a/app/views/people/index.html.erb b/app/views/people/index.html.erb index a93e9deb0..ae00bed5d 100644 --- a/app/views/people/index.html.erb +++ b/app/views/people/index.html.erb @@ -56,7 +56,7 @@ - <% orgs = person.organization_people.select { |op| !op.inactive? && (op.end_date.nil? || op.end_date >= Date.current) }.map(&:organization).compact.uniq %> + <% orgs = person.affiliations.select { |affiliation| !affiliation.inactive? && (affiliation.end_date.nil? || affiliation.end_date >= Date.current) }.map(&:organization).compact.uniq %> <% if orgs.any? %>
    <% orgs.first(3).each do |org| %> diff --git a/app/views/story_ideas/_form.html.erb b/app/views/story_ideas/_form.html.erb index d5c573d29..64dc5f9c9 100644 --- a/app/views/story_ideas/_form.html.erb +++ b/app/views/story_ideas/_form.html.erb @@ -57,7 +57,7 @@ } %>
    - <% if current_user.person&.organization_people&.count != 1 %> + <% if current_user.person&.affiliations&.count != 1 %> <%= f.input :organization_id, as: :select, collection: @organizations, @@ -72,7 +72,7 @@ input_html: { value: params[:organization_id].presence || f.object.organization_id || @organization_id, class: "#{ "readonly" if promoted_to_story } block w-full rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500" }, label_html: { class: "block text-sm font-medium text-gray-700 mb-1" } %> - <% else current_user.person&.organization_people&.count == 1 %> + <% else current_user.person&.affiliations&.count == 1 %> <%= f.hidden_field :organization_id, value: f.object.organization_id || current_user.person.primary_organization&.id %> <% end %> diff --git a/app/views/workshop_logs/_form.html.erb b/app/views/workshop_logs/_form.html.erb index c54507670..53fe11f13 100644 --- a/app/views/workshop_logs/_form.html.erb +++ b/app/views/workshop_logs/_form.html.erb @@ -33,7 +33,7 @@ label_html: { class: "block text-sm font-medium text-gray-700 mb-1" } %>
    - <% if current_user.person&.organization_people&.count != 1 %> + <% if current_user.person&.affiliations&.count != 1 %> <%= f.input :organization_id, as: :select, collection: @organizations, @@ -47,7 +47,7 @@ input_html: { value: params[:organization_id].presence || f.object.organization_id || @organization_id, class: "block w-full rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500" }, label_html: { class: "block text-sm font-medium text-gray-700 mb-1" } %> - <% else current_user.person&.organization_people&.count == 1 %> + <% else current_user.person&.affiliations&.count == 1 %> <%= f.hidden_field :organization_id, value: f.object.organization_id || current_user.person.primary_organization&.id %> <% end %> diff --git a/app/views/workshop_variation_ideas/_form.html.erb b/app/views/workshop_variation_ideas/_form.html.erb index 9275218d3..511d8e59f 100644 --- a/app/views/workshop_variation_ideas/_form.html.erb +++ b/app/views/workshop_variation_ideas/_form.html.erb @@ -58,7 +58,7 @@ } %>
    - <% if current_user.person&.organization_people&.count != 1 %> + <% if current_user.person&.affiliations&.count != 1 %> <%= f.input :organization_id, as: :select, collection: @organizations, diff --git a/lib/tasks/migrate_affiliations.rake b/lib/tasks/migrate_affiliations.rake new file mode 100644 index 000000000..299f49a60 --- /dev/null +++ b/lib/tasks/migrate_affiliations.rake @@ -0,0 +1,45 @@ +namespace :affiliations do + desc "Populate person_id from user_id in affiliations table" + task migrate_user_to_person: :environment do + puts "🚀 Starting migration of user_id to person_id in affiliations..." + puts "Environment: #{Rails.env}" + puts "===============================================" + + # Find all affiliation records that have user_id but no person_id + records_to_update = Affiliation.where.not(user_id: nil).where(person_id: nil) + + puts "Found #{records_to_update.count} records to update" + + if records_to_update.count == 0 + puts "✅ No records need updating. All affiliations already have person_id populated." + return + end + + updated_count = 0 + skipped_count = 0 + + records_to_update.find_each do |affiliation| + user = User.find_by(id: affiliation.user_id) + + if user&.person + begin + affiliation.update!(person_id: user.person.id) + updated_count += 1 + puts "✓ Updated affiliation #{affiliation.id}: user_id #{affiliation.user_id} -> person_id #{user.person.id}" + rescue => e + puts "✗ Failed to update affiliation #{affiliation.id}: #{e.message}" + skipped_count += 1 + end + else + puts "⚠ Skipping affiliation #{affiliation.id}: user_id #{affiliation.user_id} has no associated person" + skipped_count += 1 + end + end + + puts "===============================================" + puts "Migration complete!" + puts "✅ Successfully updated: #{updated_count} records" + puts "⚠ Skipped: #{skipped_count} records" + puts "Total records processed: #{records_to_update.count}" + end +end diff --git a/lib/tasks/migrate_organization_people.rake b/lib/tasks/migrate_organization_people.rake deleted file mode 100644 index 3b2f5ec79..000000000 --- a/lib/tasks/migrate_organization_people.rake +++ /dev/null @@ -1,45 +0,0 @@ -namespace :organization_people do - desc "Populate person_id from user_id in organization_people table" - task migrate_user_to_person: :environment do - puts "🚀 Starting migration of user_id to person_id in organization_people..." - puts "Environment: #{Rails.env}" - puts "===============================================" - - # Find all organization_people records that have user_id but no person_id - records_to_update = OrganizationPerson.where.not(user_id: nil).where(person_id: nil) - - puts "Found #{records_to_update.count} records to update" - - if records_to_update.count == 0 - puts "✅ No records need updating. All organization_people already have person_id populated." - return - end - - updated_count = 0 - skipped_count = 0 - - records_to_update.find_each do |org_person| - user = User.find_by(id: org_person.user_id) - - if user&.person - begin - org_person.update!(person_id: user.person.id) - updated_count += 1 - puts "✓ Updated organization_person #{org_person.id}: user_id #{org_person.user_id} -> person_id #{user.person.id}" - rescue => e - puts "✗ Failed to update organization_person #{org_person.id}: #{e.message}" - skipped_count += 1 - end - else - puts "⚠ Skipping organization_person #{org_person.id}: user_id #{org_person.user_id} has no associated person" - skipped_count += 1 - end - end - - puts "===============================================" - puts "Migration complete!" - puts "✅ Successfully updated: #{updated_count} records" - puts "⚠ Skipped: #{skipped_count} records" - puts "Total records processed: #{records_to_update.count}" - end -end diff --git a/spec/models/organization_spec.rb b/spec/models/organization_spec.rb index 06dd798c2..1aa130640 100644 --- a/spec/models/organization_spec.rb +++ b/spec/models/organization_spec.rb @@ -7,7 +7,7 @@ it { should belong_to(:location).optional } it { should belong_to(:windows_type).optional } it { should belong_to(:organization_status) } - it { should have_many(:organization_people) } + it { should have_many(:affiliations) } it { should have_many(:users).through(:people) } it { should have_many(:reports) } it { should have_many(:workshop_logs) } diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index a4f550849..7f832ee94 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -5,8 +5,8 @@ it { should have_one(:user) } it { should belong_to(:created_by).class_name("User") } it { should belong_to(:updated_by).class_name("User") } - it { should have_many(:organization_people).dependent(:destroy) } - it { should have_many(:organizations).through(:organization_people) } + it { should have_many(:affiliations).dependent(:destroy) } + it { should have_many(:organizations).through(:affiliations) } it { should have_many(:addresses) } it { should have_many(:contact_methods) } it { should have_many(:sectorable_items) } diff --git a/spec/policies/person_policy_spec.rb b/spec/policies/person_policy_spec.rb index 6f046372c..c958e4c9e 100644 --- a/spec/policies/person_policy_spec.rb +++ b/spec/policies/person_policy_spec.rb @@ -101,8 +101,8 @@ def policy_for(record: nil, user:) it "filters to searchable people with active affiliations" do scope = policy.apply_scope(Person.all, type: :active_record_relation) expect(scope.to_sql).to include('`people`.`profile_is_searchable` = TRUE') - expect(scope.to_sql).to include('INNER JOIN `organization_people`') - expect(scope.to_sql).to include('`organization_people`.`inactive` = FALSE') + expect(scope.to_sql).to include('INNER JOIN `affiliations`') + expect(scope.to_sql).to include('`affiliations`.`inactive` = FALSE') end end end From e98a374ceaa90dfa5cce174c5042804a4a75b9ae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 06:48:50 +0000 Subject: [PATCH 4/9] Fix affiliation_path reference in organizations affiliation_fields partial Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com> --- app/views/organizations/_affiliation_fields.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/organizations/_affiliation_fields.html.erb b/app/views/organizations/_affiliation_fields.html.erb index f478ddca8..fb04ab62e 100644 --- a/app/views/organizations/_affiliation_fields.html.erb +++ b/app/views/organizations/_affiliation_fields.html.erb @@ -64,7 +64,7 @@
    <% if f.object.persisted? %> <%= link_to "Remove", - organization_person_path(f.object), + affiliation_path(f.object), data: { turbo_method: :delete, turbo_confirm: "Remove this person from the organization?", From fb6c4e6906f3bf79e7bd08670fffba670ff1e10e Mon Sep 17 00:00:00 2001 From: maebeale Date: Mon, 16 Feb 2026 16:31:08 -0500 Subject: [PATCH 5/9] Rename db table to affiliations --- db/schema.rb | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index e4835041f..033518e80 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -104,6 +104,26 @@ t.index ["reset_password_token"], name: "index_admins_on_reset_password_token", unique: true end + create_table "affiliations", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| + t.datetime "created_at", precision: nil, null: false + t.date "end_date" + t.string "filemaker_code" + t.boolean "inactive", default: false, null: false + t.integer "organization_agency_id" + t.integer "organization_id", null: false + t.integer "person_id", null: false + t.integer "position" + t.boolean "primary_contact", default: false, null: false + t.date "start_date" + t.string "title" + t.datetime "updated_at", precision: nil, null: false + t.integer "user_id" + t.index ["organization_agency_id"], name: "index_affiliations_on_organization_agency_id" + t.index ["organization_id"], name: "index_affiliations_on_organization_id" + t.index ["person_id"], name: "index_affiliations_on_person_id" + t.index ["user_id"], name: "index_affiliations_on_user_id" + end + create_table "age_ranges", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| t.datetime "created_at", precision: nil, null: false t.string "name" @@ -559,26 +579,6 @@ t.index ["published"], name: "index_organization_obligations_on_published" end - create_table "organization_people", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| - t.datetime "created_at", precision: nil, null: false - t.date "end_date" - t.string "filemaker_code" - t.boolean "inactive", default: false, null: false - t.integer "organization_agency_id" - t.integer "organization_id", null: false - t.integer "person_id", null: false - t.integer "position" - t.boolean "primary_contact", default: false, null: false - t.date "start_date" - t.string "title" - t.datetime "updated_at", precision: nil, null: false - t.integer "user_id" - t.index ["organization_agency_id"], name: "index_organization_people_on_organization_agency_id" - t.index ["organization_id"], name: "index_organization_people_on_organization_id" - t.index ["person_id"], name: "index_organization_people_on_person_id" - t.index ["user_id"], name: "index_organization_people_on_user_id" - end - create_table "organization_statuses", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| t.datetime "created_at", precision: nil, null: false t.string "name" @@ -1238,6 +1238,10 @@ add_foreign_key "action_text_mentions", "action_text_rich_texts" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" + add_foreign_key "affiliations", "organizations" + add_foreign_key "affiliations", "organizations", column: "organization_agency_id" + add_foreign_key "affiliations", "people" + add_foreign_key "affiliations", "users" add_foreign_key "age_ranges", "windows_types" add_foreign_key "banners", "users", column: "created_by_id" add_foreign_key "banners", "users", column: "updated_by_id" @@ -1269,14 +1273,10 @@ add_foreign_key "form_field_answer_options", "form_fields" add_foreign_key "form_fields", "forms" add_foreign_key "forms", "form_builders" - add_foreign_key "monthly_reports", "organization_people", column: "organization_user_id" + add_foreign_key "monthly_reports", "affiliations", column: "organization_user_id" add_foreign_key "monthly_reports", "organizations" add_foreign_key "notifications", "notifications", column: "parent_notification_id" add_foreign_key "notifications", "notifications", column: "root_notification_id" - add_foreign_key "organization_people", "organizations" - add_foreign_key "organization_people", "organizations", column: "organization_agency_id" - add_foreign_key "organization_people", "people" - add_foreign_key "organization_people", "users" add_foreign_key "organizations", "locations" add_foreign_key "organizations", "organization_statuses" add_foreign_key "organizations", "windows_types" From fb89e3bdb605ce43e71765ac8f69397813193e35 Mon Sep 17 00:00:00 2001 From: maebeale Date: Mon, 16 Feb 2026 16:35:54 -0500 Subject: [PATCH 6/9] Some additional renames, esp factory references --- app/views/shared/_navbar_user.html.erb | 14 +++++++------- spec/models/person_spec.rb | 22 +++++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/app/views/shared/_navbar_user.html.erb b/app/views/shared/_navbar_user.html.erb index 0058e2d1c..ce6dc81b5 100644 --- a/app/views/shared/_navbar_user.html.erb +++ b/app/views/shared/_navbar_user.html.erb @@ -39,17 +39,17 @@ <% end %> <% end %> - <% active_org_people = @current_user_active_org_people || [] %> - <% if active_org_people.any? %> - <% active_org_people.each do |organization_person| %> - <% if allowed_to?(:show?, organization_person.organization) %> - <%= link_to organization_path(organization_person.organization), + <% active_affiliations = @current_user_active_affiliations || [] %> + <% if active_affiliations.any? %> + <% active_affiliations.each do |affiliation| %> + <% if allowed_to?(:show?, affiliation.organization) %> + <%= link_to organization_path(affiliation.organization), class: "admin-only bg-blue-100 flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 space-x-2" do %> My team - <% if active_org_people.many? %> - (<%= organization_person.organization.name.truncate(12) %>) + <% if active_affiliations.many? %> + (<%= affiliation.organization.name.truncate(12) %>) <% end %> <% end %> diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index 7f832ee94..6a9a34fc8 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -151,7 +151,7 @@ let(:person) { create(:person, profile_is_searchable: true) } context "when person is searchable with an active affiliation" do - before { create(:organization_person, person: person, inactive: false, end_date: nil) } + before { create(:affiliation, person: person, inactive: false, end_date: nil) } it "returns true" do expect(person.published?).to be true @@ -165,7 +165,7 @@ end context "when person is searchable but only has inactive affiliations" do - before { create(:organization_person, person: person, inactive: true, end_date: nil) } + before { create(:affiliation, person: person, inactive: true, end_date: nil) } it "returns false" do expect(person.published?).to be false @@ -173,7 +173,7 @@ end context "when person is searchable but affiliation has past end date" do - before { create(:organization_person, person: person, inactive: false, end_date: 1.day.ago) } + before { create(:affiliation, person: person, inactive: false, end_date: 1.day.ago) } it "returns false" do expect(person.published?).to be false @@ -182,7 +182,7 @@ context "when person is not searchable" do let(:person) { create(:person, profile_is_searchable: false) } - before { create(:organization_person, person: person, inactive: false) } + before { create(:affiliation, person: person, inactive: false) } it "returns false" do expect(person.published?).to be false @@ -196,8 +196,8 @@ let!(:person_without) { create(:person) } before do - create(:organization_person, person: person_with_active, inactive: false, end_date: nil) - create(:organization_person, person: person_with_inactive, inactive: true, end_date: nil) + create(:affiliation, person: person_with_active, inactive: false, end_date: nil) + create(:affiliation, person: person_with_inactive, inactive: true, end_date: nil) end it "includes people with active affiliations" do @@ -226,13 +226,13 @@ it "returns the most recently updated active organization" do org1 = create(:organization) org2 = create(:organization) - create(:organization_person, person: person, organization: org1, inactive: false, end_date: nil, updated_at: 1.day.ago) - create(:organization_person, person: person, organization: org2, inactive: false, end_date: nil, updated_at: Time.current) + create(:affiliation, person: person, organization: org1, inactive: false, end_date: nil, updated_at: 1.day.ago) + create(:affiliation, person: person, organization: org2, inactive: false, end_date: nil, updated_at: Time.current) expect(person.primary_organization).to eq(org2) end it "returns nil when no active affiliations exist" do - create(:organization_person, person: person, inactive: true) + create(:affiliation, person: person, inactive: true) expect(person.primary_organization).to be_nil end @@ -258,7 +258,7 @@ describe ".published" do let!(:searchable_with_active) do person = create(:person, profile_is_searchable: true) - create(:organization_person, person: person, inactive: false, end_date: nil) + create(:affiliation, person: person, inactive: false, end_date: nil) person end @@ -268,7 +268,7 @@ let!(:not_searchable_with_active) do person = create(:person, profile_is_searchable: false) - create(:organization_person, person: person, inactive: false, end_date: nil) + create(:affiliation, person: person, inactive: false, end_date: nil) person end From eb5601a40fd3c3a33dcee9157b80e879004b8c19 Mon Sep 17 00:00:00 2001 From: maebeale Date: Mon, 16 Feb 2026 16:54:51 -0500 Subject: [PATCH 7/9] Change people sorting to active/inactive, then alpha within each (ignore start date) --- app/controllers/people_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 6eb541f14..87a88984f 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -181,7 +181,6 @@ def set_form_variables .sort_by { |affiliation| expired = affiliation.inactive? || (affiliation.end_date.present? && affiliation.end_date < Date.current) [ expired ? 1 : 0, - affiliation.start_date || Date.new(9999), affiliation.organization&.name.to_s.downcase ] } @person.affiliations.proxy_association.target.replace(sorted) From 0b2f3c350e9cf84546f6bf16b7768cd241839cbb Mon Sep 17 00:00:00 2001 From: maebeale Date: Mon, 16 Feb 2026 17:14:54 -0500 Subject: [PATCH 8/9] Update spec to affiliations --- .../_organization_people.html.erb_spec.rb | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/spec/views/people/sections/_organization_people.html.erb_spec.rb b/spec/views/people/sections/_organization_people.html.erb_spec.rb index 510bef3f6..b15280458 100644 --- a/spec/views/people/sections/_organization_people.html.erb_spec.rb +++ b/spec/views/people/sections/_organization_people.html.erb_spec.rb @@ -1,35 +1,35 @@ require "rails_helper" -RSpec.describe "people/sections/_organization_people", type: :view do +RSpec.describe "people/sections/_affiliations", type: :view do let(:person) { create(:person) } it "renders organization affiliations" do - op = create(:organization_person, person: person) - organization_people = person.organization_people.active.paginate(page: 1) + op = create(:affiliation, person: person) + affiliations = person.affiliations.active.paginate(page: 1) - render partial: "people/sections/organization_people", - locals: { person: person, organization_people: organization_people } + render partial: "people/sections/affiliations", + locals: { person: person, affiliations: affiliations } expect(rendered).to include(op.organization.name) end - it "does not error when an organization_person has a nil organization" do - op = create(:organization_person, person: person) + it "does not error when an affiliation has a nil organization" do + op = create(:affiliation, person: person) allow(op).to receive(:organization).and_return(nil) - organization_people = WillPaginate::Collection.create(1, 10, 1) { |pager| pager.replace([ op ]) } + affiliations = WillPaginate::Collection.create(1, 10, 1) { |pager| pager.replace([ op ]) } expect { - render partial: "people/sections/organization_people", - locals: { person: person, organization_people: organization_people } + render partial: "people/sections/affiliations", + locals: { person: person, affiliations: affiliations } }.not_to raise_error end it "shows empty state when no affiliations exist" do - organization_people = person.organization_people.active.paginate(page: 1) + affiliations = person.affiliations.active.paginate(page: 1) - render partial: "people/sections/organization_people", - locals: { person: person, organization_people: organization_people } + render partial: "people/sections/affiliations", + locals: { person: person, affiliations: affiliations } expect(rendered).to include("No affiliations listed") end From ffc5a2487ee497172d452805780a7043384470ec Mon Sep 17 00:00:00 2001 From: maebeale Date: Mon, 16 Feb 2026 17:20:43 -0500 Subject: [PATCH 9/9] Add conditional to test --- app/views/people/sections/_affiliations.html.erb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/people/sections/_affiliations.html.erb b/app/views/people/sections/_affiliations.html.erb index 4acc7c164..82d52f05c 100644 --- a/app/views/people/sections/_affiliations.html.erb +++ b/app/views/people/sections/_affiliations.html.erb @@ -2,7 +2,9 @@ <% if affiliations.any? %>
    <% affiliations.each do |affiliation| %> - <%= organization_profile_button(affiliation.organization) %> + <% if affiliation.organization %> + <%= organization_profile_button(affiliation.organization) %> + <% end %> <% end %>