← back to Mfr Recovery 2026 08 23
zoffany durable mfr recovery builder + guarded apply/restore (TK-10677)
654c25eaf254e5406053164a54a5990a0ae20956 · 2026-08-25 08:08:39 -0700 · Steve
Files touched
A build-zoffany-durable.mjs
Diff
commit 654c25eaf254e5406053164a54a5990a0ae20956
Author: Steve <steve@designerwallcoverings.com>
Date: Tue Aug 25 08:08:39 2026 -0700
zoffany durable mfr recovery builder + guarded apply/restore (TK-10677)
---
build-zoffany-durable.mjs | 69 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/build-zoffany-durable.mjs b/build-zoffany-durable.mjs
new file mode 100644
index 0000000..fb0113b
--- /dev/null
+++ b/build-zoffany-durable.mjs
@@ -0,0 +1,69 @@
+#!/usr/bin/env node
+// Durable Zoffany mfr_sku recovery builder (TK-10677) — 2026-08-25
+// Reads the verified CSV and emits:
+// 1. zoffany_durable_apply.sql — idempotent, guarded, transactional UPDATE-by-handle (runs on Kamatera canonical AND Mac2 mirror)
+// 2. zoffany_restore.sql — reversible undo (sets the 24 mfr_sku back to '')
+// 3. prints the exact fire commands
+// This script only WRITES LOCAL FILES — no DB write, no network. Safe/reversible/$0.
+import fs from 'node:fs';
+import path from 'node:path';
+
+const DIR = path.dirname(new URL(import.meta.url).pathname);
+const csv = fs.readFileSync(path.join(DIR, 'zoffany_24_verified_20260824.csv'), 'utf8').trim().split('\n');
+const header = csv[0].split(',');
+const iHandle = header.indexOf('handle'), iMfr = header.indexOf('mfr_sku'), iDw = header.indexOf('dw_sku');
+const rows = csv.slice(1).map(l => { const c = l.split(','); return { handle: c[iHandle], mfr: c[iMfr], dw: c[iDw] }; });
+
+// sanity: every row has a plausible mfr code + handle
+const bad = rows.filter(r => !r.handle || !/^Z[A-Z]{2,4}\d{4,6}$/.test(r.mfr));
+if (bad.length) { console.error('REFUSING — malformed rows:', bad); process.exit(1); }
+if (rows.length !== 24) { console.error(`REFUSING — expected 24 rows, got ${rows.length}`); process.exit(1); }
+
+const esc = s => "'" + String(s).replace(/'/g, "''") + "'";
+const values = rows.map(r => ` (${esc(r.handle)}, ${esc(r.mfr)})`).join(',\n');
+const mfrList = rows.map(r => esc(r.mfr)).join(',');
+
+const applySql = `-- DURABLE Zoffany mfr_sku recovery — TK-10677 — generated 2026-08-25
+-- Runs identically on Kamatera-canonical dw_unified AND the Mac2 mirror.
+-- IDEMPOTENT + GUARDED: only fills rows that are still null/empty, only these 24 handles, only ACTIVE Zoffany.
+-- A re-run after success updates 0 rows. Reversible via zoffany_restore.sql.
+BEGIN;
+
+WITH recover(handle, mfr_sku) AS (
+ VALUES
+${values}
+)
+UPDATE shopify_products sp
+SET mfr_sku = r.mfr_sku
+FROM recover r
+WHERE sp.handle = r.handle
+ AND sp.vendor = 'Zoffany'
+ AND sp.status = 'ACTIVE'
+ AND (sp.mfr_sku IS NULL OR sp.mfr_sku = '');
+
+-- verify: how many of the 24 target handles now carry their mfr code
+SELECT count(*) AS zoffany_with_mfr_now
+FROM shopify_products
+WHERE vendor='Zoffany' AND status='ACTIVE' AND mfr_sku IN (${mfrList});
+
+COMMIT;
+`;
+
+const restoreSql = `-- REVERSIBLE UNDO for the durable Zoffany mfr recovery — TK-10677
+-- Sets the 24 recovered mfr_sku back to '' (only rows that currently hold exactly these codes).
+BEGIN;
+UPDATE shopify_products
+SET mfr_sku = ''
+WHERE vendor='Zoffany' AND status='ACTIVE' AND mfr_sku IN (${mfrList});
+COMMIT;
+`;
+
+fs.writeFileSync(path.join(DIR, 'zoffany_durable_apply.sql'), applySql);
+fs.writeFileSync(path.join(DIR, 'zoffany_restore.sql'), restoreSql);
+// restore-map JSON (handle -> recovered mfr, for the ledger)
+fs.writeFileSync(path.join(DIR, 'zoffany_restore_map.json'),
+ JSON.stringify({ ticket: 'TK-10677', generated: '2026-08-25', undo: "SET mfr_sku='' for the listed mfr codes", rows }, null, 2));
+
+console.log(`Built durable apply for ${rows.length} Zoffany products.`);
+console.log('Files: zoffany_durable_apply.sql, zoffany_restore.sql, zoffany_restore_map.json');
+console.log('Sample:', rows[0].handle, '->', rows[0].mfr);
← 8836003 auto-data-snapshot: 2026-08-25T07:39:06 (3 data files) — zof
·
back to Mfr Recovery 2026 08 23
·
TK-10829 Novasuede mfr recovery: authoritative novasuede.com ed86664 →