Skip to content

feat: Import Wizard relationship mapping and smart matching#76

Merged
ManukMinasyan merged 5 commits into3.xfrom
feature/import-relationship-mapping
Jan 15, 2026
Merged

feat: Import Wizard relationship mapping and smart matching#76
ManukMinasyan merged 5 commits into3.xfrom
feature/import-relationship-mapping

Conversation

@ManukMinasyan
Copy link
Copy Markdown
Contributor

@ManukMinasyan ManukMinasyan commented Jan 12, 2026

Summary

Comprehensive Import Wizard enhancement for 3.x that adds intelligent relationship mapping and smart record matching.

Relationship Mapping

  • Company linking: Match by ID, name, or domain when importing People/Opportunities
  • Contact linking: Match by ID, name, or email when importing Opportunities/Tasks/Notes
  • Polymorphic relationships: Link Tasks and Notes to Companies or People during import
  • New "Link to Records" section in mapping step with dedicated relationship controls

Smart Matching

  • Lookup identifiers: Configure unique attributes per entity (email for People, domain for Company)
  • Public email filtering: Prevent matching free email providers (gmail, yahoo, etc.) as company domains
  • LookupFieldMatcher: Match lookup custom fields by unique identifiers instead of just name

Preview Enhancements

  • Show relationship match status in preview (Matched, Will Create, Not Found)
  • Display match confidence and method used
  • Visual indicators for match type

Configuration

  • EntityModel::configure() now accepts lookupIdentifier parameter
  • People configured with emails field as lookup identifier
  • Company configured with domains field as lookup identifier

New Files

  • HasCompanyRelationshipColumns - Company linking via ID/name/domain
  • HasContactRelationshipColumns - Contact linking via ID/name/email
  • HasPolymorphicRelationshipFields - Polymorphic linking for Tasks/Notes
  • SyncsPolymorphicLinks - Sync polymorphic relationships after import
  • LookupFieldMatcher - Match lookup fields by unique attributes
  • PublicEmailDomainFilter - Filter 4700+ free email domains
  • RelationshipPreviewMatcher - Preview relationship matching
  • UpdateEmailDomainsCommand - Update free email domains list

Test plan

  • All import tests pass (157 tests)
  • Custom-fields package tests pass (581 tests)
  • PublicEmailDomainFilterTest - 119 assertions
  • RelationshipMappingTest - 362 assertions
  • Manual: Import people with company_domain column
  • Manual: Import tasks with contact_email column

Copilot AI review requested due to automatic review settings January 12, 2026 16:25
- Configure People entity with email-based lookup identifier
- Configure Company entity with domain-based lookup identifier
- Add LookupFieldMatcher service for matching records by unique attributes
- Add relationship mapping support with company/contact columns
- Add public email domain filtering for company matching
- Enhance import preview with relationship match status
- Add MatchType enum for standardized match type handling
- Improve date/timestamp format detection in CSV analysis
- Add polymorphic relationship syncing for tasks and notes
@ManukMinasyan ManukMinasyan force-pushed the feature/import-relationship-mapping branch from 7d3c184 to 4552d5f Compare January 12, 2026 16:27
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces comprehensive relationship mapping and smart matching capabilities to the Import Wizard, enabling intelligent linking of imported records through multiple matching strategies (ID, name, email, domain). The implementation includes public email domain filtering, polymorphic relationship support for Tasks/Notes, lookup field matching by unique attributes, and enhanced preview functionality showing relationship match status.

Changes:

  • Added relationship mapping UI with dedicated two-level selection controls (relationship + matcher)
  • Implemented smart matching with configurable lookup identifiers (emails for People, domains for Company)
  • Integrated public email domain filtering (4700+ domains) to prevent false company associations
  • Extended preview functionality to display relationship match status, confidence, and method
  • Added polymorphic relationship support for Tasks and Notes to link to multiple entity types

Reviewed changes

Copilot reviewed 47 out of 49 changed files in this pull request and generated no comments.

Show a summary per file
File Description
RelationshipMappingTest.php Comprehensive test suite (362 assertions) covering relationship field mapping, auto-mapping, persistence, and creation
PublicEmailDomainFilterTest.php Tests public email filtering with 119 assertions covering domain identification and CompanyMatcher integration
PublicEmailDomainFilter.php Filters 4700+ free email domains with O(1) lookup performance using hash map
RelationshipPreviewMatcher.php Matches relationship values during preview with caching for performance
LookupFieldMatcher.php Matches lookup fields by unique attributes (email/domain) with batch support
CompanyMatcher.php Enhanced with public email filtering option
PreviewChunkService.php Refactored to process relationship matches instead of company-specific logic
CsvAnalyzer.php Added choice field validation and field type determination improvements
ImportWizard.php Added relationship mapping UI, missing options creation, and choice field support
HasColumnMapping.php Implements relationship field mapping with auto-mapping and conflict resolution
StreamingImportCsv.php Added runtime flag for creating missing select options with proper cleanup
ProcessImportPreview.php Updated to track relationship counts instead of company names
TaskImporter.php Added polymorphic relationship fields and syncing via new trait
SyncsPolymorphicLinks.php New trait for syncing polymorphic entity links
config/custom-fields.php Configured lookup identifiers for People and Company entities
free-email-domains.json 4781 public email domains for filtering
composer.json/lock Changed custom-fields package to local path with @dev version

…ts in custom-fields.php and StreamingImportCsv.php
add phone number as unique identifier for people duplicate detection
during csv imports, following the same pattern as email matching.

matching precedence: id -> email -> phone

- add Phone case to MatchType enum
- mark phone_number as unique in PeopleField enum
- add findByPhone() and phone normalization to PeopleImporter
- extend ImportRecordResolver with phone cache and lookup
- add phone matcher to RelationshipField::contact()
- update RelationshipPreviewMatcher for phone match type
- simplify LookupFieldMatcher and PreviewChunkService
- Creates migration that calls custom-fields:upgrade command
- Handles lookup field migration, email/phone format conversion
- Skips cache clearing (will be handled by deployment)
- Sets appropriate memory and time limits for large datasets
@ManukMinasyan ManukMinasyan merged commit c0d1629 into 3.x Jan 15, 2026
0 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants