← back to Hollywood Import
hollywood-create: guard against creating+publishing a $0-orderable ACTIVE product (TK-11357 class)
c57152768db43b8f6db0512643d5a54b330fafa0 · 2026-09-15 01:22:21 -0700 · Steve Abrams
goLive() stamps on_hand=2026, publishes 13 channels, and flips ACTIVE, so a
blank/0 per-yard price it.hw would ship a live customer-facing $0 orderable
product. Fail-loud SKIP before POST /products.json.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
Diff
commit c57152768db43b8f6db0512643d5a54b330fafa0
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Sep 15 01:22:21 2026 -0700
hollywood-create: guard against creating+publishing a $0-orderable ACTIVE product (TK-11357 class)
goLive() stamps on_hand=2026, publishes 13 channels, and flips ACTIVE, so a
blank/0 per-yard price it.hw would ship a live customer-facing $0 orderable
product. Fail-loud SKIP before POST /products.json.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
hollywood-create.mjs | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/hollywood-create.mjs b/hollywood-create.mjs
index 82a2698..c4a2cfc 100644
--- a/hollywood-create.mjs
+++ b/hollywood-create.mjs
@@ -151,8 +151,12 @@ for (const it of todo) {
pl.product.metafields.filter(m => !(m.namespace === 'dwc' && m.key === 'real_vendor')).map(m => m.value).join(' ');
const leak = /\b(momentum|versa|innovations|muratto)\b/i.test(leakText);
const shapeOk = skuShapeOk(it.dw_sku);
+ // $0-ORDERABLE GUARD (TK-11357 class): a missing/0 per-yard price it.hw becomes a $0.00 sellable
+ // variant that goLive() then stamps on_hand=2026, publishes to 13 channels, and flips to ACTIVE —
+ // a live customer-facing $0 orderable product. Refuse to create/publish it (checked before L172).
+ const priceOk = Number.isFinite(Number(it.hw)) && Number(it.hw) > 0;
if (!APPLY) {
- console.log(`\n${it.dw_sku} "${pl.product.title}" ${leak ? '⚠LEAK' : 'clean'} ${shapeOk ? 'shape✓' : '⛔BAD-SKU-SHAPE (would SKIP)'}`);
+ console.log(`\n${it.dw_sku} "${pl.product.title}" ${leak ? '⚠LEAK' : 'clean'} ${shapeOk ? 'shape✓' : '⛔BAD-SKU-SHAPE (would SKIP)'} ${priceOk ? 'price✓' : `⛔ZERO-PRICE hw=${it.hw} (would SKIP)`}`);
console.log(` variants: [${pl.product.variants.map(v => v.option1 + ' ' + v.sku + ' $' + v.price).join(' | ')}]`);
console.log(` tags: ${pl.product.tags.slice(0, 90)} · img: ${pl.product.images[0]?.src ? 'yes' : 'NONE'}`);
continue;
@@ -168,6 +172,14 @@ for (const it of todo) {
if (out) out.write(JSON.stringify({ dw: it.dw_sku, action: 'SKIP_BAD_SKU_SHAPE' }) + '\n');
err++; continue;
}
+ // TK-11357 $0-ORDERABLE GUARD: never create+goLive a $0 sellable product. goLive() stamps
+ // on_hand=2026, publishes 13 channels, and flips ACTIVE, so a blank/0 per-yard price would
+ // ship a live $0 orderable product. Fail-loud SKIP before the POST /products.json below.
+ if (!priceOk) {
+ console.error(` SKIP ZERO-PRICE ${it.dw_sku} (hw=${it.hw}) — would create + publish a $0 orderable ACTIVE product (TK-11357 guard)`);
+ if (out) out.write(JSON.stringify({ dw: it.dw_sku, action: 'SKIP_ZERO_PRICE', hw: it.hw }) + '\n');
+ err++; continue;
+ }
try {
const r = await fetch(`${REST}/products.json`, { method: 'POST', headers: H, body: JSON.stringify(pl) });
const txt = await r.text();
← d995321 hollywood-add-yard: guard against $0-orderable yard variant
·
back to Hollywood Import
·
(newest)