← back to Designer Wallcoverings
fix luxury importer: nextNumber reads staging max (no SKU reuse) + mirror-repair destructure + boolean coercion
1b49549326075a9838971bcaf80696c4eb35b6e1 · 2026-07-09 20:25:52 -0700 · Steve
Files touched
M shopify/scripts/luxury-draft-import/import-luxury-drafts.js
Diff
commit 1b49549326075a9838971bcaf80696c4eb35b6e1
Author: Steve <steve@designerwallcoverings.com>
Date: Thu Jul 9 20:25:52 2026 -0700
fix luxury importer: nextNumber reads staging max (no SKU reuse) + mirror-repair destructure + boolean coercion
---
.../luxury-draft-import/import-luxury-drafts.js | 39 +++++++++++++++++++---
1 file changed, 34 insertions(+), 5 deletions(-)
diff --git a/shopify/scripts/luxury-draft-import/import-luxury-drafts.js b/shopify/scripts/luxury-draft-import/import-luxury-drafts.js
index 0c110b7b..ef19bca8 100644
--- a/shopify/scripts/luxury-draft-import/import-luxury-drafts.js
+++ b/shopify/scripts/luxury-draft-import/import-luxury-drafts.js
@@ -117,13 +117,16 @@ mutation ps($input: ProductSetInput!) {
}
}`;
-async function nextNumber(prefix) {
- // highest existing suffix in registry OR shopify_products, +1; fresh lines start at 100001
+async function nextNumber(prefix, table) {
+ // highest existing suffix across registry, shopify_products, AND the staging table, +1.
+ // Staging MUST be included — a stamped-but-unmirrored row would otherwise let the number be reused. (bug fix 2026-07-09)
const reg = psql(`SELECT COALESCE(MAX((regexp_replace(dw_sku,'^${prefix}-?',''))::int),0)
FROM dw_sku_registry WHERE dw_sku ~ '^${prefix}-?[0-9]+$'`) || '0';
const shp = psql(`SELECT COALESCE(MAX((regexp_replace(sku,'^${prefix}-?','','i'))::int),0)
FROM shopify_products WHERE sku ~* '^${prefix}-?[0-9]+$'`) || '0';
- const hi = Math.max(parseInt(reg, 10) || 0, parseInt(shp, 10) || 0);
+ const stg = psql(`SELECT COALESCE(MAX((regexp_replace(dw_sku,'^${prefix}-?',''))::int),0)
+ FROM ${table} WHERE dw_sku ~ '^${prefix}-?[0-9]+$'`) || '0';
+ const hi = Math.max(parseInt(reg, 10) || 0, parseInt(shp, 10) || 0, parseInt(stg, 10) || 0);
return hi >= 100000 ? hi + 1 : 100001; // fresh range
}
@@ -160,13 +163,39 @@ async function nextNumber(prefix) {
return;
}
- let num = await nextNumber(CFG.prefix);
+ // Mirror-repair: any staging row already stamped (dw_sku + shopify_product_id) but missing from
+ // shopify_products (e.g. a prior run created the Shopify product but the mirror INSERT failed).
+ const orphans = psql(`SELECT s.id, s.dw_sku, s.shopify_product_id, s.mfr_sku, s.pattern_name
+ FROM ${CFG.table} s
+ WHERE s.dw_sku IS NOT NULL AND s.shopify_product_id IS NOT NULL
+ AND NOT EXISTS (SELECT 1 FROM shopify_products p WHERE p.shopify_id = s.shopify_product_id)`)
+ .split('\n').filter(Boolean);
+ if (orphans.length) {
+ console.log(`Mirror-repair: ${orphans.length} stamped rows missing from shopify_products — re-syncing from live Shopify.`);
+ for (const line of orphans) {
+ const [, dw, pid, mfr, pat] = line.split('\x1f'); // cols: id, dw_sku, shopify_product_id, mfr_sku, pattern_name
+ const rr = await gql(`{ product(id:"gid://shopify/Product/${pid}") { handle title status vendor productType tags bodyHtml featuredImage{url} } }`);
+ const p = rr?.data?.product;
+ if (!p) { console.log(` ✗ live product ${pid} not found for ${dw}`); continue; }
+ psql(`INSERT INTO shopify_products
+ (shopify_id, handle, title, vendor, product_type, sku, dw_sku, mfr_sku, vendor_prefix,
+ tags, status, image_url, pattern_name, body_html, has_sample_variant, synced_at)
+ VALUES ('${q(pid)}','${q(p.handle)}','${q(p.title)}','${q(p.vendor)}','${q(p.productType)}',
+ '${q(dw)}','${q(dw)}','${q(mfr)}','${CFG.prefix}',
+ '${q((p.tags || []).join(', '))}','${q((p.status || 'DRAFT').toLowerCase())}',
+ '${q(p.featuredImage?.url || '')}','${q(pat || mfr)}','${q(p.bodyHtml || '')}', true, now())
+ ON CONFLICT DO NOTHING`);
+ console.log(` ✓ mirror-synced ${dw}`);
+ }
+ }
+
+ let num = await nextNumber(CFG.prefix, CFG.table);
console.log(`Starting SKU: ${CFG.prefix}-${num}\n`);
let ok = 0, fail = 0, batch = 0;
for (const r of work) {
const dwSku = `${CFG.prefix}-${num}`;
- const isPriced = CFG.priced && r.price && parseFloat(r.price) > 0;
+ const isPriced = !!(CFG.priced && r.price && parseFloat(r.price) > 0);
const isQuote = !isPriced;
const title = buildTitle(r);
if (/unknown/i.test(title)) { console.log(` ✗ SKIP (Unknown in title): ${r.mfr_sku}`); fail++; continue; }
← 217795cb add luxury-line DRAFT importer (Fromental/Gracie/Zuber, quot
·
back to Designer Wallcoverings
·
auto-save: 2026-07-09T20:42:07 (53 files) — DW-Programming/I 1566feb7 →