-
Notifications
You must be signed in to change notification settings - Fork 24
HOLD: Capture known profile data as form answers on registration & bulk payment submissions #1683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,13 +11,18 @@ def initialize(event:, form:, form_params:, person: nil) | |
| @form = form | ||
| @form_params = form_params | ||
| @person = person | ||
| @backfilled_field_ids = [] | ||
| @errors = [] | ||
| end | ||
|
|
||
| def call | ||
| ActiveRecord::Base.transaction do | ||
| person = find_or_create_person | ||
| create_phone_contact(person) if field_value("payer_phone").present? | ||
| if @person | ||
| backfill_payer_fields(@person) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤖 From Claude: Logged-in branch backfills the hidden payer fields and intentionally skips |
||
| elsif field_value("payer_phone").present? | ||
| create_phone_contact(person) | ||
| end | ||
| submission = create_form_submission(person) | ||
| send_notifications(submission, person) | ||
| Result.new(success?: true, form_submission: submission, errors: []) | ||
|
|
@@ -56,6 +61,26 @@ def field_value(key) | |
| @form_params[field.id.to_s] | ||
| end | ||
|
|
||
| # Logged-in payers never see the payer information fields (they're | ||
| # logged_out_only), so fill those answers from the signed-in person's record | ||
| # to keep the submission self-describing. Their existing contact methods are | ||
| # left untouched. | ||
| def backfill_payer_fields(person) | ||
| { | ||
| "payer_first_name" => person.first_name, | ||
| "payer_last_name" => person.last_name, | ||
| "payer_email" => person.preferred_email, | ||
| "payer_phone" => person.phone_number, | ||
| "payer_organization" => person.primary_organization&.name | ||
| }.each do |key, value| | ||
| next if value.blank? | ||
| field = @form.form_fields.find_by(field_identifier: key) | ||
| next unless field | ||
| @form_params[field.id.to_s] = value | ||
| @backfilled_field_ids << field.id | ||
| end | ||
| end | ||
|
|
||
| def find_or_create_person | ||
| return @person if @person | ||
|
|
||
|
|
@@ -117,7 +142,8 @@ def save_form_answers(submission) | |
| end | ||
|
|
||
| record = submission.form_answers.find_or_initialize_by(form_field: field) | ||
| record.update!(submitted_answer: text, question_name_when_answered: field.name) | ||
| record.update!(submitted_answer: text, question_name_when_answered: field.name, | ||
| backfilled: @backfilled_field_ids.include?(field.id)) | ||
| end | ||
| end | ||
| end | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,6 +38,7 @@ def initialize(event:, form:, form_params:, scholarship_requested: false, person | |
| @person = person | ||
| @scholarship_form = scholarship_form | ||
| @scholarship_params = scholarship_params || {} | ||
| @backfilled_field_ids = [] | ||
| @errors = [] | ||
| end | ||
|
|
||
|
|
@@ -54,6 +55,8 @@ def call | |
|
|
||
| assign_tags(person, organization) | ||
|
|
||
| backfill_profile_fields(person) if @person | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤖 From Claude: Placed after the |
||
|
|
||
| existing = @event.event_registrations.find_by(registrant: person) | ||
| if existing | ||
| existing.update!(scholarship_requested: true) if @scholarship_requested | ||
|
|
@@ -120,6 +123,60 @@ def resolve_names | |
| end | ||
| end | ||
|
|
||
| # Logged-in registrants don't see the profile fields they already have on | ||
| # file (they're hidden as logged_out_only), so those answers would otherwise | ||
| # be missing from the submission. Capture them from the person's record so | ||
| # the submission reflects all the data known at the time it was submitted. | ||
| # Only fields left blank by the registrant are filled, and the person's own | ||
| # records (addresses, contacts) are not touched. | ||
| def backfill_profile_fields(person) | ||
| profile_field_values(person).each do |key, value| | ||
| next if value.blank? | ||
| field = @form.form_fields.find_by(field_identifier: key) | ||
| next unless field | ||
| next if @form_params[field.id.to_s].present? | ||
| @form_params[field.id.to_s] = value | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤖 From Claude: Track which fields were profile-sourced (vs typed) so |
||
| @backfilled_field_ids << field.id | ||
| end | ||
| end | ||
|
|
||
| def profile_field_values(person) | ||
| { | ||
| "first_name" => person.legal_first_name.presence || person.first_name, | ||
| "last_name" => person.last_name, | ||
| "primary_email" => person.email, | ||
| "primary_email_type" => person.email_type&.capitalize, | ||
| "nickname" => (person.first_name if person.legal_first_name.present?), | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤖 From Claude: Reverses |
||
| "pronouns" => person.pronouns, | ||
| "secondary_email" => person.email_2, | ||
| "secondary_email_type" => person.email_2_type&.capitalize | ||
| }.merge(address_field_values(person)).merge(phone_field_values(person)) | ||
| end | ||
|
|
||
| def address_field_values(person) | ||
| return {} unless person.addresses.exists? | ||
|
|
||
| address = person.addresses.find_by(primary: true) || person.addresses.first | ||
| { | ||
| "mailing_street" => address.street_address, | ||
| "mailing_address_type" => address.address_type&.capitalize, | ||
| "mailing_city" => address.city, | ||
| "mailing_state" => address.state, | ||
| "mailing_zip" => address.zip_code | ||
| } | ||
| end | ||
|
|
||
| def phone_field_values(person) | ||
| phones = person.contact_methods.where(kind: :phone) | ||
| phone = phones.find_by(primary: true, inactive: false) || phones.where(inactive: false).first || phones.first | ||
| return {} unless phone | ||
|
|
||
| { | ||
| "phone" => phone.value, | ||
| "phone_type" => phone.contact_type&.capitalize | ||
| } | ||
| end | ||
|
|
||
| def find_or_create_person | ||
| return @person if @person | ||
|
|
||
|
|
@@ -377,7 +434,8 @@ def save_form_answers(submission) | |
| end | ||
|
|
||
| record = submission.form_answers.find_or_initialize_by(form_field: field) | ||
| record.update!(submitted_answer: text, question_name_when_answered: field.name) | ||
| record.update!(submitted_answer: text, question_name_when_answered: field.name, | ||
| backfilled: @backfilled_field_ids.include?(field.id)) | ||
| end | ||
| end | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| class AddBackfilledToFormAnswers < ActiveRecord::Migration[8.1] | ||
| def up | ||
| add_column :form_answers, :backfilled, :boolean, default: false, null: false | ||
| end | ||
|
|
||
| def down | ||
| remove_column :form_answers, :backfilled, if_exists: true | ||
| end | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤖 From Claude: Single place that renders the profile indicator; returns nil unless
response.backfilled?, so every submission view that calls it stays consistent.