← 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 →