@final-commerce/common 2.5.1-preprod.4 → 2.6.0-staging.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +185 -67
- package/dist/index.d.ts +185 -67
- package/dist/index.js +352 -86
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +335 -77
- package/dist/index.mjs.map +1 -1
- package/dist/pos-types/index.d.mts +175 -121
- package/dist/pos-types/index.d.ts +175 -121
- package/dist/pos-types/index.js +0 -1
- package/dist/pos-types/index.js.map +1 -1
- package/dist/pos-types/index.mjs +0 -1
- package/dist/pos-types/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -237,7 +237,6 @@ var InventorySpecificActionType = /* @__PURE__ */ ((InventorySpecificActionType2
|
|
|
237
237
|
InventorySpecificActionType2["PO_RECEIVED"] = "PO_RECEIVED";
|
|
238
238
|
InventorySpecificActionType2["EXTERNAL_SALE"] = "EXTERNAL_SALE";
|
|
239
239
|
InventorySpecificActionType2["EXTERNAL_RESTOCK"] = "EXTERNAL_RESTOCK";
|
|
240
|
-
InventorySpecificActionType2["CUSTOM"] = "CUSTOM";
|
|
241
240
|
return InventorySpecificActionType2;
|
|
242
241
|
})(InventorySpecificActionType || {});
|
|
243
242
|
var ExtensionCategory = /* @__PURE__ */ ((ExtensionCategory2) => {
|
|
@@ -424,6 +423,7 @@ var ProductType = /* @__PURE__ */ ((ProductType2) => {
|
|
|
424
423
|
ProductType2["SIMPLE"] = "simple";
|
|
425
424
|
ProductType2["VARIABLE"] = "variable";
|
|
426
425
|
ProductType2["BOOKING"] = "booking";
|
|
426
|
+
ProductType2["COMPOSITE"] = "composite";
|
|
427
427
|
return ProductType2;
|
|
428
428
|
})(ProductType || {});
|
|
429
429
|
var ProductStatus = /* @__PURE__ */ ((ProductStatus2) => {
|
|
@@ -1354,6 +1354,312 @@ function normalizeMongoIdString(value) {
|
|
|
1354
1354
|
return null;
|
|
1355
1355
|
}
|
|
1356
1356
|
|
|
1357
|
+
// utils/composite-price.util.ts
|
|
1358
|
+
var compositeItemCost = (item) => item.extraCharge * item.quantity;
|
|
1359
|
+
function cheapestCompositeItem(items) {
|
|
1360
|
+
let cheapest;
|
|
1361
|
+
items.forEach((item, index) => {
|
|
1362
|
+
if (!item.available) return;
|
|
1363
|
+
if (cheapest === void 0 || compositeItemCost(item) < compositeItemCost(items[cheapest])) cheapest = index;
|
|
1364
|
+
});
|
|
1365
|
+
return cheapest;
|
|
1366
|
+
}
|
|
1367
|
+
function cheapestCompositePrice(parts) {
|
|
1368
|
+
let total = 0;
|
|
1369
|
+
for (const part of parts) {
|
|
1370
|
+
if (part.min === 0) continue;
|
|
1371
|
+
const index = cheapestCompositeItem(part.items) ?? cheapestCompositeItem(part.items.map((item) => ({ ...item, available: true })));
|
|
1372
|
+
if (index === void 0) return void 0;
|
|
1373
|
+
total += part.min * compositeItemCost(part.items[index]);
|
|
1374
|
+
}
|
|
1375
|
+
return total;
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
// utils/modifier-resolution.util.ts
|
|
1379
|
+
function ancestorChain(categoryId, categoriesById) {
|
|
1380
|
+
const chain = [];
|
|
1381
|
+
const seen = /* @__PURE__ */ new Set([categoryId]);
|
|
1382
|
+
let current = categoriesById.get(categoryId)?.parentId ?? void 0;
|
|
1383
|
+
while (current && !seen.has(current)) {
|
|
1384
|
+
chain.push(current);
|
|
1385
|
+
seen.add(current);
|
|
1386
|
+
current = categoriesById.get(current)?.parentId ?? void 0;
|
|
1387
|
+
}
|
|
1388
|
+
return chain;
|
|
1389
|
+
}
|
|
1390
|
+
function clampRule(rule) {
|
|
1391
|
+
if (rule.min != null && rule.max != null && rule.min > rule.max) {
|
|
1392
|
+
return { ...rule, min: rule.max };
|
|
1393
|
+
}
|
|
1394
|
+
return rule;
|
|
1395
|
+
}
|
|
1396
|
+
function mergeRules(a, b) {
|
|
1397
|
+
const required = a.required || b.required;
|
|
1398
|
+
const min = a.min == null ? b.min : b.min == null ? a.min : Math.max(a.min, b.min);
|
|
1399
|
+
const max = a.max == null ? b.max : b.max == null ? a.max : Math.min(a.max, b.max);
|
|
1400
|
+
return clampRule({ required, min, max, sortOrder: Math.min(a.sortOrder, b.sortOrder) });
|
|
1401
|
+
}
|
|
1402
|
+
function toRule(row) {
|
|
1403
|
+
const required = row.required ?? false;
|
|
1404
|
+
return clampRule({
|
|
1405
|
+
required,
|
|
1406
|
+
// `required` is the gate: a stale min left on a placement that went optional is
|
|
1407
|
+
// ignored. A cleared min/max stays the explicit null it arrived as — nothing
|
|
1408
|
+
// downstream distinguishes null from absent.
|
|
1409
|
+
min: required ? row.min : void 0,
|
|
1410
|
+
max: row.max,
|
|
1411
|
+
sortOrder: row.sortOrder ?? 0
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
function toResolvedChoices(modifier) {
|
|
1415
|
+
return (modifier.choices ?? []).map((choice, index) => ({
|
|
1416
|
+
_id: String(choice._id),
|
|
1417
|
+
name: choice.name,
|
|
1418
|
+
price: choice.price ?? 0,
|
|
1419
|
+
isDefault: choice.isDefault,
|
|
1420
|
+
defaultQuantity: choice.defaultQuantity,
|
|
1421
|
+
unavailableOutletIds: choice.unavailableOutletIds?.map(String),
|
|
1422
|
+
sortOrder: choice.sortOrder ?? index
|
|
1423
|
+
})).sort((a, b) => a.sortOrder - b.sortOrder);
|
|
1424
|
+
}
|
|
1425
|
+
function resolveModifiersForProduct(inputs) {
|
|
1426
|
+
const categoriesById = new Map(
|
|
1427
|
+
inputs.categories.filter((category) => !category.isDeleted).map((category) => [String(category._id), category])
|
|
1428
|
+
);
|
|
1429
|
+
const modifiersById = new Map(
|
|
1430
|
+
inputs.modifiers.filter((modifier) => !modifier.isDeleted).map((modifier) => [String(modifier._id), modifier])
|
|
1431
|
+
);
|
|
1432
|
+
const directCategories = new Set(inputs.categoryIds.map(String));
|
|
1433
|
+
const inheritedCategories = /* @__PURE__ */ new Set();
|
|
1434
|
+
for (const categoryId of directCategories) {
|
|
1435
|
+
for (const ancestor of ancestorChain(categoryId, categoriesById)) {
|
|
1436
|
+
if (!directCategories.has(ancestor)) inheritedCategories.add(ancestor);
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
const rules = /* @__PURE__ */ new Map();
|
|
1440
|
+
for (const placement of inputs.categoryModifiers) {
|
|
1441
|
+
if (placement.isDeleted) continue;
|
|
1442
|
+
const categoryId = String(placement.categoryId);
|
|
1443
|
+
const precedence = directCategories.has(categoryId) ? 0 : inheritedCategories.has(categoryId) ? 1 : -1;
|
|
1444
|
+
if (precedence === -1) continue;
|
|
1445
|
+
const modifierId = String(placement.modifierId);
|
|
1446
|
+
if (!modifiersById.has(modifierId)) continue;
|
|
1447
|
+
const incoming = toRule(placement);
|
|
1448
|
+
const existing = rules.get(modifierId);
|
|
1449
|
+
if (!existing || precedence < existing.precedence) {
|
|
1450
|
+
rules.set(modifierId, { precedence, rule: incoming });
|
|
1451
|
+
} else if (precedence === existing.precedence) {
|
|
1452
|
+
rules.set(modifierId, { precedence, rule: mergeRules(existing.rule, incoming) });
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
const resolved = [];
|
|
1456
|
+
for (const [modifierId, { rule }] of rules) {
|
|
1457
|
+
const modifier = modifiersById.get(modifierId);
|
|
1458
|
+
if (!modifier) continue;
|
|
1459
|
+
const required = rule.required;
|
|
1460
|
+
resolved.push({
|
|
1461
|
+
_id: modifierId,
|
|
1462
|
+
name: modifier.name,
|
|
1463
|
+
selectionType: modifier.selectionType,
|
|
1464
|
+
allowQuantity: modifier.allowQuantity,
|
|
1465
|
+
required,
|
|
1466
|
+
// single-selection is implicitly capped at 1 — min/max are never carried.
|
|
1467
|
+
min: modifier.selectionType === "single" ? void 0 : rule.min,
|
|
1468
|
+
max: modifier.selectionType === "single" ? void 0 : rule.max,
|
|
1469
|
+
sortOrder: rule.sortOrder,
|
|
1470
|
+
choices: toResolvedChoices(modifier)
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
return resolved.sort((a, b) => a.sortOrder - b.sortOrder || a.name.localeCompare(b.name));
|
|
1474
|
+
}
|
|
1475
|
+
function isChoiceAvailableAtOutlet(choice, outletId) {
|
|
1476
|
+
return !(choice.unavailableOutletIds ?? []).includes(outletId);
|
|
1477
|
+
}
|
|
1478
|
+
function hasSellableChoice(modifier, outletId) {
|
|
1479
|
+
return modifier.choices.some((choice) => isChoiceAvailableAtOutlet(choice, outletId));
|
|
1480
|
+
}
|
|
1481
|
+
var modifiersSellable = (modifiers, outletId) => modifiers.every((modifier) => !modifier.required || hasSellableChoice(modifier, outletId));
|
|
1482
|
+
|
|
1483
|
+
// utils/composite-availability.util.ts
|
|
1484
|
+
function poolStockAt(rows, outletId) {
|
|
1485
|
+
if (!rows.some((row) => row.manageStock === true)) return null;
|
|
1486
|
+
return Math.max(0, rows.find((row) => String(row.outletId) === outletId)?.quantity ?? 0);
|
|
1487
|
+
}
|
|
1488
|
+
function compositeVariantInStock(variantId, quantity, outlet) {
|
|
1489
|
+
const shelf = outlet.shelves.get(variantId);
|
|
1490
|
+
if (!shelf || shelf.unresolved) return false;
|
|
1491
|
+
const onHand = outlet.poolStock.get(shelf.pool);
|
|
1492
|
+
if (onHand === void 0) return false;
|
|
1493
|
+
if (onHand === null || shelf.backorder) return true;
|
|
1494
|
+
return onHand >= (shelf.unit ? toBase(quantity, shelf.unit) : quantity);
|
|
1495
|
+
}
|
|
1496
|
+
function compositeItemUnavailable(item, rows) {
|
|
1497
|
+
const { outlet } = rows;
|
|
1498
|
+
const sellableHere = (productId2) => !outlet || !outlet.hiddenProductIds.has(productId2) && !outlet.unsellableProductIds.has(productId2);
|
|
1499
|
+
if (item.categoryId) {
|
|
1500
|
+
const variants = rows.categoryVariants.get(String(item.categoryId));
|
|
1501
|
+
if (!variants) return "deleted";
|
|
1502
|
+
const offered = variants.filter((variantId2) => sellableHere(rows.variantProducts.get(variantId2) ?? ""));
|
|
1503
|
+
if (!offered.length) return "empty";
|
|
1504
|
+
if (!outlet) return null;
|
|
1505
|
+
const unmarked = offered.filter((variantId2) => !outlet.markedVariantIds.has(variantId2));
|
|
1506
|
+
if (!unmarked.length) return "marked_sold_out";
|
|
1507
|
+
return unmarked.some((variantId2) => compositeVariantInStock(variantId2, item.quantity, outlet)) ? null : "out_of_stock";
|
|
1508
|
+
}
|
|
1509
|
+
const variantId = String(item.variantId);
|
|
1510
|
+
const productId = rows.variantProducts.get(variantId);
|
|
1511
|
+
if (!productId || !rows.productStatuses.has(productId)) return "deleted";
|
|
1512
|
+
if (rows.productStatuses.get(productId) !== "active" /* ACTIVE */) return "inactive";
|
|
1513
|
+
if (!outlet) return null;
|
|
1514
|
+
if (outlet.hiddenProductIds.has(productId)) return "hidden";
|
|
1515
|
+
if (outlet.unsellableProductIds.has(productId)) return "empty";
|
|
1516
|
+
if (outlet.markedVariantIds.has(variantId)) return "marked_sold_out";
|
|
1517
|
+
if (rows.bookableProductIds.has(productId)) {
|
|
1518
|
+
if (!outlet.bookableSeats) return "by_date";
|
|
1519
|
+
return (outlet.bookableSeats.get(productId) ?? 0) >= item.quantity ? null : "fully_booked";
|
|
1520
|
+
}
|
|
1521
|
+
return compositeVariantInStock(variantId, item.quantity, outlet) ? null : "out_of_stock";
|
|
1522
|
+
}
|
|
1523
|
+
function compositeMakeable(parts, rows) {
|
|
1524
|
+
const { outlet } = rows;
|
|
1525
|
+
if (!outlet) throw new Error("compositeMakeable counts at one outlet: rows.outlet is required");
|
|
1526
|
+
const required = parts.map((part, partIndex) => ({ ...part, partIndex })).filter((part) => part.min > 0);
|
|
1527
|
+
const isBookable = (variantId) => rows.bookableProductIds.has(rows.variantProducts.get(String(variantId)) ?? "");
|
|
1528
|
+
if (required.some((part) => part.items.some((item) => item.variantId && isBookable(item.variantId))))
|
|
1529
|
+
return { byDate: true };
|
|
1530
|
+
const optionsOf = (item) => (item.categoryId ? rows.categoryVariants.get(String(item.categoryId)) ?? [] : [String(item.variantId)]).flatMap(
|
|
1531
|
+
(variantId) => {
|
|
1532
|
+
const reason = compositeItemUnavailable({ variantId, quantity: item.quantity }, rows);
|
|
1533
|
+
const shelf = outlet.shelves.get(variantId);
|
|
1534
|
+
if (reason && reason !== "out_of_stock" || !shelf) return [];
|
|
1535
|
+
const stock = outlet.poolStock.get(shelf.pool);
|
|
1536
|
+
const onHand = shelf.unresolved || stock === void 0 ? 0 : stock === null || shelf.backorder ? null : stock;
|
|
1537
|
+
const perPick = shelf.unit ? toBase(item.quantity, shelf.unit) : item.quantity;
|
|
1538
|
+
return [{ itemId: item.id, pool: shelf.pool, perPick, onHand }];
|
|
1539
|
+
}
|
|
1540
|
+
);
|
|
1541
|
+
const counted = required.map((part) => ({ ...part, options: part.items.flatMap(optionsOf) }));
|
|
1542
|
+
const order = [...counted].sort((a, b) => Number(a.options.length !== 1) - Number(b.options.length !== 1));
|
|
1543
|
+
const picksLeft = (option, reserved) => option.onHand === null ? Infinity : Math.max(0, Math.floor((option.onHand - (reserved.get(option.pool) ?? 0)) / option.perPick));
|
|
1544
|
+
const shortAt = (n) => {
|
|
1545
|
+
const reserved = /* @__PURE__ */ new Map();
|
|
1546
|
+
for (const part of order) {
|
|
1547
|
+
let wanted = part.min * n;
|
|
1548
|
+
const ranked = [...part.options].sort((a, b) => picksLeft(b, reserved) - picksLeft(a, reserved));
|
|
1549
|
+
for (const option of ranked) {
|
|
1550
|
+
if (wanted <= 0) break;
|
|
1551
|
+
const taken = Math.min(wanted, picksLeft(option, reserved));
|
|
1552
|
+
if (option.onHand !== null)
|
|
1553
|
+
reserved.set(option.pool, (reserved.get(option.pool) ?? 0) + taken * option.perPick);
|
|
1554
|
+
wanted -= taken;
|
|
1555
|
+
}
|
|
1556
|
+
if (wanted > 0) return part.partIndex;
|
|
1557
|
+
}
|
|
1558
|
+
return void 0;
|
|
1559
|
+
};
|
|
1560
|
+
const whyRows = [];
|
|
1561
|
+
const rowPools = /* @__PURE__ */ new Map();
|
|
1562
|
+
const makes = (has, uses) => has === null ? null : Math.floor(has / uses);
|
|
1563
|
+
for (const part of counted) {
|
|
1564
|
+
const [option] = part.options;
|
|
1565
|
+
if (part.options.length === 1) {
|
|
1566
|
+
const uses = option.perPick * part.min;
|
|
1567
|
+
const row = whyRows.find((candidate) => rowPools.get(candidate) === option.pool);
|
|
1568
|
+
if (!row) {
|
|
1569
|
+
const created = { itemIds: [option.itemId], uses, has: option.onHand, makes: makes(option.onHand, uses) };
|
|
1570
|
+
rowPools.set(created, option.pool);
|
|
1571
|
+
whyRows.push(created);
|
|
1572
|
+
continue;
|
|
1573
|
+
}
|
|
1574
|
+
row.itemIds.push(option.itemId);
|
|
1575
|
+
row.uses += uses;
|
|
1576
|
+
if (option.onHand === null) row.has = null;
|
|
1577
|
+
row.makes = makes(row.has, row.uses);
|
|
1578
|
+
continue;
|
|
1579
|
+
}
|
|
1580
|
+
const perPool = /* @__PURE__ */ new Map();
|
|
1581
|
+
for (const candidate of part.options)
|
|
1582
|
+
perPool.set(candidate.pool, Math.max(perPool.get(candidate.pool) ?? 0, picksLeft(candidate, /* @__PURE__ */ new Map())));
|
|
1583
|
+
const total = [...perPool.values()].reduce((sum, picks) => sum + picks, 0);
|
|
1584
|
+
const has = total === Infinity ? null : total;
|
|
1585
|
+
whyRows.push({
|
|
1586
|
+
itemIds: part.items.map((item) => item.id),
|
|
1587
|
+
partIndex: part.partIndex,
|
|
1588
|
+
uses: part.min,
|
|
1589
|
+
has,
|
|
1590
|
+
makes: makes(has, part.min)
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
if (counted.every((part) => part.options.some((option) => option.onHand === null)))
|
|
1594
|
+
return { count: null, rows: whyRows };
|
|
1595
|
+
const ceiling = Math.min(
|
|
1596
|
+
...counted.filter((part) => !part.options.some((option) => option.onHand === null)).map(
|
|
1597
|
+
(part) => Math.floor(part.options.reduce((sum, option) => sum + picksLeft(option, /* @__PURE__ */ new Map()), 0) / part.min)
|
|
1598
|
+
)
|
|
1599
|
+
);
|
|
1600
|
+
let [low, high] = [0, ceiling];
|
|
1601
|
+
while (low < high) {
|
|
1602
|
+
const mid = Math.ceil((low + high) / 2);
|
|
1603
|
+
if (shortAt(mid) === void 0) low = mid;
|
|
1604
|
+
else high = mid - 1;
|
|
1605
|
+
}
|
|
1606
|
+
const short = shortAt(low + 1);
|
|
1607
|
+
const shortPart = counted.find((part) => part.partIndex === short);
|
|
1608
|
+
const limitedBy = whyRows.findIndex(
|
|
1609
|
+
(row) => shortPart?.options.length === 1 ? row.partIndex === void 0 && row.itemIds.includes(shortPart.options[0].itemId) : row.partIndex === short
|
|
1610
|
+
);
|
|
1611
|
+
return { count: low, rows: whyRows, ...limitedBy >= 0 ? { limitedBy } : {} };
|
|
1612
|
+
}
|
|
1613
|
+
var poolOf = (line) => line.stockVariantId || line.variantId;
|
|
1614
|
+
function poolDemand(lines) {
|
|
1615
|
+
const demand = /* @__PURE__ */ new Map();
|
|
1616
|
+
const add = (line, times) => demand.set(
|
|
1617
|
+
poolOf(line),
|
|
1618
|
+
(demand.get(poolOf(line)) ?? 0) + (line.unit ? toBase(line.quantity * times, line.unit) : line.quantity * times)
|
|
1619
|
+
);
|
|
1620
|
+
for (const line of lines) {
|
|
1621
|
+
if (line.components) for (const component of line.components) add(component, line.quantity);
|
|
1622
|
+
else add(line, 1);
|
|
1623
|
+
}
|
|
1624
|
+
return demand;
|
|
1625
|
+
}
|
|
1626
|
+
function poolShortfall(demand, poolStock, backordered = /* @__PURE__ */ new Set()) {
|
|
1627
|
+
for (const [poolId, wanted] of demand) {
|
|
1628
|
+
const available = poolStock.get(poolId);
|
|
1629
|
+
if (available === null || available === void 0 || backordered.has(poolId)) continue;
|
|
1630
|
+
if (wanted > available) return { poolId, available, wanted };
|
|
1631
|
+
}
|
|
1632
|
+
return null;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
// utils/composite-reservation.util.ts
|
|
1636
|
+
function compositeModifierMismatches(lineItems) {
|
|
1637
|
+
return lineItems.flatMap(
|
|
1638
|
+
(line) => line.components?.length ? (line.modifiers ?? []).flatMap(
|
|
1639
|
+
(modifier) => modifier.componentIndex !== void 0 && line.components[modifier.componentIndex] !== void 0 ? [] : [
|
|
1640
|
+
`Modifier ${modifier.modifierName ?? "?"} on composite line ${line.internalId ?? "?"} names no component (componentIndex ${modifier.componentIndex}) \u2014 a composite has no modifiers of its own`
|
|
1641
|
+
]
|
|
1642
|
+
) : []
|
|
1643
|
+
);
|
|
1644
|
+
}
|
|
1645
|
+
function compositeReservationMismatches(order) {
|
|
1646
|
+
return (order.reservations ?? []).flatMap((reservation) => {
|
|
1647
|
+
if (reservation.lineItemInternalId === void 0) return [];
|
|
1648
|
+
const name = `Booking ${String(reservation.bookingId ?? "?")}`;
|
|
1649
|
+
const line = order.lineItems?.find((candidate) => candidate.internalId === reservation.lineItemInternalId);
|
|
1650
|
+
if (!line) return [`${name} names line ${reservation.lineItemInternalId}, which is not on the order`];
|
|
1651
|
+
const component = reservation.componentIndex === void 0 ? void 0 : line.components?.[reservation.componentIndex];
|
|
1652
|
+
if (!component) return [`${name} names no component ${reservation.componentIndex} of line ${line.internalId}`];
|
|
1653
|
+
if (String(component.productId) !== String(reservation.productId))
|
|
1654
|
+
return [
|
|
1655
|
+
`${name} is for ${String(reservation.productId)}, but that component sold ${String(component.productId)}`
|
|
1656
|
+
];
|
|
1657
|
+
if (reservation.price !== 0 || reservation.total !== 0)
|
|
1658
|
+
return [`${name} carries money (${reservation.price}/${reservation.total}); its component already does`];
|
|
1659
|
+
return [];
|
|
1660
|
+
});
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1357
1663
|
// units/family-code.ts
|
|
1358
1664
|
var MAX_SLUG_LENGTH = 32;
|
|
1359
1665
|
var FALLBACK_SLUG = "family";
|
|
@@ -2492,51 +2798,6 @@ function inferStatesFromLegacyStatus(order) {
|
|
|
2492
2798
|
return { payment: "unpaid", fulfillment: "pending" };
|
|
2493
2799
|
}
|
|
2494
2800
|
|
|
2495
|
-
// order-state-machine/in-cart.ts
|
|
2496
|
-
function hasInCartFlag(order) {
|
|
2497
|
-
return order.inCart != null;
|
|
2498
|
-
}
|
|
2499
|
-
function isInCart(order) {
|
|
2500
|
-
if (order.inCart != null) return order.inCart.active === true;
|
|
2501
|
-
if (order.fulfillmentState) return order.fulfillmentState === "draft";
|
|
2502
|
-
return (order.status ?? "").trim().toLowerCase() === "in-cart";
|
|
2503
|
-
}
|
|
2504
|
-
|
|
2505
|
-
// order-state-machine/order-status.ts
|
|
2506
|
-
function validateOrderStatuses(statuses) {
|
|
2507
|
-
if (!Array.isArray(statuses)) {
|
|
2508
|
-
return [{ index: -1, field: "orderStatuses", message: "must be an array" }];
|
|
2509
|
-
}
|
|
2510
|
-
const errors = [];
|
|
2511
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2512
|
-
statuses.forEach((raw, index) => {
|
|
2513
|
-
const s = raw ?? {};
|
|
2514
|
-
const add = (field, message) => errors.push({ index, field, message });
|
|
2515
|
-
if (typeof s.id !== "string" || !s.id.trim()) add("id", "must be a non-empty string");
|
|
2516
|
-
else if (seen.has(s.id)) add("id", `duplicate id "${s.id}"`);
|
|
2517
|
-
else seen.add(s.id);
|
|
2518
|
-
if (typeof s.label !== "string" || !s.label.trim()) add("label", "must be a non-empty string");
|
|
2519
|
-
for (const field of ["color", "icon"]) {
|
|
2520
|
-
if (s[field] !== void 0 && typeof s[field] !== "string") add(field, "must be a string");
|
|
2521
|
-
}
|
|
2522
|
-
if (s.fulfillmentState !== void 0 && !(typeof s.fulfillmentState === "string" && isFulfillmentState(s.fulfillmentState))) {
|
|
2523
|
-
add("fulfillmentState", `"${String(s.fulfillmentState)}" is not a fulfillment state`);
|
|
2524
|
-
}
|
|
2525
|
-
if (s.requiresPaymentState !== void 0) {
|
|
2526
|
-
if (!Array.isArray(s.requiresPaymentState) || s.requiresPaymentState.length === 0) {
|
|
2527
|
-
add("requiresPaymentState", "must be a non-empty array of payment states");
|
|
2528
|
-
} else {
|
|
2529
|
-
for (const p of s.requiresPaymentState) {
|
|
2530
|
-
if (!(typeof p === "string" && isPaymentState(p))) {
|
|
2531
|
-
add("requiresPaymentState", `"${String(p)}" is not a payment state`);
|
|
2532
|
-
}
|
|
2533
|
-
}
|
|
2534
|
-
}
|
|
2535
|
-
}
|
|
2536
|
-
});
|
|
2537
|
-
return errors;
|
|
2538
|
-
}
|
|
2539
|
-
|
|
2540
2801
|
// order-state-machine/write-strategy.ts
|
|
2541
2802
|
var LegacyWriteStrategy = class {
|
|
2542
2803
|
applyState(_order) {
|
|
@@ -3048,7 +3309,9 @@ function buildGrid(rule, timeZone, from, to, now, busy = []) {
|
|
|
3048
3309
|
const start = startAt.getTime();
|
|
3049
3310
|
if (start < askedFrom || start >= askedTo) return false;
|
|
3050
3311
|
if (start < notBefore || start > notAfter) return false;
|
|
3051
|
-
return !blocked.some(
|
|
3312
|
+
return !blocked.some(
|
|
3313
|
+
({ from: blockFrom, to: blockTo }) => start < blockTo && bufferEndAt.getTime() > blockFrom
|
|
3314
|
+
);
|
|
3052
3315
|
}).sort((first, second) => +first.startAt - +second.startAt);
|
|
3053
3316
|
}
|
|
3054
3317
|
function slotsForWindow(grid, startAt, endAt) {
|
|
@@ -3167,7 +3430,14 @@ function buildAvailability({
|
|
|
3167
3430
|
for (const slot of slots2) {
|
|
3168
3431
|
const { taken, foreignProductId } = occupancyIn(mine, productId, slot.startAt, slot.bufferEndAt, shared);
|
|
3169
3432
|
const free = foreignProductId ? 0 : Math.max(capacity - taken, 0);
|
|
3170
|
-
const entry = byInstant.get(+slot.startAt) ?? {
|
|
3433
|
+
const entry = byInstant.get(+slot.startAt) ?? {
|
|
3434
|
+
...slot,
|
|
3435
|
+
capacity: 0,
|
|
3436
|
+
booked: 0,
|
|
3437
|
+
free: 0,
|
|
3438
|
+
resources: [],
|
|
3439
|
+
dayKey: shopDayKey(slot.startAt, resource.timeZone)
|
|
3440
|
+
};
|
|
3171
3441
|
entry.capacity += capacity;
|
|
3172
3442
|
entry.booked += foreignProductId ? capacity : taken;
|
|
3173
3443
|
entry.free += free;
|
|
@@ -3245,33 +3515,9 @@ var ADYEN_ROLLOUT_COUNTRY_CODES = /* @__PURE__ */ new Set(["CA"]);
|
|
|
3245
3515
|
function isAdyenRolloutCountry(alpha2) {
|
|
3246
3516
|
return ADYEN_ROLLOUT_COUNTRY_CODES.has(alpha2);
|
|
3247
3517
|
}
|
|
3248
|
-
var AFFIRM_PRICE_PLANS = ["core", "standard", "signature"];
|
|
3249
|
-
function isAffirmPricePlan(value) {
|
|
3250
|
-
return typeof value === "string" && AFFIRM_PRICE_PLANS.includes(value);
|
|
3251
|
-
}
|
|
3252
|
-
var AFFIRM_COUNTRY_CODES = /* @__PURE__ */ new Set(["CA"]);
|
|
3253
|
-
function isAffirmCountry(alpha2) {
|
|
3254
|
-
return !!alpha2 && AFFIRM_COUNTRY_CODES.has(alpha2.toUpperCase());
|
|
3255
|
-
}
|
|
3256
|
-
var BNPL_METHOD_STATUS = {
|
|
3257
|
-
ACTIVE: "active",
|
|
3258
|
-
PENDING: "pending",
|
|
3259
|
-
UNAVAILABLE: "unavailable",
|
|
3260
|
-
UNKNOWN: "unknown"
|
|
3261
|
-
};
|
|
3262
|
-
var BNPL_SKIP_REASON = {
|
|
3263
|
-
PENDING: "pending",
|
|
3264
|
-
NO_SUPPORT_EMAIL: "no_support_email",
|
|
3265
|
-
NO_CURRENCY: "no_currency",
|
|
3266
|
-
NO_BUSINESS_LINE: "no_business_line"
|
|
3267
|
-
};
|
|
3268
3518
|
export {
|
|
3269
3519
|
ADYEN_ROLLOUT_COUNTRY_CODES,
|
|
3270
|
-
AFFIRM_COUNTRY_CODES,
|
|
3271
|
-
AFFIRM_PRICE_PLANS,
|
|
3272
3520
|
AttributeType,
|
|
3273
|
-
BNPL_METHOD_STATUS,
|
|
3274
|
-
BNPL_SKIP_REASON,
|
|
3275
3521
|
BookingRatePeriod,
|
|
3276
3522
|
BookingResourceKind,
|
|
3277
3523
|
BookingResourceStatus,
|
|
@@ -3349,6 +3595,7 @@ export {
|
|
|
3349
3595
|
UserTypes,
|
|
3350
3596
|
addAmounts,
|
|
3351
3597
|
amountToString,
|
|
3598
|
+
ancestorChain,
|
|
3352
3599
|
assertUnitSane,
|
|
3353
3600
|
availableIn,
|
|
3354
3601
|
baseFor,
|
|
@@ -3362,6 +3609,14 @@ export {
|
|
|
3362
3609
|
buildResolvedConfig,
|
|
3363
3610
|
calculatePercentage,
|
|
3364
3611
|
canTransition,
|
|
3612
|
+
cheapestCompositeItem,
|
|
3613
|
+
cheapestCompositePrice,
|
|
3614
|
+
compositeItemCost,
|
|
3615
|
+
compositeItemUnavailable,
|
|
3616
|
+
compositeMakeable,
|
|
3617
|
+
compositeModifierMismatches,
|
|
3618
|
+
compositeReservationMismatches,
|
|
3619
|
+
compositeVariantInStock,
|
|
3365
3620
|
conditionSummary,
|
|
3366
3621
|
convertFixedFeeToLocalCurrency,
|
|
3367
3622
|
createAmount,
|
|
@@ -3396,15 +3651,13 @@ export {
|
|
|
3396
3651
|
getPricingRegionFromCountry,
|
|
3397
3652
|
getSettlementTotal,
|
|
3398
3653
|
getTotalCollected,
|
|
3399
|
-
|
|
3654
|
+
hasSellableChoice,
|
|
3400
3655
|
holdExpiresAt,
|
|
3401
3656
|
inferStatesFromLegacyStatus,
|
|
3402
3657
|
isAdyenRolloutCountry,
|
|
3403
|
-
|
|
3404
|
-
isAffirmPricePlan,
|
|
3658
|
+
isChoiceAvailableAtOutlet,
|
|
3405
3659
|
isConditionOperator,
|
|
3406
3660
|
isFulfillmentState,
|
|
3407
|
-
isInCart,
|
|
3408
3661
|
isPaymentState,
|
|
3409
3662
|
isSupportedCurrency,
|
|
3410
3663
|
isSystemFamilyCode,
|
|
@@ -3413,6 +3666,7 @@ export {
|
|
|
3413
3666
|
mapToLegacyStatus,
|
|
3414
3667
|
maxPrecisionFor,
|
|
3415
3668
|
mergeFragment,
|
|
3669
|
+
modifiersSellable,
|
|
3416
3670
|
multiplyAmount,
|
|
3417
3671
|
normalizeMongoIdString,
|
|
3418
3672
|
occupancyIn,
|
|
@@ -3420,9 +3674,14 @@ export {
|
|
|
3420
3674
|
parseCurrencyCode,
|
|
3421
3675
|
parseStripeCurrencyCode,
|
|
3422
3676
|
planWindow,
|
|
3677
|
+
poolDemand,
|
|
3678
|
+
poolOf,
|
|
3679
|
+
poolShortfall,
|
|
3680
|
+
poolStockAt,
|
|
3423
3681
|
presentAt,
|
|
3424
3682
|
removeFragment,
|
|
3425
3683
|
resolveFamily,
|
|
3684
|
+
resolveModifiersForProduct,
|
|
3426
3685
|
resolveTemplate,
|
|
3427
3686
|
resolveUnit,
|
|
3428
3687
|
roundToPrecision,
|
|
@@ -3438,7 +3697,6 @@ export {
|
|
|
3438
3697
|
toMinorUnits,
|
|
3439
3698
|
validateConfig,
|
|
3440
3699
|
validateFragmentCompatibility,
|
|
3441
|
-
validateOrderStatuses,
|
|
3442
3700
|
violatesFinancialInvariant,
|
|
3443
3701
|
windowEndsAt,
|
|
3444
3702
|
withinPresence
|