Files
hedena_gold/apps/api/scripts/report-name-split.cjs
T
s.esmaeili ea86636027 Initial commit: Hedena Gold monorepo.
First commit of the Hedena Gold product (separate from gold-bank): branding, package names, and deploy defaults aligned to the new brand; legacy Henza trees stay local-only via .gitignore.
2026-10-15 17:19:10 +03:30

87 lines
3.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* D0 requirement 3 — review report for names that cannot be split safely.
*
* The migration backfills firstName = first token, lastName = the rest. That is
* correct for two-token names and a guess for anything longer: "سید محمد
* حسینی" should almost certainly be firstName="سید محمد", and the migration
* writes firstName="سید" instead. Those rows need a human.
*
* READ-ONLY. It changes nothing; it prints what a person has to check.
*
* node scripts/report-name-split.cjs # print to stdout
* node scripts/report-name-split.cjs --csv out.csv
*
* Run it AFTER the 20260922120000_customer_name_parts migration.
*/
const { PrismaClient } = require('@prisma/client');
const fs = require('fs');
const prisma = new PrismaClient();
/** Same normalisation the migration's SQL uses. */
const tokens = (s) => String(s ?? '').trim().replace(/\s+/g, ' ').split(' ').filter(Boolean);
(async () => {
const customers = await prisma.$queryRawUnsafe(`
SELECT id, "fullName", "firstName", "lastName", mobile, "memberCode"
FROM "Customer"
ORDER BY "createdAt"
`);
const multi = [];
const empty = [];
const single = [];
for (const c of customers) {
const t = tokens(c.fullName);
if (t.length === 0) empty.push(c);
else if (t.length === 1) single.push(c);
else if (t.length > 2) multi.push({ ...c, tokenCount: t.length });
}
console.log(`Customers scanned: ${customers.length}`);
console.log(` two tokens (split is reliable): ${customers.length - multi.length - empty.length - single.length}`);
console.log(` one token (lastName is NULL): ${single.length}`);
console.log(` empty name (nothing to split): ${empty.length}`);
console.log(` MORE THAN TWO TOKENS — NEEDS REVIEW: ${multi.length}`);
if (single.length) {
console.log('\n--- single-token names (no surname recorded) ---');
for (const c of single) console.log(` ${c.id} ${c.mobile} "${c.fullName}"`);
}
if (empty.length) {
console.log('\n--- empty names ---');
for (const c of empty) console.log(` ${c.id} ${c.mobile}`);
}
if (multi.length) {
console.log('\n--- NEEDS REVIEW: more than two tokens ---');
console.log('The migration guessed first-token / rest. Verify each one.\n');
for (const c of multi) {
console.log(` ${c.id} ${c.mobile} (${c.tokenCount} tokens)`);
console.log(` fullName : "${c.fullName}"`);
console.log(` guessed : firstName="${c.firstName}" lastName="${c.lastName}"`);
}
}
const csvArg = process.argv.indexOf('--csv');
if (csvArg !== -1 && process.argv[csvArg + 1]) {
const esc = (v) => `"${String(v ?? '').replace(/"/g, '""')}"`;
const rows = [
['id', 'mobile', 'memberCode', 'fullName', 'guessedFirstName', 'guessedLastName', 'tokenCount'].join(','),
...multi.map((c) =>
[c.id, c.mobile, c.memberCode, c.fullName, c.firstName, c.lastName, c.tokenCount].map(esc).join(','),
),
];
// BOM so Excel opens the Persian text in the right encoding.
fs.writeFileSync(process.argv[csvArg + 1], '' + rows.join('\n'), 'utf8');
console.log(`\nCSV written: ${process.argv[csvArg + 1]} (${multi.length} rows)`);
}
await prisma.$disconnect();
})().catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});