fix(migration): modernize stale NocoDB→CRM pipeline stage map to current 7 stages
The 2026-05-03 migration pipeline (src/lib/dedup/*) predates the 9→7 pipeline-stage refactor; its STAGE_MAP emitted invalid stages (open/details_sent/eoi_sent/…) that would write bad pipeline_stage values on --apply. Remap to the current PIPELINE_STAGES (enquiry/qualified/ nurturing/eoi/reservation/deposit_paid/contract) + a deposit-received → deposit_paid override. Frozen-fixture test expectations updated (17/17 pass). Validated: live --dry-run = 239 clients / 255 interests / 41 EOI docs (matches independent snapshot analysis; pipeline is more conservative and flags 3 borderline pairs for review). Adds the migration design spec (source map, scope lock to Port Nimara + Expenses bases, EOI coverage 48/48, in-flight Documenso state, remaining gaps: interest eoiStatus, expenses, doc-blob backfill). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -201,15 +201,19 @@ const DEFAULT_OPTIONS: TransformOptions = {
|
||||
|
||||
// ─── Stage mapping ──────────────────────────────────────────────────────────
|
||||
|
||||
// Updated 2026-06-01 to the current 7-stage pipeline. The prior map targeted
|
||||
// the pre-(9→7)-refactor vocab (open/details_sent/eoi_sent/…) and would have
|
||||
// written invalid `pipeline_stage` values. Current stages live in
|
||||
// `src/lib/constants.ts` PIPELINE_STAGES.
|
||||
const STAGE_MAP: Record<string, string> = {
|
||||
'General Qualified Interest': 'open',
|
||||
'Specific Qualified Interest': 'details_sent',
|
||||
'EOI and NDA Sent': 'eoi_sent',
|
||||
'Signed EOI and NDA': 'eoi_signed',
|
||||
'Made Reservation': 'deposit_10pct',
|
||||
'Contract Negotiation': 'contract_sent',
|
||||
'Contract Negotiations Finalized': 'contract_sent',
|
||||
'Contract Signed': 'contract_signed',
|
||||
'General Qualified Interest': 'qualified',
|
||||
'Specific Qualified Interest': 'nurturing',
|
||||
'EOI and NDA Sent': 'eoi',
|
||||
'Signed EOI and NDA': 'eoi',
|
||||
'Made Reservation': 'reservation',
|
||||
'Contract Negotiation': 'contract',
|
||||
'Contract Negotiations Finalized': 'contract',
|
||||
'Contract Signed': 'contract',
|
||||
};
|
||||
|
||||
const LEAD_CATEGORY_MAP: Record<string, string> = {
|
||||
@@ -622,6 +626,12 @@ function buildPlannedClient(
|
||||
function buildPlannedInterest(row: NocoDbRow, clientTempId: string): PlannedInterest {
|
||||
const stage = (row['Sales Process Level'] as string | undefined) ?? '';
|
||||
const cat = (row['Lead Category'] as string | undefined) ?? '';
|
||||
// Deposit received overrides the mapped stage → deposit_paid (unless the deal
|
||||
// is already at contract). Default for unmapped/blank legacy stage = enquiry.
|
||||
const depositReceived =
|
||||
((row['Deposit 10% Status'] as string | undefined) ?? '').trim() === 'Received';
|
||||
let mappedStage = STAGE_MAP[stage] ?? 'enquiry';
|
||||
if (depositReceived && mappedStage !== 'contract') mappedStage = 'deposit_paid';
|
||||
|
||||
const notesParts: string[] = [];
|
||||
const internalNotes = row['Internal Notes'] as string | undefined;
|
||||
@@ -634,7 +644,7 @@ function buildPlannedInterest(row: NocoDbRow, clientTempId: string): PlannedInte
|
||||
return {
|
||||
sourceId: row.Id,
|
||||
clientTempId,
|
||||
pipelineStage: STAGE_MAP[stage] ?? 'open',
|
||||
pipelineStage: mappedStage,
|
||||
leadCategory: LEAD_CATEGORY_MAP[cat] ?? null,
|
||||
source: ((row['Source'] as string | undefined) ?? null) || null,
|
||||
notes: notesParts.join('\n\n') || null,
|
||||
|
||||
Reference in New Issue
Block a user