Untitled

 avatar
unknown
plain_text
10 months ago
5.1 kB
14
Indexable
function(properties, context) {
  function _toArray(list) {
    if (!list) return [];
    if (Array.isArray(list)) return list;
    if (typeof list.length === "function" && typeof list.get === "function") {
      return list.get(0, list.length());
    }
    return [];
  }
  function _thingId(t) {
    if (!t) return null;
    if (typeof t === "string") return t;
    if (t.get) return t.get("_id") || t.get("unique_id") || t.get("id") || null;
    return t._id || t.unique_id || t.id || null;
  }
  function _thingName(t, candidates = ["name","label","title","value"]) {
    if (!t) return null;
    if (t.get) {
      for (const f of candidates) {
        const v = t.get(f);
        if (v != null) return v;
      }
      return null;
    }
    for (const f of candidates) if (t[f] != null) return t[f];
    return null;
  }
  function _cartesian(arrays) {
    if (!arrays.length) return [];
    return arrays.reduce((acc, curr) => acc.flatMap(a => curr.map(b => [...a, b])), [[]]);
  }

  function _build({ variantsList, optionOrderList, primaryOptionThing, skuPrefix="SKU", defaultPrice=0, defaultQty=1 }) {
    const rows = _toArray(variantsList);
    if (!rows.length) return { productId: null, count: 0, combinations: [] };

    const firstRow = rows[0];
    const productThing = firstRow.get ? firstRow.get("product") : firstRow.product;
    const productId = _thingId(productThing);

    const byOptionId = new Map();
    const optionLabelById = new Map();
    const valueLabelById  = new Map();
    const firstSeenOrder  = new Map();
    let seenIndex = 0;

    for (const r of rows) {
      const product = r.get ? r.get("product") : r.product;
      if (_thingId(product) !== productId) continue;

      const opt = r.get ? r.get("option") : r.option;
      const val = r.get ? r.get("optionValue") : r.optionValue;
      const optionId = _thingId(opt);
      const valueId  = _thingId(val);
      if (!optionId || !valueId) continue;

      const optionName = _thingName(opt);
      const valueName  = _thingName(val);
      if (optionName != null && !optionLabelById.has(optionId)) optionLabelById.set(optionId, optionName);
      if (valueName  != null && !valueLabelById.has(valueId))   valueLabelById.set(valueId, valueName);

      if (!byOptionId.has(optionId)) {
        byOptionId.set(optionId, new Set());
        if (!firstSeenOrder.has(optionId)) firstSeenOrder.set(optionId, seenIndex++);
      }
      byOptionId.get(optionId).add(valueId);
    }

    // up to 4 options
    let optionIds = Array.from(byOptionId.keys()).slice(0, 4);

    const providedOrder = _toArray(optionOrderList);
    if (providedOrder.length) {
      const providedIds = providedOrder.map(_thingId).filter(Boolean);
      const providedSet = new Set(providedIds);
      optionIds = providedIds.filter(id => byOptionId.has(id)).slice(0, 4);
      for (const id of byOptionId.keys()) {
        if (!providedSet.has(id) && optionIds.length < 4) optionIds.push(id);
      }
    } else {
      const primaryId = _thingId(primaryOptionThing);
      optionIds.sort((a, b) => {
        if (primaryId && a === primaryId) return -1;
        if (primaryId && b === primaryId) return 1;
        return (firstSeenOrder.get(a) ?? 0) - (firstSeenOrder.get(b) ?? 0);
      });
    }

    const valueArrays = optionIds.map(id => Array.from(byOptionId.get(id) || []));
    if (!valueArrays.length) return { productId, count: 0, combinations: [] };

    const combos = _cartesian(valueArrays);

    const out = combos.map((valueIds, i) => {
      const key = optionIds.map((optId, idx) => `${optId}:${valueIds[idx]}`).join("|");
      const optionLabels = optionIds.map(id => optionLabelById.get(id)).filter(v => v != null);
      const valueLabels  = valueIds.map(id => valueLabelById.get(id)).filter(v => v != null);
      return {
        productId,
        optionIds,
        valueIds,
        combination_key_ids: key,
        sku: `${skuPrefix}-${String(i + 1).padStart(4, "0")}`,
        price: Number(defaultPrice) || 0,
        quantity: Number(defaultQty) || 1,
        ...(optionLabels.length === optionIds.length ? { optionLabels } : {}),
        ...(valueLabels.length  === valueIds.length  ? { valueLabels }  : {})
      };
    });

    return { productId, count: out.length, combinations: out };
  }

  const result = _build({
    variantsList:       properties.thing_list_1,         // REQUIRED (ProductVariants list)
    optionOrderList:    properties.thing_list_2,         // OPTIONAL (productOptions list)
    primaryOptionThing: properties.thing_1,              // OPTIONAL (productOption)
    skuPrefix:          properties.sku_prefix || "SKU",  // OPTIONAL (text)
    defaultPrice:       properties.default_price != null ? Number(properties.default_price) : 0,
    defaultQty:         properties.default_qty   != null ? Number(properties.default_qty)   : 1
  });

  // Return a single TEXT value (JSON string)
  return JSON.stringify(result);
}
Editor is loading...
Leave a Comment