From 791ff63e17d4d3ff27a0137509d2fe1c19930a4b Mon Sep 17 00:00:00 2001 From: maebeale Date: Mon, 22 Jun 2026 11:17:02 -0400 Subject: [PATCH 1/2] Sync registration "Other" organization type onto the linked org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: a registrant who picked "Other" for organization type had nowhere to record what that "other" was, and the org's agency_type_other column was only ever set from the admin edit form. Make the registration "Other" choice behave like every other specify option (reveals a box, stores "Other: ") and mirror the answer onto the linked organization so the free text isn't lost. Latest registration wins; AhoyTrackable records the before/after on each update. No data migration — new behavior applies to forms built after this change. Co-Authored-By: Claude Opus 4.8 --- .../public_registration.rb | 18 ++++++- app/services/form_builder_service.rb | 3 +- app/views/organizations/_form.html.erb | 2 +- .../public_registration_spec.rb | 53 +++++++++++++++++++ spec/services/form_builder_service_spec.rb | 7 ++- 5 files changed, 78 insertions(+), 5 deletions(-) diff --git a/app/services/event_registration_services/public_registration.rb b/app/services/event_registration_services/public_registration.rb index 6dc60d988a..0efaf27a1e 100644 --- a/app/services/event_registration_services/public_registration.rb +++ b/app/services/event_registration_services/public_registration.rb @@ -187,7 +187,23 @@ def sync_person_profile(person) def sync_organization_profile(organization) apply_value(organization, :website_url, field_value("agency_website")) - apply_value(organization, :agency_type, field_value("agency_type")) + sync_agency_type(organization) + end + + # The "Organization Type" answer folds an "Other" choice's free text in as + # "Other: " (a specify option). Split the option label from the typed + # text: the label drives agency_type and the stripped text fills + # agency_type_other, which is cleared for the non-"Other" classifications so + # no stale free text lingers. Follows the same latest-wins / never-clobber-on- + # blank contract as apply_value. + def sync_agency_type(organization) + raw = field_value("agency_type") + return if raw.blank? + + label, _separator, specified = raw.strip.partition(":") + label = label.strip + other_text = FormField.other_option?(label) ? specified.strip.presence : nil + organization.update!(agency_type: label, agency_type_other: other_text) end # Write value onto attribute when a non-blank value was submitted, overwriting diff --git a/app/services/form_builder_service.rb b/app/services/form_builder_service.rb index daa33f5721..c52810eb19 100644 --- a/app/services/form_builder_service.rb +++ b/app/services/form_builder_service.rb @@ -407,8 +407,7 @@ def build_person_contact_info_fields(form, position) position = add_field(form, position, "Organization Type", :single_select_radio, key: "agency_type", group: "person_contact_info", required: false, options: [ - "501c3/nonprofit", "For-profit", "Government agency", - "Other (please specify below)" + "501c3/nonprofit", "For-profit", "Government agency", "Other" ]) position = add_field(form, position, "Organization Street Address", :free_form_input_one_line, key: "agency_street", group: "person_contact_info", required: false) diff --git a/app/views/organizations/_form.html.erb b/app/views/organizations/_form.html.erb index 76b865bde5..a7766f9cd7 100644 --- a/app/views/organizations/_form.html.erb +++ b/app/views/organizations/_form.html.erb @@ -113,7 +113,7 @@ "501c3/nonprofit", "For-profit", "Government agency", - "Other (please specify below)" + "Other" ], selected: f.object.agency_type, input_html: { diff --git a/spec/services/event_registration_services/public_registration_spec.rb b/spec/services/event_registration_services/public_registration_spec.rb index abe26dd270..6c68fa1a7c 100644 --- a/spec/services/event_registration_services/public_registration_spec.rb +++ b/spec/services/event_registration_services/public_registration_spec.rb @@ -288,6 +288,59 @@ def register_with_org(extra) end end + describe "organization type sync" do + let!(:organization) { create(:organization, name: "Helping Hands") } + + def register_with_agency_type(value) + params = base_form_params(first_name: "Sam", last_name: "Rowe", email: "sam@example.com").merge( + field_id(described_class::ORGANIZATION_NAME_IDENTIFIER) => "Helping Hands", + field_id("agency_type") => value + ) + described_class.call(event: event, form: form, form_params: params) + organization.reload + end + + it "folds an 'Other' answer into agency_type and the stripped free text into agency_type_other" do + register_with_agency_type("Other: Equine therapy") + + expect(organization.agency_type).to eq("Other") + expect(organization.agency_type_other).to eq("Equine therapy") + end + + it "stores the answer as 'Other: ' on the form submission, like other specify options" do + register_with_agency_type("Other: Equine therapy") + + answer = FormAnswer.joins(:form_field) + .find_by(form_fields: { field_identifier: "agency_type" }) + expect(answer.submitted_answer).to eq("Other: Equine therapy") + end + + it "stores a non-'Other' classification with no agency_type_other" do + register_with_agency_type("501c3/nonprofit") + + expect(organization.agency_type).to eq("501c3/nonprofit") + expect(organization.agency_type_other).to be_nil + end + + it "overwrites a previously stored type with the latest registrant's answer" do + organization.update!(agency_type: "501c3/nonprofit", agency_type_other: nil) + + register_with_agency_type("Other: Equine therapy") + + expect(organization.agency_type).to eq("Other") + expect(organization.agency_type_other).to eq("Equine therapy") + end + + it "clears a stale agency_type_other when the latest answer is no longer 'Other'" do + organization.update!(agency_type: "Other", agency_type_other: "Equine therapy") + + register_with_agency_type("Government agency") + + expect(organization.agency_type).to eq("Government agency") + expect(organization.agency_type_other).to be_nil + end + end + describe "matching an existing registrant by name" do it "matches a person stored under a nickname when the registrant types their legal first name" do existing = create(:person, first_name: "Bob", legal_first_name: "Robert", diff --git a/spec/services/form_builder_service_spec.rb b/spec/services/form_builder_service_spec.rb index b6717e268c..ea67bd2aa6 100644 --- a/spec/services/form_builder_service_spec.rb +++ b/spec/services/form_builder_service_spec.rb @@ -75,9 +75,14 @@ it "offers the agency type as the four organization classifications" do field = form.form_fields.find_by(field_identifier: "agency_type") expect(field.answer_options.pluck(:name)).to contain_exactly( - "501c3/nonprofit", "For-profit", "Government agency", "Other (please specify below)" + "501c3/nonprofit", "For-profit", "Government agency", "Other" ) end + + it "treats the agency type 'Other' as a specify option that reveals a free-text box" do + field = form.form_fields.find_by(field_identifier: "agency_type") + expect(field.specify_option_labels).to contain_exactly("Other") + end end context "scholarship section" do From 517f00201485c73284c6a584ee573a3fdb61658b Mon Sep 17 00:00:00 2001 From: maebeale Date: Sat, 4 Jul 2026 16:37:34 -0400 Subject: [PATCH 2/2] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../event_registration_services/public_registration.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/services/event_registration_services/public_registration.rb b/app/services/event_registration_services/public_registration.rb index 0efaf27a1e..5475845dc2 100644 --- a/app/services/event_registration_services/public_registration.rb +++ b/app/services/event_registration_services/public_registration.rb @@ -197,11 +197,12 @@ def sync_organization_profile(organization) # no stale free text lingers. Follows the same latest-wins / never-clobber-on- # blank contract as apply_value. def sync_agency_type(organization) - raw = field_value("agency_type") + raw = field_value("agency_type")&.strip return if raw.blank? - label, _separator, specified = raw.strip.partition(":") + label, _separator, specified = raw.partition(":") label = label.strip + return if label.blank? other_text = FormField.other_option?(label) ? specified.strip.presence : nil organization.update!(agency_type: label, agency_type_other: other_text) end