[object Object]

← back to York Reprice 2026 08

bridge-reprice: valid-MAP-set guard (dup-MAP SKUs) + NaN/0 price skip -> WOULD WRITE 0

d27db3510e913666178ad2c73f17c2a1b5e55417 · 2026-07-28 16:00:29 -0700 · Steve Abrams

- VMAP: load all us_map values per SKU from york_master_aug2026; skip when live matches ANY (the deduped
  CSV kept only one, so bridge was pushing correctly-priced dup-MAP rolls to the other value: NW3503/04/93).
- NaN/0 guard: dirty master-priced-by-sku.csv rows no longer pollute the held DOWN bucket (46 skipped).
- Full-scan dry-run: UP 0 / DOWN 0 / WOULD WRITE 0 — now agrees with york-cadence (0 legit reprice).

Files touched

Diff

commit d27db3510e913666178ad2c73f17c2a1b5e55417
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jul 28 16:00:29 2026 -0700

    bridge-reprice: valid-MAP-set guard (dup-MAP SKUs) + NaN/0 price skip -> WOULD WRITE 0
    
    - VMAP: load all us_map values per SKU from york_master_aug2026; skip when live matches ANY (the deduped
      CSV kept only one, so bridge was pushing correctly-priced dup-MAP rolls to the other value: NW3503/04/93).
    - NaN/0 guard: dirty master-priced-by-sku.csv rows no longer pollute the held DOWN bucket (46 skipped).
    - Full-scan dry-run: UP 0 / DOWN 0 / WOULD WRITE 0 — now agrees with york-cadence (0 legit reprice).
---
 bridge-reprice.mjs | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/bridge-reprice.mjs b/bridge-reprice.mjs
index f582049..2b016b9 100644
--- a/bridge-reprice.mjs
+++ b/bridge-reprice.mjs
@@ -22,6 +22,15 @@ try{ const out=execSync(`PGPASSWORD=DW2024! /opt/homebrew/opt/postgresql@14/bin/
   for(const line of out.trim().split('\n').filter(Boolean)){const [s,p]=line.split(String.fromCharCode(31)); if(!RPS.has(s))RPS.set(s,parseFloat(p));}
   console.log(`  single-roll targets loaded: ${RPS.size}`);
 }catch(e){ console.log('  ⚠ single-roll load failed (falling back to MAP-only):',String(e.message||e).slice(0,80)); }
+// VALID-MAP SET (parity with york-cadence): york_master_aug2026 has dup rows per SKU (two roll sizes →
+// conflicting us_map, e.g. NW3503 carries BOTH $102 and $123.25). master-priced-by-sku.csv keeps only ONE
+// (first-wins), so bridge would push a correctly-priced live roll to the OTHER dup value. Skip when live
+// already matches ANY valid master MAP row.
+const VMAP=new Map();
+try{ const out=execSync(`PGPASSWORD=DW2024! /opt/homebrew/opt/postgresql@14/bin/psql -h 127.0.0.1 -U dw_admin -d dw_unified -tA -c "select upper(trim(export_sku))||chr(31)||coalesce(us_map,round(us_msrp*0.75,2)) from york_master_aug2026 where export_sku is not null"`,{encoding:'utf8'});
+  for(const line of out.trim().split('\n').filter(Boolean)){const [s,p]=line.split(String.fromCharCode(31)); if(!VMAP.has(s))VMAP.set(s,new Set()); VMAP.get(s).add(parseFloat(p));}
+  console.log(`  valid-MAP sets loaded: ${VMAP.size}`);
+}catch(e){ console.log('  ⚠ valid-MAP load failed (falling back to single CSV price):',String(e.message||e).slice(0,80)); }
 let cur=null, live=[];
 // JS catalog ~6,193 products; old 90×60=5,400 cap truncated the scan (missed ~793). 120×100 headroom.
 for(let pg=0;pg<120;pg++){
@@ -34,12 +43,15 @@ for(let pg=0;pg<120;pg++){
   if(!d.pageInfo.hasNextPage)break; cur=d.pageInfo.endCursor;
 }
 console.log(`live JS w/ mfr_sku+roll: ${live.length} | mode: ${APPLY?'⚠️ LIVE APPLY':'DRY-RUN'}${INCLUDE_DOWN?' +DOWN':''}`);
-const b={up:[],down:[],fix:[],already:0,anomaly:[],mismatch:[],notmaster:0,notsell:0};
+const b={up:[],down:[],fix:[],already:0,anomaly:[],mismatch:[],notmaster:0,notsell:0,badprice:0};
 for(const p of live){
   const m=M.get(p.mfr); if(!m){b.notmaster++;continue;}
   if(!['Active','New'].includes(m.status)||p.status!=='ACTIVE'){b.notsell++;continue;}
-  const map=m.newp,cur=p.cur; if(Math.abs(cur-map)<0.01){b.already++;continue;}
+  const map=m.newp,cur=p.cur;
+  if(!Number.isFinite(map)||map<=0){b.badprice++;continue;} // dirty master-priced-by-sku.csv -> NaN/0 target; never write it
+  if(Math.abs(cur-map)<0.01){b.already++;continue;}
   const rps=RPS.get(p.mfr); if(rps&&Math.abs(cur-rps)<0.01){b.already++;continue;} // already at valid single-roll price (naturals) — not a reprice
+  const vm=VMAP.get(p.mfr); if(vm&&[...vm].some(v=>Math.abs(cur-v)<0.01)){b.already++;continue;} // already at a valid master MAP row (dup-MAP SKUs) — not a reprice
   if(m.pattern&&!share(p.title,m.pattern)){b.mismatch.push({mfr:p.mfr,master:m.pattern,live:p.title});continue;}
   const rec={pid:p.pid,vid:p.vid,mfr:p.mfr,cur,map,fb:m.fb,title:p.title};
   if(cur<=10)b.fix.push(rec); else if(map/cur>2.5||map/cur<0.4)b.anomaly.push(rec);
@@ -49,7 +61,7 @@ console.log(`  already at MAP: ${b.already}`);
 console.log(`  UP to MAP (increases): ${b.up.length}  | fix garbage(<=$10): ${b.fix.length}`);
 console.log(`  DOWN to MAP (decreases): ${b.down.length}  ${INCLUDE_DOWN?'(WILL apply)':'(HELD unless --include-down)'}`);
 console.log(`  ⚠ anomaly(skip): ${b.anomaly.length} | ⚠ title-mismatch(skip): ${b.mismatch.length}`);
-console.log(`  live-not-in-master: ${b.notmaster} | not-sellable/active(skip): ${b.notsell}`);
+console.log(`  live-not-in-master: ${b.notmaster} | not-sellable/active(skip): ${b.notsell} | ⚠ bad master price NaN/0(skip): ${b.badprice}`);
 const toWrite=[...b.up,...b.fix,...(INCLUDE_DOWN?b.down:[])];
 console.log(`  => WOULD WRITE: ${toWrite.length}`);
 fs.writeFileSync('data/bridge-reprice-plan.json',JSON.stringify(b,null,2));

← 4b91284 York cadence/bridge: fix scan-truncation cap (90x60=5400 ->  ·  back to York Reprice 2026 08  ·  auto-save: 2026-07-28T16:01:35 (1 files) — data/bridge-repri 2004540 →