[object Object]

← back to Designerwallcoverings

WM reprice: add one-command revert.mjs (restores old prices from restore-map, TK-11814)

c7cb7c832477e6686578a47acffc481d7ea34be9 · 2026-09-16 08:55:17 -0700 · Steve Abrams

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DsSmHLJqGWrvjf65UNVQx

Files touched

Diff

commit c7cb7c832477e6686578a47acffc481d7ea34be9
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 16 08:55:17 2026 -0700

    WM reprice: add one-command revert.mjs (restores old prices from restore-map, TK-11814)
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_017DsSmHLJqGWrvjf65UNVQx
---
 scripts/wm-reprice/revert.mjs | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/scripts/wm-reprice/revert.mjs b/scripts/wm-reprice/revert.mjs
new file mode 100644
index 0000000..dff88e7
--- /dev/null
+++ b/scripts/wm-reprice/revert.mjs
@@ -0,0 +1,34 @@
+/* TK-11814 — REVERT the William Morris live reprice.
+   Reads scripts/wm-reprice/restore-map.csv (variant_gid,sku,old_price,new_price) and writes
+   every variant's OLD price back via productVariantsBulkUpdate. DRY by default; APPLY=1 writes.
+   This is the one-command undo referenced in the executed-reversible ledger.                */
+import fs from 'node:fs';
+import { gql } from '../lib/shopify.mjs';
+
+const APPLY = process.env.APPLY === '1';
+const DIR = new URL('.', import.meta.url).pathname;
+const rows = fs.readFileSync(DIR + 'restore-map.csv', 'utf8').trim().split('\n').slice(1).map(l => {
+  const [vgid, sku, oldp, newp] = l.split(',');
+  return { vgid, sku, oldp: +oldp, newp: +newp };
+});
+const MUT = `mutation($pid:ID!,$variants:[ProductVariantsBulkInput!]!){ productVariantsBulkUpdate(productId:$pid,variants:$variants){ productVariants{ id price } userErrors{ field message } } }`;
+
+(async () => {
+  console.log(`MODE: ${APPLY ? 'APPLY (reverting live)' : 'DRY (no writes — set APPLY=1)'} | variants: ${rows.length}\n`);
+  const byPid = {};
+  for (const r of rows) {
+    const d = await gql(`{ productVariant(id:"${r.vgid}"){ price product{ id } } }`);
+    const pid = d?.productVariant?.product?.id;
+    if (!pid) { console.error(`  skip ${r.sku}: not found`); continue; }
+    (byPid[pid] ||= []).push(r);
+  }
+  if (!APPLY) { console.log(`DRY: would restore ${rows.length} variants to their old prices. Re-run APPLY=1.`); return; }
+  let wrote = 0, err = 0;
+  for (const [pid, vs] of Object.entries(byPid)) {
+    const r = await gql(MUT, { pid, variants: vs.map(v => ({ id: v.vgid, price: String(v.oldp) })) });
+    const ue = r?.productVariantsBulkUpdate?.userErrors || [];
+    if (ue.length) { err += vs.length; console.error(`  ERR ${pid}: ${JSON.stringify(ue)}`); continue; }
+    wrote += (r.productVariantsBulkUpdate.productVariants || []).length;
+  }
+  console.log(`\n=== REVERTED === wrote:${wrote} err:${err}`);
+})();

← 41d4d1e WM reprice: 375 William Morris products to cost/0.65/0.85 (+  ·  back to Designerwallcoverings  ·  auto-data-snapshot: 2026-09-16T09:33:20 (1 data files) — dat 6eab755 →