← back to Tk 10965 Zero Price Analysis

evidence/tk10965_vendors.mjs

20 lines

import fs from 'node:fs';
const env=fs.readFileSync('/Users/macstudio3/Projects/secrets-manager/.env','utf8');
const val=k=>(env.match(new RegExp('^'+k+'=(.*)$','m'))||[])[1]?.trim();
const DOM=val('SHOPIFY_STORE_DOMAIN'), TOK=val('SHOPIFY_ADMIN_TOKEN');
const API=`https://${DOM}/admin/api/2024-10/graphql.json`;
async function gql(q,v){for(let a=0;a<8;a++){const r=await fetch(API,{method:'POST',headers:{'X-Shopify-Access-Token':TOK,'Content-Type':'application/json'},body:JSON.stringify({query:q,variables:v})});const j=await r.json();if(j.errors){if(JSON.stringify(j.errors).includes('THROTTLED')){await new Promise(s=>setTimeout(s,1800*(a+1)));continue;}throw new Error(JSON.stringify(j.errors));}return j.data;}throw new Error('retries');}
async function scanVendor(vendor){
  let after=null,pages=0,n=0,bad=0,q2026=0,hasQO=0;
  do{ const d=await gql(`query($q:String!,$after:String){products(first:100,query:$q,after:$after){pageInfo{hasNextPage endCursor} nodes{id tags variants(first:20){nodes{title price availableForSale inventoryQuantity}}}}}`,{q:`status:active AND vendor:'${vendor}'`,after});
    for(const p of d.products.nodes){ n++;
      const qo=p.tags.some(t=>/^quote[-_ ]?only$/i.test(t));
      for(const v of p.variants.nodes){ if(!/sample/i.test(v.title||'')&&Number(v.price)===0&&v.availableForSale===true){bad++; if(v.inventoryQuantity===2026)q2026++; if(qo)hasQO++; break;} }
    }
    after=d.products.pageInfo.hasNextPage?d.products.pageInfo.endCursor:null; pages++;
  }while(after&&pages<80);
  console.log(`${vendor}: active=${n} $0-orderable=${bad} qty2026=${q2026} taggedQuoteOnly=${hasQO}`);
  return {vendor,active:n,bad,q2026,hasQO};
}
for(const v of ['Fentucci Naturals','Phillipe Romano','De Gournay','Justin David','Command54']) await scanVendor(v);