← back to Wolfgordon Crawl
push: publish ACTIVE products to ALL channels + set inventory 2026 on activation
f41202103d217b949e061724b10dcf977a8589d3 · 2026-06-20 04:02:03 -0700 · Steve
Mirrors cadence-import.js (Steve 2026-06-20, activation-all-channels-and-2026-inventory).
publish() now publishes to ALL publications (was Online Store only — the bug that left
419 active WG products on ~6/13 channels); setInventory2026() sets on_hand=2026 at
Ventura Blvd on the sellable variant after activation. Both cap-free + idempotent.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Files touched
Diff
commit f41202103d217b949e061724b10dcf977a8589d3
Author: Steve <steve@designerwallcoverings.com>
Date: Sat Jun 20 04:02:03 2026 -0700
push: publish ACTIVE products to ALL channels + set inventory 2026 on activation
Mirrors cadence-import.js (Steve 2026-06-20, activation-all-channels-and-2026-inventory).
publish() now publishes to ALL publications (was Online Store only — the bug that left
419 active WG products on ~6/13 channels); setInventory2026() sets on_hand=2026 at
Ventura Blvd on the sellable variant after activation. Both cap-free + idempotent.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---
push-shopify.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 46 insertions(+), 8 deletions(-)
diff --git a/push-shopify.js b/push-shopify.js
index 44d8d41..7b270eb 100644
--- a/push-shopify.js
+++ b/push-shopify.js
@@ -408,24 +408,62 @@ async function createProduct(row, { draft } = {}) {
const ue = data.productSet.userErrors;
if (ue && ue.length) throw new Error('productSet: ' + JSON.stringify(ue));
const prod = data.productSet.product;
- if (!isDraft) await publish(prod.id);
+ if (!isDraft) {
+ // Steve 2026-06-20 (memory activation-all-channels-and-2026-inventory): every
+ // ACTIVE product must be published to ALL sales channels AND carry inventory
+ // 2026 at Ventura Blvd on its sellable variant. Mirrors cadence-import.js.
+ await publish(prod.id); // ALL channels (was: Online Store only)
+ await setInventory2026([row.dw_sku]); // on_hand=2026 on the sellable (non-Sample) variant
+ }
await recordPid(row.mfr_sku, prod.id.split('/').pop());
return prod;
}
-// Publish a product to the Online Store sales channel.
+// Publish a product to ALL sales channels (was: Online Store only — the bug that
+// left 419 active WG products on ~6 of 13 channels). "already published" userErrors
+// are benign. Copies cadence-import.js publishToChannels().
+let _PUBLICATION_IDS = null;
+async function loadPublications() {
+ if (_PUBLICATION_IDS) return _PUBLICATION_IDS;
+ const r = await gql(`{ publications(first:50){ edges{ node{ id name } } } }`);
+ _PUBLICATION_IDS = (r.publications?.edges || []).map(e => e.node);
+ return _PUBLICATION_IDS;
+}
async function publish(productId) {
try {
- const pubs = await gql(`{ publications(first:10){ edges{ node{ id name } } } }`);
- const online = pubs.publications.edges.find(e => /online store/i.test(e.node.name));
- if (!online) return;
+ const pubs = await loadPublications();
+ if (!pubs.length) return;
+ const input = pubs.map(p => ({ publicationId: p.id }));
await gql(`
- mutation($id:ID!,$pid:ID!){
- publishablePublish(id:$id, input:{ publicationId:$pid }){ userErrors{ message } }
- }`, { id: productId, pid: online.node.id });
+ mutation($id:ID!,$input:[PublicationInput!]!){
+ publishablePublish(id:$id, input:$input){ userErrors{ field message } }
+ }`, { id: productId, input });
} catch (e) { console.error(' publish warn:', e.message); }
}
+// Inventory on_hand=2026 at the Ventura Blvd location on the given (sellable) SKUs.
+// Cap-free (touches existing variants). Copies cadence-import.js setInventory2026().
+const INV_LOCATION_2026 = 'gid://shopify/Location/5795643504'; // 15442 Ventura Blvd.
+async function setInventory2026(skus) {
+ if (!skus.length) return;
+ try {
+ const map = new Map();
+ for (let i = 0; i < skus.length; i += 40) {
+ const batch = skus.slice(i, i + 40);
+ const q = batch.map(s => `sku:"${String(s).replace(/"/g, '\\"')}"`).join(' OR ');
+ const r = await gql(`query($q:String!){ productVariants(first:250,query:$q){ edges{ node{ sku inventoryItem{ id } } } } }`, { q });
+ for (const e of (r.productVariants?.edges || [])) {
+ if (e.node.sku && e.node.inventoryItem?.id) map.set(e.node.sku, e.node.inventoryItem.id);
+ }
+ }
+ const pairs = skus.filter(s => map.has(s)).map(s => ({ inventoryItemId: map.get(s), locationId: INV_LOCATION_2026, quantity: 2026 }));
+ for (let i = 0; i < pairs.length; i += 250) {
+ await gql(`mutation($input:InventorySetQuantitiesInput!){ inventorySetQuantities(input:$input){ userErrors{ field message code } } }`,
+ { input: { name: 'on_hand', reason: 'correction', ignoreCompareQuantity: true, quantities: pairs.slice(i, i + 250) } });
+ }
+ } catch (e) { console.error(' inventory-2026 warn:', e.message); }
+}
+
// UPDATE: fix the $4.25 placeholder -> catalog retail price + replace SKU with
// the sequential DW SKU. Images ADD-only (never delete).
async function updateProduct(item) {
← 2fe399e Wire net-new pusher to shared variant-budget ledger + kill-s
·
back to Wolfgordon Crawl
·
chore: macstudio3 migration — reconcile from mac2 + repoint 6e1cabb →