Untitled
unknown
plain_text
a year ago
5.1 kB
16
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