← 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
M scripts/maharam-onboard/create-drafts.mjsM scripts/maharam-onboard/go-live.mjs
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 →