Grid/contacts unification step 1: real contact_id link + grid as front door (v0.1.0:52)
Structural fix for the duplicate-people class of bug: instead of matching a grid contact "pill" to a contacts row heuristically by name/email (which drifted and caused the 1406 double-count), link them by id. Backend: - Migration 0004: fundraising_contacts.contact_id (additive, nullable, logical FK to contacts(id)) + index. Paired down migration. - sync_fundraising_relational now stores the id that _upsert_contact_from_fundraising already returns, so every grid contact carries its contacts-table id. - _backfill_grid_contact_ids: one-time, idempotent backfill on startup (re-runs the grid sync once if any row lacks contact_id), so existing data links immediately. - entity_resolution: grid pass prefers the explicit contact_id link (match_kind 'grid_link') over heuristic email / name+investor, guarded by a PRAGMA check so older DBs without the column still work. Frontend: - Fundraising grid "+ Row" -> "+ Investor" (clear, single investor entry point). - Contacts page: the "+ Add Contact" trigger is replaced by a pointer to the grid; the page is now a read/search/edit view (ContactDetailPanel still edits all fields). New people are added from the grid. No contact data is removed. Tests: backend/ingest/test_entity_resolution.py extended (explicit-link case, 11/11) and a new backend/test_grid_contact_link.py integration test (init_db applies 0004, sync populates contact_id to the right contact, re-sync is idempotent). py_compile + frontend html.parser clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -16,8 +16,9 @@ export const PACKAGE_TITLE = 'Ten31 Database'
|
||||
// * 0.1.0:48 (entity model: investors vs people; fixes double-count)
|
||||
// * 0.1.0:49 (Architect: Claude thesis generation + Thesis Workshop screen)
|
||||
// * 0.1.0:50 (Set Anthropic API Key UI action — no terminal needed)
|
||||
// * Current: 0.1.0:51 (entity-resolution fix: people double-count + duplicate queue)
|
||||
export const PACKAGE_VERSION = '0.1.0:51'
|
||||
// * 0.1.0:51 (entity-resolution fix: people double-count + duplicate queue)
|
||||
// * Current: 0.1.0:52 (grid/contacts unification: contact_id link + grid as front door)
|
||||
export const PACKAGE_VERSION = '0.1.0:52'
|
||||
|
||||
export const DATA_MOUNT_PATH = '/data'
|
||||
export const WEB_PORT = 8080
|
||||
|
||||
@@ -12,8 +12,9 @@ import { v_0_1_0_48 } from './v0.1.0.48'
|
||||
import { v_0_1_0_49 } from './v0.1.0.49'
|
||||
import { v_0_1_0_50 } from './v0.1.0.50'
|
||||
import { v_0_1_0_51 } from './v0.1.0.51'
|
||||
import { v_0_1_0_52 } from './v0.1.0.52'
|
||||
|
||||
export const versionGraph = VersionGraph.of({
|
||||
current: v_0_1_0_51,
|
||||
other: [v_0_1_0_39, v_0_1_0_40, v_0_1_0_41, v_0_1_0_42, v_0_1_0_43, v_0_1_0_44, v_0_1_0_45, v_0_1_0_46, v_0_1_0_47, v_0_1_0_48, v_0_1_0_49, v_0_1_0_50],
|
||||
current: v_0_1_0_52,
|
||||
other: [v_0_1_0_39, v_0_1_0_40, v_0_1_0_41, v_0_1_0_42, v_0_1_0_43, v_0_1_0_44, v_0_1_0_45, v_0_1_0_46, v_0_1_0_47, v_0_1_0_48, v_0_1_0_49, v_0_1_0_50, v_0_1_0_51],
|
||||
})
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { VersionInfo } from '@start9labs/start-sdk'
|
||||
|
||||
// Grid/contacts unification (step 1): the fundraising grid is the single front
|
||||
// door. Adds a real link (fundraising_contacts.contact_id, migration 0004) from
|
||||
// each grid contact "pill" to its contacts-table row — populated by the grid sync
|
||||
// and backfilled once on upgrade — so entity resolution links by id instead of
|
||||
// heuristic name/email matching (ending the duplicate-people class of bug). UI:
|
||||
// the grid's "+ Row" is now "+ Investor"; the Contacts page is a read/search/edit
|
||||
// view (new people are added from the grid). Additive migration; no data loss.
|
||||
export const v_0_1_0_52 = VersionInfo.of({
|
||||
version: '0.1.0:52',
|
||||
releaseNotes: {
|
||||
en_US: [
|
||||
'Grid/contacts unification: the Fundraising Grid is now the single place to',
|
||||
'add investors and contacts, each grid contact is linked to its contact record',
|
||||
'by a real id (no more name-matching), and the Contacts page becomes a',
|
||||
'view/search/edit list. Existing links are backfilled automatically on upgrade.',
|
||||
].join(' '),
|
||||
},
|
||||
migrations: { up: async () => {}, down: async () => {} },
|
||||
})
|
||||
Reference in New Issue
Block a user