diff --git a/app/models/organization.rb b/app/models/organization.rb index a507aa8dae..e5686a54e1 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -3,7 +3,7 @@ class Organization < ApplicationRecord include Communicable include FilemakerCoded filemaker_archived_in FmProject, FmOrganization - belongs_to :organization_status + belongs_to :organization_status, optional: true belongs_to :created_by, class_name: "User", optional: true belongs_to :updated_by, class_name: "User", optional: true belongs_to :organization_obligation, optional: true @@ -86,7 +86,6 @@ def self.info_email content_type: %w[image/png image/jpeg image/webp], size: { less_than: 5.megabytes } validates :name, presence: true, length: { maximum: 255 } - validates :organization_status_id, presence: true validates :email, format: { with: URI::MailTo::EMAIL_REGEXP, message: "must be a valid email address" }, allow_blank: true, length: { maximum: 255 } validates :organization_type_other, length: { maximum: 255 } validates :website_url, length: { maximum: 255 } diff --git a/app/views/dedupes/_preview.html.erb b/app/views/dedupes/_preview.html.erb index 94d1d02647..06416e6f03 100644 --- a/app/views/dedupes/_preview.html.erb +++ b/app/views/dedupes/_preview.html.erb @@ -192,7 +192,7 @@ class: "w-full px-2 py-1 border border-gray-300 rounded text-gray-900 focus:border-blue-500 focus:ring-blue-200", data: { controller: "remote-select", remote_select_model_value: remote_select_options[col.name] } %> <% elsif col_assoc && belongs_to_options[col.name].present? %> - <%= keep_f.collection_select col.name.to_sym, belongs_to_options[col.name], :id, :name, {}, class: "w-full px-2 py-1 border border-gray-300 rounded text-gray-900 focus:border-blue-500 focus:ring-blue-200" %> + <%= keep_f.collection_select col.name.to_sym, belongs_to_options[col.name], :id, :name, { include_blank: "(none)" }, class: "w-full px-2 py-1 border border-gray-300 rounded text-gray-900 focus:border-blue-500 focus:ring-blue-200" %> <% elsif col.type == :integer && col_assoc.nil? %> <%= keep_f.number_field col.name.to_sym, class: "w-32 px-2 py-1 border border-gray-300 rounded text-gray-900 focus:border-blue-500 focus:ring-blue-200" %> <% elsif col.type == :text %> diff --git a/app/views/organizations/_form.html.erb b/app/views/organizations/_form.html.erb index 572f087472..edc5f91269 100644 --- a/app/views/organizations/_form.html.erb +++ b/app/views/organizations/_form.html.erb @@ -283,9 +283,8 @@ <%= f.input :organization_status_id, as: :select, collection: @organization_statuses, - include_blank: true, + include_blank: "(none)", label: "Organization status", - required: true, wrapper_html: { class: "mb-0" }, input_html: { class: "w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200" diff --git a/spec/models/organization_spec.rb b/spec/models/organization_spec.rb index c0b543ee52..aff1b0d5f5 100644 --- a/spec/models/organization_spec.rb +++ b/spec/models/organization_spec.rb @@ -6,7 +6,7 @@ describe 'associations' do it { should belong_to(:location).optional } it { should belong_to(:windows_type).optional } - it { should belong_to(:organization_status) } + it { should belong_to(:organization_status).optional } it { should belong_to(:parent).class_name("Organization").optional } it { should have_many(:children).class_name("Organization").with_foreign_key(:parent_id).dependent(:nullify) } it { should have_many(:affiliations) } @@ -18,7 +18,7 @@ describe 'validations' do subject { build(:organization) } it { should validate_presence_of(:name) } - it { should validate_presence_of(:organization_status_id) } + it { should_not validate_presence_of(:organization_status_id) } it { should allow_value("info@example.com").for(:email) } it { should allow_value("").for(:email) } diff --git a/spec/requests/dedupable_spec.rb b/spec/requests/dedupable_spec.rb index a0645e6e20..ff18dda1c8 100644 --- a/spec/requests/dedupable_spec.rb +++ b/spec/requests/dedupable_spec.rb @@ -340,6 +340,32 @@ expect(response.body).to include("Website url") expect(response.body).not_to include("Profile show age ranges") end + + it "leaves a blank status blank instead of preselecting one" do + keep.update_column(:organization_status_id, nil) + + get dedupe_preview_organizations_path( + organization_to_keep_id: keep.id, + organization_to_delete_id: delete_rec.id + ) + + status_select = Nokogiri::HTML(response.body).at_css("select[name$='[organization_status_id]']") + expect(status_select.at_css("option[selected]")).to be_nil + expect(status_select.at_css("option[value='']").text).to eq("(none)") + end + end + + describe "PATCH dedupe_update_keep" do + it "autosaves a keeper that has no status" do + keep = create(:organization, name: "Keep Org") + keep.update_column(:organization_status_id, nil) + + patch dedupe_update_keep_organizations_path, + params: { id: keep.id, organization_to_keep: { name: "Renamed Org" } } + + expect(response).to have_http_status(:ok) + expect(keep.reload.name).to eq("Renamed Org") + end end describe "POST dedupe_perform" do @@ -401,6 +427,22 @@ expect(keep.reload.filemaker_code).to eq("FM-100, FM-273") end + it "merges when neither organization has a status" do + keep.update_column(:organization_status_id, nil) + delete_rec.update_column(:organization_status_id, nil) + + expect { + post dedupe_perform_organizations_path, params: { + organization_to_delete_id: delete_rec.id, + organization_to_keep_id: keep.id, + organization_to_keep: { name: "Canonical Org", organization_status_id: "" } + } + }.to change(Organization, :count).by(-1) + + expect(response).to redirect_to(organizations_path) + expect(keep.reload).to have_attributes(name: "Canonical Org", organization_status_id: nil) + end + it "reassigns the duplicate's invoices instead of blocking the merge" do invoice = create(:invoice, invoicee: delete_rec) diff --git a/spec/requests/organizations_spec.rb b/spec/requests/organizations_spec.rb index 0f73e9eba6..d94d757678 100644 --- a/spec/requests/organizations_spec.rb +++ b/spec/requests/organizations_spec.rb @@ -175,6 +175,15 @@ expect(response).to be_successful end + it "shows (none) in the admin status select when the organization has no status" do + organization = Organization.create!(valid_attributes.merge(organization_status_id: nil)) + get edit_organization_url(organization, admin: 1) + + status_select = Nokogiri::HTML(response.body).at_css("select[name='organization[organization_status_id]']") + expect(status_select.at_css("option[selected]")).to be_nil + expect(status_select.at_css("option[value='']").text).to eq("(none)") + end + it "hides the Monthly reports row when there are no monthly reports" do organization = Organization.create!(valid_attributes) get edit_organization_url(organization)