@final-commerce/common 2.1.1 → 2.2.0-beta.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/bin/gate-save.mjs +20 -1
- package/dist/index.d.mts +78 -1
- package/dist/index.d.ts +78 -1
- package/dist/index.js +325 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +299 -1
- package/dist/index.mjs.map +1 -1
- package/dist/pos-types/index.d.mts +35 -0
- package/dist/pos-types/index.d.ts +35 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ __export(index_exports, {
|
|
|
31
31
|
DEFAULT_CROSS_AXIS_RULES: () => DEFAULT_CROSS_AXIS_RULES,
|
|
32
32
|
DEFAULT_DISPLAY_STATE_MAP: () => DEFAULT_DISPLAY_STATE_MAP,
|
|
33
33
|
DEFAULT_RESOLVED_CONFIG: () => DEFAULT_RESOLVED_CONFIG,
|
|
34
|
+
DEFAULT_UNIT_ID: () => DEFAULT_UNIT_ID,
|
|
34
35
|
DualWriteStrategy: () => DualWriteStrategy,
|
|
35
36
|
EUFixedRates: () => EUFixedRates,
|
|
36
37
|
EUROPE: () => EUROPE,
|
|
@@ -43,6 +44,7 @@ __export(index_exports, {
|
|
|
43
44
|
InvoiceStatus: () => InvoiceStatus,
|
|
44
45
|
LegacyWriteStrategy: () => LegacyWriteStrategy,
|
|
45
46
|
LibraryItemType: () => LibraryItemType,
|
|
47
|
+
MAX_PRECISION: () => MAX_PRECISION,
|
|
46
48
|
MenuProject: () => MenuProject,
|
|
47
49
|
NAFixedRates: () => NAFixedRates,
|
|
48
50
|
NORTH_AMERICA: () => NORTH_AMERICA,
|
|
@@ -75,6 +77,10 @@ __export(index_exports, {
|
|
|
75
77
|
ResidualStatus: () => ResidualStatus,
|
|
76
78
|
STATE_SCHEMA: () => STATE_SCHEMA,
|
|
77
79
|
STRIPE_SUPPORTED_COUNTRIES: () => STRIPE_SUPPORTED_COUNTRIES,
|
|
80
|
+
SYSTEM_FAMILIES: () => SYSTEM_FAMILIES,
|
|
81
|
+
SYSTEM_FAMILY_IDS: () => SYSTEM_FAMILY_IDS,
|
|
82
|
+
SYSTEM_UNITS: () => SYSTEM_UNITS,
|
|
83
|
+
SYSTEM_UNIT_IDS: () => SYSTEM_UNIT_IDS,
|
|
78
84
|
StationStatus: () => StationStatus,
|
|
79
85
|
StripeCurrencyCode: () => StripeCurrencyCode,
|
|
80
86
|
StripeStatus: () => StripeStatus,
|
|
@@ -83,7 +89,11 @@ __export(index_exports, {
|
|
|
83
89
|
UserTypes: () => UserTypes,
|
|
84
90
|
addAmounts: () => addAmounts,
|
|
85
91
|
amountToString: () => amountToString,
|
|
92
|
+
assertUnitSane: () => assertUnitSane,
|
|
93
|
+
availableIn: () => availableIn,
|
|
94
|
+
baseFor: () => baseFor,
|
|
86
95
|
baseFulfillmentDefinitions: () => baseFulfillmentDefinitions,
|
|
96
|
+
baseOf: () => baseOf,
|
|
87
97
|
basePaymentDefinitions: () => basePaymentDefinitions,
|
|
88
98
|
buildOrderContext: () => buildOrderContext,
|
|
89
99
|
buildPosPresetConfig: () => buildPosPresetConfig,
|
|
@@ -95,12 +105,19 @@ __export(index_exports, {
|
|
|
95
105
|
createAmount: () => createAmount,
|
|
96
106
|
crossAxisRuleApplies: () => crossAxisRuleApplies,
|
|
97
107
|
deriveDisplayState: () => deriveDisplayState,
|
|
108
|
+
deriveFamilyCode: () => deriveFamilyCode,
|
|
109
|
+
deriveUnitId: () => deriveUnitId,
|
|
98
110
|
displayRuleMatchesPair: () => displayRuleMatchesPair,
|
|
99
111
|
divideAmount: () => divideAmount,
|
|
100
112
|
evaluateCondition: () => evaluateCondition,
|
|
101
113
|
evaluateConditionSet: () => evaluateConditionSet,
|
|
114
|
+
extendPrice: () => extendPrice,
|
|
115
|
+
extendPriceFor: () => extendPriceFor,
|
|
102
116
|
formatCurrency: () => formatCurrency,
|
|
117
|
+
formatInUnit: () => formatInUnit,
|
|
103
118
|
formatMinorUnitsToString: () => formatMinorUnitsToString,
|
|
119
|
+
formatQuantity: () => formatQuantity,
|
|
120
|
+
fromBase: () => fromBase,
|
|
104
121
|
fromMinorUnits: () => fromMinorUnits,
|
|
105
122
|
generateMongoID: () => generateMongoID,
|
|
106
123
|
getAvailableTransitions: () => getAvailableTransitions,
|
|
@@ -122,7 +139,11 @@ __export(index_exports, {
|
|
|
122
139
|
isFulfillmentState: () => isFulfillmentState,
|
|
123
140
|
isPaymentState: () => isPaymentState,
|
|
124
141
|
isSupportedCurrency: () => isSupportedCurrency,
|
|
142
|
+
isSystemFamilyCode: () => isSystemFamilyCode,
|
|
143
|
+
isValidQuantity: () => isValidQuantity,
|
|
144
|
+
isWhole: () => isWhole,
|
|
125
145
|
mapToLegacyStatus: () => mapToLegacyStatus,
|
|
146
|
+
maxPrecisionFor: () => maxPrecisionFor,
|
|
126
147
|
mergeFragment: () => mergeFragment,
|
|
127
148
|
multiplyAmount: () => multiplyAmount,
|
|
128
149
|
normalizeMongoIdString: () => normalizeMongoIdString,
|
|
@@ -130,11 +151,16 @@ __export(index_exports, {
|
|
|
130
151
|
parseCurrencyCode: () => parseCurrencyCode,
|
|
131
152
|
parseStripeCurrencyCode: () => parseStripeCurrencyCode,
|
|
132
153
|
removeFragment: () => removeFragment,
|
|
154
|
+
resolveFamily: () => resolveFamily,
|
|
133
155
|
resolveTemplate: () => resolveTemplate,
|
|
156
|
+
resolveUnit: () => resolveUnit,
|
|
157
|
+
roundToPrecision: () => roundToPrecision,
|
|
158
|
+
sameFamily: () => sameFamily,
|
|
134
159
|
setOrderState: () => setOrderState,
|
|
135
160
|
signReportForDisplay: () => signReportForDisplay,
|
|
136
161
|
stringifyMinorUnits: () => stringifyMinorUnits,
|
|
137
162
|
subtractAmounts: () => subtractAmounts,
|
|
163
|
+
toBase: () => toBase,
|
|
138
164
|
toMinorUnits: () => toMinorUnits,
|
|
139
165
|
validateConfig: () => validateConfig,
|
|
140
166
|
validateFragmentCompatibility: () => validateFragmentCompatibility,
|
|
@@ -372,6 +398,7 @@ var InventorySpecificActionType = /* @__PURE__ */ ((InventorySpecificActionType2
|
|
|
372
398
|
InventorySpecificActionType2["REFUND_RESTOCK_RETURN"] = "REFUND_RESTOCK_RETURN";
|
|
373
399
|
InventorySpecificActionType2["REFUND_DAMAGE"] = "REFUND_DAMAGE";
|
|
374
400
|
InventorySpecificActionType2["SALE"] = "SALE";
|
|
401
|
+
InventorySpecificActionType2["COMPOSED_FOR_SALE"] = "COMPOSED_FOR_SALE";
|
|
375
402
|
InventorySpecificActionType2["TRANSFER"] = "TRANSFER";
|
|
376
403
|
InventorySpecificActionType2["BULK_RECOUNT"] = "BULK_RECOUNT";
|
|
377
404
|
InventorySpecificActionType2["APPLIED_FROM_WOO"] = "APPLIED_FROM_WOO";
|
|
@@ -861,6 +888,252 @@ function amountToString(amount) {
|
|
|
861
888
|
return majorValue.toFixed(amount.minorUnits);
|
|
862
889
|
}
|
|
863
890
|
|
|
891
|
+
// units/system-units.ts
|
|
892
|
+
var SYSTEM_FAMILY_IDS = {
|
|
893
|
+
COUNT: "count",
|
|
894
|
+
WEIGHT: "weight-metric",
|
|
895
|
+
WEIGHT_IMPERIAL: "weight-imperial",
|
|
896
|
+
VOLUME: "volume-metric",
|
|
897
|
+
VOLUME_IMPERIAL: "volume-imperial",
|
|
898
|
+
LENGTH: "length-metric",
|
|
899
|
+
LENGTH_IMPERIAL: "length-imperial",
|
|
900
|
+
AREA: "area-metric",
|
|
901
|
+
AREA_IMPERIAL: "area-imperial"
|
|
902
|
+
};
|
|
903
|
+
var SYSTEM_UNIT_IDS = {
|
|
904
|
+
EACH: "EA",
|
|
905
|
+
GRAM: "GRM",
|
|
906
|
+
KILOGRAM: "KGM",
|
|
907
|
+
/** 100 g is a hectogram; the merchant-facing name stays "100 g". */
|
|
908
|
+
HECTOGRAM: "HGM",
|
|
909
|
+
MILLILITRE: "MLT",
|
|
910
|
+
LITRE: "LTR"
|
|
911
|
+
};
|
|
912
|
+
var SYSTEM_FAMILIES = [
|
|
913
|
+
{
|
|
914
|
+
familyId: SYSTEM_FAMILY_IDS.COUNT,
|
|
915
|
+
companyId: null,
|
|
916
|
+
name: "Count",
|
|
917
|
+
base: { name: "Piece", abbreviation: "ea", ratioToBase: 1, precision: 0 }
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
familyId: SYSTEM_FAMILY_IDS.WEIGHT,
|
|
921
|
+
companyId: null,
|
|
922
|
+
name: "Weight",
|
|
923
|
+
base: { name: "Gram", abbreviation: "g", ratioToBase: 1, precision: 0 }
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
familyId: SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL,
|
|
927
|
+
companyId: null,
|
|
928
|
+
name: "Weight (imperial)",
|
|
929
|
+
base: { name: "Hundred-thousandth of an ounce", abbreviation: "10\u207B\u2075 oz", ratioToBase: 1, precision: 0 }
|
|
930
|
+
},
|
|
931
|
+
{
|
|
932
|
+
familyId: SYSTEM_FAMILY_IDS.VOLUME,
|
|
933
|
+
companyId: null,
|
|
934
|
+
name: "Volume",
|
|
935
|
+
base: { name: "Millilitre", abbreviation: "ml", ratioToBase: 1, precision: 0 }
|
|
936
|
+
},
|
|
937
|
+
{
|
|
938
|
+
// Cubic inches, not fluid ounces: a US gallon is 231 in³ and 128 fl oz, and 231 = 3 × 7 × 11.
|
|
939
|
+
// With an ounce base the board foot lands on 6144000/77 — and lumber is the reason this family
|
|
940
|
+
// exists at all.
|
|
941
|
+
familyId: SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL,
|
|
942
|
+
companyId: null,
|
|
943
|
+
name: "Volume (imperial)",
|
|
944
|
+
base: { name: "1/128000 cubic inch", abbreviation: "\xB5in\xB3", ratioToBase: 1, precision: 0 }
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
familyId: SYSTEM_FAMILY_IDS.LENGTH,
|
|
948
|
+
companyId: null,
|
|
949
|
+
name: "Length",
|
|
950
|
+
base: { name: "Millimetre", abbreviation: "mm", ratioToBase: 1, precision: 0 }
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
familyId: SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL,
|
|
954
|
+
companyId: null,
|
|
955
|
+
name: "Length (imperial)",
|
|
956
|
+
base: { name: "Millionth of an inch", abbreviation: "\xB5in", ratioToBase: 1, precision: 0 }
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
familyId: SYSTEM_FAMILY_IDS.AREA,
|
|
960
|
+
companyId: null,
|
|
961
|
+
name: "Area",
|
|
962
|
+
base: { name: "Square millimetre", abbreviation: "mm\xB2", ratioToBase: 1, precision: 0 }
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
familyId: SYSTEM_FAMILY_IDS.AREA_IMPERIAL,
|
|
966
|
+
companyId: null,
|
|
967
|
+
name: "Area (imperial)",
|
|
968
|
+
base: { name: "Thousandth of a square inch", abbreviation: "m-sq in", ratioToBase: 1, precision: 0 }
|
|
969
|
+
}
|
|
970
|
+
];
|
|
971
|
+
var unit = (unitId, familyId, name, abbreviation, ratioToBase, precision) => ({ unitId, companyId: null, familyId, name, abbreviation, ratioToBase, precision });
|
|
972
|
+
var SELLABLE_UNITS = [
|
|
973
|
+
// ── Count ────────────────────────────────────────────────────────────────
|
|
974
|
+
unit("EA", SYSTEM_FAMILY_IDS.COUNT, "Each", "ea", 1, 0),
|
|
975
|
+
unit("PR", SYSTEM_FAMILY_IDS.COUNT, "Pair", "pr", 2, 0),
|
|
976
|
+
unit("DZN", SYSTEM_FAMILY_IDS.COUNT, "Dozen", "dz", 12, 0),
|
|
977
|
+
unit("GRO", SYSTEM_FAMILY_IDS.COUNT, "Gross", "gro", 144, 0),
|
|
978
|
+
unit("CEN", SYSTEM_FAMILY_IDS.COUNT, "Hundred", "C", 100, 0),
|
|
979
|
+
unit("MIL", SYSTEM_FAMILY_IDS.COUNT, "Thousand", "M", 1e3, 0),
|
|
980
|
+
// ── Weight, metric ───────────────────────────────────────────────────────
|
|
981
|
+
unit("GRM", SYSTEM_FAMILY_IDS.WEIGHT, "Gram", "g", 1, 0),
|
|
982
|
+
unit("HGM", SYSTEM_FAMILY_IDS.WEIGHT, "100 g", "100g", 100, 2),
|
|
983
|
+
unit("KGM", SYSTEM_FAMILY_IDS.WEIGHT, "Kilogram", "kg", 1e3, 3),
|
|
984
|
+
unit("TNE", SYSTEM_FAMILY_IDS.WEIGHT, "Tonne", "t", 1e6, 3),
|
|
985
|
+
// ── Weight, imperial ─────────────────────────────────────────────────────
|
|
986
|
+
unit("ONZ", SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, "Ounce", "oz", 1e5, 2),
|
|
987
|
+
unit("LBR", SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, "Pound", "lb", 16e5, 2),
|
|
988
|
+
unit("STI", SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, "Stone", "st", 224e5, 2),
|
|
989
|
+
// `(US)` is not decoration: Rec 20 also carries `CWI`, the UK hundredweight, at 112 lb — 12 % more.
|
|
990
|
+
// The code here is the right one; an unqualified "cwt" on screen is what would be ambiguous.
|
|
991
|
+
unit("CWA", SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, "Hundredweight (US)", "cwt (US)", 16e7, 2),
|
|
992
|
+
unit("STN", SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, "Ton (short)", "tn", 32e8, 3),
|
|
993
|
+
// ── Volume, metric ───────────────────────────────────────────────────────
|
|
994
|
+
unit("MLT", SYSTEM_FAMILY_IDS.VOLUME, "Millilitre", "ml", 1, 0),
|
|
995
|
+
unit("CLT", SYSTEM_FAMILY_IDS.VOLUME, "Centilitre", "cl", 10, 1),
|
|
996
|
+
unit("LTR", SYSTEM_FAMILY_IDS.VOLUME, "Litre", "l", 1e3, 3),
|
|
997
|
+
unit("HLT", SYSTEM_FAMILY_IDS.VOLUME, "Hectolitre", "hl", 1e5, 3),
|
|
998
|
+
unit("MTQ", SYSTEM_FAMILY_IDS.VOLUME, "Cubic metre", "m\xB3", 1e6, 3),
|
|
999
|
+
// ── Volume, imperial ─────────────────────────────────────────────────────
|
|
1000
|
+
unit("OZA", SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, "Fluid ounce", "fl oz", 231e3, 2),
|
|
1001
|
+
unit("PTL", SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, "Pint", "pt", 3696e3, 2),
|
|
1002
|
+
unit("QTL", SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, "Quart", "qt", 7392e3, 2),
|
|
1003
|
+
unit("GLL", SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, "Gallon", "gal", 29568e3, 3),
|
|
1004
|
+
unit("INQ", SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, "Cubic inch", "in\xB3", 128e3, 2),
|
|
1005
|
+
unit("BFT", SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, "Board foot", "fbm", 18432e3, 2),
|
|
1006
|
+
unit("FTQ", SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, "Cubic foot", "ft\xB3", 221184e3, 3),
|
|
1007
|
+
unit("YDQ", SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, "Cubic yard", "yd\xB3", 5971968e3, 3),
|
|
1008
|
+
// ── Length, metric ───────────────────────────────────────────────────────
|
|
1009
|
+
unit("MMT", SYSTEM_FAMILY_IDS.LENGTH, "Millimetre", "mm", 1, 0),
|
|
1010
|
+
unit("CMT", SYSTEM_FAMILY_IDS.LENGTH, "Centimetre", "cm", 10, 1),
|
|
1011
|
+
unit("MTR", SYSTEM_FAMILY_IDS.LENGTH, "Metre", "m", 1e3, 3),
|
|
1012
|
+
unit("KMT", SYSTEM_FAMILY_IDS.LENGTH, "Kilometre", "km", 1e6, 3),
|
|
1013
|
+
// ── Length, imperial ─────────────────────────────────────────────────────
|
|
1014
|
+
// `INH` carries four decimals, not three: an eighth of an inch is 0.125 but a sixteenth is
|
|
1015
|
+
// 0.0625, and sixteenths are the everyday fraction on a tape measure. A thirty-second needs five,
|
|
1016
|
+
// which is the ceiling; a sixty-fourth has no decimal form at all and is a question about
|
|
1017
|
+
// fraction input, not about precision.
|
|
1018
|
+
unit("INH", SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, "Inch", "in", 1e6, 4),
|
|
1019
|
+
unit("FOT", SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, "Foot", "ft", 12e6, 3),
|
|
1020
|
+
unit("LF", SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, "Linear foot", "lin ft", 12e6, 2),
|
|
1021
|
+
unit("YRD", SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, "Yard", "yd", 36e6, 3),
|
|
1022
|
+
unit("SMI", SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, "Mile", "mi", 6336e7, 3),
|
|
1023
|
+
// ── Area, metric ─────────────────────────────────────────────────────────
|
|
1024
|
+
unit("MMK", SYSTEM_FAMILY_IDS.AREA, "Square millimetre", "mm\xB2", 1, 0),
|
|
1025
|
+
unit("CMK", SYSTEM_FAMILY_IDS.AREA, "Square centimetre", "cm\xB2", 100, 2),
|
|
1026
|
+
unit("MTK", SYSTEM_FAMILY_IDS.AREA, "Square metre", "m\xB2", 1e6, 3),
|
|
1027
|
+
unit("HAR", SYSTEM_FAMILY_IDS.AREA, "Hectare", "ha", 1e10, 3),
|
|
1028
|
+
// ── Area, imperial ───────────────────────────────────────────────────────
|
|
1029
|
+
unit("INK", SYSTEM_FAMILY_IDS.AREA_IMPERIAL, "Square inch", "sq in", 1e3, 2),
|
|
1030
|
+
unit("FTK", SYSTEM_FAMILY_IDS.AREA_IMPERIAL, "Square foot", "sq ft", 144e3, 2),
|
|
1031
|
+
unit("YDK", SYSTEM_FAMILY_IDS.AREA_IMPERIAL, "Square yard", "sq yd", 1296e3, 2),
|
|
1032
|
+
// A roofing square is exactly 100 square feet — a trade unit with a precise definition, which is
|
|
1033
|
+
// why it is a real row and not a label.
|
|
1034
|
+
unit("SQR", SYSTEM_FAMILY_IDS.AREA_IMPERIAL, "Square (roofing)", "sq", 144e5, 2),
|
|
1035
|
+
unit("ACR", SYSTEM_FAMILY_IDS.AREA_IMPERIAL, "Acre", "ac", 627264e4, 2)
|
|
1036
|
+
];
|
|
1037
|
+
var BASE_UNITS = SYSTEM_FAMILIES.filter(
|
|
1038
|
+
(family) => !SELLABLE_UNITS.some((u) => u.familyId === family.familyId && u.ratioToBase === 1)
|
|
1039
|
+
).map((family) => ({
|
|
1040
|
+
unitId: `${family.familyId}-base`,
|
|
1041
|
+
companyId: null,
|
|
1042
|
+
familyId: family.familyId,
|
|
1043
|
+
name: family.base.name,
|
|
1044
|
+
abbreviation: family.base.abbreviation,
|
|
1045
|
+
ratioToBase: 1,
|
|
1046
|
+
precision: 0,
|
|
1047
|
+
sellable: false
|
|
1048
|
+
}));
|
|
1049
|
+
var SYSTEM_UNITS = [...SELLABLE_UNITS, ...BASE_UNITS];
|
|
1050
|
+
var DEFAULT_UNIT_ID = SYSTEM_UNIT_IDS.EACH;
|
|
1051
|
+
|
|
1052
|
+
// units/convert.ts
|
|
1053
|
+
var EPSILON = 1e-9;
|
|
1054
|
+
function isWhole(value) {
|
|
1055
|
+
return Math.abs(value - Math.round(value)) <= EPSILON * Math.max(1, Math.abs(value));
|
|
1056
|
+
}
|
|
1057
|
+
var MAX_PRECISION = 5;
|
|
1058
|
+
function resolveUnit(unitId, companyUnits = []) {
|
|
1059
|
+
const unit2 = SYSTEM_UNITS.find((u) => u.unitId === unitId) ?? companyUnits.find((u) => u.unitId === unitId);
|
|
1060
|
+
if (!unit2) throw new Error(`Unknown measurement unit: ${unitId}`);
|
|
1061
|
+
return unit2;
|
|
1062
|
+
}
|
|
1063
|
+
function resolveFamily(familyId, companyFamilies = []) {
|
|
1064
|
+
const family = SYSTEM_FAMILIES.find((f) => f.familyId === familyId) ?? companyFamilies.find((f) => f.familyId === familyId);
|
|
1065
|
+
if (!family) throw new Error(`Unknown measurement unit family: ${familyId}`);
|
|
1066
|
+
return family;
|
|
1067
|
+
}
|
|
1068
|
+
function baseOf(familyId, companyFamilies = []) {
|
|
1069
|
+
return resolveFamily(familyId, companyFamilies).base;
|
|
1070
|
+
}
|
|
1071
|
+
function baseFor(unit2, companyFamilies = []) {
|
|
1072
|
+
return baseOf(unit2.familyId, companyFamilies);
|
|
1073
|
+
}
|
|
1074
|
+
function sameFamily(a, b) {
|
|
1075
|
+
return a.familyId === b.familyId;
|
|
1076
|
+
}
|
|
1077
|
+
function assertUnitSane(unit2) {
|
|
1078
|
+
const { ratioToBase, precision, name } = unit2;
|
|
1079
|
+
if (!Number.isInteger(ratioToBase) || ratioToBase < 1)
|
|
1080
|
+
throw new Error(`Unit "${name}": ratioToBase must be a positive integer, got ${ratioToBase}`);
|
|
1081
|
+
if (!Number.isInteger(precision) || precision < 0 || precision > MAX_PRECISION)
|
|
1082
|
+
throw new Error(`Unit "${name}": precision must be an integer 0\u2013${MAX_PRECISION}, got ${precision}`);
|
|
1083
|
+
if (ratioToBase % 10 ** precision !== 0)
|
|
1084
|
+
throw new Error(
|
|
1085
|
+
`Unit "${name}": precision ${precision} is finer than a ratio of ${ratioToBase} allows \u2014 at most ${maxPrecisionFor(ratioToBase)}. For anything finer the family needs a smaller base unit.`
|
|
1086
|
+
);
|
|
1087
|
+
}
|
|
1088
|
+
function maxPrecisionFor(ratioToBase) {
|
|
1089
|
+
if (!Number.isInteger(ratioToBase) || ratioToBase < 1)
|
|
1090
|
+
throw new Error(`ratioToBase must be a positive integer, got ${ratioToBase}`);
|
|
1091
|
+
let precision = 0;
|
|
1092
|
+
while (precision < MAX_PRECISION && ratioToBase % 10 ** (precision + 1) === 0) precision++;
|
|
1093
|
+
return precision;
|
|
1094
|
+
}
|
|
1095
|
+
function isValidQuantity(quantity, unit2) {
|
|
1096
|
+
if (!Number.isFinite(quantity) || quantity < 0) return false;
|
|
1097
|
+
return isWhole(quantity * 10 ** unit2.precision);
|
|
1098
|
+
}
|
|
1099
|
+
function toBase(quantity, unit2) {
|
|
1100
|
+
const exact = quantity * unit2.ratioToBase;
|
|
1101
|
+
const whole = Math.round(exact);
|
|
1102
|
+
if (!isWhole(exact))
|
|
1103
|
+
throw new Error(
|
|
1104
|
+
`${quantity} ${unit2.abbreviation} is ${exact} base units \u2014 not whole. Check the quantity against precision ${unit2.precision}.`
|
|
1105
|
+
);
|
|
1106
|
+
return whole;
|
|
1107
|
+
}
|
|
1108
|
+
function fromBase(baseQuantity, unit2) {
|
|
1109
|
+
return baseQuantity / unit2.ratioToBase;
|
|
1110
|
+
}
|
|
1111
|
+
function availableIn(baseQuantity, unit2) {
|
|
1112
|
+
const step = unit2.ratioToBase / 10 ** unit2.precision;
|
|
1113
|
+
return Math.floor(baseQuantity / step) / 10 ** unit2.precision;
|
|
1114
|
+
}
|
|
1115
|
+
function formatQuantity(baseQuantity, unit2) {
|
|
1116
|
+
return fromBase(baseQuantity, unit2).toFixed(unit2.precision);
|
|
1117
|
+
}
|
|
1118
|
+
function formatInUnit(quantity, unit2) {
|
|
1119
|
+
return quantity.toFixed(unit2.precision);
|
|
1120
|
+
}
|
|
1121
|
+
function roundToPrecision(quantity, precision) {
|
|
1122
|
+
const scale = 10 ** precision;
|
|
1123
|
+
return Math.round(quantity * scale) / scale;
|
|
1124
|
+
}
|
|
1125
|
+
function extendPrice(priceMinor, quantity) {
|
|
1126
|
+
const scale = 10 ** MAX_PRECISION;
|
|
1127
|
+
const scaled = BigInt(Math.round(priceMinor)) * BigInt(Math.round(quantity * scale));
|
|
1128
|
+
const divisor = BigInt(scale);
|
|
1129
|
+
return Number((scaled + divisor / 2n) / divisor);
|
|
1130
|
+
}
|
|
1131
|
+
function extendPriceFor(priceMinor, quantity, unit2) {
|
|
1132
|
+
if (!isValidQuantity(quantity, unit2))
|
|
1133
|
+
throw new Error(`${quantity} ${unit2.abbreviation} has more decimals than precision ${unit2.precision} allows.`);
|
|
1134
|
+
return extendPrice(priceMinor, quantity);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
864
1137
|
// utils/order-totals.util.ts
|
|
865
1138
|
function toMinorUnits2(value) {
|
|
866
1139
|
return Number(value) || 0;
|
|
@@ -878,7 +1151,7 @@ function getSettlementTotal(payments, tipTotal) {
|
|
|
878
1151
|
return toMinorUnits2(payments?.cardTotal) + toMinorUnits2(payments?.cashTotal) + toMinorUnits2(payments?.customTotal) + toMinorUnits2(tipTotal);
|
|
879
1152
|
}
|
|
880
1153
|
function getLineSubtotal(price, quantity) {
|
|
881
|
-
return toMinorUnits2(price)
|
|
1154
|
+
return extendPrice(toMinorUnits2(price), toMinorUnits2(quantity));
|
|
882
1155
|
}
|
|
883
1156
|
function getGoodsPortion(total, totalTax) {
|
|
884
1157
|
return toMinorUnits2(total) - toMinorUnits2(totalTax);
|
|
@@ -1202,6 +1475,31 @@ function normalizeMongoIdString(value) {
|
|
|
1202
1475
|
return null;
|
|
1203
1476
|
}
|
|
1204
1477
|
|
|
1478
|
+
// units/family-code.ts
|
|
1479
|
+
var MAX_SLUG_LENGTH = 32;
|
|
1480
|
+
var FALLBACK_SLUG = "family";
|
|
1481
|
+
var SYSTEM_FAMILY_CODES = new Set(SYSTEM_FAMILIES.map((family) => family.familyId));
|
|
1482
|
+
function slugify(name) {
|
|
1483
|
+
const slug = name.normalize("NFKD").replace(/\p{Diacritic}/gu, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, MAX_SLUG_LENGTH).replace(/^-+|-+$/g, "");
|
|
1484
|
+
return slug || FALLBACK_SLUG;
|
|
1485
|
+
}
|
|
1486
|
+
function deriveFamilyCode(name, companyId, takenCodes = []) {
|
|
1487
|
+
if (!companyId) throw new Error(`Cannot derive a family code for "${name}" without a companyId.`);
|
|
1488
|
+
const taken = new Set(takenCodes);
|
|
1489
|
+
const slug = slugify(name);
|
|
1490
|
+
for (let attempt = 1; ; attempt++) {
|
|
1491
|
+
const code = attempt === 1 ? `${slug}-${companyId}` : `${slug}-${attempt}-${companyId}`;
|
|
1492
|
+
if (!taken.has(code) && !isSystemFamilyCode(code)) return code;
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
function isSystemFamilyCode(code) {
|
|
1496
|
+
return SYSTEM_FAMILY_CODES.has(code);
|
|
1497
|
+
}
|
|
1498
|
+
function deriveUnitId(abbreviation, documentId) {
|
|
1499
|
+
if (!documentId) throw new Error(`Cannot derive a unit id for "${abbreviation}" without a document id.`);
|
|
1500
|
+
return `${slugify(abbreviation)}-${documentId}`;
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1205
1503
|
// order-state-machine/types.ts
|
|
1206
1504
|
var PAYMENT_STATES = [
|
|
1207
1505
|
"unpaid",
|
|
@@ -2632,6 +2930,7 @@ var DualWriteStrategy = class {
|
|
|
2632
2930
|
DEFAULT_CROSS_AXIS_RULES,
|
|
2633
2931
|
DEFAULT_DISPLAY_STATE_MAP,
|
|
2634
2932
|
DEFAULT_RESOLVED_CONFIG,
|
|
2933
|
+
DEFAULT_UNIT_ID,
|
|
2635
2934
|
DualWriteStrategy,
|
|
2636
2935
|
EUFixedRates,
|
|
2637
2936
|
EUROPE,
|
|
@@ -2644,6 +2943,7 @@ var DualWriteStrategy = class {
|
|
|
2644
2943
|
InvoiceStatus,
|
|
2645
2944
|
LegacyWriteStrategy,
|
|
2646
2945
|
LibraryItemType,
|
|
2946
|
+
MAX_PRECISION,
|
|
2647
2947
|
MenuProject,
|
|
2648
2948
|
NAFixedRates,
|
|
2649
2949
|
NORTH_AMERICA,
|
|
@@ -2676,6 +2976,10 @@ var DualWriteStrategy = class {
|
|
|
2676
2976
|
ResidualStatus,
|
|
2677
2977
|
STATE_SCHEMA,
|
|
2678
2978
|
STRIPE_SUPPORTED_COUNTRIES,
|
|
2979
|
+
SYSTEM_FAMILIES,
|
|
2980
|
+
SYSTEM_FAMILY_IDS,
|
|
2981
|
+
SYSTEM_UNITS,
|
|
2982
|
+
SYSTEM_UNIT_IDS,
|
|
2679
2983
|
StationStatus,
|
|
2680
2984
|
StripeCurrencyCode,
|
|
2681
2985
|
StripeStatus,
|
|
@@ -2684,7 +2988,11 @@ var DualWriteStrategy = class {
|
|
|
2684
2988
|
UserTypes,
|
|
2685
2989
|
addAmounts,
|
|
2686
2990
|
amountToString,
|
|
2991
|
+
assertUnitSane,
|
|
2992
|
+
availableIn,
|
|
2993
|
+
baseFor,
|
|
2687
2994
|
baseFulfillmentDefinitions,
|
|
2995
|
+
baseOf,
|
|
2688
2996
|
basePaymentDefinitions,
|
|
2689
2997
|
buildOrderContext,
|
|
2690
2998
|
buildPosPresetConfig,
|
|
@@ -2696,12 +3004,19 @@ var DualWriteStrategy = class {
|
|
|
2696
3004
|
createAmount,
|
|
2697
3005
|
crossAxisRuleApplies,
|
|
2698
3006
|
deriveDisplayState,
|
|
3007
|
+
deriveFamilyCode,
|
|
3008
|
+
deriveUnitId,
|
|
2699
3009
|
displayRuleMatchesPair,
|
|
2700
3010
|
divideAmount,
|
|
2701
3011
|
evaluateCondition,
|
|
2702
3012
|
evaluateConditionSet,
|
|
3013
|
+
extendPrice,
|
|
3014
|
+
extendPriceFor,
|
|
2703
3015
|
formatCurrency,
|
|
3016
|
+
formatInUnit,
|
|
2704
3017
|
formatMinorUnitsToString,
|
|
3018
|
+
formatQuantity,
|
|
3019
|
+
fromBase,
|
|
2705
3020
|
fromMinorUnits,
|
|
2706
3021
|
generateMongoID,
|
|
2707
3022
|
getAvailableTransitions,
|
|
@@ -2723,7 +3038,11 @@ var DualWriteStrategy = class {
|
|
|
2723
3038
|
isFulfillmentState,
|
|
2724
3039
|
isPaymentState,
|
|
2725
3040
|
isSupportedCurrency,
|
|
3041
|
+
isSystemFamilyCode,
|
|
3042
|
+
isValidQuantity,
|
|
3043
|
+
isWhole,
|
|
2726
3044
|
mapToLegacyStatus,
|
|
3045
|
+
maxPrecisionFor,
|
|
2727
3046
|
mergeFragment,
|
|
2728
3047
|
multiplyAmount,
|
|
2729
3048
|
normalizeMongoIdString,
|
|
@@ -2731,11 +3050,16 @@ var DualWriteStrategy = class {
|
|
|
2731
3050
|
parseCurrencyCode,
|
|
2732
3051
|
parseStripeCurrencyCode,
|
|
2733
3052
|
removeFragment,
|
|
3053
|
+
resolveFamily,
|
|
2734
3054
|
resolveTemplate,
|
|
3055
|
+
resolveUnit,
|
|
3056
|
+
roundToPrecision,
|
|
3057
|
+
sameFamily,
|
|
2735
3058
|
setOrderState,
|
|
2736
3059
|
signReportForDisplay,
|
|
2737
3060
|
stringifyMinorUnits,
|
|
2738
3061
|
subtractAmounts,
|
|
3062
|
+
toBase,
|
|
2739
3063
|
toMinorUnits,
|
|
2740
3064
|
validateConfig,
|
|
2741
3065
|
validateFragmentCompatibility,
|