[object Object]

← back to Designer Wallcoverings

fix(TK-11403/TK-11539): stage bulk imports as DRAFT so they pass the activation gate

93f6b2e6847e340e5cdd92ca2aa3954b9ea6911f · 2026-09-14 13:58:03 -0700 · Steve

Code-review finding: /api/import/batch built products with no status (Shopify REST
defaults an omitted status to ACTIVE) and no weight, running only the banned-word
cleaner — so bulk imports went live at zero weight and without the price-integrity
/ below-cost gate wired into the main import path. Add status:'draft' so bulk
imports stage as DRAFT and inherit the existing validateBeforeActivate gate at
promotion. (This file also carries the pre-existing TK-11357 $0-orderable guard.)

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

Files touched

Diff

commit 93f6b2e6847e340e5cdd92ca2aa3954b9ea6911f
Author: Steve <steve@designerwallcoverings.com>
Date:   Mon Sep 14 13:58:03 2026 -0700

    fix(TK-11403/TK-11539): stage bulk imports as DRAFT so they pass the activation gate
    
    Code-review finding: /api/import/batch built products with no status (Shopify REST
    defaults an omitted status to ACTIVE) and no weight, running only the banned-word
    cleaner — so bulk imports went live at zero weight and without the price-integrity
    / below-cost gate wired into the main import path. Add status:'draft' so bulk
    imports stage as DRAFT and inherit the existing validateBeforeActivate gate at
    promotion. (This file also carries the pre-existing TK-11357 $0-orderable guard.)
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01U39xV6JiBLLjXBYbfbSxgw
---
 .../app/api/import/batch/route.ts                  | 33 ++++++++++++++++++----
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/DW-Programming/ImportNewSkufromURL/app/api/import/batch/route.ts b/DW-Programming/ImportNewSkufromURL/app/api/import/batch/route.ts
index e4fbbda8..94642eee 100644
--- a/DW-Programming/ImportNewSkufromURL/app/api/import/batch/route.ts
+++ b/DW-Programming/ImportNewSkufromURL/app/api/import/batch/route.ts
@@ -44,18 +44,39 @@ export async function POST(request: NextRequest) {
           body_html: `<p>Imported from ${vendorId}</p>`,
           vendor: privateLabel ? (customVendorName || 'Private Label') : product.vendor,
           product_type: 'Wallcovering',
+          // TK-11403/TK-11539 (review 2026-09-14): bulk imports stage as DRAFT so they must
+          // pass the gated activation path (price-integrity gate + weight-guard) before going
+          // live. Without this, Shopify REST treats an omitted status as ACTIVE, so bulk
+          // imports went live at zero weight and without the below-cost/sample-leak gate.
+          status: 'draft',
           tags: [
             ...(product.tags || []),
             vendorId,
             privateLabel ? 'private-label' : 'manufacturer-brand'
           ].join(','),
           images: product.images.map(url => ({ src: url })),
-          variants: [{
-            price: product.price?.replace(/[^0-9.]/g, '') || '0.00',
-            sku: product.sku || '',
-            inventory_quantity: 100,
-            inventory_management: 'shopify'
-          }]
+          variants: [(() => {
+            // ── GUARD TK-11357 BEGIN ─ never mint a $0 ORDERABLE variant ──────────────
+            // Before: `price: … || '0.00'` paired with a flat `inventory_quantity: 100`
+            // and tracked inventory. A vendor page with a missing/unparseable price
+            // therefore created a $0.00 variant STOCKED at 100 => availableForSale =>
+            // checkout-orderable for $0.00. That is the TK-10825/10965/11140/11301/11357
+            // defect at its source (1,255 live products in the last recurrence).
+            // After: a variant that is not genuinely priced is created UNSTOCKED and
+            // DENY, so it stays addressable (quote-only imports still work) but can
+            // never be bought for nothing. Steve's 2026-06-20 "active products are never
+            // out of stock" rule is preserved for PRICED goods — they keep qty 100.
+            const cleaned = product.price?.replace(/[^0-9.]/g, '') || '';
+            const priced = Number(cleaned) > 0;   // fail-safe: '', NaN, 0 all => not priced
+            return {
+              price: priced ? cleaned : '0.00',
+              sku: product.sku || '',
+              inventory_quantity: priced ? 100 : 0,
+              inventory_policy: priced ? 'continue' : 'deny',
+              inventory_management: 'shopify'
+            };
+            // ── GUARD TK-11357 END ───────────────────────────────────────────────────
+          })()]
         };
         
         // Create product in Shopify

← 058dde0f fix(TK-11738): pass --apply so the sample-variant cron creat  ·  back to Designer Wallcoverings  ·  fix(versa-20oz): read descriptionHtml not deprecated bodyHtm a4365bb4 →