← back to Dwjs Consolidation 2026 04 23
send_sku_csv.js
106 lines
#!/usr/bin/env node
/**
* Build CSV of legacy SKU renumber (old → new) and send via George Gmail Agent
* to info@designerwallcoverings.com.
*/
const fs = require('fs');
const http = require('http');
const path = require('path');
const EXEC = '/Users/macstudio3/Projects/dwjs-consolidation-2026-04-23/phase3_legacy_execution.ndjson';
const GEORGE_HOST = '45.61.58.125';
const GEORGE_PORT = 9850;
const TO = 'info@designerwallcoverings.com';
// Read execution log
const rows = fs.readFileSync(EXEC, 'utf8').split('\n').filter(Boolean).map(JSON.parse);
console.log(`loaded ${rows.length} renumbered products`);
// CSV columns: product_id, old_prefix, series, resolved_mfr, old_sku, new_sku, variant_type
const cols = ['product_id','series','old_prefix','resolved_mfr','old_sku','new_sku','variant_type'];
const lines = [cols.join(',')];
const esc = s => { if (s==null) return ''; const str=String(s); return /[",\n]/.test(str) ? '"'+str.replace(/"/g,'""')+'"' : str; };
let variantCount = 0;
for (const r of rows) {
for (const v of r.variants) {
const type = /sample/i.test(v.new) ? 'sample' : 'bolt';
lines.push(cols.map(c => esc(({
product_id: r.pid.replace('gid://shopify/Product/',''),
series: r.series,
old_prefix: r.old_prefix,
resolved_mfr: r.resolved_mfr,
old_sku: v.old,
new_sku: v.new,
variant_type: type,
})[c])).join(','));
variantCount++;
}
}
const csv = lines.join('\n');
const ts = new Date().toISOString().slice(0,10);
const filename = `dwjs-legacy-sku-renumber-${ts}.csv`;
fs.writeFileSync(path.join(path.dirname(EXEC), filename), csv);
console.log(`CSV: ${variantCount} variant rows, ${rows.length} products, size=${csv.length} bytes`);
// Summary by prefix + series
const summary = {};
for (const r of rows) {
const k = `${r.old_prefix} → ${r.series}`;
summary[k] = (summary[k]||0)+1;
}
const summaryHtml = Object.entries(summary).sort((a,b)=>b[1]-a[1]).map(([k,v])=>`<li><b>${k}</b>: ${v} products</li>`).join('');
const subject = `[DW] Legacy SKU Renumber Complete — ${rows.length} products → DWJS-90000+`;
const body = `
<html><body style="font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;max-width:720px;color:#111">
<h2>Legacy SKU Renumber — DWBR / CCA / TRF / GGA → DWJS-90000+</h2>
<p>Completed <b>${new Date().toISOString().slice(0,10)}</b>. Attached CSV has every variant's old and new SKU.</p>
<p><b>Totals:</b> ${rows.length} products / ${variantCount} variants renumbered, zero failures.</p>
<h3>Breakdown (old prefix → series)</h3>
<ul style="line-height:1.6">${summaryHtml}</ul>
<h3>What changed, per product</h3>
<ul>
<li>Variant SKU renamed from <code>OLD-#####</code> to <code>DWJS-9####</code></li>
<li><code>custom.manufacturer_sku</code> metafield refreshed with the real mfr SKU (recovered from fmpro master)</li>
<li><code>global.old_dw_sku</code> metafield stores the original DW SKU (audit trail / rollback reference)</li>
<li>Tag <code>Series: York</code> (TRF) or <code>Series: Brewster</code> (DWBR / CCA / GGA) added</li>
<li>Title, vendor, status, images, prices, and inventory untouched</li>
</ul>
<h3>CSV columns</h3>
<code>product_id, series, old_prefix, resolved_mfr, old_sku, new_sku, variant_type</code>
<hr><p style="color:#666;font-size:12px">Generated by Designer Wallcoverings automation. Questions → reply to this email.</p>
</body></html>`;
const payload = JSON.stringify({
to: TO,
subject,
body,
attachments: [{
filename,
content_base64: Buffer.from(csv).toString('base64'),
mime_type: 'text/csv',
}],
});
const auth = 'Basic ' + Buffer.from('admin:DWSecure2024!').toString('base64');
const req = http.request({
hostname: GEORGE_HOST, port: GEORGE_PORT, method: 'POST',
path: '/api/send-with-attachment',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(payload),
'Authorization': auth,
},
}, res => {
let c = '';
res.on('data', d => c += d);
res.on('end', () => {
console.log(`HTTP ${res.statusCode}`);
console.log(c);
});
});
req.on('error', e => { console.error('request error:', e.message); process.exit(1); });
req.setTimeout(30000, () => { req.destroy(); console.error('timeout'); process.exit(1); });
req.write(payload);
req.end();