[object Object]

← back to Sister Parish Onboarding

auto-save: 2026-06-21T18:53:00 (1 files) — scripts/_deep-probe.js

16193e692ea2bff047265f5dfbd16035d864e151 · 2026-06-21 18:53:03 -0700 · Steve Abrams

Files touched

Diff

commit 16193e692ea2bff047265f5dfbd16035d864e151
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sun Jun 21 18:53:03 2026 -0700

    auto-save: 2026-06-21T18:53:00 (1 files) — scripts/_deep-probe.js
---
 scripts/_deep-probe.js | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/scripts/_deep-probe.js b/scripts/_deep-probe.js
new file mode 100644
index 0000000..95917b8
--- /dev/null
+++ b/scripts/_deep-probe.js
@@ -0,0 +1,63 @@
+// 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}`)
+  );
+})();

← f1ec46d broaden .gitignore to exclude .bak/.pre-* snapshot files and  ·  back to Sister Parish Onboarding  ·  chore: macstudio3 migration — reconcile from mac2 + repoint e058c64 →