← back to York Reprice 2026 08
build-onboard-payloads-12.mjs
60 lines
#!/usr/bin/env node
// build-onboard-payloads-12.mjs — same proven logic as build-onboard-payloads.mjs, but:
// • reads data/onboard-rows-12.json • writes data/onboard-payloads-12.json
// • SKU allocation starts at DWJS-92941 (maxN=92940 = true max across live Shopify + both enriched files;
// the original builder only scanned the phase-1 632 and would COLLIDE with the 735 batch's numbers).
import fs from 'node:fs';
const rows=JSON.parse(fs.readFileSync('data/onboard-rows-12.json','utf8'));
const slug=s=>String(s||'').toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,'');
const isNat=m=>/grasscloth|sisal|paperweave|paper weave|\bcork\b|\bhemp\b|\bjute\b|raffia|abaca|arrowroot/i.test(m||'');
const map=r=> (r.us_map>0?r.us_map : (r.us_msrp>0?Math.round(r.us_msrp*75)/100 : null));
let n=92941; // collision-safe start (verified true max DWJS = 92940)
const payloads=[]; const skipped=[]; const skipReason={};
for(const r of rows){
const pn=(r.pattern_name||'').trim(), cw=(r.colorway||'').trim();
if(!r.image_url){ skipped.push([r.export_sku,'no-image']); skipReason['no-image']=(skipReason['no-image']||0)+1; continue; }
if(!pn){ skipped.push([r.export_sku,'no-pattern-name']); skipReason['no-pattern-name']=(skipReason['no-pattern-name']||0)+1; continue; }
const nat=isNat(r.technical_material);
let price=null, optName=null, uom=null, min='1', step='1', pricedUom='Priced Per Single Roll';
if(nat){ price=r.roll_price_single; optName='Sold Per Single Roll'; uom='BLT'; min='2'; step='2'; }
else {
const u=(r.uom||'').toUpperCase();
if(u==='YD'){ price=map(r); optName='Sold By The Yard'; uom='YD'; min='1'; step='1'; pricedUom='Priced Per Yard'; }
else if(u==='EA'||u==='BDR'){ price=map(r); optName='Sold Each'; uom=u; min='1'; step='1'; pricedUom='Priced Each'; }
else { price=map(r); optName='Sold Per Single Roll'; uom='BLT'; min='2'; step='2'; }
}
const P=Number(price);
if(!(P>0) || !isFinite(P)){ skipped.push([r.export_sku,'no-price']); skipReason['no-price']=(skipReason['no-price']||0)+1; continue; }
const SKU=`DWJS-${n++}`;
const addCw = cw && !pn.toLowerCase().includes(cw.toLowerCase());
const title=`${pn}${addCw?' '+cw:''} | Jeffrey Stevens`;
const handle=slug(`${pn}-${cw}-wallpaper-${r.export_sku}`);
const mf={}; const put=(k,v)=>{ if(v!==null&&v!==undefined&&String(v).trim()!=='') mf[k]=String(v); };
put('custom.manufacturer_sku',r.export_sku); put('dwc.manufacturer_sku',r.export_sku);
put('custom.pattern_name',pn); put('custom.collection_name',r.book_name);
put('custom.brand_name',r.brand); put('custom.parent_brand',r.parent_brand);
put('custom.us_msrp',r.us_msrp); put('custom.wholesale_price',r.wholesale);
if(r.width_inches&&r.length_feet) put('global.width',`${r.width_inches}" x ${r.length_feet} ft`);
put('custom.width',r.width_inches); put('global.length',r.length_feet?`${r.length_feet} ft`:'');
put('global.repeat',r.pattern_repeat); put('custom.pattern_repeat',r.pattern_repeat);
put('global.MATCH',r.match_type); put('custom.match_type',r.match_type);
put('custom.backing',r.backing); put('specs.coverage',r.coverage);
put('specs.style',r.marketing_style); put('specs.pattern',r.marketing_pattern);
put('custom.color_family',r.color_family);
put('global.unit_of_measure',pricedUom);
put('global.v_prods_quantity_order_min',min); put('global.v_prods_quantity_order_units',step);
if(min==='2') put('global.packaged','Shipped in Doubles');
payloads.push({ mfr_sku:r.export_sku, title, handle, vendor:'Jeffrey Stevens', productType:'Wallcovering', status:'DRAFT',
descriptionHtml:r.dynamic_description||'',
options:[{name:'Size',values:['Sample',optName]}],
variants:[{sku:`${SKU}-Sample`,price:'4.25',option:'Sample',inventoryPolicy:'CONTINUE'},
{sku:SKU,price:P.toFixed(2),option:optName,inventoryPolicy:'CONTINUE'}],
image:r.image_url, metafields:mf, uom });
}
const seen=new Set();
for(const p of payloads){ let h=p.handle,i=2; while(seen.has(h)){h=`${p.handle}-${i++}`;} p.handle=h; seen.add(h); }
fs.writeFileSync('data/onboard-payloads-12.json',JSON.stringify(payloads,null,1));
console.log(`built ${payloads.length} payloads | skipped ${skipped.length} ${JSON.stringify(skipReason)}`);
console.log(` SKU ${payloads[0]?.variants[1].sku}..${payloads.at(-1)?.variants[1].sku} | all DRAFT+priced: ${payloads.every(p=>p.status==='DRAFT'&&+p.variants[1].price>0)}`);
console.log('$0 (local)');