← back to Sister Parish Onboarding

scripts/_deep-probe.js

64 lines

// Per-variant per-location inventory probe. Surfaces variants where:
//  - inventory is tracked at >1 location (Shopify admin SUMS across locations)
//  - inventory_management is null (not tracked at all)
//  - any single location is not at 2026
// This is the "what does the Shopify admin actually display" view.

require('dotenv').config({ path: __dirname + '/../.env' });
const STORE = process.env.SHOPIFY_STORE || 'designer-laboratory-sandbox';
const TOK   = process.env.SHOPIFY_ADMIN_TOKEN;
const API   = `https://${STORE}/admin/api/2026-01`;

async function call(path) {
  const r = await fetch(`${API}${path}`, { headers: { 'X-Shopify-Access-Token': TOK } });
  if (!r.ok) throw new Error(`${path} → ${r.status} ${await r.text()}`);
  return r.json();
}

(async () => {
  console.log('Fetching ALL Sister Parish products...');
  let cursor = '';
  let products = [];
  while (true) {
    const url = `/products.json?vendor=Sister%20Parish&limit=250&status=active${cursor}`.replace(/${cursor}`;status=any/, "");
    const j = await call(url);
    products = products.concat(j.products);
    if (j.products.length < 250) break;
    const last = j.products[j.products.length - 1].id;
    cursor = `&since_id=${last}`;
  }
  console.log(`  fetched ${products.length} products`);

  let totalVariants = 0, multiLoc = 0, notTracked = 0, offTarget = [];
  let totalInventoryAcrossLocations = {};

  for (const p of products) {
    for (const v of p.variants) {
      totalVariants++;
      if (!v.inventory_management) { notTracked++; continue; }
      // Get all locations for this inventory item
      const inv = await call(`/inventory_levels.json?inventory_item_ids=${v.inventory_item_id}`);
      const levels = inv.inventory_levels || [];
      if (levels.length > 1) multiLoc++;
      const sum = levels.reduce((s,l) => s + (l.available || 0), 0);
      const summary = levels.map(l => `${l.location_id}=${l.available}`).join(' ');
      totalInventoryAcrossLocations[`${p.title} (${v.sku})`] = { sum, summary, locs: levels.length };
      if (sum !== 2026) offTarget.push({ sku: v.sku, product: p.title, sum, summary });
      await new Promise(r => setTimeout(r, 350));
    }
  }
  console.log(`\nresults across all ${totalVariants} variants:`);
  console.log(`  multi-location  : ${multiLoc}`);
  console.log(`  not tracked     : ${notTracked}`);
  console.log(`  sum != 2026     : ${offTarget.length}`);
  if (offTarget.length) {
    console.log(`\noff-target details:`);
    offTarget.slice(0, 10).forEach(o => console.log(`  ${o.sku.padEnd(15)} sum=${String(o.sum).padStart(6)}  ${o.summary}  — ${o.product}`));
  }
  // Spot-check the first 3 — what does Shopify *show* the admin user
  console.log(`\nspot-check first 3 variants — exact location-level data:`);
  Object.entries(totalInventoryAcrossLocations).slice(0, 3).forEach(([k, v]) =>
    console.log(`  ${k.padEnd(50)} sum=${v.sum}  locs=${v.locs}  raw=${v.summary}`)
  );
})();