fix(migration): NocoDB import safety + dedup helpers + lead-source backfill
migration-apply: residential client + interest inserts now wrap in db.transaction so a partial failure can't leave an orphan client row without its interest (or vice versa). migration-transform: buildPlannedDocument returns null when there are no signers so the apply pass doesn't try to send a Documenso envelope without recipients. mapDocumentStatus gets an explicit "Awaiting Further Details" branch that no longer auto-promotes via stale sign-time fields. parseFlexibleDate handles ISO and DD-MM-YYYY inputs uniformly. backfill-legacy-lead-source: chunk UPDATE WHERE clause now isNull(source) on top of the inArray match, so a re-run can't overwrite a more accurate source written between batches. Adds 235 lines of vitest coverage on migration-transform. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* Auth: `xc-token` header per NocoDB v2 API.
|
||||
*
|
||||
* The shape returned is a verbatim record of the row's fields — caller
|
||||
* The shape returned is a verbatim record of the row's fields - caller
|
||||
* is responsible for mapping to the new schema via `nocodb-transform.ts`.
|
||||
*/
|
||||
|
||||
@@ -34,7 +34,7 @@ export function loadNocoDbConfig(env: NodeJS.ProcessEnv = process.env): NocoDbCo
|
||||
|
||||
// ─── Table identifiers ──────────────────────────────────────────────────────
|
||||
//
|
||||
// These IDs are stable per the NocoDB base — they were captured during the
|
||||
// These IDs are stable per the NocoDB base - they were captured during the
|
||||
// 2026-05-03 audit and won't change unless the base is rebuilt. If the
|
||||
// base is reset, regenerate them from `getTablesList`.
|
||||
export const NOCO_TABLES = {
|
||||
@@ -67,7 +67,7 @@ export type NocoDbRow = Record<string, unknown> & { Id: number };
|
||||
/**
|
||||
* Fetch all rows from a NocoDB table. Auto-paginates until the API
|
||||
* reports `isLastPage`. The legacy base is small (252 Interests rows
|
||||
* being the largest table) so we keep this simple — no streaming.
|
||||
* being the largest table) so we keep this simple - no streaming.
|
||||
*/
|
||||
export async function fetchAllRows(
|
||||
tableId: string,
|
||||
@@ -95,7 +95,7 @@ export async function fetchAllRows(
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(
|
||||
`NocoDB fetch failed: ${res.status} ${res.statusText} — table ${tableId} page ${page}`,
|
||||
`NocoDB fetch failed: ${res.status} ${res.statusText} - table ${tableId} page ${page}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ export async function fetchAllRows(
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience snapshot — pulls every table the migration cares about
|
||||
* Convenience snapshot - pulls every table the migration cares about
|
||||
* in parallel. Returned shape is the input the transform layer expects.
|
||||
*/
|
||||
export interface NocoDbSnapshot {
|
||||
|
||||
Reference in New Issue
Block a user