← 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
M scripts/kravet-master-2026/add_roll_variants.mjs
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 →