← back to Dw Yolo Loop

scripts/osborne-little-basis/ol-basis-decode.mjs

34 lines

// ol-basis-decode — READ-ONLY, $0. Cycle 81. Decodes Osborne & Little's pricing basis +
// lifecycle for the c68 abnormal-sample set (single-variant "Sample" at non-$0/non-$4.25).
// Lifecycle-first (c74): status counts. Basis by elimination (c72/c73): barcode? in
// kravet_authoritative_pricing? in product_map? costed? Classifies current-mislabel vs
// disco-straggler. Read-only Admin GraphQL + psql. EXCLUDES Phillip Jeffries (n/a).
import fs from 'fs'; import { execSync } from 'child_process';
const ENV=fs.readFileSync('/Users/macstudio3/Projects/secrets-manager/.env','utf8');
const TOK=((ENV.match(/^SHOPIFY_ADMIN_TOKEN=(.+)$/m)||[])[1]||'').replace(/['"\r]/g,'').trim();
const GQL='https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/graphql.json';
const PSQL='/opt/homebrew/opt/postgresql@14/bin/psql', DB='postgresql:///dw_unified?host=/tmp';
const VENDOR=process.argv[2]||'Osborne & Little';
const sleep=ms=>new Promise(r=>setTimeout(r,ms));
async function gql(q,v){for(let a=0;a<6;a++){const r=await fetch(GQL,{method:'POST',headers:{'X-Shopify-Access-Token':TOK,'Content-Type':'application/json'},body:JSON.stringify({query:q,variables:v})});if(r.status===429){await sleep(2000*(a+1));continue;}const j=await r.json();if(j.errors&&JSON.stringify(j.errors).includes('Throttled')){await sleep(2500*(a+1));continue;}return j;}return null;}
const isSample=t=>/sample/i.test(t||'');
const Q=`query($cursor:String,$q:String!){ products(first:100, after:$cursor, query:$q){ pageInfo{hasNextPage endCursor} edges{node{handle variants(first:5){edges{node{title price sku barcode createdAt}}}}} } }`;
let cursor=null,pages=0,total=0; const abn=[];
while(pages<15){ const j=await gql(Q,{cursor,q:`status:active vendor:'${VENDOR}'`}); if(!j?.data)break; const c=j.data.products;
  for(const e of c.edges){ const n=e.node; total++; const vs=(n.variants?.edges||[]).map(x=>x.node); if(vs.length!==1)continue; const v=vs[0]; const p=parseFloat(v.price);
    if(isSample(v.title)&&!isNaN(p)&&p!==0&&p!==4.25) abn.push({h:n.handle,price:p,sku:v.sku||'',bc:v.barcode||'',vc:(v.createdAt||'').slice(0,7)}); }
  if(!c.pageInfo.hasNextPage)break; cursor=c.pageInfo.endCursor; pages++; await sleep(180); }
const prices=abn.map(a=>a.price).sort((x,y)=>x-y); const distinct=[...new Set(prices)];
const years={}; abn.forEach(a=>years[a.vc.slice(0,4)]=(years[a.vc.slice(0,4)]||0)+1);
const q=s=>"'"+s.replace(/'/g,"''")+"'";
const inKap=execSync(`${PSQL} "${DB}" -tAc "SELECT count(*) FROM kravet_authoritative_pricing WHERE mfr_sku ILIKE '%${(abn[0]?.sku||'XX').slice(0,3)}%'"`,{encoding:'utf8'}).trim();
const inPm=execSync(`${PSQL} "${DB}" -tAc "SELECT count(*) FROM product_map WHERE vendor ILIKE ${q('%'+VENDOR.split(' ')[0]+'%')}"`,{encoding:'utf8'}).trim();
const costed=execSync(`${PSQL} "${DB}" -tAc "SELECT count(*) FILTER (WHERE cost_price>0)||'/'||count(*) FROM shopify_products WHERE vendor ILIKE ${q('%'+VENDOR.split(' ')[0]+'%')}"`,{encoding:'utf8'}).trim();
console.log(`=== ol-basis-decode: ${VENDOR} ===`);
console.log(`abnormal-sample (active): ${abn.length} | price $${prices[0]}..$${prices[prices.length-1]} | ${distinct.length} distinct (${distinct.length<=2?'FLAT placeholder=disco signal':'VARIED per-pattern=current'})`);
console.log(`createdAt year: ${JSON.stringify(years)} | with barcode: ${abn.filter(a=>a.bc).length}/${abn.length}`);
console.log(`basis-elimination: in kravet_authoritative_pricing(prefix)=${inKap} | in product_map=${inPm} | costed=${costed}`);
console.log(`→ ${inPm==='0'&&inKap==='0' ? 'NOT Kravet-MAP (RRP/other basis)' : 'has Kravet-MAP rows'}; ${distinct.length>2?'CURRENT-mislabel (varied prices)':'likely disco/placeholder'}`);
fs.writeFileSync('/tmp/ol-basis-decode.json',JSON.stringify({vendor:VENDOR,abnormal:abn.length,priceMin:prices[0],priceMax:prices[prices.length-1],distinct:distinct.length,years,withBarcode:abn.filter(a=>a.bc).length,inKap,inPm,costed},null,2));
console.log('wrote /tmp/ol-basis-decode.json');