← back to Designer Wallcoverings
kravet25-reactivate: reprice before activate to close $0-orderable-ACTIVE window
89429b051d67b7ca183f9829b3790c5df3328739 · 2026-09-18 13:09:52 -0700 · Steve
On a reprice userError the loop previously left the product ACTIVE at its
prior (possibly $0) price. Reorder so reprice happens first and a reprice
failure continues before ACTIVATE — a reprice failure can no longer produce a
$0-orderable ACTIVE product. Fixes TK-11911 review finding 2.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJ5w7swHA8QqX7KwJ6vuXJ
Files touched
M shopify/scripts/data/kravet-map-pricing/kravet25-reactivate.js
Diff
commit 89429b051d67b7ca183f9829b3790c5df3328739
Author: Steve <steve@designerwallcoverings.com>
Date: Fri Sep 18 13:09:52 2026 -0700
kravet25-reactivate: reprice before activate to close $0-orderable-ACTIVE window
On a reprice userError the loop previously left the product ACTIVE at its
prior (possibly $0) price. Reorder so reprice happens first and a reprice
failure continues before ACTIVATE — a reprice failure can no longer produce a
$0-orderable ACTIVE product. Fixes TK-11911 review finding 2.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJ5w7swHA8QqX7KwJ6vuXJ
---
.../data/kravet-map-pricing/kravet25-reactivate.js | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/shopify/scripts/data/kravet-map-pricing/kravet25-reactivate.js b/shopify/scripts/data/kravet-map-pricing/kravet25-reactivate.js
index dae085f3..7ed31949 100644
--- a/shopify/scripts/data/kravet-map-pricing/kravet25-reactivate.js
+++ b/shopify/scripts/data/kravet-map-pricing/kravet25-reactivate.js
@@ -150,15 +150,21 @@ async function setInvAll(product, variants) {
console.log(`${APPLY ? '✎' : '·'} ${row.mfr.padEnd(7)} ${tag} | ${p.title.slice(0, 42)}`);
if (!APPLY) { activated++; repriced++; costSet++; published++; invOK++; continue; }
- // 1. status ACTIVE
+ // 1. price + cost on main variant — FIRST, before ACTIVATE (TK-11911 review 2026-09-18).
+ // FAIL CLOSED: if the reprice write does NOT land we `continue` BEFORE flipping status, so a
+ // reprice failure can never leave a product ACTIVE at its prior (possibly $0) price — the
+ // $0-orderable-ACTIVE window the fleet's zero-price tripwires guard. (Was: activate → reprice,
+ // which left the product ACTIVE at $0 on a reprice userError.) No dependency inverted: the
+ // reprice targets main.id/pid and does not require the product to be ACTIVE first.
+ const vr = await gqlR(M_VAR, { pid, variants: [{ id: main.id, price: map.toFixed(2), inventoryItem: { cost: cost.toFixed(2) } }] });
+ const ve = vr.data?.productVariantsBulkUpdate?.userErrors || [];
+ if (ve.length) { console.log(` ❌ variant ${JSON.stringify(ve)}`); failed++; continue; }
+ repriced++; costSet++;
+ // 2. status ACTIVE — only after the reprice is confirmed live.
const sr = await gqlR(M_STATUS, { input: { id: pid, status: 'ACTIVE' } });
const se = sr.data?.productUpdate?.userErrors || [];
if (se.length) { console.log(` ❌ status ${JSON.stringify(se)}`); failed++; continue; }
activated++;
- // 2. price + cost on main variant
- const vr = await gqlR(M_VAR, { pid, variants: [{ id: main.id, price: map.toFixed(2), inventoryItem: { cost: cost.toFixed(2) } }] });
- const ve = vr.data?.productVariantsBulkUpdate?.userErrors || [];
- if (ve.length) { console.log(` ❌ variant ${JSON.stringify(ve)}`); failed++; } else { repriced++; costSet++; }
// 3. metafields
await gqlR(M_MF, { mf: [
{ ownerId: pid, namespace: 'custom', key: 'cost', type: 'number_decimal', value: cost.toFixed(2) },
@@ -175,7 +181,8 @@ async function setInvAll(product, variants) {
// GUARD TK-11357 CORRECTNESS NOTE: `vs` is the PRE-reprice snapshot, so the main variant may
// still read $0 there even though step 2 just set it to MAP. Pass the POST-reprice price or the
// guard would refuse to stock a legitimately-priced roll (breaking Steve's 2026-06-20 rule).
- // `map > 0` is already asserted above, so this substitution can never launder a real $0.
+ // Reaching here now guarantees the reprice write SUCCEEDED (step 1 `continue`s on a
+ // reprice userError, before ACTIVATE), so substituting the confirmed-live MAP price cannot launder a $0.
const vsForGuard = vs.map(v => (v.id === main.id ? { ...v, price: map.toFixed(2) } : v));
const inv = await setInvAll(p, vsForGuard);
if (inv.err) console.log(` ⚠ inv errors ${inv.err}`); else invOK++;
← 4709904d auto-data-snapshot: 2026-09-18T12:40:33 (3 data files) — sho
·
back to Designer Wallcoverings
·
PJ Fall 2026 mailer: 1 hero + 3 tiles (drop dup Idyllic tile 80fbb708 →