← back to Dw Daily Catchup 20260909

lib/five-field-extra.js

44 lines

'use strict';

// The universal memo-sample price. A "sellable" (non-sample) variant stuck at
// exactly this value is the $4.25 sample-price LEAK, NOT a real sellable price —
// so it must NOT satisfy the price>0 gate (else the activator flips DRAFT→ACTIVE
// on a product that is orderable at $4.25). Fail-safe: this can only BLOCK an
// activation, never cause one. (TK-10456, 2026-08-31 — the rotation was
// re-activating reverted $4.25 murals/Chloe because $4.25 > 0 passed the gate.)
const SAMPLE_LEAK_PRICE = 4.25;

function fiveFieldExtra(product) {
  const hasValidVariantsShape = Array.isArray(product?.variants?.nodes);
  const hasValidTagsShape = Array.isArray(product?.tags);
  const variants = hasValidVariantsShape ? product.variants.nodes : [];
  const tags = hasValidTagsShape
    ? product.tags.map((tag) => String(tag).trim().toLowerCase())
    : [];
  const hasSample = variants.some((variant) => /-sample$/i.test(variant.sku || ''));
  const sellable = variants.filter((variant) => !/-sample$/i.test(variant.sku || ''));
  const pricedSellable = sellable.filter((variant) => {
    if (typeof variant.price !== 'string' || !/^\d+(?:\.\d+)?$/.test(variant.price)) return false;
    const price = Number(variant.price);
    return Number.isFinite(price) && price > 0;
  });
  const hasSellablePriced = pricedSellable.length > 0;
  // If the ONLY priced sellable variant(s) sit at the sample-leak price, this is a
  // $4.25 leak, not a real price → block. A real price on any sellable variant
  // (e.g. a $384 roll alongside a $4.25 sample) still passes.
  const onlySampleLeakPriced = hasSellablePriced &&
    pricedSellable.every((variant) => Number(variant.price) === SAMPLE_LEAK_PRICE);
  const isQuoteOnly = tags.includes('quotes');
  const reasons = [];
  if (!hasValidVariantsShape) reasons.push('invalid-variants-shape');
  if (!hasValidTagsShape) reasons.push('invalid-tags-shape');
  if (!hasSample) reasons.push('no-sample-variant');
  if (!sellable.length && !isQuoteOnly) reasons.push('no-sellable-variant');
  if (!hasSellablePriced && !isQuoteOnly) reasons.push('sellable-price-not-gt-0');
  else if (onlySampleLeakPriced && !isQuoteOnly) reasons.push('sellable-price-is-sample-leak-4.25');
  if (tags.length < 2) reasons.push('fewer-than-2-tags');
  return { ok: reasons.length === 0, reasons };
}

module.exports = { fiveFieldExtra };