Repository navigation
Conversation
Collaborator
|
Should this also handle worksite address? Also I think these are just optional pointers. I think we need to iterate on the fm_address table. Same thoughts on fm_phone_numbers. Or maybe the intent of the pr is to just import based on the rolodex table and do other tables separately? |
Collaborator
|
A number of "other" email types that would be dropped in the import. Some might be worth mapping to our values. |
Collaborator
|
We can pull in address county information from the fm tables. |
maebeale
force-pushed
the
maebeale/rolodex-import-rake-task
branch
from
October 12, 2026 17:41
da095fc to
a2e4424
Compare
maebeale
force-pushed
the
maebeale/rolodex-import-rake-task
branch
2 times, most recently
from
October 12, 2026 19:02
a2e4424 to
7a70493
Compare
maebeale
marked this pull request as ready for review
October 12, 2026 20:03
maebeale
force-pushed
the
maebeale/rolodex-import-rake-task
branch
4 times, most recently
from
October 13, 2026 14:23
f02b1ab to
3d7d6e6
Compare
The FileMaker Rolodex is archived in fm_rolodexes but none of those contacts exist as people yet. Links on exact name + email so existing people aren't duplicated, and reports looser collisions for hand review. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A dry run over 39,000 rows is only useful if the rows it reports are the rows it would write: - Two-digit years landed in the first century (10/5/83 became 83 AD), and because strptime stops where the format ends, 10-5-1983 read as 1910-05-19 — a date the archive never recorded. Formats now have to match the whole value, and a bare year pair gets a century. - An over-long address line or note failed the entire person on a 255-character column, dropping a usable record over an incidental field. Copied free text is truncated instead. - The house number has its own field, so addresses imported without it unless the first line happened to repeat it. - Phone types were resolved against the address set, letting a phone claim a type the contact-method form can't show. Each model now declares the slice it accepts, and a type we can't place reads as unknown rather than leaving the record untyped. Also drops the credentials.yml key that came back in a rebase — #2579 removed it deliberately — and corrects the rake-task count in AGENTS.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every address and contact method now answers "what kind?": a blank type is written as unknown on save, from any path, so the gap closes as records are touched rather than needing a backfill. Rows nothing saves keep their blank. Knowing that a type is unknown isn't the same as knowing the type, so the public registration form still asks a signed-in registrant for their address type — Address#known_type? keeps the normalized value from reading as an answer already on file and hiding the question. With the models owning the fallback, the Rolodex import drops its own. Features & tips gains the import and the new Unknown type. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Main's #2632/#2633 made PersonMatcher the one rule for "which person does this name + email belong to" — it reaches the secondary and login addresses a person counts as theirs, and compares names with look-alike dashes folded. The import was a new matching path with its own narrower query, so it would have created a fresh person for anyone the archive knows by their login address, reopening the gap that just closed. PersonMatcher gains #matches so a caller that has to tell one match from several can have the relation. Archive names go through Person.normalize_name before they're compared, since that's the form they'll be stored in. The merge reconcilers read unknown and blank as the same type, so a row written before an untyped address or number said so still folds into its twin. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#2647 lets a person carry several codes, so an index built from whole column values would miss the row whose ID sits inside one and import it again. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
FmRolodex::PORTAL_FIELDS documents which archive field answers to which portal column; the import only wrote half of them. It now also carries the email type, the facilitator start month/year as member_since, the service areas and age group (through SubmissionTagging, the same seam a submission uses, additively), and the archive's own entry and modification dates — so an imported person dates from when FileMaker first knew them rather than from the import run. Addresses and phones come from FmRolodex#addresses / #phone_numbers rather than the single PrimaryAddrsID/PrimaryPhoneID, so a contact's other addresses arrive too, the row's primary first. A service area no sector answers to is counted in #unmatched_tags and printed by the task, since "Child Abuse" and "Child Abuse/Neglect" are the same sector but "Homelessness" with no seeded sector is a gap someone has to close. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
maebeale
force-pushed
the
maebeale/rolodex-import-rake-task
branch
from
October 15, 2026 00:34
3d7d6e6 to
872fd1d
Compare
maebeale
force-pushed
the
maebeale/rolodex-import-rake-task
branch
from
October 15, 2026 01:41
1eb7308 to
872fd1d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 suggested review level: 5 Inspect 🔬 a one-off import that now writes most of a person's profile, plus a save-time default on two shared models that changes one public-form question's visibility
Adds
fm:import_people, which turns FileMaker Rolodex archive rows into people so the old contact list lives in the portal instead of only in the read-only archive.What is the goal of this PR and why is this important?
fm_rolodexesholds ~39k contacts, none of which exist asPersonrecords yet.The import
PersonServices::ImportFromRolodexdoes the work; the rake task wraps it in a dry-run transaction.DRY_RUN=falsewrites;VERBOSE=truelists every row.PersonMatcher, so a person the archive knows by their secondary or login address is linked rather than recreated. Names run throughPerson.normalize_namefirst.isAgency__c), soft-deleted (Delete), and nameless rows.What an imported person carries
Everything
FmRolodex::PORTAL_FIELDSmaps onto a person:FacilitatorSinceMonth+Year→member_since(a year with no month reads as January)PrimaryAgeGroup→ age group, throughSubmissionTagging— the same seam a submission uses, additivelyDateEntered/DateTimeModifiedascreated_at/updated_at, so a profile dates from when FileMaker first knew the personFmRolodex#addresses/#phone_numbers), the row's primary first#unmatched_tagsand printed by the task —Child Abuseresolves toChild Abuse/Neglect, but a name nothing answers to is a gap for a human, not a guessReading the archive's messier fields
10-5-1983used to read as1910-05-19). A two-digit year gets a century:83→ 1983,05→ 2005.StreetNois prepended to the first address line unless that line already starts with it.Unknown as a type (worth the closest look)
AddressandContactMethodwrite"unknown"on save when the type is blank, from any path — no backfill, so rows nothing saves keep their blank."unknown"is new toContactMethod::CONTACT_TYPES, so an Unknown option now appears in the contact-method type select.Addressalready declared it.Address#known_type?is why this isn't a silent regression:person_known_identifiershideslogged_out_onlyquestions a registrant has already answered, and treating"unknown"as an answer would have stopped the public registration form from asking for an address type.AddressDeduperandReconcileContactMethodsread"unknown"and blank as the same type, so a pre-change row still folds into its twin.Anything else to add?
update_columnsfor the archive dates is deliberate: tagging touches the person, so the dates are written once more after it.PersonMatcher#matchesis new — the relation behind#call, for a caller that must tell one match from several. Existing callers unchanged.EnteredBy/ModifiedBy→created_by/updated_byare left unmapped: they're FileMaker usernames, with no reliable path to a portalUser.DRY_RUN=false;db:seed:dev:fm_archivegives dev something to run it against.OrgIDare out of scope.🤖 Generated with Claude Code