← back to Filemaker Mcp

audit-fm-last.mjs

44 lines

import fs from 'fs';
const Q = String.fromCharCode(34);
function parseCSV(t) { const R = []; let i = 0, f = '', r = [], q = false; while (i < t.length) { const c = t[i]; if (q) { if (c === Q) { if (t[i + 1] === Q) { f += Q; i++; } else q = false; } else f += c; } else { if (c === Q) q = true; else if (c === ',') { r.push(f); f = ''; } else if (c === '\n') { r.push(f); R.push(r); r = []; f = ''; } else if (c !== '\r') f += c; } i++; } if (f.length || r.length) { r.push(f); R.push(r); } return R; }
const raw = parseCSV(fs.readFileSync(process.argv[2], 'utf8'));
const h = raw.shift(); const ix = Object.fromEntries(h.map((x, i) => [x, i]));
const norm = s => (s || '').toUpperCase().replace(/[^A-Z0-9]/g, '');
const recs = raw.filter(r => r.length && r[ix.combo_sku] !== undefined);

const bySeries = {}, byDate = {}, bySupplier = {};
let mfrIsDwsku = [], mfrBlank = 0, seriesBlank = 0, dupCombo = {};
for (const r of recs) {
  const combo = norm(r[ix.combo_sku]);
  const num = norm(r[ix.js_pattern]);
  const mfr = norm(r[ix.mfr_pattern]);
  const series = r[ix.series] || '(blank)';
  bySeries[series] = (bySeries[series] || 0) + 1;
  const d = (r[ix.date_put_up] || '').split(' ')[0] || '(blank)';
  byDate[d] = (byDate[d] || 0) + 1;
  bySupplier[r[ix.supplier] || '(blank)'] = (bySupplier[r[ix.supplier] || '(blank)'] || 0) + 1;
  if (!mfr) mfrBlank++;
  else if (mfr === num || mfr === combo || mfr === 'GRS' + num || mfr === series.toUpperCase().replace(/[^A-Z0-9]/g, '') + num) mfrIsDwsku.push(r);
  if (!r[ix.series]) seriesBlank++;
  dupCombo[combo] = (dupCombo[combo] || 0) + 1;
}
const dups = Object.entries(dupCombo).filter(([k, v]) => v > 1 && k).sort((a, b) => b[1] - a[1]);
const top = (o, n = 12) => Object.entries(o).sort((a, b) => b[1] - a[1]).slice(0, n).map(([k, v]) => `  ${String(v).padStart(4)}  ${k}`).join('\n');

console.log('=== AUDIT: last', recs.length, 'FM records (newest by internal order) ===\n');
console.log('BY SERIES:\n' + top(bySeries));
console.log('\nBY DATE PUT UP:\n' + top(byDate));
console.log('\nBY SUPPLIER:\n' + top(bySupplier));
console.log('\n--- PROBLEMS ---');
console.log('Mfr field = DW SKU (WRONG):', mfrIsDwsku.length);
console.log('Mfr field BLANK:', mfrBlank);
console.log('Series BLANK:', seriesBlank);
console.log('Duplicate combo_sku within last 1000:', dups.length, dups.length ? '(top: ' + dups.slice(0, 8).map(d => d[0] + '×' + d[1]).join(', ') + ')' : '');
console.log('\n--- sample Mfr=DW-SKU wrong rows (combo | mfr | series | supplier | recId) ---');
for (const r of mfrIsDwsku.slice(0, 20)) console.log('  ' + r[ix.combo_sku] + ' | ' + JSON.stringify(r[ix.mfr_pattern]) + ' | ' + r[ix.series] + ' | ' + JSON.stringify(r[ix.supplier]) + ' | ' + r[ix.record_id]);

const out = process.env.HOME + '/Desktop/FM_last1000_WRONG_mfr_20260819.csv';
const qq = x => Q + String(x ?? '').replace(/"/g, Q + Q) + Q;
fs.writeFileSync(out, h.join(',') + '\n' + mfrIsDwsku.map(r => r.map(qq).join(',')).join('\n') + '\n');
console.log('\nwrote wrong-mfr rows ->', out);