@pisell/pisellos 2.3.101 → 2.3.102

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.
Files changed (52) hide show
  1. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
  2. package/dist/model/strategy/adapter/dataVariant/evaluator.js +287 -101
  3. package/dist/model/strategy/adapter/dataVariant/type.d.ts +25 -0
  4. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  5. package/dist/modules/Discount/index.d.ts +2 -0
  6. package/dist/modules/Discount/index.js +38 -5
  7. package/dist/modules/Discount/types.d.ts +11 -0
  8. package/dist/modules/Order/index.d.ts +14 -0
  9. package/dist/modules/Order/index.js +617 -368
  10. package/dist/modules/Order/types.d.ts +11 -3
  11. package/dist/modules/Order/utils/virtualSettlement.d.ts +63 -0
  12. package/dist/modules/Order/utils/virtualSettlement.js +284 -0
  13. package/dist/modules/Order/utils.d.ts +1 -0
  14. package/dist/modules/Order/utils.js +63 -24
  15. package/dist/modules/Product/types.d.ts +23 -0
  16. package/dist/modules/SalesSummary/index.d.ts +1 -0
  17. package/dist/modules/SalesSummary/index.js +4 -3
  18. package/dist/modules/SalesSummary/types.d.ts +1 -0
  19. package/dist/modules/SalesSummary/utils.d.ts +1 -0
  20. package/dist/modules/SalesSummary/utils.js +21 -1
  21. package/dist/solution/BaseSales/index.d.ts +10 -1
  22. package/dist/solution/BaseSales/index.js +1099 -784
  23. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  24. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +72 -9
  25. package/dist/solution/BookingByStep/index.d.ts +1 -1
  26. package/dist/solution/BookingTicket/utils/addProductDecision.js +2 -1
  27. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
  28. package/lib/model/strategy/adapter/dataVariant/evaluator.js +137 -6
  29. package/lib/model/strategy/adapter/dataVariant/type.d.ts +25 -0
  30. package/lib/modules/Discount/index.d.ts +2 -0
  31. package/lib/modules/Discount/index.js +31 -2
  32. package/lib/modules/Discount/types.d.ts +11 -0
  33. package/lib/modules/Order/index.d.ts +14 -0
  34. package/lib/modules/Order/index.js +195 -15
  35. package/lib/modules/Order/types.d.ts +11 -3
  36. package/lib/modules/Order/utils/virtualSettlement.d.ts +63 -0
  37. package/lib/modules/Order/utils/virtualSettlement.js +262 -0
  38. package/lib/modules/Order/utils.d.ts +1 -0
  39. package/lib/modules/Order/utils.js +57 -20
  40. package/lib/modules/Product/types.d.ts +23 -0
  41. package/lib/modules/SalesSummary/index.d.ts +1 -0
  42. package/lib/modules/SalesSummary/index.js +4 -2
  43. package/lib/modules/SalesSummary/types.d.ts +1 -0
  44. package/lib/modules/SalesSummary/utils.d.ts +1 -0
  45. package/lib/modules/SalesSummary/utils.js +17 -1
  46. package/lib/solution/BaseSales/index.d.ts +10 -1
  47. package/lib/solution/BaseSales/index.js +211 -9
  48. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  49. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +38 -0
  50. package/lib/solution/BookingByStep/index.d.ts +1 -1
  51. package/lib/solution/BookingTicket/utils/addProductDecision.js +1 -0
  52. package/package.json +1 -1
@@ -46,6 +46,7 @@ export interface BaseProductDetailPayload {
46
46
  original_price?: number | string;
47
47
  tax_fee?: number | string;
48
48
  is_charge_tax?: number;
49
+ metadata?: Record<string, any>;
49
50
  note?: string;
50
51
  [key: string]: any;
51
52
  }
@@ -4,6 +4,13 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
5
5
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
6
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
8
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
9
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
10
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
11
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
12
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
13
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
7
14
  import { composeLinePrice, getBundleSellingMagnitude, normalizeProductSkuOptions, sumOptionUnitPrice } from "../../../modules/Order/utils";
8
15
  import { buildManualProductDiscountItem, mergeManualProductDiscountIntoList, resolveManualDiscountOriginTotal, resolveManualDiscountReasonFromSources, shouldBuildManualProductDiscount } from "../../../modules/Order/utils/manualProductDiscount";
9
16
  function toNumber(value) {
@@ -45,6 +52,54 @@ function firstNonBlank() {
45
52
  return !isBlankValue(value);
46
53
  });
47
54
  }
55
+
56
+ /**
57
+ * 取第一份接口权威 Data Variant 命中结果并复制数组。
58
+ * 空数组表示规则已计算但无命中,必须与字段缺失区分。
59
+ */
60
+ function cloneFirstDataVariantIds() {
61
+ for (var _len2 = arguments.length, values = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
62
+ values[_key2] = arguments[_key2];
63
+ }
64
+ var ids = values.find(function (value) {
65
+ return Array.isArray(value);
66
+ });
67
+ return Array.isArray(ids) ? _toConsumableArray(ids) : undefined;
68
+ }
69
+
70
+ /**
71
+ * 在接口权威命中结果后追加本地应用及最终选中的 Data Variant ID。
72
+ * 以字符串身份去重,同时将新增 ID 归一为正整数。
73
+ */
74
+ function appendDataVariantIds(base) {
75
+ var result = Array.isArray(base) ? _toConsumableArray(base) : [];
76
+ var seen = new Set(result.map(function (id) {
77
+ return String(id);
78
+ }));
79
+ for (var _len3 = arguments.length, values = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
80
+ values[_key3 - 1] = arguments[_key3];
81
+ }
82
+ for (var _i = 0, _values = values; _i < _values.length; _i++) {
83
+ var value = _values[_i];
84
+ var candidates = Array.isArray(value) ? value : [value];
85
+ var _iterator = _createForOfIteratorHelper(candidates),
86
+ _step;
87
+ try {
88
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
89
+ var candidate = _step.value;
90
+ var id = Number(candidate);
91
+ if (!Number.isFinite(id) || id <= 0 || seen.has(String(id))) continue;
92
+ result.push(id);
93
+ seen.add(String(id));
94
+ }
95
+ } catch (err) {
96
+ _iterator.e(err);
97
+ } finally {
98
+ _iterator.f();
99
+ }
100
+ }
101
+ return Array.isArray(base) || result.length ? result : undefined;
102
+ }
48
103
  function normalizeOptionItems(optionItems) {
49
104
  if (!Array.isArray(optionItems)) return [];
50
105
  return optionItems.map(function (optionItem) {
@@ -108,7 +163,7 @@ function findVariantById(origin, variantId) {
108
163
  * 注意:这里不生成 identity,缺省时由 OrderModule 自动补齐。
109
164
  */
110
165
  export function transformBaseProductToOrderProduct(params) {
111
- var _ref10, _ref11, _ref12, _payload$product_id, _ref13, _ref14, _payload$product_vari, _payload$_origin, _payload$_origin2, _ref15, _findVariantById, _origin$production_co, _ref16, _ref17, _ref18, _ref19, _ref20, _matchedVariant$price, _ref21, _ref22, _payload$price, _ref23, _payload$line_total, _payload$_extend, _ref24, _ref25, _payload$product_sku$, _payload$product_sku, _payload$bundle, _payload$quantity, _payload$_extend2, _extend, _extend2, _ref26, _ref27, _origin$base_price, _ref28, _ref29, _payload$line_total2, _payload$_extend3, _payload$_extend4, _extend3, _payload$_extend5, _payload$_extend6, _ref30, _ref31, _payload$tax_fee, _ref32, _ref33, _payload$is_charge_ta;
166
+ var _ref10, _ref11, _ref12, _payload$product_id, _ref13, _ref14, _payload$product_vari, _payload$_origin, _payload$_origin2, _payload$metadata, _sourceProduct$metada, _callbackOrigin$metad, _origin$metadata, _payload$metadata2, _payload$_extend, _sourceProduct$metada2, _sourceProduct$_exten, _callbackOrigin$metad2, _callbackOrigin$_exte, _payload$_dataVariant, _sourceProduct$_dataV, _callbackOrigin$_data, _origin$_dataVariant, _ref15, _findVariantById, _origin$production_co, _ref16, _ref17, _ref18, _ref19, _ref20, _matchedVariant$price, _ref21, _ref22, _payload$price, _ref23, _payload$line_total, _payload$_extend2, _ref24, _ref25, _payload$product_sku$, _payload$product_sku, _payload$bundle, _payload$quantity, _payload$_extend3, _extend, _extend2, _ref26, _ref27, _origin$base_price, _ref28, _ref29, _payload$line_total2, _payload$_extend4, _payload$_extend5, _extend3, _payload$_extend6, _payload$_extend7, _ref30, _ref31, _payload$tax_fee, _ref32, _ref33, _payload$is_charge_ta;
112
167
  var payload = params.payload,
113
168
  _params$fallbackProdu = params.fallbackProductId,
114
169
  fallbackProductId = _params$fallbackProdu === void 0 ? null : _params$fallbackProdu;
@@ -119,6 +174,10 @@ export function transformBaseProductToOrderProduct(params) {
119
174
  var productVariantId = toNumber((_ref13 = (_ref14 = (_payload$product_vari = payload.product_variant_id) !== null && _payload$product_vari !== void 0 ? _payload$product_vari : payload.variant_id) !== null && _ref14 !== void 0 ? _ref14 : sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.product_variant_id) !== null && _ref13 !== void 0 ? _ref13 : sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.variant_id, 0);
120
175
  var callbackOrigin = payload.origin || ((_payload$_origin = payload._origin) === null || _payload$_origin === void 0 ? void 0 : _payload$_origin.sourceProduct) || ((_payload$_origin2 = payload._origin) === null || _payload$_origin2 === void 0 ? void 0 : _payload$_origin2.sourceItem) || payload._origin || {};
121
176
  var origin = _objectSpread(_objectSpread({}, sourceProduct || {}), callbackOrigin || {});
177
+ var authoritativeDataVariantIds = cloneFirstDataVariantIds((_payload$metadata = payload.metadata) === null || _payload$metadata === void 0 ? void 0 : _payload$metadata.data_variant_ids, sourceProduct === null || sourceProduct === void 0 || (_sourceProduct$metada = sourceProduct.metadata) === null || _sourceProduct$metada === void 0 ? void 0 : _sourceProduct$metada.data_variant_ids, callbackOrigin === null || callbackOrigin === void 0 || (_callbackOrigin$metad = callbackOrigin.metadata) === null || _callbackOrigin$metad === void 0 ? void 0 : _callbackOrigin$metad.data_variant_ids, origin === null || origin === void 0 || (_origin$metadata = origin.metadata) === null || _origin$metadata === void 0 ? void 0 : _origin$metadata.data_variant_ids);
178
+ var selectedSettlementSnapshot = firstNonBlank(payload.selected_settlement_snapshot, (_payload$metadata2 = payload.metadata) === null || _payload$metadata2 === void 0 ? void 0 : _payload$metadata2.selected_settlement_snapshot, (_payload$_extend = payload._extend) === null || _payload$_extend === void 0 || (_payload$_extend = _payload$_extend.metadata) === null || _payload$_extend === void 0 ? void 0 : _payload$_extend.selected_settlement_snapshot, sourceProduct === null || sourceProduct === void 0 || (_sourceProduct$metada2 = sourceProduct.metadata) === null || _sourceProduct$metada2 === void 0 ? void 0 : _sourceProduct$metada2.selected_settlement_snapshot, sourceProduct === null || sourceProduct === void 0 || (_sourceProduct$_exten = sourceProduct._extend) === null || _sourceProduct$_exten === void 0 || (_sourceProduct$_exten = _sourceProduct$_exten.metadata) === null || _sourceProduct$_exten === void 0 ? void 0 : _sourceProduct$_exten.selected_settlement_snapshot, callbackOrigin === null || callbackOrigin === void 0 || (_callbackOrigin$metad2 = callbackOrigin.metadata) === null || _callbackOrigin$metad2 === void 0 ? void 0 : _callbackOrigin$metad2.selected_settlement_snapshot, callbackOrigin === null || callbackOrigin === void 0 || (_callbackOrigin$_exte = callbackOrigin._extend) === null || _callbackOrigin$_exte === void 0 || (_callbackOrigin$_exte = _callbackOrigin$_exte.metadata) === null || _callbackOrigin$_exte === void 0 ? void 0 : _callbackOrigin$_exte.selected_settlement_snapshot);
179
+ var locallyAppliedVariantIds = authoritativeDataVariantIds === undefined ? cloneFirstDataVariantIds((_payload$_dataVariant = payload._dataVariant) === null || _payload$_dataVariant === void 0 ? void 0 : _payload$_dataVariant.appliedVariantIds, sourceProduct === null || sourceProduct === void 0 || (_sourceProduct$_dataV = sourceProduct._dataVariant) === null || _sourceProduct$_dataV === void 0 ? void 0 : _sourceProduct$_dataV.appliedVariantIds, callbackOrigin === null || callbackOrigin === void 0 || (_callbackOrigin$_data = callbackOrigin._dataVariant) === null || _callbackOrigin$_data === void 0 ? void 0 : _callbackOrigin$_data.appliedVariantIds, origin === null || origin === void 0 || (_origin$_dataVariant = origin._dataVariant) === null || _origin$_dataVariant === void 0 ? void 0 : _origin$_dataVariant.appliedVariantIds) : undefined;
180
+ var dataVariantIds = appendDataVariantIds(authoritativeDataVariantIds, locallyAppliedVariantIds, selectedSettlementSnapshot === null || selectedSettlementSnapshot === void 0 ? void 0 : selectedSettlementSnapshot.data_variant_id);
122
181
  var matchedVariant = (_ref15 = (_findVariantById = findVariantById(callbackOrigin, productVariantId)) !== null && _findVariantById !== void 0 ? _findVariantById : findVariantById(sourceProduct, productVariantId)) !== null && _ref15 !== void 0 ? _ref15 : findVariantById(origin, productVariantId);
123
182
  var productionCode = normalizeProductionCode(Object.prototype.hasOwnProperty.call(payload, 'production_code') ? payload.production_code : productVariantId > 0 ? matchedVariant === null || matchedVariant === void 0 ? void 0 : matchedVariant.production_code : (_origin$production_co = origin === null || origin === void 0 ? void 0 : origin.production_code) !== null && _origin$production_co !== void 0 ? _origin$production_co : sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.production_code);
124
183
  var hasPriceOverride = payload.price_override !== undefined && payload.price_override !== null && payload.price_override !== '';
@@ -126,7 +185,7 @@ export function transformBaseProductToOrderProduct(params) {
126
185
  // 此时优先从商品/variant 快照读取目录价;售价仍由 line_total - bundle 推导。
127
186
  var catalogSourcePrice = (_ref16 = (_ref17 = (_ref18 = (_ref19 = (_ref20 = (_matchedVariant$price = matchedVariant === null || matchedVariant === void 0 ? void 0 : matchedVariant.price) !== null && _matchedVariant$price !== void 0 ? _matchedVariant$price : matchedVariant === null || matchedVariant === void 0 ? void 0 : matchedVariant.base_price) !== null && _ref20 !== void 0 ? _ref20 : origin === null || origin === void 0 ? void 0 : origin.price) !== null && _ref19 !== void 0 ? _ref19 : origin === null || origin === void 0 ? void 0 : origin.base_price) !== null && _ref18 !== void 0 ? _ref18 : sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.price) !== null && _ref17 !== void 0 ? _ref17 : sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.selling_price) !== null && _ref16 !== void 0 ? _ref16 : sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.base_price;
128
187
  var sourceProductPrice = toPriceString(hasPriceOverride ? (_ref21 = catalogSourcePrice !== null && catalogSourcePrice !== void 0 ? catalogSourcePrice : payload.price) !== null && _ref21 !== void 0 ? _ref21 : payload.selling_price : (_ref22 = (_payload$price = payload.price) !== null && _payload$price !== void 0 ? _payload$price : payload.selling_price) !== null && _ref22 !== void 0 ? _ref22 : catalogSourcePrice, '0.00');
129
- var explicitLineTotal = (_ref23 = (_payload$line_total = payload.line_total) !== null && _payload$line_total !== void 0 ? _payload$line_total : payload.total) !== null && _ref23 !== void 0 ? _ref23 : (_payload$_extend = payload._extend) === null || _payload$_extend === void 0 ? void 0 : _payload$_extend.total;
188
+ var explicitLineTotal = (_ref23 = (_payload$line_total = payload.line_total) !== null && _payload$line_total !== void 0 ? _payload$line_total : payload.total) !== null && _ref23 !== void 0 ? _ref23 : (_payload$_extend2 = payload._extend) === null || _payload$_extend2 === void 0 ? void 0 : _payload$_extend2.total;
130
189
  var hasExplicitLineTotal = Number.isFinite(Number(explicitLineTotal));
131
190
  var lineCompositeTotal = toPriceString(explicitLineTotal, sourceProductPrice);
132
191
  var productOptionItem = normalizeProductSkuOptions(normalizeOptionItems((_ref24 = (_ref25 = (_payload$product_sku$ = (_payload$product_sku = payload.product_sku) === null || _payload$product_sku === void 0 ? void 0 : _payload$product_sku.option) !== null && _payload$product_sku$ !== void 0 ? _payload$product_sku$ : payload.option) !== null && _ref25 !== void 0 ? _ref25 : payload.options) !== null && _ref24 !== void 0 ? _ref24 : payload.product_option_item));
@@ -137,16 +196,16 @@ export function transformBaseProductToOrderProduct(params) {
137
196
  var resolvedQuantity = toSafePositiveInt((_payload$quantity = payload.quantity) !== null && _payload$quantity !== void 0 ? _payload$quantity : payload.num, 1);
138
197
  var originTotal = resolveManualDiscountOriginTotal({
139
198
  originTotal: payload.origin_total,
140
- extendOriginTotal: (_payload$_extend2 = payload._extend) === null || _payload$_extend2 === void 0 ? void 0 : _payload$_extend2.origin_total,
199
+ extendOriginTotal: (_payload$_extend3 = payload._extend) === null || _payload$_extend3 === void 0 ? void 0 : _payload$_extend3.origin_total,
141
200
  originExtendOriginTotal: origin === null || origin === void 0 || (_extend = origin._extend) === null || _extend === void 0 ? void 0 : _extend.origin_total,
142
201
  sourceExtendOriginTotal: sourceProduct === null || sourceProduct === void 0 || (_extend2 = sourceProduct._extend) === null || _extend2 === void 0 ? void 0 : _extend2.origin_total,
143
202
  catalogUnitPrice: (_ref26 = (_ref27 = (_origin$base_price = origin === null || origin === void 0 ? void 0 : origin.base_price) !== null && _origin$base_price !== void 0 ? _origin$base_price : origin === null || origin === void 0 ? void 0 : origin.price) !== null && _ref27 !== void 0 ? _ref27 : sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.base_price) !== null && _ref26 !== void 0 ? _ref26 : sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.price,
144
203
  quantity: resolvedQuantity
145
204
  });
146
- var sellingTotal = Number((_ref28 = (_ref29 = (_payload$line_total2 = payload.line_total) !== null && _payload$line_total2 !== void 0 ? _payload$line_total2 : payload.total) !== null && _ref29 !== void 0 ? _ref29 : (_payload$_extend3 = payload._extend) === null || _payload$_extend3 === void 0 ? void 0 : _payload$_extend3.total) !== null && _ref28 !== void 0 ? _ref28 : lineCompositeTotal);
205
+ var sellingTotal = Number((_ref28 = (_ref29 = (_payload$line_total2 = payload.line_total) !== null && _payload$line_total2 !== void 0 ? _payload$line_total2 : payload.total) !== null && _ref29 !== void 0 ? _ref29 : (_payload$_extend4 = payload._extend) === null || _payload$_extend4 === void 0 ? void 0 : _payload$_extend4.total) !== null && _ref28 !== void 0 ? _ref28 : lineCompositeTotal);
147
206
  var discountReason = resolveManualDiscountReasonFromSources({
148
207
  discountReason: payload.discount_reason,
149
- extendDiscountReason: (_payload$_extend4 = payload._extend) === null || _payload$_extend4 === void 0 ? void 0 : _payload$_extend4.discount_reason,
208
+ extendDiscountReason: (_payload$_extend5 = payload._extend) === null || _payload$_extend5 === void 0 ? void 0 : _payload$_extend5.discount_reason,
150
209
  originExtendDiscountReason: origin === null || origin === void 0 || (_extend3 = origin._extend) === null || _extend3 === void 0 ? void 0 : _extend3.discount_reason
151
210
  });
152
211
  var lineOriginalPrice = hasPriceOverride && Number.isFinite(originTotal) ? toPriceString(originTotal) : lineCompositeTotal;
@@ -159,8 +218,8 @@ export function transformBaseProductToOrderProduct(params) {
159
218
  sellingTotal: Number.isFinite(sellingTotal) ? sellingTotal : Number(lineCompositeTotal),
160
219
  quantity: resolvedQuantity,
161
220
  message: discountReason,
162
- discountway: (_payload$_extend5 = payload._extend) === null || _payload$_extend5 === void 0 ? void 0 : _payload$_extend5.discountway,
163
- discount_per: (_payload$_extend6 = payload._extend) === null || _payload$_extend6 === void 0 ? void 0 : _payload$_extend6.discount_per
221
+ discountway: (_payload$_extend6 = payload._extend) === null || _payload$_extend6 === void 0 ? void 0 : _payload$_extend6.discountway,
222
+ discount_per: (_payload$_extend7 = payload._extend) === null || _payload$_extend7 === void 0 ? void 0 : _payload$_extend7.discount_per
164
223
  })) : payload.discount_list || [];
165
224
 
166
225
  // v2:source 不含 option;main_product_* 含 option(与 normalizeOrderProduct 一致)
@@ -172,7 +231,7 @@ export function transformBaseProductToOrderProduct(params) {
172
231
  });
173
232
  var derivedMainSelling = hasExplicitLineTotal ? Number(lineCompositeTotal) - Number(bundleOnlyComposite) : Number(mainProductOriginalPrice);
174
233
  var mainProductSellingPrice = toPriceString(Number.isFinite(derivedMainSelling) && derivedMainSelling >= 0 ? derivedMainSelling : Number(mainProductOriginalPrice));
175
- var metadata = _objectSpread(_objectSpread({
234
+ var metadata = _objectSpread(_objectSpread(_objectSpread(_objectSpread({
176
235
  unique: payload.unique,
177
236
  session: payload.session,
178
237
  form: payload.form,
@@ -187,7 +246,11 @@ export function transformBaseProductToOrderProduct(params) {
187
246
  main_product_original_price: mainProductOriginalPrice,
188
247
  price_schema_version: 2,
189
248
  holder_config: sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.holder_config
190
- }, hasPriceOverride ? {
249
+ }, dataVariantIds !== undefined ? {
250
+ data_variant_ids: dataVariantIds
251
+ } : {}), selectedSettlementSnapshot ? {
252
+ selected_settlement_snapshot: selectedSettlementSnapshot
253
+ } : {}), hasPriceOverride ? {
191
254
  price_override: String(payload.price_override),
192
255
  is_manual_discount: 1
193
256
  } : {}), payload.bundle_edit !== undefined ? {
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 1 | 2 | 6 | 4 | 5 | 3;
329
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -319,7 +319,7 @@ export function transformDetailToProductAndBooking(cacheItem, ctx) {
319
319
  * 把 cacheItem._extend.other 中的字段 + 顶层运行态拼成 `BaseProductDetailPayload`。
320
320
  */
321
321
  function buildBasePayloadFromCacheItem(cacheItem, ctx) {
322
- var _cacheItem$_extend, _cacheItem$_extend$qu, _cacheItem$_extend2, _cacheItem$product_id, _cacheItem$id, _ref5, _other$product_varian, _other$production_cod, _extend$skuValue, _extend$_skuValue, _extend$price, _extend$price2;
322
+ var _cacheItem$_extend, _cacheItem$_extend$qu, _cacheItem$_extend2, _cacheItem$product_id, _cacheItem$id, _ref5, _other$product_varian, _other$production_cod, _extend$skuValue, _extend$_skuValue, _extend$price, _extend$price2, _cacheItem$metadata$s, _cacheItem$metadata, _extend$metadata;
323
323
  var other = (cacheItem === null || cacheItem === void 0 || (_cacheItem$_extend = cacheItem._extend) === null || _cacheItem$_extend === void 0 ? void 0 : _cacheItem$_extend.other) || {};
324
324
  var quantity = (ctx === null || ctx === void 0 ? void 0 : ctx.quantity) != null && ctx.quantity > 0 ? ctx.quantity : (_cacheItem$_extend$qu = cacheItem === null || cacheItem === void 0 || (_cacheItem$_extend2 = cacheItem._extend) === null || _cacheItem$_extend2 === void 0 ? void 0 : _cacheItem$_extend2.quantity) !== null && _cacheItem$_extend$qu !== void 0 ? _cacheItem$_extend$qu : 1;
325
325
  var resolvedPid = (_cacheItem$product_id = cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.product_id) !== null && _cacheItem$product_id !== void 0 ? _cacheItem$product_id : cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.id;
@@ -350,6 +350,7 @@ function buildBasePayloadFromCacheItem(cacheItem, ctx) {
350
350
  bundle_edit: extend === null || extend === void 0 ? void 0 : extend.bundle_edit,
351
351
  discount_reason: extend === null || extend === void 0 ? void 0 : extend.discount_reason,
352
352
  discount_list: cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.discount_list,
353
+ selected_settlement_snapshot: (_cacheItem$metadata$s = cacheItem === null || cacheItem === void 0 || (_cacheItem$metadata = cacheItem.metadata) === null || _cacheItem$metadata === void 0 ? void 0 : _cacheItem$metadata.selected_settlement_snapshot) !== null && _cacheItem$metadata$s !== void 0 ? _cacheItem$metadata$s : extend === null || extend === void 0 || (_extend$metadata = extend.metadata) === null || _extend$metadata === void 0 ? void 0 : _extend$metadata.selected_settlement_snapshot,
353
354
  _extend: extend
354
355
  };
355
356
  }
@@ -3,7 +3,7 @@ import type { ConditionScope, DataVariantBusinessData, DataVariantMenu, DataVari
3
3
  /**
4
4
  * Data Variant 评估器。
5
5
  *
6
- * 当前阶段只提供策略模型能力和示例验证,不接入 ProductList 业务链路。
6
+ * OS Server 商品路由开启时由 ProductsModule 调用;路由关闭时由 ProductList 在远端响应后调用。
7
7
  */
8
8
  export declare class DataVariantEvaluator {
9
9
  private adapter;
@@ -17,7 +17,7 @@ export declare class DataVariantEvaluator {
17
17
  /**
18
18
  * 批量解析商品 Data Variant。
19
19
  *
20
- * 先执行全局预计算,再只针对商品自身 data_variants 引用到的规则做商品级判断。
20
+ * 优先使用商品 metadata.data_variant_ids;缺少权威命中结果时才执行本地策略判断。
21
21
  */
22
22
  resolveProducts(businessData: DataVariantBusinessData): ResolvedDataVariantResult;
23
23
  /**
@@ -34,8 +34,24 @@ export declare class DataVariantEvaluator {
34
34
  * 这里不依赖餐牌,只读取策略配置和调用方传入的 scheduleList。
35
35
  */
36
36
  buildScheduleTimePoints(strategyConfigs: StrategyConfig<DataVariantRuleMetadata>[], scheduleList: NonNullable<DataVariantBusinessData['scheduleList']>): string[];
37
+ /**
38
+ * 判断商品(含套餐子商品)是否仍需要本地执行策略条件。
39
+ * metadata.data_variant_ids 只要是数组,即使为空,也表示接口已经给出权威命中结果。
40
+ */
41
+ private requiresLocalStrategyEvaluation;
42
+ /**
43
+ * 将接口返回的高 -> 低优先级 Variant ID 转成数值优先级。
44
+ * 返回 null 表示接口没有提供该字段;空 Map 表示已计算但没有任何命中。
45
+ */
46
+ private getAuthoritativeVariantPriorities;
47
+ private normalizeDataVariantId;
37
48
  private buildGlobalEffectiveRuleMap;
38
49
  private resolveProduct;
50
+ /**
51
+ * 多货币 Data Variant 只生成候选列表,不参与商品字段覆盖。
52
+ * rule_id=0 是无条件默认价;同币种命中的条件价优先于默认价。
53
+ */
54
+ private resolveSettlementOptions;
39
55
  /**
40
56
  * 解析套餐子商品上的 Data Variant 覆盖。
41
57
  *
@@ -10,7 +10,7 @@ var _adapter = require("./adapter");
10
10
  /**
11
11
  * Data Variant 评估器。
12
12
  *
13
- * 当前阶段只提供策略模型能力和示例验证,不接入 ProductList 业务链路。
13
+ * OS Server 商品路由开启时由 ProductsModule 调用;路由关闭时由 ProductList 在远端响应后调用。
14
14
  */
15
15
  class DataVariantEvaluator {
16
16
  adapter;
@@ -32,16 +32,22 @@ class DataVariantEvaluator {
32
32
  /**
33
33
  * 批量解析商品 Data Variant。
34
34
  *
35
- * 先执行全局预计算,再只针对商品自身 data_variants 引用到的规则做商品级判断。
35
+ * 优先使用商品 metadata.data_variant_ids;缺少权威命中结果时才执行本地策略判断。
36
36
  */
37
37
  resolveProducts(businessData) {
38
38
  const strategyConfigs = businessData.strategyConfigs ? this.normalizeStrategyConfigs(businessData.strategyConfigs) : this.strategyConfigs;
39
39
  const menuScopeMap = this.buildMenuScopeMap(businessData.menuList || []);
40
40
  const scheduleTimePoints = this.buildScheduleTimePoints(strategyConfigs, businessData.scheduleList || []);
41
+ // metadata.data_variant_ids 存在时,接口已经完成规则计算;只有仍有商品缺少
42
+ // 该权威结果时才初始化本地策略引擎,避免 OS/接口与客户端重复评估。
43
+ const shouldEvaluateStrategies = businessData.products.some(product => this.requiresLocalStrategyEvaluation(product));
41
44
  const {
42
45
  globalEffectiveRuleMap,
43
46
  rawResults
44
- } = this.buildGlobalEffectiveRuleMap(strategyConfigs, businessData, menuScopeMap);
47
+ } = shouldEvaluateStrategies ? this.buildGlobalEffectiveRuleMap(strategyConfigs, businessData, menuScopeMap) : {
48
+ globalEffectiveRuleMap: new Map(),
49
+ rawResults: []
50
+ };
45
51
  const products = businessData.products.map(product => {
46
52
  const resolvedProduct = this.resolveProduct(product, businessData, globalEffectiveRuleMap, menuScopeMap);
47
53
  // 套餐子商品也可能携带 data_variants,需在同一策略上下文内继续评估并写回 bundle_item。
@@ -124,6 +130,46 @@ class DataVariantEvaluator {
124
130
  const matchedSchedules = scheduleList.filter(schedule => scheduleIdSet.has(Number(schedule.id)));
125
131
  return this.extractTimePointsFromSchedules(matchedSchedules);
126
132
  }
133
+
134
+ /**
135
+ * 判断商品(含套餐子商品)是否仍需要本地执行策略条件。
136
+ * metadata.data_variant_ids 只要是数组,即使为空,也表示接口已经给出权威命中结果。
137
+ */
138
+ requiresLocalStrategyEvaluation(product) {
139
+ const dataVariants = this.getProductDataVariants(product);
140
+ const hasConditionalVariant = dataVariants.some(variant => Number(variant.data_variant_rule_id) !== 0);
141
+ if (hasConditionalVariant && this.getAuthoritativeVariantPriorities(product) === null) {
142
+ return true;
143
+ }
144
+ const bundleGroups = Array.isArray(product.bundle_group) ? product.bundle_group : [];
145
+ return bundleGroups.some(group => {
146
+ const bundleItems = Array.isArray(group?.bundle_item) ? group.bundle_item : [];
147
+ return bundleItems.some(item => this.requiresLocalStrategyEvaluation(this.toBundleItemDataVariantProduct(item)));
148
+ });
149
+ }
150
+
151
+ /**
152
+ * 将接口返回的高 -> 低优先级 Variant ID 转成数值优先级。
153
+ * 返回 null 表示接口没有提供该字段;空 Map 表示已计算但没有任何命中。
154
+ */
155
+ getAuthoritativeVariantPriorities(product) {
156
+ const rawIds = product?.metadata?.data_variant_ids;
157
+ if (!Array.isArray(rawIds)) return null;
158
+ const orderedIds = [];
159
+ const seen = new Set();
160
+ for (const rawId of rawIds) {
161
+ const id = this.normalizeDataVariantId(rawId);
162
+ if (id === null || seen.has(id)) continue;
163
+ seen.add(id);
164
+ orderedIds.push(id);
165
+ }
166
+ return new Map(orderedIds.map((id, index) => [id, orderedIds.length - index]));
167
+ }
168
+ normalizeDataVariantId(value) {
169
+ if (value === undefined || value === null) return null;
170
+ const normalized = String(value).trim();
171
+ return normalized || null;
172
+ }
127
173
  buildGlobalEffectiveRuleMap(strategyConfigs, businessData, menuScopeMap) {
128
174
  const globalEffectiveRuleMap = new Map();
129
175
  const rawResults = [];
@@ -155,7 +201,22 @@ class DataVariantEvaluator {
155
201
  const dataVariants = this.getProductDataVariants(product);
156
202
  if (!dataVariants.length) return product;
157
203
  const matchedVariants = [];
204
+ const authoritativeVariantPriorities = this.getAuthoritativeVariantPriorities(product);
205
+ const settlementVariants = dataVariants.filter(variant => variant.business_type === 'multi_currency_settlement' && variant.status === 'enable');
158
206
  for (const variant of dataVariants) {
207
+ if (variant.business_type === 'multi_currency_settlement') continue;
208
+ if (authoritativeVariantPriorities !== null) {
209
+ const variantId = this.normalizeDataVariantId(variant.id);
210
+ const priority = variantId === null ? undefined : authoritativeVariantPriorities.get(variantId);
211
+ if (priority === undefined) continue;
212
+ matchedVariants.push({
213
+ ruleId: String(variant.data_variant_rule_id),
214
+ priority,
215
+ data: variant.data || {},
216
+ variant
217
+ });
218
+ continue;
219
+ }
159
220
  const rule = globalEffectiveRuleMap.get(String(variant.data_variant_rule_id));
160
221
  if (!rule) continue;
161
222
  if (!this.evaluateProductRules(rule, product, businessData, menuScopeMap)) {
@@ -168,8 +229,76 @@ class DataVariantEvaluator {
168
229
  variant
169
230
  });
170
231
  }
171
- if (!matchedVariants.length) return product;
172
- return this.mergeMatchedVariants(product, matchedVariants);
232
+ const resolvedProduct = matchedVariants.length ? this.mergeMatchedVariants(product, matchedVariants) : product;
233
+ const availableSettlementOptions = this.resolveSettlementOptions(settlementVariants, product, businessData, globalEffectiveRuleMap, menuScopeMap, authoritativeVariantPriorities);
234
+ if (!settlementVariants.length) return resolvedProduct;
235
+ return {
236
+ ...resolvedProduct,
237
+ available_settlement_options: availableSettlementOptions
238
+ };
239
+ }
240
+
241
+ /**
242
+ * 多货币 Data Variant 只生成候选列表,不参与商品字段覆盖。
243
+ * rule_id=0 是无条件默认价;同币种命中的条件价优先于默认价。
244
+ */
245
+ resolveSettlementOptions(variants, product, businessData, globalEffectiveRuleMap, menuScopeMap, authoritativeVariantPriorities) {
246
+ if (!variants.length) return [];
247
+ const candidates = variants.flatMap(variant => {
248
+ const settlement = variant.data?.multi_currency_settlement;
249
+ if (!settlement || typeof settlement !== 'object') return [];
250
+ const ruleId = String(variant.data_variant_rule_id);
251
+ const isDefault = Number(variant.data_variant_rule_id) === 0;
252
+ const rule = isDefault ? undefined : globalEffectiveRuleMap.get(ruleId);
253
+ const variantId = this.normalizeDataVariantId(variant.id);
254
+ const authoritativePriority = variantId === null ? undefined : authoritativeVariantPriorities?.get(variantId);
255
+ let available;
256
+ let priority;
257
+ if (isDefault) {
258
+ // rule 0 是无条件默认候选,不依赖接口命中 ID 或本地策略引擎。
259
+ available = true;
260
+ priority = Number.NEGATIVE_INFINITY;
261
+ } else if (authoritativeVariantPriorities !== null) {
262
+ // 数组存在(包括 [])即表示接口已经算过规则,不再在客户端二次判断。
263
+ available = authoritativePriority !== undefined;
264
+ priority = authoritativePriority ?? rule?.priority ?? Number.NEGATIVE_INFINITY;
265
+ } else {
266
+ available = Boolean(rule && this.evaluateProductRules(rule, product, businessData, menuScopeMap));
267
+ priority = rule?.priority ?? Number.NEGATIVE_INFINITY;
268
+ }
269
+ const settlementType = String(settlement.settlement_type || '');
270
+ const currencyProductId = this.toNumber(settlement.currency_product_id);
271
+ const settlementKey = settlementType === 'virtual_currency' ? `virtual_currency:${currencyProductId || ''}` : settlementType || `variant:${variant.id ?? ruleId}`;
272
+ return [{
273
+ key: settlementKey,
274
+ priority,
275
+ isDefault,
276
+ option: {
277
+ ...settlement,
278
+ settlement_type: settlementType,
279
+ ...(currencyProductId ? {
280
+ currency_product_id: currencyProductId
281
+ } : {}),
282
+ price: String(variant.data?.price ?? '0'),
283
+ data_variant_id: variant.id,
284
+ data_variant_rule_id: variant.data_variant_rule_id,
285
+ available,
286
+ disabled_reason: available ? '' : String(settlement.disabled_reason || 'Not available for this purchase.')
287
+ }
288
+ }];
289
+ });
290
+ const grouped = new Map();
291
+ for (const candidate of candidates) {
292
+ const group = grouped.get(candidate.key) || [];
293
+ group.push(candidate);
294
+ grouped.set(candidate.key, group);
295
+ }
296
+ return Array.from(grouped.values()).map(group => {
297
+ const matchedConditional = group.filter(candidate => !candidate.isDefault && candidate.option.available).sort((a, b) => b.priority - a.priority)[0];
298
+ const defaultCandidate = group.find(candidate => candidate.isDefault);
299
+ const unavailableCandidate = [...group].filter(candidate => !candidate.option.available).sort((a, b) => b.priority - a.priority)[0];
300
+ return (matchedConditional || defaultCandidate || unavailableCandidate).option;
301
+ });
173
302
  }
174
303
 
175
304
  /**
@@ -222,7 +351,8 @@ class DataVariantEvaluator {
222
351
  product_variant_id: variantId,
223
352
  variant_id: variantId,
224
353
  collection: item.collection,
225
- data_variants: item.data_variants
354
+ data_variants: item.data_variants,
355
+ metadata: item.metadata
226
356
  };
227
357
  }
228
358
 
@@ -453,6 +583,7 @@ class DataVariantEvaluator {
453
583
  }
454
584
  result._dataVariant = {
455
585
  appliedRuleIds,
586
+ appliedVariantIds: Array.from(new Set([...sortedVariants].reverse().map(matched => this.normalizeDataVariantId(matched.variant.id)).filter(id => id !== null))),
456
587
  appliedFields: Array.from(appliedFields),
457
588
  original
458
589
  };
@@ -35,6 +35,10 @@ export interface DataVariantItem {
35
35
  module_data_id?: number;
36
36
  /** 关联策略模型 metadata.id / data_variant_rule.id */
37
37
  data_variant_rule_id: number | string;
38
+ /** 业务类型;多货币结算候选不会走普通字段覆盖 */
39
+ business_type?: 'multi_currency_settlement' | string;
40
+ /** 数据状态;多货币结算仅处理 enable 记录 */
41
+ status?: 'enable' | 'disable' | string;
38
42
  /** 命中策略后需要覆盖到商品上的字段 */
39
43
  data: Record<string, any>;
40
44
  created_at?: string | null;
@@ -53,11 +57,30 @@ export interface DataVariantProduct {
53
57
  id?: number | string;
54
58
  [key: string]: any;
55
59
  }>;
60
+ /**
61
+ * 商品接口已经完成规则计算时返回的命中结果。
62
+ * 数组按 Data Variant 优先级从高到低排列;空数组表示已计算但无命中。
63
+ */
64
+ metadata?: {
65
+ data_variant_ids?: Array<number | string>;
66
+ [key: string]: any;
67
+ };
56
68
  /** 后端 /product/query with dataVariants 返回的智能定价变体列表 */
57
69
  data_variants?: DataVariantItem[];
70
+ /** 当前上下文解析后的可选结算货币,不覆盖商品原始多货币配置 */
71
+ available_settlement_options?: AvailableSettlementOption[];
58
72
  _dataVariant?: DataVariantAppliedInfo;
59
73
  [key: string]: any;
60
74
  }
75
+ export interface AvailableSettlementOption extends Record<string, any> {
76
+ settlement_type: 'legal_currency' | 'virtual_currency' | string;
77
+ currency_product_id?: number;
78
+ price: string;
79
+ data_variant_id?: number;
80
+ data_variant_rule_id: number | string;
81
+ available: boolean;
82
+ disabled_reason?: string;
83
+ }
61
84
  /**
62
85
  * 餐牌商品配置项。
63
86
  */
@@ -131,6 +154,8 @@ export interface MatchedDataVariant {
131
154
  */
132
155
  export interface DataVariantAppliedInfo {
133
156
  appliedRuleIds: string[];
157
+ /** 本地策略实际应用的 Data Variant ID,按优先级从高到低排列。 */
158
+ appliedVariantIds?: Array<number | string>;
134
159
  appliedFields: string[];
135
160
  original: DataVariantProduct;
136
161
  }
@@ -25,9 +25,11 @@ export declare class DiscountModule extends BaseModule implements Module, Discou
25
25
  with_wallet_pass_holder: 0 | 1;
26
26
  with_available_wallet_flag?: 0 | 1;
27
27
  with_available_wallet_pass_flag?: 0 | 1;
28
+ with_virtual_currency?: 0 | 1;
28
29
  request_timezone: string;
29
30
  order_id?: number | string;
30
31
  }): Promise<DiscountPrepareConfigResult>;
32
+ private normalizeVirtualCurrencyList;
31
33
  batchSearch(code: string, options?: {
32
34
  customerId?: number;
33
35
  orderId?: number;
@@ -80,21 +80,50 @@ class DiscountModule extends _BaseModule.BaseModule {
80
80
  const prepareConfig = await this.request.post(`/order/prepare/config`, {
81
81
  ...params,
82
82
  with_available_wallet_flag: params.with_available_wallet_flag ?? 1,
83
- with_available_wallet_pass_flag: params.with_available_wallet_pass_flag ?? 1
83
+ with_available_wallet_pass_flag: params.with_available_wallet_pass_flag ?? 1,
84
+ with_virtual_currency: params.with_virtual_currency ?? 1
84
85
  });
85
86
  const rawDiscountList = [...(prepareConfig?.data?.good_pass_list || []), ...(prepareConfig?.data?.discount_card_list || [])];
86
87
  const availableWalletList = [...(prepareConfig?.data?.avaiable_wallet_list || []), ...(prepareConfig?.data?.available_wallet_list || [])];
87
88
  const availableWalletPassList = prepareConfig?.data?.available_wallet_pass_list || [];
88
89
  const availableWalletIds = this.normalizePositiveNumberIds([...availableWalletList.map(item => item?.wallet_id), ...availableWalletPassList.map(item => item?.product_id)]);
90
+ const virtualCurrencyList = this.normalizeVirtualCurrencyList(prepareConfig?.data?.virtual_currency_list);
89
91
  const goodPassList = this.filterEnabledDiscountList(rawDiscountList) || [];
90
92
 
91
93
  // this.setDiscountList(goodPassList);
92
94
 
93
95
  return {
94
96
  discountList: goodPassList,
95
- availableWalletIds
97
+ availableWalletIds,
98
+ virtualCurrencyList
96
99
  };
97
100
  }
101
+ normalizeVirtualCurrencyList(value) {
102
+ if (!Array.isArray(value)) return [];
103
+ return value.flatMap(item => {
104
+ const id = Number(item?.id);
105
+ const productId = Number(item?.product_id);
106
+ if (!Number.isFinite(id) || id <= 0 || !Number.isFinite(productId) || productId <= 0) {
107
+ return [];
108
+ }
109
+ const displayExtension = Array.isArray(item?.extension_data) ? item.extension_data.find(extension => extension?.field_key === 'virtual_currency_display') : undefined;
110
+ let display = displayExtension?.value;
111
+ if (typeof display === 'string') {
112
+ try {
113
+ display = JSON.parse(display);
114
+ } catch {
115
+ display = {};
116
+ }
117
+ }
118
+ return [{
119
+ ...item,
120
+ id,
121
+ product_id: productId,
122
+ balance: String(item?.balance ?? '0'),
123
+ virtual_currency_display: display && typeof display === 'object' && !Array.isArray(display) ? display : {}
124
+ }];
125
+ });
126
+ }
98
127
  async batchSearch(code, options) {
99
128
  const {
100
129
  customerId,
@@ -71,6 +71,17 @@ export interface DiscountWithReason {
71
71
  export interface DiscountPrepareConfigResult {
72
72
  discountList: Discount[];
73
73
  availableWalletIds: number[];
74
+ virtualCurrencyList?: VirtualCurrencyAsset[];
75
+ }
76
+ export interface VirtualCurrencyAsset extends Record<string, any> {
77
+ id: number;
78
+ product_id: number;
79
+ balance: string;
80
+ product_name?: string;
81
+ format_title?: Record<string, any>;
82
+ code?: string;
83
+ encoded?: string;
84
+ virtual_currency_display?: Record<string, any>;
74
85
  }
75
86
  interface ExtensionData {
76
87
  id: number;
@@ -60,6 +60,8 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
60
60
  * orderModule.updateOtherParams({ cacheId: 'cache-2', channel: 'pos' });
61
61
  */
62
62
  updateOtherParams(params: Record<string, any>): void;
63
+ /** PC/H5 属于在线店铺;其它或缺失平台统一沿用 POS 行为。 */
64
+ isOnlineStorePlatform(): boolean;
63
65
  /**
64
66
  * 记录信息日志
65
67
  */
@@ -82,6 +84,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
82
84
  }): Promise<Discount[]>;
83
85
  getDiscountList(): Discount[];
84
86
  getAvailableWalletIds(): number[];
87
+ getVirtualCurrencyList(): import("../Discount/types").VirtualCurrencyAsset[];
85
88
  private syncScannedDiscountsToOriginalDiscountList;
86
89
  private ensureEditDiscountConfigForProductChange;
87
90
  scanCode(code: string, customerId?: number): Promise<{
@@ -400,6 +403,13 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
400
403
  * this.hasLinkedBookingUid({ metadata: { booking_uid: 'booking-1' } });
401
404
  */
402
405
  private hasLinkedBookingUid;
406
+ private isMultiCurrencySettlementEnabled;
407
+ private isActiveVirtualSettlementOrder;
408
+ private shouldUseVirtualSettlementSummary;
409
+ private normalizeVirtualSettlementProductIfEnabled;
410
+ private assertAndLockProductSettlement;
411
+ private syncTempOrderSettlementState;
412
+ private prepareVirtualSettlementTempOrder;
403
413
  /**
404
414
  * 预约商品加车后的统一收尾:促销、折扣、summary 重算与持久化(批量拆行时只调用一次)。
405
415
  *
@@ -472,6 +482,10 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
472
482
  * 普通整单 note 保持不变;以商品行为主体的 Sales Notes 同步删除。
473
483
  */
474
484
  clearOrderCartLines(): Promise<OrderTempOrder>;
485
+ /**
486
+ * 切换购物车结算单位时清理所有会影响新币种的订单状态,但保留当前客户。
487
+ */
488
+ clearOrderForSettlementSwitch(): Promise<OrderTempOrder>;
475
489
  buildCurrentSubmitPayloadForLocalPrint(params?: {
476
490
  cacheId?: string;
477
491
  platform?: string;