Organization deduper (festi-inspired, on the existing dedup framework) - #2374
Open
maebeale wants to merge 9 commits into
Open
Organization deduper (festi-inspired, on the existing dedup framework)#2374maebeale wants to merge 9 commits into
maebeale wants to merge 9 commits into
Conversation
…red) Extend ModelDeduper to reassign every FK reference to a model (not just polymorphic tagging joins), unioning declared has_many/:as associations with a schema-driven scan of DB foreign keys so FK children without an inverse has_many (payments, stories, monthly_reports, …) are reassigned rather than orphaned or blocked by their FK constraint. Collisions are resolved from DB unique indexes. Add OrganizationServices::DuplicateFinder (name, legal-suffix, FileMaker-code, and address clustering, with FileMaker treated as source of truth) and wire OrganizationsController into the Dedupable concern with a custom candidate finder. The index now renders annotated candidate groups with per-pair preview links. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the generic festi-style preview with awbw conventions: DomainTheme colors, sentence-case copy, btn classes, eyebrow nav, and the standard blue form-focus. The preview now shows a meaningful reassignment summary (counts of each association that moves) instead of a single polymorphic join's items, and orgs edit only a curated set of fields rather than every column. Index groups gain reason chips, a suggested-keeper badge, and per-pair preview links. Add a Dedupe entry point on the Organizations page and a Features & tips entry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
FileMaker is the source of truth and a record can map to more than one FileMaker record, so the deduper now reads filemaker_code as a trimmed, comma-separated list. Candidate detection matches on set intersection (FM-27 no longer matches FM-273), and merging keeps the union of both records' codes so no FileMaker linkage is lost. The preview marks a union field being combined with a 'Kept on merge' badge rather than 'Will be dropped'. Adds a generic union_columns + merge_keeper hook to the Dedupable framework. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
maebeale
marked this pull request as ready for review
August 25, 2026 14:58
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…refs - Reassignment summary now lists a few truncated record names per association, not just the rollup count. - Merge repoints ahoy_events + versions to the kept record so analytics and audit history survive instead of orphaning. - Preview surfaces attached files (logo) that are deleted with the duplicate, and adds space above the action buttons. - Coverage safeguard: a data-driven scan blocks the merge (banner + disabled button + server guard) if anything references the record that the deduper won't reassign, so a future association can't silently break referential integrity. Billing (Pay gem) links are deferred to #2378. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…refs - Reassignment summary now lists a few truncated record names per association, not just the rollup count. - Merge repoints ahoy_events + versions to the kept record so analytics and audit history survive instead of orphaning. - Preview surfaces attached files (logo) that are deleted with the duplicate, and adds space above the action buttons. - Coverage safeguard: a data-driven scan blocks the merge (banner + disabled button + server guard) if anything references the record that the deduper won't reassign, so a future association can't silently break referential integrity. Billing (Pay gem) links are deferred to #2378. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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 🔬 substantive merge logic that reassigns every FK reference across ~20 tables, repoints analytics/audit, and deletes records
Admin-only organization deduper, built on the existing dedup framework (
ModelDeduper+Dedupable+ shareddedupes/views), extended for FK-based models. Built festi-first, then an awbw design pass.Engine (
ModelDeduper):aschildren, and tagging joins.has_many/:asplus a schema-driven scan of DB foreign keys, so FK children with no inversehas_many(payments, stories, monthly_reports, …) are reassigned rather than orphaned.reports.owner).ahoy_events,versions) are repointed to the kept record so history follows the survivor instead of orphaning.Coverage safeguard
unhandled_references) checks the actual record for any table that still references it but that the merge wouldn't reassign — independent ofdependent:options.dedupe_performalso refuses server-side. So a future association added to Organization can't silently break referential integrity.Detection (
OrganizationServices::DuplicateFinder)UI (awbw)
DomainThemecolors, sentence-case copy,btnclasses, eyebrow nav, blue form-focus.Screenshots
In
.context/screenshots/:dedupe_index.png,dedupe_preview_final.png,dedupe_blocked.png,dedupe_filemaker.png,admin_deprecated_dedupe_card.png.Follow-up
Tests
FK reassignment (restrict-dependent, natural-key collisions, FK-only children); analytics/audit repoint; lost-file reporting; coverage-safeguard block; finder clustering incl. multi-code; FileMaker union; org request flow. All dedupe/org/finder/model/admin specs green.