/** * One-time backfill script (SCHEMA-03, D-05) — computes and persists * `Tender.fingerprint` for every pre-existing row. * * The TenderSource row backfill itself lives in the migration SQL * (20260723120000_add_tender_source/migration.sql) because it's a pure * column copy. The fingerprint backfill does NOT belong in SQL: it needs * the umlaut/CPV-normalization logic in tender-fingerprint.ts, which is * code, not SQL (13-RESEARCH.md "Backfill-Migration"). * * Run once, manually, after the migration has been applied (compiled first * — this file uses standard extensionless TS imports, so it must run as * built CommonJS, not as a raw .ts file): * pnpm --filter @tessera/api build * DATABASE_URL=... node dist/tenders/backfill-tender-source.js * * Idempotent: recomputes and overwrites fingerprint for every row it reads, * so re-running is safe (same deterministic output for unchanged inputs). * * This script remains the manual, force-recompute-everything path. As of * Task 3 of the WINDOWS.md #11 fix, the automatic path for ordinary * startup is TenderFingerprintBackfillService, which recomputes only rows * whose stored fingerprint doesn't yet carry FINGERPRINT_VERSION_PREFIX — * this script stays useful for a deliberate full recompute (e.g. after a * formula change) or ad-hoc verification. */ import { PrismaClient } from '@prisma/client'; import { tenderFingerprint } from './tender-fingerprint'; async function main(): Promise { const prisma = new PrismaClient(); try { const tenders = await prisma.tender.findMany({ select: { id: true, title: true, buyerName: true, deadlineAt: true, }, }); let updated = 0; for (const t of tenders) { const fingerprint = tenderFingerprint({ buyerName: t.buyerName, title: t.title, deadlineAt: t.deadlineAt, }); await prisma.tender.update({ where: { id: t.id }, data: { fingerprint }, }); updated += 1; } console.log(`backfill-tender-source: fingerprint set on ${updated}/${tenders.length} tenders`); } finally { await prisma.$disconnect(); } } main().catch((err) => { console.error('backfill-tender-source failed:', err); process.exitCode = 1; });