[object Object]

← back to Dw Yolo Loop

add_roll_variants: enforce ROLL-unit in-script (standing rule: no per-yard MAP on per-roll product); verified 305/305 ROLL, 0 dropped

72fbe08a53fc2a0d19eb930c7d4330f00822e501 · 2026-06-16 15:44:32 -0700 · Steve Abrams

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Files touched

Diff

commit 72fbe08a53fc2a0d19eb930c7d4330f00822e501
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jun 16 15:44:32 2026 -0700

    add_roll_variants: enforce ROLL-unit in-script (standing rule: no per-yard MAP on per-roll product); verified 305/305 ROLL, 0 dropped
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---
 scripts/kravet-master-2026/add_roll_variants.mjs | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/scripts/kravet-master-2026/add_roll_variants.mjs b/scripts/kravet-master-2026/add_roll_variants.mjs
index f15a56a..31a7c76 100644
--- a/scripts/kravet-master-2026/add_roll_variants.mjs
+++ b/scripts/kravet-master-2026/add_roll_variants.mjs
@@ -27,19 +27,24 @@ if(!TOKEN){ console.error('no SHOPIFY_ADMIN_TOKEN'); process.exit(1); }
 const sleep=ms=>new Promise(r=>setTimeout(r,ms));
 const log=s=>{ console.log(s); fs.appendFileSync('/tmp/add_roll_variants.log',s+'\n'); };
 
-// new_map per gid from Kamatera (source file built earlier)
-const nm={};
+// new_map + unit per gid from Kamatera (source file built earlier)
+// cols: gid | vendor | sku | new_map | unit_of_measure | ... | product_type
+const nm={}, unitOf={};
 for(const line of fs.readFileSync(SRC_FILE,'utf8').trim().split('\n')){
-  const c=line.split('|'); if(c.length>=4) nm[c[0]]=parseFloat(c[3]);
+  const c=line.split('|'); if(c.length>=5){ nm[c[0]]=parseFloat(c[3]); unitOf[c[0]]=(c[4]||'').trim().toUpperCase(); }
 }
 // the 305 sample-only gids
 // PRICE FLOOR: a ROLL MAP below this is almost certainly a sample/per-yard/garbage
 // value (the $4.25 sample-as-price trap). Reject + log rather than write it live.
 const MIN_ROLL_PRICE=10;
 const rawTargets=fs.readFileSync(CSV_FILE,'utf8').trim().split('\n')
-  .filter(l=>l.includes('SAMPLE_ONLY_NEEDS_PRICE')).map(l=>{const c=l.split(','); return {gid:c[0],vendor:c[1],sku:c[2],new_map:nm[c[0]]};});
-const priceDropped=rawTargets.filter(t=>!(t.new_map>=MIN_ROLL_PRICE) || t.new_map===4.25);
-const targets=rawTargets.filter(t=>t.new_map>=MIN_ROLL_PRICE && t.new_map!==4.25);
+  .filter(l=>l.includes('SAMPLE_ONLY_NEEDS_PRICE')).map(l=>{const c=l.split(','); return {gid:c[0],vendor:c[1],sku:c[2],new_map:nm[c[0]],unit:unitOf[c[0]]};});
+// UNIT GUARD (standing rule kravet-map-table-mixes-yard-and-roll-units): only
+// write per-roll MAP onto these per-roll products. A per-yard MAP here would be
+// ~3x underpriced — drop + log anything not explicitly ROLL.
+const unitDropped=rawTargets.filter(t=>t.unit!=='ROLL');
+const priceDropped=rawTargets.filter(t=>t.unit==='ROLL' && (!(t.new_map>=MIN_ROLL_PRICE) || t.new_map===4.25));
+const targets=rawTargets.filter(t=>t.unit==='ROLL' && t.new_map>=MIN_ROLL_PRICE && t.new_map!==4.25);
 
 async function gql(query,variables){
   for(let a=0;a<4;a++){
@@ -60,7 +65,8 @@ const CREATE=`mutation($pid:ID!,$variants:[ProductVariantsBulkInput!]!){
     userErrors{ field message } } }`;
 
 let added=0,skipped=0,failed=0,n=0;
-log(`\n=== add_roll_variants ${APPLY?'APPLY':'DRY-RUN'} limit=${LIMIT} targets=${targets.length} (price-floor dropped ${priceDropped.length}) @ ${new Date().toISOString?.()||'now'} ===`);
+log(`\n=== add_roll_variants ${APPLY?'APPLY':'DRY-RUN'} limit=${LIMIT} targets=${targets.length} (dropped: non-ROLL ${unitDropped.length}, below-floor ${priceDropped.length}) @ ${new Date().toISOString?.()||'now'} ===`);
+for(const d of unitDropped) log(`DROP non-ROLL-unit ${d.vendor} ${d.sku} unit=${d.unit||'∅'} new_map=${d.new_map}`);
 for(const d of priceDropped) log(`DROP below-floor ${d.vendor} ${d.sku} new_map=${d.new_map}`);
 for(const t of targets){
   if(n>=LIMIT) break; n++;

← b10bbb7 dark-vendor check (c43): 4 vendors fully DARK (not mis-colle  ·  back to Dw Yolo Loop  ·  cycle-44: broken-image delivery pilot (312 active sampled, 9 31803d5 →