[object Object]

← back to Designerwallcoverings

TK-00060: register Maharam SKUs in dw_sku_registry (create-drafts + go-live) — stops orphan-publish-guard mis-drafting them

ec8a6c6b71ef215cb581f87d8f3d4f737a5acdf9 · 2026-08-12 07:57:40 -0700 · Steve Abrams

The Maharam onboard was the only sample-only line that never registered its SKUs in
dw_sku_registry (stout/stroheim/muralsource all do). create-drafts' dbWriteBack only
UPDATEd maharam_catalog, and go-live's did a bare UPDATE dw_sku_registry WHERE dw_sku=
that hit 0 rows — so the shopify_products mirror carried no real dw_sku for these, and
orphan-publish-guard.mjs (fingerprint: mfr_sku=upper(handle) AND no-real-dw_sku)
mis-classified them as slug-SKU sample-only orphans and --enforce drafted 62 off the
live storefront (app '81026 API', 2026-08-11 06:36). Now both write-backs UPSERT the
DWAX registry row (create=draft, go-live=active) with real mfr_sku, mirroring the proven
stout pattern. Backfill of the 1429 already-onboarded SKUs applied separately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit ec8a6c6b71ef215cb581f87d8f3d4f737a5acdf9
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Aug 12 07:57:40 2026 -0700

    TK-00060: register Maharam SKUs in dw_sku_registry (create-drafts + go-live) — stops orphan-publish-guard mis-drafting them
    
    The Maharam onboard was the only sample-only line that never registered its SKUs in
    dw_sku_registry (stout/stroheim/muralsource all do). create-drafts' dbWriteBack only
    UPDATEd maharam_catalog, and go-live's did a bare UPDATE dw_sku_registry WHERE dw_sku=
    that hit 0 rows — so the shopify_products mirror carried no real dw_sku for these, and
    orphan-publish-guard.mjs (fingerprint: mfr_sku=upper(handle) AND no-real-dw_sku)
    mis-classified them as slug-SKU sample-only orphans and --enforce drafted 62 off the
    live storefront (app '81026 API', 2026-08-11 06:36). Now both write-backs UPSERT the
    DWAX registry row (create=draft, go-live=active) with real mfr_sku, mirroring the proven
    stout pattern. Backfill of the 1429 already-onboarded SKUs applied separately.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 scripts/maharam-onboard/create-drafts.mjs | 14 +++++++++++---
 scripts/maharam-onboard/go-live.mjs       | 20 +++++++++++++-------
 2 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/scripts/maharam-onboard/create-drafts.mjs b/scripts/maharam-onboard/create-drafts.mjs
index 7a14ba6..4e11adc 100644
--- a/scripts/maharam-onboard/create-drafts.mjs
+++ b/scripts/maharam-onboard/create-drafts.mjs
@@ -37,11 +37,19 @@ const loadJsonl = f => fs.existsSync(path.join(OUT, f))
   ? fs.readFileSync(path.join(OUT, f), 'utf8').trim().split('\n').filter(Boolean).map(l => JSON.parse(l)) : [];
 
 // PG-FIRST write-back: stamp the real product_id onto the staging row immediately.
-function dbWriteBack(sku, pid) {
+function dbWriteBack(sku, pid, mfrSku) {
   const safePid = String(parseInt(pid, 10));                       // numeric-only (Shopify id) — safety belt
+  const q = sku.replace(/'/g, "''"), mq = String(mfrSku || '').replace(/'/g, "''");
   try {
     execFileSync(PSQL, ['-d', 'dw_unified', '-c',
-      `UPDATE maharam_catalog SET shopify_product_id='${safePid}', updated_at=NOW() WHERE dw_sku='${sku.replace(/'/g, "''")}';`],
+      // Stamp the pid onto staging AND REGISTER the DWAX sku in dw_sku_registry (status=draft) — the SKUs
+      // are pre-assigned in maharam_catalog but were NEVER registered, so the shopify_products mirror
+      // carried no real dw_sku and orphan-publish-guard mis-drafted them as slug-SKU orphans (TK-00060).
+      // Mirrors the proven stout/stroheim/muralsource onboard pattern; go-live flips the row to active.
+      `UPDATE maharam_catalog SET shopify_product_id='${safePid}', updated_at=NOW() WHERE dw_sku='${q}';
+       INSERT INTO dw_sku_registry (dw_sku, vendor_prefix, vendor_name, mfr_sku, shopify_product_id, status, min_order_qty, order_increment, created_at, updated_at)
+       VALUES ('${q}','DWAX','Maharam','${mq}','${safePid}','draft',1,1,NOW(),NOW())
+       ON CONFLICT (dw_sku) DO UPDATE SET shopify_product_id=EXCLUDED.shopify_product_id, mfr_sku=EXCLUDED.mfr_sku, updated_at=NOW();`],
       { env: PGENV, stdio: 'ignore' });
   } catch (e) { console.error(`  ⚠ dbWriteBack ${sku}: ${String(e.message || e).slice(0, 120)}`); } // non-fatal but VISIBLE — created.jsonl is durable, go-live re-writes
 }
@@ -92,7 +100,7 @@ async function main() {
       const body = await res.json().catch(() => ({}));
       if (res.status === 201 && body?.product?.id) {
         const pid = body.product.id;
-        dbWriteBack(o.sku, pid);                                   // PG-FIRST
+        dbWriteBack(o.sku, pid, o.mfr_sku);                        // PG-FIRST (+ registry register)
         if (o.metafields.length) {
           const gid = `gid://shopify/Product/${pid}`;
           const d = await gql(M_MF, { mf: o.metafields.map(m => ({ ownerId: gid, namespace: m.namespace, key: m.key, type: m.type, value: m.value })) });
diff --git a/scripts/maharam-onboard/go-live.mjs b/scripts/maharam-onboard/go-live.mjs
index 5e16768..32ba632 100644
--- a/scripts/maharam-onboard/go-live.mjs
+++ b/scripts/maharam-onboard/go-live.mjs
@@ -45,24 +45,30 @@ const M_SETQTY = `mutation($input:InventorySetQuantitiesInput!){ inventorySetQua
 const M_PUBLISH = `mutation($id:ID!,$pubs:[PublicationInput!]!){ publishablePublish(id:$id, input:$pubs){ userErrors{message} } }`;
 const M_ACTIVE = `mutation($id:ID!){ productUpdate(input:{id:$id, status:ACTIVE}){ product{status} userErrors{message} } }`;
 
-function dbWriteBack(sku, pid, handle) {
+function dbWriteBack(sku, pid, handle, mfrSku) {
   const safePid = String(parseInt(pid, 10));                       // numeric-only (Shopify id)
   const safeHandle = /^[a-z0-9-]+$/.test(handle || '') ? handle : null;  // slug-safe or NULL
-  const s = sku.replace(/'/g, "''");
+  const s = sku.replace(/'/g, "''"), mq = String(mfrSku || '').replace(/'/g, "''");
   try {
     execFileSync(PSQL, ['-d', 'dw_unified', '-c',
+      // UPSERT (not bare UPDATE) so go-live self-heals registration: create-drafts registers at mint,
+      // but if that row is missing (e.g. the pre-fix backlog) this INSERTs it, else flips it to active.
+      // Without a registered dw_sku the shopify_products mirror carried no real dw_sku and
+      // orphan-publish-guard mis-drafted these as slug-SKU orphans (TK-00060).
       `UPDATE maharam_catalog SET shopify_product_id='${safePid}', updated_at=NOW() WHERE dw_sku='${s}';
-       UPDATE dw_sku_registry SET shopify_product_id='${safePid}', shopify_handle=${safeHandle ? `'${safeHandle}'` : 'NULL'}, status='active', updated_at=NOW() WHERE dw_sku='${s}';`],
+       INSERT INTO dw_sku_registry (dw_sku, vendor_prefix, vendor_name, mfr_sku, shopify_product_id, shopify_handle, status, min_order_qty, order_increment, created_at, updated_at)
+       VALUES ('${s}','DWAX','Maharam','${mq}','${safePid}',${safeHandle ? `'${safeHandle}'` : 'NULL'},'active',1,1,NOW(),NOW())
+       ON CONFLICT (dw_sku) DO UPDATE SET shopify_product_id=EXCLUDED.shopify_product_id, shopify_handle=COALESCE(EXCLUDED.shopify_handle, dw_sku_registry.shopify_handle), mfr_sku=COALESCE(NULLIF(EXCLUDED.mfr_sku,''), dw_sku_registry.mfr_sku), status='active', updated_at=NOW();`],
       { env: PGENV, stdio: 'ignore' });
   } catch (e) { console.error(`  ⚠ dbWriteBack ${sku}: ${String(e.message || e).slice(0, 120)}`); } // non-fatal but VISIBLE — Shopify write is authoritative; mirror re-syncs
 }
 
-async function goLive(pid, sku) {
+async function goLive(pid, sku, mfrSku) {
   const gidP = `gid://shopify/Product/${pid}`;
   const errs = [];
   const d = await gql(Q_VARIANTS, { id: gidP });
   if (!d?.product) return { missing: true };
-  if (d.product.status === 'ACTIVE') { dbWriteBack(sku, pid, d.product.handle); return { skipped: true }; }
+  if (d.product.status === 'ACTIVE') { dbWriteBack(sku, pid, d.product.handle, mfrSku); return { skipped: true }; }
   const items = d.product.variants.edges.map(e => e.node.inventoryItem.id);
   for (const iid of items) {
     let r = await gql(M_TRACK, { id: iid }); (r.inventoryItemUpdate?.userErrors || []).forEach(e => errs.push('track:' + e.message));
@@ -84,7 +90,7 @@ async function goLive(pid, sku) {
   const r4 = await gql(M_ACTIVE, { id: gidP });
   (r4.productUpdate?.userErrors || []).forEach(e => errs.push('active:' + e.message));
   const status = r4.productUpdate?.product?.status;
-  if (status === 'ACTIVE') dbWriteBack(sku, pid, d.product.handle);
+  if (status === 'ACTIVE') dbWriteBack(sku, pid, d.product.handle, mfrSku);
   return { status, errs };
 }
 
@@ -105,7 +111,7 @@ function loadJsonl(file) {
   let ok = 0, skip = 0, withErr = 0, miss = 0;
   for (const r of todo) {
     try {
-      const res = await goLive(r.product_id, r.sku);
+      const res = await goLive(r.product_id, r.sku, r.mfr_sku);
       if (res.missing) { miss++; console.error(`  ? ${r.sku}: product not found`); }
       else if (res.skipped) skip++;
       else if (res.errs?.length) { withErr++; console.error(`  ⚠ ${r.sku} ${res.status||'?'}: ${res.errs.slice(0,3).join(' | ')}`); }

← b7ad7be auto-data-snapshot: 2026-08-12T07:20:53 (1 data files) — dat  ·  back to Designerwallcoverings  ·  chore: v0.1.7 (session close) — TK-00060 maharam registry fi 0e397e8 →