[object Object]

← back to Designer Wallcoverings

feat: add --below-cost mode to knoll-reprice.js (TK-10302 follow-up)

23966f88c6f2cd08f0ca7ec26091966e13d9edcf · 2026-08-09 04:12:10 -0700 · steve@designerwallcoverings.com

15 Knoll rolls (DWKN-250156-170: Drift/Drizzle/Elixir) are priced below cost
($29.50-$59 vs $53-$107 cost). The original at-cost mode skips them. New
--below-cost flag targets rolls where cur < cost and reprices to cost/0.65/0.85.
Steve-approved to add; `--commit` execution stays gated.

Files touched

Diff

commit 23966f88c6f2cd08f0ca7ec26091966e13d9edcf
Author: steve@designerwallcoverings.com <steve@designerwallcoverings.com>
Date:   Sun Aug 9 04:12:10 2026 -0700

    feat: add --below-cost mode to knoll-reprice.js (TK-10302 follow-up)
    
    15 Knoll rolls (DWKN-250156-170: Drift/Drizzle/Elixir) are priced below cost
    ($29.50-$59 vs $53-$107 cost). The original at-cost mode skips them. New
    --below-cost flag targets rolls where cur < cost and reprices to cost/0.65/0.85.
    Steve-approved to add; `--commit` execution stays gated.
---
 shopify/scripts/knoll-reprice.js | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/shopify/scripts/knoll-reprice.js b/shopify/scripts/knoll-reprice.js
index 302c5954..0f0c65d3 100644
--- a/shopify/scripts/knoll-reprice.js
+++ b/shopify/scripts/knoll-reprice.js
@@ -7,16 +7,19 @@
  * price ≈ its knoll_catalog cost (the bug signature). Any roll already priced != cost is
  * SKIPPED (never touched). Never touches the Sample variant. Target is always > current.
  *
- *   node knoll-reprice.js            # DRY (all)
- *   node knoll-reprice.js 3          # DRY, first 3 (canary preview)
- *   node knoll-reprice.js 3 --commit # CANARY: commit 3
- *   node knoll-reprice.js --commit   # commit all fixable
+ *   node knoll-reprice.js                      # DRY (at-cost mode, all)
+ *   node knoll-reprice.js 3                    # DRY, first 3 canary preview
+ *   node knoll-reprice.js 3 --commit           # CANARY: commit 3
+ *   node knoll-reprice.js --commit             # commit all at-cost fixable
+ *   node knoll-reprice.js --below-cost         # DRY: show rolls priced BELOW cost
+ *   node knoll-reprice.js --below-cost --commit # commit below-cost reprices (gated, Steve-approved)
  */
 const https = require('https'); const fs = require('fs'); const os = require('os');
 const { execFileSync } = require('child_process');
 const argN = process.argv.find(a => /^\d+$/.test(a));
 const N = argN ? parseInt(argN, 10) : Infinity;
 const COMMIT = process.argv.includes('--commit');
+const BELOW_COST_MODE = process.argv.includes('--below-cost');
 const SAMPLE = 4.25;
 const COST_TOL = 0.02;                        // current price must be within 2¢ of cost to qualify
 const TOKEN = (fs.readFileSync(os.homedir() + '/Projects/secrets-manager/.env', 'utf8').match(/^SHOPIFY_ADMIN_TOKEN=(.*)$/m) || [])[1].replace(/['"]/g, '').trim();
@@ -53,13 +56,21 @@ for (const line of psql("SELECT dw_sku, price_retail FROM knoll_catalog WHERE pr
     if (!cost) { nocost.push(roll.sku); continue; }
     const cur = parseFloat(roll.price);
     const target = Math.round((cost / 0.65 / 0.85) * 100) / 100;
-    if (Math.abs(cur - cost) <= COST_TOL && target > cur) fixable.push({ pid: n.id, roll, cost, cur, target, title: n.title });
-    else skip_priced.push({ sku: roll.sku, cur, cost });        // already != cost → leave alone
+    if (BELOW_COST_MODE) {
+      // below-cost mode: catch rolls where current price < cost (selling at a loss)
+      if (cur < cost - COST_TOL && target > cur) fixable.push({ pid: n.id, roll, cost, cur, target, title: n.title });
+      else skip_priced.push({ sku: roll.sku, cur, cost });
+    } else {
+      // default mode: catch rolls priced AT cost (importer bug)
+      if (Math.abs(cur - cost) <= COST_TOL && target > cur) fixable.push({ pid: n.id, roll, cost, cur, target, title: n.title });
+      else skip_priced.push({ sku: roll.sku, cur, cost });
+    }
   }
   const list = Number.isFinite(N) ? fixable.slice(0, N) : fixable;
-  console.log(`fixable (roll priced at cost) ${fixable.length} | skip already-repriced/other ${skip_priced.length} | no-cost ${nocost.length}`);
-  list.slice(0, 6).forEach(t => console.log(`   ${t.roll.sku}  $${t.cur} (cost) → $${t.target}   ${t.title.slice(0,38)}`));
-  if (skip_priced.length) console.log(`   e.g. skipped: ${skip_priced.slice(0,4).map(s=>s.sku+'@$'+s.cur).join(', ')}`);
+  const modeLabel = BELOW_COST_MODE ? 'roll priced BELOW cost' : 'roll priced at cost';
+  console.log(`fixable (${modeLabel}) ${fixable.length} | skip ${skip_priced.length} | no-cost ${nocost.length}`);
+  list.slice(0, 6).forEach(t => console.log(`   ${t.roll.sku}  $${t.cur} (cur, cost $${t.cost}) → $${t.target}   ${t.title.slice(0,38)}`));
+  if (skip_priced.length && !BELOW_COST_MODE) console.log(`   e.g. skipped: ${skip_priced.slice(0,4).map(s=>s.sku+'@$'+s.cur).join(', ')}`);
   if (!COMMIT) { console.log(`\nDRY — --commit will reprice ${list.length} roll variants (Sample untouched).`); return; }
 
   const M = `mutation($pid:ID!,$variants:[ProductVariantsBulkInput!]!){productVariantsBulkUpdate(productId:$pid,variants:$variants){userErrors{field message}}}`;

← 3d75135e auto-data-snapshot: 2026-08-09T03:04:53 (3 data files) — DW-  ·  back to Designer Wallcoverings  ·  auto-data-snapshot: 2026-08-09T06:41:43 (1 data files) — sho 590c1c47 →