Files
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 Permalink 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);
});