@pisell/pisellos 2.1.129 → 2.1.131

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 (54) hide show
  1. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  2. package/dist/modules/Order/index.d.ts +7 -6
  3. package/dist/modules/Order/index.js +137 -42
  4. package/dist/modules/Order/types.d.ts +32 -6
  5. package/dist/modules/Order/types.js +2 -0
  6. package/dist/modules/Order/utils.d.ts +73 -11
  7. package/dist/modules/Order/utils.js +304 -52
  8. package/dist/modules/SalesSummary/utils.js +33 -68
  9. package/dist/modules/ScanOrderLogger/providers/feishu.js +168 -60
  10. package/dist/modules/ScanOrderLogger/types.d.ts +6 -0
  11. package/dist/modules/Summary/utils.js +6 -21
  12. package/dist/solution/ScanOrder/index.d.ts +57 -8
  13. package/dist/solution/ScanOrder/index.js +1531 -583
  14. package/dist/solution/ScanOrder/types.d.ts +86 -26
  15. package/dist/solution/ScanOrder/types.js +20 -1
  16. package/dist/solution/ScanOrder/utils.d.ts +53 -5
  17. package/dist/solution/ScanOrder/utils.js +257 -37
  18. package/dist/solution/VenueBooking/index.d.ts +30 -10
  19. package/dist/solution/VenueBooking/index.js +460 -217
  20. package/dist/solution/VenueBooking/types.d.ts +23 -0
  21. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -1
  22. package/dist/solution/VenueBooking/utils/dateSummary.js +1 -1
  23. package/dist/solution/VenueBooking/utils/resource.d.ts +11 -1
  24. package/dist/solution/VenueBooking/utils/resource.js +57 -21
  25. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
  26. package/dist/solution/VenueBooking/utils/slotMerge.js +33 -12
  27. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
  28. package/dist/solution/VenueBooking/utils/timeSlot.js +259 -62
  29. package/lib/modules/Order/index.d.ts +7 -6
  30. package/lib/modules/Order/index.js +123 -31
  31. package/lib/modules/Order/types.d.ts +32 -6
  32. package/lib/modules/Order/utils.d.ts +73 -11
  33. package/lib/modules/Order/utils.js +203 -28
  34. package/lib/modules/SalesSummary/utils.js +13 -47
  35. package/lib/modules/ScanOrderLogger/providers/feishu.js +100 -34
  36. package/lib/modules/ScanOrderLogger/types.d.ts +6 -0
  37. package/lib/modules/Summary/utils.js +4 -18
  38. package/lib/solution/ScanOrder/index.d.ts +57 -8
  39. package/lib/solution/ScanOrder/index.js +713 -117
  40. package/lib/solution/ScanOrder/types.d.ts +86 -26
  41. package/lib/solution/ScanOrder/utils.d.ts +53 -5
  42. package/lib/solution/ScanOrder/utils.js +186 -19
  43. package/lib/solution/VenueBooking/index.d.ts +30 -10
  44. package/lib/solution/VenueBooking/index.js +206 -51
  45. package/lib/solution/VenueBooking/types.d.ts +23 -0
  46. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -1
  47. package/lib/solution/VenueBooking/utils/dateSummary.js +1 -1
  48. package/lib/solution/VenueBooking/utils/resource.d.ts +11 -1
  49. package/lib/solution/VenueBooking/utils/resource.js +15 -4
  50. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
  51. package/lib/solution/VenueBooking/utils/slotMerge.js +29 -12
  52. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
  53. package/lib/solution/VenueBooking/utils/timeSlot.js +182 -43
  54. package/package.json +1 -1
@@ -0,0 +1,9 @@
1
+ // 导出评估器
2
+ export { PromotionEvaluator } from "./evaluator";
3
+
4
+ // 导出适配器
5
+ export { PromotionAdapter } from "./adapter";
6
+ export { default } from "./adapter";
7
+
8
+ // 导出策略配置示例常量
9
+ export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY } from "./examples";
@@ -1,7 +1,8 @@
1
1
  import { Module, PisellCore, ModuleOptions } from '../../types';
2
2
  import { BaseModule } from '../BaseModule';
3
- import { OrderModuleAPI, CommitOrderParams, SubmitScanOrderParams, ScanOrderMoreParams, CheckoutOrderParams } from './types';
3
+ import { OrderModuleAPI, CommitOrderParams, SubmitScanOrderParams, ScanOrderMoreParams, CheckoutOrderParams, UpdateProductInOrderParams } from './types';
4
4
  import { CartItem } from '../Cart/types';
5
+ import { type SubmitPayloadEnhancer } from './utils';
5
6
  import type { ScanOrderOrderProduct, ScanOrderOrderProductIdentity, ScanOrderSummary, ScanOrderTempOrder } from '../../solution/ScanOrder/types';
6
7
  import type { Discount } from '../Discount/types';
7
8
  import { UnavailableReason } from '../Rules/types';
@@ -57,6 +58,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
57
58
  persistTempOrder(): void;
58
59
  private createDefaultTempOrderInstance;
59
60
  ensureTempOrder(): ScanOrderTempOrder;
61
+ restoreOrder(): ScanOrderTempOrder;
60
62
  getTempOrder(): ScanOrderTempOrder | null;
61
63
  addNewOrder(): Promise<ScanOrderTempOrder>;
62
64
  getOrderProducts(): ScanOrderOrderProduct[];
@@ -66,13 +68,10 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
66
68
  }): Promise<ScanOrderSummary | null>;
67
69
  getScanOrderSummary(): Promise<ScanOrderSummary>;
68
70
  updateTempOrderNote(note: string): string;
71
+ updateTempOrderBuzzer(buzzer: string): string;
69
72
  updateTempOrderContactsInfo(contactsInfo: any[]): any[];
70
73
  addProductToOrder(product: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity): Promise<ScanOrderOrderProduct[]>;
71
- updateProductInOrder(params: {
72
- product_id: number | null;
73
- product_variant_id: number;
74
- updates: Partial<ScanOrderOrderProduct>;
75
- }): Promise<ScanOrderOrderProduct[]>;
74
+ updateProductInOrder(params: UpdateProductInOrderParams): Promise<ScanOrderOrderProduct[]>;
76
75
  removeProductFromOrder(identity: ScanOrderOrderProductIdentity): Promise<ScanOrderOrderProduct[]>;
77
76
  submitTempOrder<T = any>(params?: {
78
77
  cacheId?: string;
@@ -80,6 +79,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
80
79
  businessCode?: string;
81
80
  channel?: string;
82
81
  type?: string;
82
+ enhancePayload?: SubmitPayloadEnhancer;
83
83
  }): Promise<T>;
84
84
  createOrder(params: CommitOrderParams['query']): {
85
85
  type: "virtual" | "appointment_booking";
@@ -115,3 +115,4 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
115
115
  getOrderInfoByRemote(order_id: number): Promise<any>;
116
116
  getLastOrderInfo(): Record<string, any> | undefined;
117
117
  }
118
+ export type { UpdateProductInOrderParams } from './types';
@@ -1,4 +1,3 @@
1
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
1
  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; } } }; }
3
2
  function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
4
3
  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."); }
@@ -6,6 +5,7 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
6
5
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
7
6
  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
8
7
  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; }
8
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
9
9
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
10
10
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
11
11
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
@@ -25,10 +25,10 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
25
25
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
26
26
  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); }
27
27
  import { BaseModule } from "../BaseModule";
28
- import { generateDuration, getAllDiscountList, mergeRelationForms, buildSubmitPayload, createDefaultTempOrder, createDefaultOrderRulesHooks, createEmptySummary, formatDateTime, formatV1Product, isTempOrder } from "./utils";
28
+ import { generateDuration, getAllDiscountList, mergeRelationForms, buildSubmitPayload, createDefaultTempOrder, createDefaultOrderRulesHooks, createEmptySummary, createUuidV4, formatDateTime, filterProductsForScanOrderMore, isTempOrder } from "./utils";
29
29
  import { isNormalProduct } from "../Product/utils";
30
30
  import dayjs from 'dayjs';
31
- import { getProductIdentityIndex, getSafeProductNum, isIdentityMatch, normalizeOrderProduct } from "../../solution/ScanOrder/utils";
31
+ import { buildProductLineFingerprint, getProductIdentityIndex, getSafeProductNum, isIdentityMatch, normalizeOrderProduct } from "../../solution/ScanOrder/utils";
32
32
  import { DiscountModule } from "../Discount";
33
33
  import { RulesModule } from "../Rules";
34
34
  import { UnavailableReason } from "../Rules/types";
@@ -386,6 +386,38 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
386
386
  this.window.localStorage.removeItem(key);
387
387
  return;
388
388
  }
389
+ if (Array.isArray(parsedData.products)) {
390
+ for (var i = 0; i < parsedData.products.length; i++) {
391
+ var p = parsedData.products[i];
392
+ if (!p || _typeof(p) !== 'object') continue;
393
+ if (!Array.isArray(p.product_option_item)) {
394
+ p.product_option_item = [];
395
+ }
396
+ if (!Array.isArray(p.product_bundle)) {
397
+ p.product_bundle = [];
398
+ }
399
+ // 不透明 identity 契约:旧缓存里可能没有 identity_key,
400
+ // 此处统一回填 UUID 并同步 metadata.unique_identification_number,
401
+ // 避免升级后 UI 侧持有的 rowKey 找不到对应行。
402
+ var row = p;
403
+ if (typeof row.identity_key !== 'string' || row.identity_key.length === 0) {
404
+ var newKey = createUuidV4();
405
+ row.identity_key = newKey;
406
+ if (!row.metadata || _typeof(row.metadata) !== 'object') {
407
+ row.metadata = {};
408
+ }
409
+ if (!row.metadata.unique_identification_number) {
410
+ row.metadata.unique_identification_number = newKey;
411
+ }
412
+ }
413
+ // 价格 schema 迁移:重跑 normalizeOrderProduct。
414
+ // `metadata.price_schema_version === 2` → 已是新语义,保留现有 main_product_* 折扣;
415
+ // 否则(v1 或无 metadata)→ 走 legacyDiscount 反推分支,基于新的 source + options
416
+ // 重算出含 option 的 main_product_*,并打上 price_schema_version: 2。
417
+ // 幂等:多次 restore 不会重复叠加 option/bundle。
418
+ parsedData.products[i] = normalizeOrderProduct(row);
419
+ }
420
+ }
389
421
  this.store.tempOrder = parsedData;
390
422
  } catch (_unused2) {
391
423
  var _this$window;
@@ -419,6 +451,14 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
419
451
  this.persistTempOrder();
420
452
  return newOrder;
421
453
  }
454
+ }, {
455
+ key: "restoreOrder",
456
+ value: function restoreOrder() {
457
+ var freshTempOrder = this.createDefaultTempOrderInstance();
458
+ this.store.tempOrder = freshTempOrder;
459
+ this.persistTempOrder();
460
+ return freshTempOrder;
461
+ }
422
462
  }, {
423
463
  key: "getTempOrder",
424
464
  value: function getTempOrder() {
@@ -560,6 +600,14 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
560
600
  this.persistTempOrder();
561
601
  return tempOrder.note;
562
602
  }
603
+ }, {
604
+ key: "updateTempOrderBuzzer",
605
+ value: function updateTempOrderBuzzer(buzzer) {
606
+ var tempOrder = this.ensureTempOrder();
607
+ tempOrder.buzzer = String(buzzer || '');
608
+ this.persistTempOrder();
609
+ return tempOrder.buzzer;
610
+ }
563
611
  }, {
564
612
  key: "updateTempOrderContactsInfo",
565
613
  value: function updateTempOrderContactsInfo(contactsInfo) {
@@ -574,31 +622,59 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
574
622
  key: "addProductToOrder",
575
623
  value: function () {
576
624
  var _addProductToOrder = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(product) {
577
- var tempOrder, normalizedProduct, productIndex, targetProduct;
625
+ var tempOrder, hasExplicitIdentityKey, normalizedProduct, productIndex, targetProduct, incomingFingerprint, matchedIndex, _normalizedProduct, _targetProduct, _normalizedProduct2;
578
626
  return _regeneratorRuntime().wrap(function _callee7$(_context7) {
579
627
  while (1) switch (_context7.prev = _context7.next) {
580
628
  case 0:
581
629
  tempOrder = this.ensureTempOrder();
582
- normalizedProduct = normalizeOrderProduct(product);
583
- productIndex = getProductIdentityIndex(tempOrder.products, normalizedProduct);
584
- if (productIndex === -1) {
585
- tempOrder.products.push(normalizedProduct);
630
+ hasExplicitIdentityKey = typeof product.identity_key === 'string' && product.identity_key.length > 0;
631
+ if (hasExplicitIdentityKey) {
632
+ // 调用方自持 identity_key(如 VenueBooking 外部生成)→ 走严格 identity 合并。
633
+ normalizedProduct = normalizeOrderProduct(product);
634
+ productIndex = getProductIdentityIndex(tempOrder.products, normalizedProduct);
635
+ if (productIndex === -1) {
636
+ tempOrder.products.push(normalizedProduct);
637
+ } else {
638
+ targetProduct = tempOrder.products[productIndex];
639
+ tempOrder.products[productIndex] = _objectSpread(_objectSpread(_objectSpread({}, targetProduct), normalizedProduct), {}, {
640
+ num: getSafeProductNum(targetProduct.num + normalizedProduct.num),
641
+ _origin: normalizedProduct._origin || targetProduct._origin
642
+ });
643
+ }
586
644
  } else {
587
- targetProduct = tempOrder.products[productIndex];
588
- tempOrder.products[productIndex] = _objectSpread(_objectSpread(_objectSpread({}, targetProduct), normalizedProduct), {}, {
589
- num: getSafeProductNum(targetProduct.num + normalizedProduct.num),
590
- _origin: normalizedProduct._origin || targetProduct._origin
645
+ // identity_key:按 SKU + 内容指纹(options + bundle)匹配既有行以累加数量;
646
+ // 命中时保留已有 identity_key,未命中才由 normalizeOrderProduct 自动生成 UUID。
647
+ incomingFingerprint = buildProductLineFingerprint(product.product_option_item, product.product_bundle);
648
+ matchedIndex = tempOrder.products.findIndex(function (item) {
649
+ if (item.product_id !== product.product_id) return false;
650
+ if (item.product_variant_id !== product.product_variant_id) return false;
651
+ var existedFingerprint = buildProductLineFingerprint(item.product_option_item, item.product_bundle);
652
+ return existedFingerprint === incomingFingerprint;
591
653
  });
654
+ if (matchedIndex === -1) {
655
+ _normalizedProduct = normalizeOrderProduct(product);
656
+ tempOrder.products.push(_normalizedProduct);
657
+ } else {
658
+ _targetProduct = tempOrder.products[matchedIndex];
659
+ _normalizedProduct2 = normalizeOrderProduct(_objectSpread(_objectSpread({}, product), {}, {
660
+ identity_key: _targetProduct.identity_key
661
+ }));
662
+ tempOrder.products[matchedIndex] = _objectSpread(_objectSpread(_objectSpread({}, _targetProduct), _normalizedProduct2), {}, {
663
+ identity_key: _targetProduct.identity_key,
664
+ num: getSafeProductNum(_targetProduct.num + _normalizedProduct2.num),
665
+ _origin: _normalizedProduct2._origin || _targetProduct._origin
666
+ });
667
+ }
592
668
  }
593
669
  this.applyDiscount();
594
- _context7.next = 7;
670
+ _context7.next = 6;
595
671
  return this.recalculateSummary({
596
672
  createIfMissing: true
597
673
  });
598
- case 7:
674
+ case 6:
599
675
  this.persistTempOrder();
600
676
  return _context7.abrupt("return", tempOrder.products);
601
- case 9:
677
+ case 8:
602
678
  case "end":
603
679
  return _context7.stop();
604
680
  }
@@ -613,38 +689,61 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
613
689
  key: "updateProductInOrder",
614
690
  value: function () {
615
691
  var _updateProductInOrder = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(params) {
616
- var product_id, product_variant_id, updates, tempOrder, productIndex, targetProduct, nextProduct;
692
+ var _metadata, _metadata2, _metadata3;
693
+ var product_id, product_variant_id, updates, identity_key, product_option_item, product_bundle, tempOrder, identityLookup, productIndex, targetProduct, nextProduct, callerUpdatesTopPrice, callerUpdatesMainMeta, existedMeta;
617
694
  return _regeneratorRuntime().wrap(function _callee8$(_context8) {
618
695
  while (1) switch (_context8.prev = _context8.next) {
619
696
  case 0:
620
- product_id = params.product_id, product_variant_id = params.product_variant_id, updates = params.updates;
697
+ product_id = params.product_id, product_variant_id = params.product_variant_id, updates = params.updates, identity_key = params.identity_key, product_option_item = params.product_option_item, product_bundle = params.product_bundle;
621
698
  tempOrder = this.ensureTempOrder();
622
- productIndex = getProductIdentityIndex(tempOrder.products, {
699
+ identityLookup = {
623
700
  product_id: product_id,
624
701
  product_variant_id: product_variant_id
625
- });
702
+ };
703
+ if (identity_key !== undefined) identityLookup.identity_key = identity_key;
704
+ if (product_option_item !== undefined) identityLookup.product_option_item = product_option_item;
705
+ if (product_bundle !== undefined) identityLookup.product_bundle = product_bundle;
706
+ productIndex = getProductIdentityIndex(tempOrder.products, identityLookup);
626
707
  if (!(productIndex === -1)) {
627
- _context8.next = 5;
708
+ _context8.next = 9;
628
709
  break;
629
710
  }
630
711
  throw new Error('[Order] 目标商品不存在,无法更新');
631
- case 5:
712
+ case 9:
632
713
  targetProduct = tempOrder.products[productIndex];
633
714
  nextProduct = _objectSpread(_objectSpread(_objectSpread({}, targetProduct), updates), {}, {
634
715
  product_id: product_id,
635
716
  product_variant_id: product_variant_id
636
717
  });
637
718
  nextProduct.num = getSafeProductNum(nextProduct.num);
638
- tempOrder.products[productIndex] = nextProduct;
719
+ // 兜底:caller 通过 updates 直接改了 selling_price / original_price 时,
720
+ // 视为 "重新给 source-level 主价"(caller 侧旧约定仍是 main-only 单价)。
721
+ // 清掉 metadata 里的 source_product_price / main_product_* / price_schema_version,
722
+ // 让 normalize 把顶层 selling_price 当作 source 来重算 main_original(=source+options) /
723
+ // main_selling / composite;否则旧 metadata 会反压顶层新值,触发口径不一致。
724
+ // 如果 caller 走推荐路径(updates.metadata.* 显式指定主价),保留 metadata 由 normalize 认它。
725
+ callerUpdatesTopPrice = Object.prototype.hasOwnProperty.call(updates || {}, 'selling_price') || Object.prototype.hasOwnProperty.call(updates || {}, 'original_price');
726
+ callerUpdatesMainMeta = (updates === null || updates === void 0 || (_metadata = updates.metadata) === null || _metadata === void 0 ? void 0 : _metadata.main_product_selling_price) !== undefined || (updates === null || updates === void 0 || (_metadata2 = updates.metadata) === null || _metadata2 === void 0 ? void 0 : _metadata2.main_product_original_price) !== undefined || (updates === null || updates === void 0 || (_metadata3 = updates.metadata) === null || _metadata3 === void 0 ? void 0 : _metadata3.source_product_price) !== undefined;
727
+ if (callerUpdatesTopPrice && !callerUpdatesMainMeta) {
728
+ existedMeta = nextProduct.metadata || {};
729
+ nextProduct.metadata = _objectSpread({}, existedMeta);
730
+ delete nextProduct.metadata.source_product_price;
731
+ delete nextProduct.metadata.main_product_selling_price;
732
+ delete nextProduct.metadata.main_product_original_price;
733
+ delete nextProduct.metadata.price_schema_version;
734
+ }
735
+ // normalizeOrderProduct 幂等:v2 metadata 存在 → 保留 main_product_* 折扣重算 composite;
736
+ // 否则 → 把顶层 selling_price 视作 source,派生 main_product_* 并写 price_schema_version: 2。
737
+ tempOrder.products[productIndex] = normalizeOrderProduct(nextProduct);
639
738
  this.applyDiscount();
640
- _context8.next = 12;
739
+ _context8.next = 19;
641
740
  return this.recalculateSummary({
642
741
  createIfMissing: true
643
742
  });
644
- case 12:
743
+ case 19:
645
744
  this.persistTempOrder();
646
745
  return _context8.abrupt("return", tempOrder.products);
647
- case 14:
746
+ case 21:
648
747
  case "end":
649
748
  return _context8.stop();
650
749
  }
@@ -659,32 +758,23 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
659
758
  key: "removeProductFromOrder",
660
759
  value: function () {
661
760
  var _removeProductFromOrder = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9(identity) {
662
- var tempOrder, beforeProducts, removedByStrictIdentity;
761
+ var tempOrder;
663
762
  return _regeneratorRuntime().wrap(function _callee9$(_context9) {
664
763
  while (1) switch (_context9.prev = _context9.next) {
665
764
  case 0:
666
765
  tempOrder = this.ensureTempOrder();
667
- beforeProducts = tempOrder.products;
668
766
  tempOrder.products = tempOrder.products.filter(function (item) {
669
767
  return !isIdentityMatch(item, identity);
670
768
  });
671
- removedByStrictIdentity = beforeProducts.length - tempOrder.products.length;
672
- if (removedByStrictIdentity === 0 && identity.identity_key) {
673
- tempOrder.products = tempOrder.products.filter(function (item) {
674
- var isSameProduct = String(item.product_id) === String(identity.product_id) && String(item.product_variant_id) === String(identity.product_variant_id);
675
- var hasNoIdentityKey = !item.identity_key;
676
- return !(isSameProduct && hasNoIdentityKey);
677
- });
678
- }
679
769
  this.applyDiscount();
680
- _context9.next = 8;
770
+ _context9.next = 5;
681
771
  return this.recalculateSummary({
682
772
  createIfMissing: true
683
773
  });
684
- case 8:
774
+ case 5:
685
775
  this.persistTempOrder();
686
776
  return _context9.abrupt("return", tempOrder.products);
687
- case 10:
777
+ case 7:
688
778
  case "end":
689
779
  return _context9.stop();
690
780
  }
@@ -713,13 +803,14 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
713
803
  platform: params === null || params === void 0 ? void 0 : params.platform,
714
804
  businessCode: params === null || params === void 0 ? void 0 : params.businessCode,
715
805
  channel: params === null || params === void 0 ? void 0 : params.channel,
716
- type: params === null || params === void 0 ? void 0 : params.type
806
+ type: params === null || params === void 0 ? void 0 : params.type,
807
+ enhance: params === null || params === void 0 ? void 0 : params.enhancePayload
717
808
  });
718
809
  if (!tempOrder.order_id) {
719
810
  _context10.next = 12;
720
811
  break;
721
812
  }
722
- products = formatV1Product(payload.products);
813
+ products = filterProductsForScanOrderMore(payload.products);
723
814
  _context10.next = 8;
724
815
  return this.scanOrderMore({
725
816
  query: {
@@ -1030,7 +1121,9 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1030
1121
  case 0:
1031
1122
  url = params.url, query = params.query;
1032
1123
  fetchUrl = url || '/order/sales/checkout';
1033
- return _context13.abrupt("return", this.request.post(fetchUrl, query));
1124
+ return _context13.abrupt("return", this.request.post(fetchUrl, query, {
1125
+ customToast: function customToast() {}
1126
+ }));
1034
1127
  case 3:
1035
1128
  case "end":
1036
1129
  return _context13.stop();
@@ -1056,7 +1149,9 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1056
1149
  products: query.products,
1057
1150
  request_unique_idempotency_token: query.request_unique_idempotency_token
1058
1151
  };
1059
- return _context14.abrupt("return", this.request.put(fetchUrl, requestBody));
1152
+ return _context14.abrupt("return", this.request.put(fetchUrl, requestBody, {
1153
+ customToast: function customToast() {}
1154
+ }));
1060
1155
  case 4:
1061
1156
  case "end":
1062
1157
  return _context14.stop();
@@ -3,6 +3,7 @@ import type { ScanOrderTempOrder, ScanOrderOrderProduct, ScanOrderOrderProductId
3
3
  import type { DiscountModule } from '../Discount';
4
4
  import type { RulesModule } from '../Rules';
5
5
  import type { Discount } from '../Discount/types';
6
+ import type { SubmitPayloadEnhancer } from './utils';
6
7
  export declare enum OrderHooks {
7
8
  OnOrderCreate = "order:onOrderCreate",
8
9
  OnOrderUpdate = "order:onOrderUpdate",
@@ -15,6 +16,15 @@ export interface OrderState {
15
16
  discount: DiscountModule | null;
16
17
  rules: RulesModule | null;
17
18
  }
19
+ /** 更新购物车行:仅传 SKU 时命中同 SKU 第一行;多行同 SKU 须传 identity_key / 选项指纹等 */
20
+ export interface UpdateProductInOrderParams {
21
+ product_id: number | null;
22
+ product_variant_id: number;
23
+ updates: Partial<ScanOrderOrderProduct>;
24
+ identity_key?: string;
25
+ product_option_item?: any[];
26
+ product_bundle?: any[];
27
+ }
18
28
  /**
19
29
  * 订单信息
20
30
  */
@@ -34,14 +44,27 @@ export interface SubmitScanOrderProduct {
34
44
  num: number;
35
45
  product_variant_id: number;
36
46
  product_option_item: any[];
47
+ /**
48
+ * 行 composite 券后单价。
49
+ * 公式:`metadata.main_product_selling_price` + Σ(bundle_selling_price × num)。
50
+ * 主商品(含 option、含主商品折扣)的单价存在 `metadata.main_product_selling_price`。
51
+ */
37
52
  selling_price: string;
53
+ /**
54
+ * 行 composite 券前单价。
55
+ * 公式:`metadata.main_product_original_price` + Σ(bundle 原价 × num)。
56
+ * 主商品(含 option、不含折扣)的单价存在 `metadata.main_product_original_price`。
57
+ */
38
58
  original_price: string;
59
+ /** 出站兼容字段,直接由 `selling_price` 派生,语义同 composite。 */
39
60
  payment_price: string;
40
61
  tax_fee: string;
41
62
  is_charge_tax: number;
42
63
  discount_list: any[];
43
64
  product_bundle: any[];
44
65
  metadata: Record<string, any>;
66
+ /** 商品行备注 */
67
+ note?: string;
45
68
  }
46
69
  export interface SubmitScanOrderSummary {
47
70
  product_quantity: number;
@@ -68,10 +91,12 @@ export interface SubmitScanOrderBooking {
68
91
  start_time?: string;
69
92
  end_time?: string;
70
93
  metadata?: Record<string, any>;
94
+ resources?: Array<Record<string, any>>;
95
+ product_uid?: string;
71
96
  }
72
97
  export interface SubmitScanOrderFormRecord {
73
98
  form_id: number | string;
74
- form_record_ids: Array<number | string>;
99
+ form_record_id: number | string;
75
100
  }
76
101
  export interface SubmitScanOrderParams {
77
102
  url?: string;
@@ -107,6 +132,8 @@ export interface SubmitScanOrderParams {
107
132
  shop_discount: string;
108
133
  surcharge_fee: string;
109
134
  note: string;
135
+ delivery_type?: string;
136
+ table_number?: Record<string, any>;
110
137
  schedule_date: string;
111
138
  created_at?: string;
112
139
  products: SubmitScanOrderProduct[];
@@ -195,19 +222,17 @@ export interface OrderModuleAPI {
195
222
  getTempOrder: () => ScanOrderTempOrder | null;
196
223
  ensureTempOrder: () => ScanOrderTempOrder;
197
224
  addNewOrder: () => Promise<ScanOrderTempOrder>;
225
+ restoreOrder: () => ScanOrderTempOrder;
198
226
  getOrderProducts: () => ScanOrderOrderProduct[];
199
227
  getScanOrderSummary: () => Promise<ScanOrderSummary>;
200
228
  recalculateSummary: (options?: {
201
229
  createIfMissing?: boolean;
202
230
  }) => Promise<ScanOrderSummary | null>;
203
231
  updateTempOrderNote: (note: string) => string;
232
+ updateTempOrderBuzzer: (buzzer: string) => string;
204
233
  updateTempOrderContactsInfo: (contactsInfo: any[]) => any[];
205
234
  addProductToOrder: (product: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity) => Promise<ScanOrderOrderProduct[]>;
206
- updateProductInOrder: (params: {
207
- product_id: number | null;
208
- product_variant_id: number;
209
- updates: Partial<ScanOrderOrderProduct>;
210
- }) => Promise<ScanOrderOrderProduct[]>;
235
+ updateProductInOrder: (params: UpdateProductInOrderParams) => Promise<ScanOrderOrderProduct[]>;
211
236
  removeProductFromOrder: (identity: ScanOrderOrderProductIdentity) => Promise<ScanOrderOrderProduct[]>;
212
237
  persistTempOrder: () => void;
213
238
  submitTempOrder: <T = any>(params?: {
@@ -216,6 +241,7 @@ export interface OrderModuleAPI {
216
241
  businessCode?: string;
217
242
  channel?: string;
218
243
  type?: string;
244
+ enhancePayload?: SubmitPayloadEnhancer;
219
245
  }) => Promise<T>;
220
246
  loadDiscountConfig: (params: {
221
247
  customerId: number;
@@ -6,6 +6,8 @@ export var OrderHooks = /*#__PURE__*/function (OrderHooks) {
6
6
  return OrderHooks;
7
7
  }({});
8
8
 
9
+ /** 更新购物车行:仅传 SKU 时命中同 SKU 第一行;多行同 SKU 须传 identity_key / 选项指纹等 */
10
+
9
11
  /**
10
12
  * 订单信息
11
13
  */
@@ -1,21 +1,66 @@
1
+ import Decimal from 'decimal.js';
1
2
  import { CartItem } from "../Cart";
2
3
  import type { ScanOrderSubmitPayload, ScanOrderSubmitProduct, ScanOrderSummary, ScanOrderTempOrder } from '../../solution/ScanOrder/types';
3
4
  import type { RulesParamsHooks } from '../Rules/types';
5
+ /**
6
+ * 把"含 option 的主商品单价"与 bundle 合成"单行 composite 单价"。
7
+ *
8
+ * 新语义 v2 约定:
9
+ * - `mainPrice` 必须是**已经包含 option 的主商品单价**(即 `metadata.main_product_selling_price`
10
+ * 或 `metadata.main_product_original_price`),option 价格不由本函数叠加。
11
+ * - 套餐价:Σ((bundle.bundle_selling_price ?? bundle.price) × (bundle.num ?? bundle.quantity ?? 1))
12
+ * 当 `useOriginalBundle=true` 时,改用 `bundle.original_price ?? bundle.product_price ?? bundle.price`。
13
+ * - 返回值:保留 2 位小数的字符串,方便直接写回 `selling_price` / `original_price` 字段。
14
+ *
15
+ * 被 `normalizeOrderProduct`、Rules setProduct 钩子、各 Solution 的 setDiscountSelected 共用,
16
+ * 保证合成逻辑单点来源。
17
+ */
18
+ export declare function composeLinePrice(params: {
19
+ mainPrice: string | number | null | undefined;
20
+ bundle?: Array<{
21
+ bundle_selling_price?: any;
22
+ price?: any;
23
+ num?: any;
24
+ quantity?: any;
25
+ original_price?: any;
26
+ product_price?: any;
27
+ }> | null;
28
+ useOriginalBundle?: boolean;
29
+ }): string;
30
+ /**
31
+ * 计算 option 单价合计:Σ(option.price × option.num)。
32
+ * 在新语义 v2 下,main_product_original_price = source_product_price + 本函数结果。
33
+ */
34
+ export declare function sumOptionUnitPrice(options?: Array<{
35
+ price?: any;
36
+ num?: any;
37
+ }> | null): Decimal;
4
38
  /**
5
39
  * OrderModule 默认 Rules 钩子工厂。
6
40
  *
7
- * 价格语义约定(订单域):
8
- * - `selling_price`:券后单品单价(实际成交单价)。初次加购 = `original_price`;券应用后由 Rules 引擎更新。
9
- * - `original_price`:券前单品单价(店铺售价)。不承载后台划线价语义。
10
- * - `payment_price`:已从内部字段移除;只在出站 payload 中由 `selling_price` 派生以兼容后端。
41
+ * 价格语义约定(订单域,v2 composite 口径):
42
+ * - `selling_price`:券后 **行 composite 单价**
43
+ * = `metadata.main_product_selling_price` + Σ(bundle_selling_price × num)。
44
+ * - `original_price`:券前 **行 composite 单价**
45
+ * = `metadata.main_product_original_price` + Σ(bundle 原价 × num)。
46
+ * - `metadata.source_product_price`:主商品/variant 基础价(已应用报价单),不含 option、
47
+ * 不含折扣。**权威源**。
48
+ * - `metadata.main_product_original_price` = source + Σ(option.price × option.num)(含 option、不含折扣)。
49
+ * - `metadata.main_product_selling_price` = main_original − 主商品券 per-unit amount(含 option、含折扣)。
50
+ * - `payment_price`:出站 payload 中由 `selling_price` 派生以兼容后端(composite)。
11
51
  *
12
- * Rules 钩子契约:
13
- * - `getProduct.total` = `selling_price × num`(当前成交总价)
14
- * - `getProduct.origin_total` = `original_price × num`(券前总价)
15
- * - `setProduct` 写回 `selling_price` 的优先级:
16
- * 1. `values.main_product_selling_price`(券应用分支,per-unit 券后主价)
17
- * 2. `values.price`(还原分支 `restoredPrice`、good_pass 归零)
18
- * 3. `values.total / num`(仅当 Rules 只给出总价时的兜底)
52
+ * Rules 钩子契约(hook_adapt 方案,Rules 内部保持不变):
53
+ * - `getProduct.price` / `getProduct.original_price` 回传 **source-level 主价**
54
+ * (`metadata.source_product_price`)。Rules 内部 `getProductTotalPrice` /
55
+ * `getProductOriginTotalPrice` 会自行叠加 option + bundle,喂 source 可避免 option 双加。
56
+ * - `getProduct.total` = `selling_price × num`(行 composite × num),与 Rules 内部产出的
57
+ * total(source + option + bundle)对齐。
58
+ * - `setProduct` 反向流程:把 Rules 返回的 source-level `main_product_selling_price` / `price`
59
+ * 加回 Σoptions,重新合成含 option 的 main_product_* 并派生 composite。
60
+ * 优先级:
61
+ * 1. `values.main_product_selling_price`(券应用分支,per-unit 券后 source-level 主价)
62
+ * 2. `values.price`(还原分支 `restoredPrice`、good_pass 归零)
63
+ * 3. `values.total / num`(仅当 Rules 只给出总价时的兜底)
19
64
  *
20
65
  * 导出为纯函数方便单测直接驱动钩子,不依赖 OrderModule 实例。
21
66
  */
@@ -56,6 +101,12 @@ export declare function createDefaultTempOrder(params: {
56
101
  now: string;
57
102
  summary?: ScanOrderSummary;
58
103
  }): ScanOrderTempOrder;
104
+ export interface SubmitPayloadEnhancerContext {
105
+ tempOrder: ScanOrderTempOrder;
106
+ bookingUuid: string;
107
+ now: Date;
108
+ }
109
+ export type SubmitPayloadEnhancer = (payload: ScanOrderSubmitPayload, ctx: SubmitPayloadEnhancerContext) => ScanOrderSubmitPayload;
59
110
  export declare function buildSubmitPayload(params: {
60
111
  tempOrder: ScanOrderTempOrder;
61
112
  cacheId?: string;
@@ -64,7 +115,17 @@ export declare function buildSubmitPayload(params: {
64
115
  businessCode?: string;
65
116
  channel?: string;
66
117
  type?: string;
118
+ enhance?: SubmitPayloadEnhancer;
67
119
  }): ScanOrderSubmitPayload;
120
+ /** 加单(scanOrderMore)不应提交 booking 关联的虚拟规则商品行 */
121
+ export declare function filterProductsForScanOrderMore(products: ScanOrderSubmitProduct[]): ScanOrderSubmitProduct[];
122
+ /**
123
+ * 历史 V1 加餐结构映射器。
124
+ *
125
+ * @deprecated 加餐(`PUT /order/order/product/:id`)已改为与正常 checkout 共用
126
+ * `ScanOrderSubmitProduct` 新结构(见 `OrderModule.submitTempOrder` 的加餐分支)。
127
+ * 本函数仅保留以兼容历史接入方,未来会移除。新代码请勿再调用。
128
+ */
68
129
  export declare function formatV1Product(products: ScanOrderSubmitProduct[]): {
69
130
  bundle: any[];
70
131
  key: number | null;
@@ -72,6 +133,7 @@ export declare function formatV1Product(products: ScanOrderSubmitProduct[]): {
72
133
  product_id: number | null;
73
134
  product_variant_id: number;
74
135
  num: number;
136
+ note: string;
75
137
  rowKey: number | null;
76
138
  session: null;
77
139
  unique: string;