Skip to content

Unified contacts (Flutter mobile β€” shipped) ​

Cross-reference for React web (aldilaijanre) parity. Mobile Flutter is the reference implementation.

Routes (mobile) ​

PurposePath
Contacts list/clients
Party 360 detail/clients/:unifiedPersonId
Duplicate review (admin)/admin/duplicate-review
Legacy party registry/admin/party-registry β†’ redirects to /clients?admin=1
Legacy CRM client id/brokerage/crm/clients/:clientsTableId β†’ redirects when unified_person_id set
Brokerage CRM list/brokerage/crm/clients β†’ unified list

Data spine ​

  • Identity: unified_persons (individuals + organizations)
  • CRM overlays: clients β€” max one row per (unified_person_id, system) (aldilaijan / khobara)
  • Detail id: always unified_persons.id on /clients/:id

List UX ​

  • Segmented People / Entities
  • Server-side searchParties() β€” no fetch-all registry
  • Khobara personas: same list with linkedSystem: khobara
  • Nav label: People & entities (nav.clients)

Detail UX (360) ​

PartyDetailScreen tabs (persona-gated via PartyDetailVisibility):

  1. Profile β€” individual or organization
  2. Brokerage β€” deals, requests, properties, Aldilaijan CRM
  3. Valuation β€” valuations, requests, tahdeed, Khobara CRM
  4. Financial β€” invoices
  5. Activity β€” interaction timeline

Web parity checklist ​

  • [x] Single list over unified_persons (people + entities), not separate Party Registry browse β€” React /clients
  • [x] Detail at party id with brokerage / valuation / finance sections β€” React /clients/:id (PartyDetail)
  • [x] Legacy CRM client detail redirects to /clients/:unifiedPersonId when linked β€” CrmClientDetailGate
  • [x] Persona-scoped tab visibility β€” partyDetailVisibility.ts
  • [x] Bilingual names: name_ar + structured parts + name_en β€” list + detail display
  • [x] Admin duplicate review + orphan relink tooling β€” /admin/duplicate-review
  • [x] Organization edit on party 360 β€” Flutter OrganizationFormScreen + React OrganizationForm via /clients/:id/edit
  • [x] Inline CRM actions on party tabs β€” Flutter showCrmActionPicker; React CrmActionMenu (note / contact / interaction)
  • [x] Legacy pages retired β€” UnifiedPersons, BuyersList removed; routes redirect to /clients

Key Flutter files ​

  • lib/features/individuals/screens/individuals_list_screen.dart
  • lib/features/parties/screens/party_detail_screen.dart
  • lib/data/repositories/party_registry_repository.dart
  • lib/data/repositories/party_activity_repository.dart

Production ops β€” identity convergence ​

After bulk imports or duplicate merges, admins should verify Phase-5 monitor views trend toward zero:

ViewMeaningResolve via
vw_potential_duplicate_parties (match_kind = civil_id)Same civil ID on multiple unified_personsDuplicate review β†’ Parties tab β†’ merge
vw_potential_duplicate_parties (match_kind = folded_name)Folded-name collisionDuplicate review β†’ Parties tab β†’ merge
vw_duplicate_clientsMultiple clients rows per (unified_person_id, system)Duplicate review β†’ Clients tab β†’ merge
vw_clients_without_partyCRM client with no unified_person_idDuplicate review β†’ Relink orphan clients
vw_identity_drift_watchSnapshot name drift vs party registryData quality dashboard β†’ review row

Where to watch

  • Flutter: /clients admin KPI strip + Identity convergence row (admins only); app-bar merge badge when party dupes > 0.
  • React: /clients (admin) β€” same summary + convergence tiles; /admin/duplicate-review for merge + orphan relink.
  • Valuation data quality (both): full convergence card with deep links.

Weekly checklist

  1. Open /clients?admin=1 β€” confirm convergence counts (or zero).
  2. Run orphan relink once if clientsWithoutParty > 0.
  3. Clear party/client duplicate queues before large imports.
  4. After merge sessions, refresh list β€” vw_potential_duplicate_parties should drop for merged keys.

See migration supabase/migrations/20260622120000_phase5_dedup_drift_views.sql and lib/data/repositories/data_quality_repository.dart (fetchConvergenceHealth).

Aldilaijan & Khobara Real Estate Platform