feat(migration): add expenses + interest EOI status to NocoDB→CRM pipeline

A single idempotent --apply now seeds the full legacy dataset:
- Expenses: fetch the separate "Expenses" NocoDB base (mxfcefkk4dqs6uq),
  transform (price→amount+currency, payment status, receipt marker), apply to
  the expenses table under a new nocodb_expenses ledger tag.
- Interest EOI display state: set interests.eoiStatus/eoiDocStatus from the
  legacy EOI Status / LOI process so deals show signed / awaiting-signature
  (in-flight) state, not only a separate documents row.
- Runner reports expenses + tags createdBy with the seeded super-admin id.

Validated via --apply on the dev DB: 239 clients (multi-deal grouping intact),
255 interests (qualified 171/eoi 51/nurturing 30/reservation 2/contract 1),
48 signed + 3 in-flight EOIs, 165 expenses (5 currencies), 41 docs + 119
signers, 45 residential. tsc clean; 67 dedup unit tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 19:18:28 +02:00
parent 7dba1a47bb
commit 6c040a617b
4 changed files with 202 additions and 3 deletions

View File

@@ -44,6 +44,9 @@ export const NOCO_TABLES = {
websiteContactFormSubmissions: 'mxk5cd0pmwnwlcl',
websiteBerthEoiSupplements: 'mglmioo0ku8zgqj',
berths: 'mczgos9hr3oa9qc',
// Lives in a *separate* NocoDB base ("Expenses", p3hq2fxdevqcaq8) but the
// v2 records API addresses tables by id, so no per-base config is needed.
expenses: 'mxfcefkk4dqs6uq',
} as const;
// ─── HTTP shape ─────────────────────────────────────────────────────────────
@@ -120,6 +123,9 @@ export interface NocoDbSnapshot {
websiteContactFormSubmissions: NocoDbRow[];
websiteBerthEoiSupplements: NocoDbRow[];
berths: NocoDbRow[];
/** From the separate "Expenses" base. Optional so test fixtures and other
* snapshot sources needn't provide it; `fetchSnapshot` always does. */
expenses?: NocoDbRow[];
fetchedAt: string;
}
@@ -131,6 +137,7 @@ export async function fetchSnapshot(config: NocoDbConfig): Promise<NocoDbSnapsho
websiteContactFormSubmissions,
websiteBerthEoiSupplements,
berths,
expenses,
] = await Promise.all([
fetchAllRows(NOCO_TABLES.interests, config),
fetchAllRows(NOCO_TABLES.residentialInterests, config),
@@ -138,6 +145,7 @@ export async function fetchSnapshot(config: NocoDbConfig): Promise<NocoDbSnapsho
fetchAllRows(NOCO_TABLES.websiteContactFormSubmissions, config),
fetchAllRows(NOCO_TABLES.websiteBerthEoiSupplements, config),
fetchAllRows(NOCO_TABLES.berths, config),
fetchAllRows(NOCO_TABLES.expenses, config),
]);
return {
@@ -147,6 +155,7 @@ export async function fetchSnapshot(config: NocoDbConfig): Promise<NocoDbSnapsho
websiteContactFormSubmissions,
websiteBerthEoiSupplements,
berths,
expenses,
fetchedAt: new Date().toISOString(),
};
}