@final-commerce/common 2.5.0-staging.1 → 2.5.0
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 +4 -181
- package/dist/index.d.ts +4 -181
- package/dist/index.js +3 -349
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -332
- package/dist/index.mjs.map +1 -1
- package/dist/pos-types/index.d.mts +97 -174
- package/dist/pos-types/index.d.ts +97 -174
- package/dist/pos-types/index.js.map +1 -1
- package/dist/pos-types/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -98,7 +98,6 @@ __export(index_exports, {
|
|
|
98
98
|
UserTypes: () => UserTypes,
|
|
99
99
|
addAmounts: () => addAmounts,
|
|
100
100
|
amountToString: () => amountToString,
|
|
101
|
-
ancestorChain: () => ancestorChain,
|
|
102
101
|
assertUnitSane: () => assertUnitSane,
|
|
103
102
|
availableIn: () => availableIn,
|
|
104
103
|
baseFor: () => baseFor,
|
|
@@ -112,14 +111,6 @@ __export(index_exports, {
|
|
|
112
111
|
buildResolvedConfig: () => buildResolvedConfig,
|
|
113
112
|
calculatePercentage: () => calculatePercentage,
|
|
114
113
|
canTransition: () => canTransition,
|
|
115
|
-
cheapestCompositeItem: () => cheapestCompositeItem,
|
|
116
|
-
cheapestCompositePrice: () => cheapestCompositePrice,
|
|
117
|
-
compositeItemCost: () => compositeItemCost,
|
|
118
|
-
compositeItemUnavailable: () => compositeItemUnavailable,
|
|
119
|
-
compositeMakeable: () => compositeMakeable,
|
|
120
|
-
compositeModifierMismatches: () => compositeModifierMismatches,
|
|
121
|
-
compositeReservationMismatches: () => compositeReservationMismatches,
|
|
122
|
-
compositeVariantInStock: () => compositeVariantInStock,
|
|
123
114
|
conditionSummary: () => conditionSummary,
|
|
124
115
|
convertFixedFeeToLocalCurrency: () => convertFixedFeeToLocalCurrency,
|
|
125
116
|
createAmount: () => createAmount,
|
|
@@ -154,11 +145,9 @@ __export(index_exports, {
|
|
|
154
145
|
getPricingRegionFromCountry: () => getPricingRegionFromCountry,
|
|
155
146
|
getSettlementTotal: () => getSettlementTotal,
|
|
156
147
|
getTotalCollected: () => getTotalCollected,
|
|
157
|
-
hasSellableChoice: () => hasSellableChoice,
|
|
158
148
|
holdExpiresAt: () => holdExpiresAt,
|
|
159
149
|
inferStatesFromLegacyStatus: () => inferStatesFromLegacyStatus,
|
|
160
150
|
isAdyenRolloutCountry: () => isAdyenRolloutCountry,
|
|
161
|
-
isChoiceAvailableAtOutlet: () => isChoiceAvailableAtOutlet,
|
|
162
151
|
isConditionOperator: () => isConditionOperator,
|
|
163
152
|
isFulfillmentState: () => isFulfillmentState,
|
|
164
153
|
isPaymentState: () => isPaymentState,
|
|
@@ -169,7 +158,6 @@ __export(index_exports, {
|
|
|
169
158
|
mapToLegacyStatus: () => mapToLegacyStatus,
|
|
170
159
|
maxPrecisionFor: () => maxPrecisionFor,
|
|
171
160
|
mergeFragment: () => mergeFragment,
|
|
172
|
-
modifiersSellable: () => modifiersSellable,
|
|
173
161
|
multiplyAmount: () => multiplyAmount,
|
|
174
162
|
normalizeMongoIdString: () => normalizeMongoIdString,
|
|
175
163
|
occupancyIn: () => occupancyIn,
|
|
@@ -177,14 +165,9 @@ __export(index_exports, {
|
|
|
177
165
|
parseCurrencyCode: () => parseCurrencyCode,
|
|
178
166
|
parseStripeCurrencyCode: () => parseStripeCurrencyCode,
|
|
179
167
|
planWindow: () => planWindow,
|
|
180
|
-
poolDemand: () => poolDemand,
|
|
181
|
-
poolOf: () => poolOf,
|
|
182
|
-
poolShortfall: () => poolShortfall,
|
|
183
|
-
poolStockAt: () => poolStockAt,
|
|
184
168
|
presentAt: () => presentAt,
|
|
185
169
|
removeFragment: () => removeFragment,
|
|
186
170
|
resolveFamily: () => resolveFamily,
|
|
187
|
-
resolveModifiersForProduct: () => resolveModifiersForProduct,
|
|
188
171
|
resolveTemplate: () => resolveTemplate,
|
|
189
172
|
resolveUnit: () => resolveUnit,
|
|
190
173
|
roundToPrecision: () => roundToPrecision,
|
|
@@ -445,6 +428,7 @@ var InventorySpecificActionType = /* @__PURE__ */ ((InventorySpecificActionType2
|
|
|
445
428
|
InventorySpecificActionType2["PO_RECEIVED"] = "PO_RECEIVED";
|
|
446
429
|
InventorySpecificActionType2["EXTERNAL_SALE"] = "EXTERNAL_SALE";
|
|
447
430
|
InventorySpecificActionType2["EXTERNAL_RESTOCK"] = "EXTERNAL_RESTOCK";
|
|
431
|
+
InventorySpecificActionType2["CUSTOM"] = "CUSTOM";
|
|
448
432
|
return InventorySpecificActionType2;
|
|
449
433
|
})(InventorySpecificActionType || {});
|
|
450
434
|
var ExtensionCategory = /* @__PURE__ */ ((ExtensionCategory2) => {
|
|
@@ -631,7 +615,6 @@ var ProductType = /* @__PURE__ */ ((ProductType2) => {
|
|
|
631
615
|
ProductType2["SIMPLE"] = "simple";
|
|
632
616
|
ProductType2["VARIABLE"] = "variable";
|
|
633
617
|
ProductType2["BOOKING"] = "booking";
|
|
634
|
-
ProductType2["COMPOSITE"] = "composite";
|
|
635
618
|
return ProductType2;
|
|
636
619
|
})(ProductType || {});
|
|
637
620
|
var ProductStatus = /* @__PURE__ */ ((ProductStatus2) => {
|
|
@@ -1562,309 +1545,6 @@ function normalizeMongoIdString(value) {
|
|
|
1562
1545
|
return null;
|
|
1563
1546
|
}
|
|
1564
1547
|
|
|
1565
|
-
// utils/composite-price.util.ts
|
|
1566
|
-
var compositeItemCost = (item) => item.extraCharge * item.quantity;
|
|
1567
|
-
function cheapestCompositeItem(items) {
|
|
1568
|
-
let cheapest;
|
|
1569
|
-
items.forEach((item, index) => {
|
|
1570
|
-
if (!item.available) return;
|
|
1571
|
-
if (cheapest === void 0 || compositeItemCost(item) < compositeItemCost(items[cheapest])) cheapest = index;
|
|
1572
|
-
});
|
|
1573
|
-
return cheapest;
|
|
1574
|
-
}
|
|
1575
|
-
function cheapestCompositePrice(parts) {
|
|
1576
|
-
let total = 0;
|
|
1577
|
-
for (const part of parts) {
|
|
1578
|
-
if (part.min === 0) continue;
|
|
1579
|
-
const index = cheapestCompositeItem(part.items) ?? cheapestCompositeItem(part.items.map((item) => ({ ...item, available: true })));
|
|
1580
|
-
if (index === void 0) return void 0;
|
|
1581
|
-
total += part.min * compositeItemCost(part.items[index]);
|
|
1582
|
-
}
|
|
1583
|
-
return total;
|
|
1584
|
-
}
|
|
1585
|
-
|
|
1586
|
-
// utils/modifier-resolution.util.ts
|
|
1587
|
-
function ancestorChain(categoryId, categoriesById) {
|
|
1588
|
-
const chain = [];
|
|
1589
|
-
const seen = /* @__PURE__ */ new Set([categoryId]);
|
|
1590
|
-
let current = categoriesById.get(categoryId)?.parentId ?? void 0;
|
|
1591
|
-
while (current && !seen.has(current)) {
|
|
1592
|
-
chain.push(current);
|
|
1593
|
-
seen.add(current);
|
|
1594
|
-
current = categoriesById.get(current)?.parentId ?? void 0;
|
|
1595
|
-
}
|
|
1596
|
-
return chain;
|
|
1597
|
-
}
|
|
1598
|
-
function clampRule(rule) {
|
|
1599
|
-
if (rule.min != null && rule.max != null && rule.min > rule.max) {
|
|
1600
|
-
return { ...rule, min: rule.max };
|
|
1601
|
-
}
|
|
1602
|
-
return rule;
|
|
1603
|
-
}
|
|
1604
|
-
function mergeRules(a, b) {
|
|
1605
|
-
const required = a.required || b.required;
|
|
1606
|
-
const min = a.min == null ? b.min : b.min == null ? a.min : Math.max(a.min, b.min);
|
|
1607
|
-
const max = a.max == null ? b.max : b.max == null ? a.max : Math.min(a.max, b.max);
|
|
1608
|
-
return clampRule({ required, min, max, sortOrder: Math.min(a.sortOrder, b.sortOrder) });
|
|
1609
|
-
}
|
|
1610
|
-
function toRule(row) {
|
|
1611
|
-
const required = row.required ?? false;
|
|
1612
|
-
return clampRule({
|
|
1613
|
-
required,
|
|
1614
|
-
// `required` is the gate: a stale min left on a placement that went optional is
|
|
1615
|
-
// ignored. A cleared min/max stays the explicit null it arrived as — nothing
|
|
1616
|
-
// downstream distinguishes null from absent.
|
|
1617
|
-
min: required ? row.min : void 0,
|
|
1618
|
-
max: row.max,
|
|
1619
|
-
sortOrder: row.sortOrder ?? 0
|
|
1620
|
-
});
|
|
1621
|
-
}
|
|
1622
|
-
function toResolvedChoices(modifier) {
|
|
1623
|
-
return (modifier.choices ?? []).map((choice, index) => ({
|
|
1624
|
-
_id: String(choice._id),
|
|
1625
|
-
name: choice.name,
|
|
1626
|
-
price: choice.price ?? 0,
|
|
1627
|
-
isDefault: choice.isDefault,
|
|
1628
|
-
defaultQuantity: choice.defaultQuantity,
|
|
1629
|
-
unavailableOutletIds: choice.unavailableOutletIds?.map(String),
|
|
1630
|
-
sortOrder: choice.sortOrder ?? index
|
|
1631
|
-
})).sort((a, b) => a.sortOrder - b.sortOrder);
|
|
1632
|
-
}
|
|
1633
|
-
function resolveModifiersForProduct(inputs) {
|
|
1634
|
-
const categoriesById = new Map(
|
|
1635
|
-
inputs.categories.filter((category) => !category.isDeleted).map((category) => [String(category._id), category])
|
|
1636
|
-
);
|
|
1637
|
-
const modifiersById = new Map(
|
|
1638
|
-
inputs.modifiers.filter((modifier) => !modifier.isDeleted).map((modifier) => [String(modifier._id), modifier])
|
|
1639
|
-
);
|
|
1640
|
-
const directCategories = new Set(inputs.categoryIds.map(String));
|
|
1641
|
-
const inheritedCategories = /* @__PURE__ */ new Set();
|
|
1642
|
-
for (const categoryId of directCategories) {
|
|
1643
|
-
for (const ancestor of ancestorChain(categoryId, categoriesById)) {
|
|
1644
|
-
if (!directCategories.has(ancestor)) inheritedCategories.add(ancestor);
|
|
1645
|
-
}
|
|
1646
|
-
}
|
|
1647
|
-
const rules = /* @__PURE__ */ new Map();
|
|
1648
|
-
for (const placement of inputs.categoryModifiers) {
|
|
1649
|
-
if (placement.isDeleted) continue;
|
|
1650
|
-
const categoryId = String(placement.categoryId);
|
|
1651
|
-
const precedence = directCategories.has(categoryId) ? 0 : inheritedCategories.has(categoryId) ? 1 : -1;
|
|
1652
|
-
if (precedence === -1) continue;
|
|
1653
|
-
const modifierId = String(placement.modifierId);
|
|
1654
|
-
if (!modifiersById.has(modifierId)) continue;
|
|
1655
|
-
const incoming = toRule(placement);
|
|
1656
|
-
const existing = rules.get(modifierId);
|
|
1657
|
-
if (!existing || precedence < existing.precedence) {
|
|
1658
|
-
rules.set(modifierId, { precedence, rule: incoming });
|
|
1659
|
-
} else if (precedence === existing.precedence) {
|
|
1660
|
-
rules.set(modifierId, { precedence, rule: mergeRules(existing.rule, incoming) });
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
const resolved = [];
|
|
1664
|
-
for (const [modifierId, { rule }] of rules) {
|
|
1665
|
-
const modifier = modifiersById.get(modifierId);
|
|
1666
|
-
if (!modifier) continue;
|
|
1667
|
-
const required = rule.required;
|
|
1668
|
-
resolved.push({
|
|
1669
|
-
_id: modifierId,
|
|
1670
|
-
name: modifier.name,
|
|
1671
|
-
selectionType: modifier.selectionType,
|
|
1672
|
-
allowQuantity: modifier.allowQuantity,
|
|
1673
|
-
required,
|
|
1674
|
-
// single-selection is implicitly capped at 1 — min/max are never carried.
|
|
1675
|
-
min: modifier.selectionType === "single" ? void 0 : rule.min,
|
|
1676
|
-
max: modifier.selectionType === "single" ? void 0 : rule.max,
|
|
1677
|
-
sortOrder: rule.sortOrder,
|
|
1678
|
-
choices: toResolvedChoices(modifier)
|
|
1679
|
-
});
|
|
1680
|
-
}
|
|
1681
|
-
return resolved.sort((a, b) => a.sortOrder - b.sortOrder || a.name.localeCompare(b.name));
|
|
1682
|
-
}
|
|
1683
|
-
function isChoiceAvailableAtOutlet(choice, outletId) {
|
|
1684
|
-
return !(choice.unavailableOutletIds ?? []).includes(outletId);
|
|
1685
|
-
}
|
|
1686
|
-
function hasSellableChoice(modifier, outletId) {
|
|
1687
|
-
return modifier.choices.some((choice) => isChoiceAvailableAtOutlet(choice, outletId));
|
|
1688
|
-
}
|
|
1689
|
-
var modifiersSellable = (modifiers, outletId) => modifiers.every((modifier) => !modifier.required || hasSellableChoice(modifier, outletId));
|
|
1690
|
-
|
|
1691
|
-
// utils/composite-availability.util.ts
|
|
1692
|
-
function poolStockAt(rows, outletId) {
|
|
1693
|
-
if (!rows.some((row) => row.manageStock === true)) return null;
|
|
1694
|
-
return Math.max(0, rows.find((row) => String(row.outletId) === outletId)?.quantity ?? 0);
|
|
1695
|
-
}
|
|
1696
|
-
function compositeVariantInStock(variantId, quantity, outlet) {
|
|
1697
|
-
const shelf = outlet.shelves.get(variantId);
|
|
1698
|
-
if (!shelf || shelf.unresolved) return false;
|
|
1699
|
-
const onHand = outlet.poolStock.get(shelf.pool);
|
|
1700
|
-
if (onHand === void 0) return false;
|
|
1701
|
-
if (onHand === null || shelf.backorder) return true;
|
|
1702
|
-
return onHand >= (shelf.unit ? toBase(quantity, shelf.unit) : quantity);
|
|
1703
|
-
}
|
|
1704
|
-
function compositeItemUnavailable(item, rows) {
|
|
1705
|
-
const { outlet } = rows;
|
|
1706
|
-
const sellableHere = (productId2) => !outlet || !outlet.hiddenProductIds.has(productId2) && !outlet.unsellableProductIds.has(productId2);
|
|
1707
|
-
if (item.categoryId) {
|
|
1708
|
-
const variants = rows.categoryVariants.get(String(item.categoryId));
|
|
1709
|
-
if (!variants) return "deleted";
|
|
1710
|
-
const offered = variants.filter((variantId2) => sellableHere(rows.variantProducts.get(variantId2) ?? ""));
|
|
1711
|
-
if (!offered.length) return "empty";
|
|
1712
|
-
if (!outlet) return null;
|
|
1713
|
-
return offered.some((variantId2) => compositeVariantInStock(variantId2, item.quantity, outlet)) ? null : "out_of_stock";
|
|
1714
|
-
}
|
|
1715
|
-
const variantId = String(item.variantId);
|
|
1716
|
-
const productId = rows.variantProducts.get(variantId);
|
|
1717
|
-
if (!productId || !rows.productStatuses.has(productId)) return "deleted";
|
|
1718
|
-
if (rows.productStatuses.get(productId) !== "active" /* ACTIVE */) return "inactive";
|
|
1719
|
-
if (!outlet) return null;
|
|
1720
|
-
if (outlet.hiddenProductIds.has(productId)) return "hidden";
|
|
1721
|
-
if (outlet.unsellableProductIds.has(productId)) return "empty";
|
|
1722
|
-
if (rows.bookableProductIds.has(productId)) {
|
|
1723
|
-
if (!outlet.bookableSeats) return "by_date";
|
|
1724
|
-
return (outlet.bookableSeats.get(productId) ?? 0) >= item.quantity ? null : "fully_booked";
|
|
1725
|
-
}
|
|
1726
|
-
return compositeVariantInStock(variantId, item.quantity, outlet) ? null : "out_of_stock";
|
|
1727
|
-
}
|
|
1728
|
-
function compositeMakeable(parts, rows) {
|
|
1729
|
-
const { outlet } = rows;
|
|
1730
|
-
if (!outlet) throw new Error("compositeMakeable counts at one outlet: rows.outlet is required");
|
|
1731
|
-
const required = parts.map((part, partIndex) => ({ ...part, partIndex })).filter((part) => part.min > 0);
|
|
1732
|
-
const isBookable = (variantId) => rows.bookableProductIds.has(rows.variantProducts.get(String(variantId)) ?? "");
|
|
1733
|
-
if (required.some((part) => part.items.some((item) => item.variantId && isBookable(item.variantId))))
|
|
1734
|
-
return { byDate: true };
|
|
1735
|
-
const optionsOf = (item) => (item.categoryId ? rows.categoryVariants.get(String(item.categoryId)) ?? [] : [String(item.variantId)]).flatMap(
|
|
1736
|
-
(variantId) => {
|
|
1737
|
-
const reason = compositeItemUnavailable({ variantId, quantity: item.quantity }, rows);
|
|
1738
|
-
const shelf = outlet.shelves.get(variantId);
|
|
1739
|
-
if (reason && reason !== "out_of_stock" || !shelf) return [];
|
|
1740
|
-
const stock = outlet.poolStock.get(shelf.pool);
|
|
1741
|
-
const onHand = shelf.unresolved || stock === void 0 ? 0 : stock === null || shelf.backorder ? null : stock;
|
|
1742
|
-
const perPick = shelf.unit ? toBase(item.quantity, shelf.unit) : item.quantity;
|
|
1743
|
-
return [{ itemId: item.id, pool: shelf.pool, perPick, onHand }];
|
|
1744
|
-
}
|
|
1745
|
-
);
|
|
1746
|
-
const counted = required.map((part) => ({ ...part, options: part.items.flatMap(optionsOf) }));
|
|
1747
|
-
const order = [...counted].sort((a, b) => Number(a.options.length !== 1) - Number(b.options.length !== 1));
|
|
1748
|
-
const picksLeft = (option, reserved) => option.onHand === null ? Infinity : Math.max(0, Math.floor((option.onHand - (reserved.get(option.pool) ?? 0)) / option.perPick));
|
|
1749
|
-
const shortAt = (n) => {
|
|
1750
|
-
const reserved = /* @__PURE__ */ new Map();
|
|
1751
|
-
for (const part of order) {
|
|
1752
|
-
let wanted = part.min * n;
|
|
1753
|
-
const ranked = [...part.options].sort((a, b) => picksLeft(b, reserved) - picksLeft(a, reserved));
|
|
1754
|
-
for (const option of ranked) {
|
|
1755
|
-
if (wanted <= 0) break;
|
|
1756
|
-
const taken = Math.min(wanted, picksLeft(option, reserved));
|
|
1757
|
-
if (option.onHand !== null)
|
|
1758
|
-
reserved.set(option.pool, (reserved.get(option.pool) ?? 0) + taken * option.perPick);
|
|
1759
|
-
wanted -= taken;
|
|
1760
|
-
}
|
|
1761
|
-
if (wanted > 0) return part.partIndex;
|
|
1762
|
-
}
|
|
1763
|
-
return void 0;
|
|
1764
|
-
};
|
|
1765
|
-
const whyRows = [];
|
|
1766
|
-
const rowPools = /* @__PURE__ */ new Map();
|
|
1767
|
-
const makes = (has, uses) => has === null ? null : Math.floor(has / uses);
|
|
1768
|
-
for (const part of counted) {
|
|
1769
|
-
const [option] = part.options;
|
|
1770
|
-
if (part.options.length === 1) {
|
|
1771
|
-
const uses = option.perPick * part.min;
|
|
1772
|
-
const row = whyRows.find((candidate) => rowPools.get(candidate) === option.pool);
|
|
1773
|
-
if (!row) {
|
|
1774
|
-
const created = { itemIds: [option.itemId], uses, has: option.onHand, makes: makes(option.onHand, uses) };
|
|
1775
|
-
rowPools.set(created, option.pool);
|
|
1776
|
-
whyRows.push(created);
|
|
1777
|
-
continue;
|
|
1778
|
-
}
|
|
1779
|
-
row.itemIds.push(option.itemId);
|
|
1780
|
-
row.uses += uses;
|
|
1781
|
-
if (option.onHand === null) row.has = null;
|
|
1782
|
-
row.makes = makes(row.has, row.uses);
|
|
1783
|
-
continue;
|
|
1784
|
-
}
|
|
1785
|
-
const perPool = /* @__PURE__ */ new Map();
|
|
1786
|
-
for (const candidate of part.options)
|
|
1787
|
-
perPool.set(candidate.pool, Math.max(perPool.get(candidate.pool) ?? 0, picksLeft(candidate, /* @__PURE__ */ new Map())));
|
|
1788
|
-
const total = [...perPool.values()].reduce((sum, picks) => sum + picks, 0);
|
|
1789
|
-
const has = total === Infinity ? null : total;
|
|
1790
|
-
whyRows.push({
|
|
1791
|
-
itemIds: part.items.map((item) => item.id),
|
|
1792
|
-
partIndex: part.partIndex,
|
|
1793
|
-
uses: part.min,
|
|
1794
|
-
has,
|
|
1795
|
-
makes: makes(has, part.min)
|
|
1796
|
-
});
|
|
1797
|
-
}
|
|
1798
|
-
if (counted.every((part) => part.options.some((option) => option.onHand === null)))
|
|
1799
|
-
return { count: null, rows: whyRows };
|
|
1800
|
-
const ceiling = Math.min(
|
|
1801
|
-
...counted.filter((part) => !part.options.some((option) => option.onHand === null)).map(
|
|
1802
|
-
(part) => Math.floor(part.options.reduce((sum, option) => sum + picksLeft(option, /* @__PURE__ */ new Map()), 0) / part.min)
|
|
1803
|
-
)
|
|
1804
|
-
);
|
|
1805
|
-
let [low, high] = [0, ceiling];
|
|
1806
|
-
while (low < high) {
|
|
1807
|
-
const mid = Math.ceil((low + high) / 2);
|
|
1808
|
-
if (shortAt(mid) === void 0) low = mid;
|
|
1809
|
-
else high = mid - 1;
|
|
1810
|
-
}
|
|
1811
|
-
const short = shortAt(low + 1);
|
|
1812
|
-
const shortPart = counted.find((part) => part.partIndex === short);
|
|
1813
|
-
const limitedBy = whyRows.findIndex(
|
|
1814
|
-
(row) => shortPart?.options.length === 1 ? row.partIndex === void 0 && row.itemIds.includes(shortPart.options[0].itemId) : row.partIndex === short
|
|
1815
|
-
);
|
|
1816
|
-
return { count: low, rows: whyRows, ...limitedBy >= 0 ? { limitedBy } : {} };
|
|
1817
|
-
}
|
|
1818
|
-
var poolOf = (line) => line.stockVariantId || line.variantId;
|
|
1819
|
-
function poolDemand(lines) {
|
|
1820
|
-
const demand = /* @__PURE__ */ new Map();
|
|
1821
|
-
const add = (line, times) => demand.set(
|
|
1822
|
-
poolOf(line),
|
|
1823
|
-
(demand.get(poolOf(line)) ?? 0) + (line.unit ? toBase(line.quantity * times, line.unit) : line.quantity * times)
|
|
1824
|
-
);
|
|
1825
|
-
for (const line of lines) {
|
|
1826
|
-
if (line.components) for (const component of line.components) add(component, line.quantity);
|
|
1827
|
-
else add(line, 1);
|
|
1828
|
-
}
|
|
1829
|
-
return demand;
|
|
1830
|
-
}
|
|
1831
|
-
function poolShortfall(demand, poolStock, backordered = /* @__PURE__ */ new Set()) {
|
|
1832
|
-
for (const [poolId, wanted] of demand) {
|
|
1833
|
-
const available = poolStock.get(poolId);
|
|
1834
|
-
if (available === null || available === void 0 || backordered.has(poolId)) continue;
|
|
1835
|
-
if (wanted > available) return { poolId, available, wanted };
|
|
1836
|
-
}
|
|
1837
|
-
return null;
|
|
1838
|
-
}
|
|
1839
|
-
|
|
1840
|
-
// utils/composite-reservation.util.ts
|
|
1841
|
-
function compositeModifierMismatches(lineItems) {
|
|
1842
|
-
return lineItems.flatMap(
|
|
1843
|
-
(line) => line.components?.length ? (line.modifiers ?? []).flatMap(
|
|
1844
|
-
(modifier) => modifier.componentIndex !== void 0 && line.components[modifier.componentIndex] !== void 0 ? [] : [
|
|
1845
|
-
`Modifier ${modifier.modifierName ?? "?"} on composite line ${line.internalId ?? "?"} names no component (componentIndex ${modifier.componentIndex}) \u2014 a composite has no modifiers of its own`
|
|
1846
|
-
]
|
|
1847
|
-
) : []
|
|
1848
|
-
);
|
|
1849
|
-
}
|
|
1850
|
-
function compositeReservationMismatches(order) {
|
|
1851
|
-
return (order.reservations ?? []).flatMap((reservation) => {
|
|
1852
|
-
if (reservation.lineItemInternalId === void 0) return [];
|
|
1853
|
-
const name = `Booking ${String(reservation.bookingId ?? "?")}`;
|
|
1854
|
-
const line = order.lineItems?.find((candidate) => candidate.internalId === reservation.lineItemInternalId);
|
|
1855
|
-
if (!line) return [`${name} names line ${reservation.lineItemInternalId}, which is not on the order`];
|
|
1856
|
-
const component = reservation.componentIndex === void 0 ? void 0 : line.components?.[reservation.componentIndex];
|
|
1857
|
-
if (!component) return [`${name} names no component ${reservation.componentIndex} of line ${line.internalId}`];
|
|
1858
|
-
if (String(component.productId) !== String(reservation.productId))
|
|
1859
|
-
return [
|
|
1860
|
-
`${name} is for ${String(reservation.productId)}, but that component sold ${String(component.productId)}`
|
|
1861
|
-
];
|
|
1862
|
-
if (reservation.price !== 0 || reservation.total !== 0)
|
|
1863
|
-
return [`${name} carries money (${reservation.price}/${reservation.total}); its component already does`];
|
|
1864
|
-
return [];
|
|
1865
|
-
});
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
1548
|
// units/family-code.ts
|
|
1869
1549
|
var MAX_SLUG_LENGTH = 32;
|
|
1870
1550
|
var FALLBACK_SLUG = "family";
|
|
@@ -3514,9 +3194,7 @@ function buildGrid(rule, timeZone, from, to, now, busy = []) {
|
|
|
3514
3194
|
const start = startAt.getTime();
|
|
3515
3195
|
if (start < askedFrom || start >= askedTo) return false;
|
|
3516
3196
|
if (start < notBefore || start > notAfter) return false;
|
|
3517
|
-
return !blocked.some(
|
|
3518
|
-
({ from: blockFrom, to: blockTo }) => start < blockTo && bufferEndAt.getTime() > blockFrom
|
|
3519
|
-
);
|
|
3197
|
+
return !blocked.some(({ from: blockFrom, to: blockTo }) => start < blockTo && bufferEndAt.getTime() > blockFrom);
|
|
3520
3198
|
}).sort((first, second) => +first.startAt - +second.startAt);
|
|
3521
3199
|
}
|
|
3522
3200
|
function slotsForWindow(grid, startAt, endAt) {
|
|
@@ -3635,14 +3313,7 @@ function buildAvailability({
|
|
|
3635
3313
|
for (const slot of slots2) {
|
|
3636
3314
|
const { taken, foreignProductId } = occupancyIn(mine, productId, slot.startAt, slot.bufferEndAt, shared);
|
|
3637
3315
|
const free = foreignProductId ? 0 : Math.max(capacity - taken, 0);
|
|
3638
|
-
const entry = byInstant.get(+slot.startAt) ?? {
|
|
3639
|
-
...slot,
|
|
3640
|
-
capacity: 0,
|
|
3641
|
-
booked: 0,
|
|
3642
|
-
free: 0,
|
|
3643
|
-
resources: [],
|
|
3644
|
-
dayKey: shopDayKey(slot.startAt, resource.timeZone)
|
|
3645
|
-
};
|
|
3316
|
+
const entry = byInstant.get(+slot.startAt) ?? { ...slot, capacity: 0, booked: 0, free: 0, resources: [], dayKey: shopDayKey(slot.startAt, resource.timeZone) };
|
|
3646
3317
|
entry.capacity += capacity;
|
|
3647
3318
|
entry.booked += foreignProductId ? capacity : taken;
|
|
3648
3319
|
entry.free += free;
|
|
@@ -3801,7 +3472,6 @@ function isAdyenRolloutCountry(alpha2) {
|
|
|
3801
3472
|
UserTypes,
|
|
3802
3473
|
addAmounts,
|
|
3803
3474
|
amountToString,
|
|
3804
|
-
ancestorChain,
|
|
3805
3475
|
assertUnitSane,
|
|
3806
3476
|
availableIn,
|
|
3807
3477
|
baseFor,
|
|
@@ -3815,14 +3485,6 @@ function isAdyenRolloutCountry(alpha2) {
|
|
|
3815
3485
|
buildResolvedConfig,
|
|
3816
3486
|
calculatePercentage,
|
|
3817
3487
|
canTransition,
|
|
3818
|
-
cheapestCompositeItem,
|
|
3819
|
-
cheapestCompositePrice,
|
|
3820
|
-
compositeItemCost,
|
|
3821
|
-
compositeItemUnavailable,
|
|
3822
|
-
compositeMakeable,
|
|
3823
|
-
compositeModifierMismatches,
|
|
3824
|
-
compositeReservationMismatches,
|
|
3825
|
-
compositeVariantInStock,
|
|
3826
3488
|
conditionSummary,
|
|
3827
3489
|
convertFixedFeeToLocalCurrency,
|
|
3828
3490
|
createAmount,
|
|
@@ -3857,11 +3519,9 @@ function isAdyenRolloutCountry(alpha2) {
|
|
|
3857
3519
|
getPricingRegionFromCountry,
|
|
3858
3520
|
getSettlementTotal,
|
|
3859
3521
|
getTotalCollected,
|
|
3860
|
-
hasSellableChoice,
|
|
3861
3522
|
holdExpiresAt,
|
|
3862
3523
|
inferStatesFromLegacyStatus,
|
|
3863
3524
|
isAdyenRolloutCountry,
|
|
3864
|
-
isChoiceAvailableAtOutlet,
|
|
3865
3525
|
isConditionOperator,
|
|
3866
3526
|
isFulfillmentState,
|
|
3867
3527
|
isPaymentState,
|
|
@@ -3872,7 +3532,6 @@ function isAdyenRolloutCountry(alpha2) {
|
|
|
3872
3532
|
mapToLegacyStatus,
|
|
3873
3533
|
maxPrecisionFor,
|
|
3874
3534
|
mergeFragment,
|
|
3875
|
-
modifiersSellable,
|
|
3876
3535
|
multiplyAmount,
|
|
3877
3536
|
normalizeMongoIdString,
|
|
3878
3537
|
occupancyIn,
|
|
@@ -3880,14 +3539,9 @@ function isAdyenRolloutCountry(alpha2) {
|
|
|
3880
3539
|
parseCurrencyCode,
|
|
3881
3540
|
parseStripeCurrencyCode,
|
|
3882
3541
|
planWindow,
|
|
3883
|
-
poolDemand,
|
|
3884
|
-
poolOf,
|
|
3885
|
-
poolShortfall,
|
|
3886
|
-
poolStockAt,
|
|
3887
3542
|
presentAt,
|
|
3888
3543
|
removeFragment,
|
|
3889
3544
|
resolveFamily,
|
|
3890
|
-
resolveModifiersForProduct,
|
|
3891
3545
|
resolveTemplate,
|
|
3892
3546
|
resolveUnit,
|
|
3893
3547
|
roundToPrecision,
|