@pisell/pisellos 2.3.21 → 2.3.23

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.
@@ -1,3 +1,4 @@
1
+ import type { Discount } from '../../modules/Discount/types';
1
2
  import { OrderModule, ProductList, QuotationModule, SalesSummaryModule, ScanOrderLoggerModule as BaseSalesLoggerModule, ScheduleModule } from '../../modules';
2
3
  import type { ScanOrderLogInput as BaseSalesLogInput, ScanOrderLoggerProviderConfig as BaseSalesLoggerProviderConfig, ScanOrderLoggerProviderType as BaseSalesLoggerProviderType } from '../../modules/ScanOrderLogger/types';
3
4
  import type { QuantityCheckResult, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
@@ -383,9 +384,11 @@ export interface BaseSalesLoggerRuntimeConfig {
383
384
  }
384
385
  export interface BaseSalesAddLogParams extends BaseSalesLogInput {
385
386
  }
386
- /** BaseSales.scanPromotionCode 对外的轻量结果(不含 discountList,UI resolve 后调 getDiscountList) */
387
+ /** BaseSales.scanPromotionCode 对外的轻量结果(UI 可用 getDiscountList scannedDiscountList 补 Holder) */
387
388
  export interface BaseSalesScanCodeResult {
388
389
  isAvailable: boolean;
389
390
  type?: 'server' | string;
390
391
  unavailableReason?: 'time_limit' | string;
392
+ /** batchSearch 原始结果;isAvailable=false 时 discountList 可能未写入 store,Holder 补全需读此字段 */
393
+ scannedDiscountList?: Discount[];
391
394
  }
@@ -37,4 +37,4 @@ export function createBaseSalesHook(moduleName, hookName) {
37
37
 
38
38
  /** `/order/resource/occupy-detail` 单条 `occupy_details[i]` */
39
39
 
40
- /** BaseSales.scanPromotionCode 对外的轻量结果(不含 discountList,UI resolve 后调 getDiscountList) */
40
+ /** BaseSales.scanPromotionCode 对外的轻量结果(UI 可用 getDiscountList scannedDiscountList 补 Holder) */
@@ -30,6 +30,17 @@ function toPriceString(value) {
30
30
  if (!Number.isFinite(parsedValue)) return fallback;
31
31
  return parsedValue.toFixed(2);
32
32
  }
33
+ function isBlankValue(value) {
34
+ return value === undefined || value === null || typeof value === 'string' && value.trim() === '';
35
+ }
36
+ function firstNonBlank() {
37
+ for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {
38
+ values[_key] = arguments[_key];
39
+ }
40
+ return values.find(function (value) {
41
+ return !isBlankValue(value);
42
+ });
43
+ }
33
44
  function normalizeOptionItems(optionItems) {
34
45
  if (!Array.isArray(optionItems)) return [];
35
46
  return optionItems.map(function (optionItem) {
@@ -199,7 +210,7 @@ export function transformBaseProductToOrderProduct(params) {
199
210
  metadata: metadata,
200
211
  note: payload.note != null ? String(payload.note) : '',
201
212
  product_title: productTitle,
202
- product_cover: sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.cover,
213
+ product_cover: firstNonBlank(matchedVariant === null || matchedVariant === void 0 ? void 0 : matchedVariant.cover, sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.cover),
203
214
  _origin: _objectSpread(_objectSpread({}, sourceProduct || {}), {}, {
204
215
  callbackData: payload
205
216
  })
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
314
+ weekNum: 0 | 1 | 2 | 6 | 3 | 4 | 5;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;
@@ -358,7 +358,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
358
358
  };
359
359
  setOtherData(key: string, value: any): void;
360
360
  getOtherData(key: string): any;
361
- getProductTypeById(id: number): Promise<"duration" | "session" | "normal">;
361
+ getProductTypeById(id: number): Promise<"normal" | "duration" | "session">;
362
362
  /**
363
363
  * 提供给 UI 的方法,减轻 UI 层的计算压力,UI 层只需要传递 cartItemId 和 resourceCode 即返回对应的 renderList
364
364
  *
@@ -1,8 +1,8 @@
1
1
  var _excluded = ["id"],
2
2
  _excluded2 = ["product_id"],
3
3
  _excluded3 = ["product_id"];
4
- 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; } } }; }
5
4
  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); }
5
+ 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; } } }; }
6
6
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
7
7
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
8
8
  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; }
@@ -549,7 +549,7 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
549
549
  key: "scanPromotionCode",
550
550
  value: function () {
551
551
  var _scanPromotionCode = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(code, customerId) {
552
- var raw;
552
+ var raw, scannedList, extractedCustomerId, hasOrderCustomer;
553
553
  return _regeneratorRuntime().wrap(function _callee7$(_context7) {
554
554
  while (1) switch (_context7.prev = _context7.next) {
555
555
  case 0:
@@ -563,26 +563,34 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
563
563
  return this.store.order.scanCode(code, customerId);
564
564
  case 4:
565
565
  raw = _context7.sent;
566
- if (!raw.isAvailable) {
566
+ scannedList = raw.scannedDiscountList || [];
567
+ extractedCustomerId = this.getDiscountCustomerId(scannedList);
568
+ hasOrderCustomer = Boolean(this.store.order.getOrderCustomer()); // 缺 Holder 等场景 isAvailable=false,但仍需把 Pass 归属客户带入订单,供 Holder 弹窗使用。
569
+ if (!(!hasOrderCustomer && extractedCustomerId)) {
567
570
  _context7.next = 11;
568
571
  break;
569
572
  }
570
- _context7.next = 8;
571
- return this.hydrateOrderCustomerFromScanDiscounts(raw.scannedDiscountList || []);
572
- case 8:
573
- _context7.next = 10;
573
+ _context7.next = 11;
574
+ return this.hydrateOrderCustomerFromScanDiscounts(scannedList);
575
+ case 11:
576
+ if (!raw.isAvailable) {
577
+ _context7.next = 15;
578
+ break;
579
+ }
580
+ _context7.next = 14;
574
581
  return this.store.order.recalculateSummary({
575
582
  createIfMissing: true
576
583
  });
577
- case 10:
584
+ case 14:
578
585
  this.store.order.persistTempOrder();
579
- case 11:
586
+ case 15:
580
587
  return _context7.abrupt("return", {
581
588
  isAvailable: raw.isAvailable,
582
589
  type: raw.type,
583
- unavailableReason: raw.unavailableReason
590
+ unavailableReason: raw.unavailableReason,
591
+ scannedDiscountList: raw.scannedDiscountList
584
592
  });
585
- case 12:
593
+ case 16:
586
594
  case "end":
587
595
  return _context7.stop();
588
596
  }
@@ -641,12 +649,22 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
641
649
  }, {
642
650
  key: "getDiscountCustomerId",
643
651
  value: function getDiscountCustomerId(discounts) {
644
- var discount = discounts.find(function (item) {
645
- return item.customer_id != null;
646
- });
647
- var customerId = Number(discount === null || discount === void 0 ? void 0 : discount.customer_id);
648
- if (!Number.isFinite(customerId) || customerId <= 0) return null;
649
- return customerId;
652
+ var _iterator = _createForOfIteratorHelper(discounts),
653
+ _step;
654
+ try {
655
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
656
+ var item = _step.value;
657
+ var topLevelId = Number(item.customer_id);
658
+ if (Number.isFinite(topLevelId) && topLevelId > 0) {
659
+ return topLevelId;
660
+ }
661
+ }
662
+ } catch (err) {
663
+ _iterator.e(err);
664
+ } finally {
665
+ _iterator.f();
666
+ }
667
+ return null;
650
668
  }
651
669
  }, {
652
670
  key: "resolveCustomerByDiscountCustomerId",
@@ -2468,7 +2486,7 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
2468
2486
  var _addAddTimeProductsToBooking = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee30(input) {
2469
2487
  var _this7 = this,
2470
2488
  _input$bookingPatch;
2471
- var bookingUid, orderLines, coveredMinutes, bookingTimePatch, result, _iterator, _step, line;
2489
+ var bookingUid, orderLines, coveredMinutes, bookingTimePatch, result, _iterator2, _step2, line;
2472
2490
  return _regeneratorRuntime().wrap(function _callee30$(_context30) {
2473
2491
  while (1) switch (_context30.prev = _context30.next) {
2474
2492
  case 0:
@@ -2508,15 +2526,15 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
2508
2526
  }));
2509
2527
  case 11:
2510
2528
  result = [];
2511
- _iterator = _createForOfIteratorHelper(orderLines);
2529
+ _iterator2 = _createForOfIteratorHelper(orderLines);
2512
2530
  _context30.prev = 13;
2513
- _iterator.s();
2531
+ _iterator2.s();
2514
2532
  case 15:
2515
- if ((_step = _iterator.n()).done) {
2533
+ if ((_step2 = _iterator2.n()).done) {
2516
2534
  _context30.next = 29;
2517
2535
  break;
2518
2536
  }
2519
- line = _step.value;
2537
+ line = _step2.value;
2520
2538
  _context30.t0 = result.splice;
2521
2539
  _context30.t1 = result;
2522
2540
  _context30.t2 = [0, result.length];
@@ -2537,10 +2555,10 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
2537
2555
  case 31:
2538
2556
  _context30.prev = 31;
2539
2557
  _context30.t7 = _context30["catch"](13);
2540
- _iterator.e(_context30.t7);
2558
+ _iterator2.e(_context30.t7);
2541
2559
  case 34:
2542
2560
  _context30.prev = 34;
2543
- _iterator.f();
2561
+ _iterator2.f();
2544
2562
  return _context30.finish(34);
2545
2563
  case 37:
2546
2564
  return _context30.abrupt("return", result);
@@ -276,6 +276,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
276
276
  updateTempOrderContactsInfo(contactsInfo: Record<string, any> | null): Record<string, any> | null;
277
277
  private buildTempOrderCustomer;
278
278
  private isCustomerBoundDiscount;
279
+ private shouldKeepCustomerBoundDiscountAfterCustomerChange;
279
280
  private productHasCustomerBoundDiscount;
280
281
  private shouldSkipDiscountCalculation;
281
282
  private clearCustomerBoundDiscounts;
@@ -463,7 +464,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
463
464
  generateIdempotencyToken(): string;
464
465
  syncPaymentsToOrder<T = any>(params: SyncPaymentsToOrderParams): Promise<SyncPaymentsToOrderResult<T>>;
465
466
  createOrder(params: CommitOrderParams['query']): {
466
- type: "appointment_booking" | "virtual";
467
+ type: "virtual" | "appointment_booking";
467
468
  platform: string;
468
469
  sales_channel: string;
469
470
  order_sales_channel: string;
@@ -445,9 +445,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
445
445
  ...orderId ? { order_id: orderId } : {}
446
446
  }));
447
447
  if (discountList) {
448
- const currentEditDiscounts = (((_c = this.store.discount) == null ? void 0 : _c.getDiscountList()) || []).filter((discount) => discount == null ? void 0 : discount.isEditMode);
448
+ const currentDiscountList = ((_c = this.store.discount) == null ? void 0 : _c.getDiscountList()) || [];
449
+ const currentEditDiscounts = currentDiscountList.filter((discount) => discount == null ? void 0 : discount.isEditMode);
450
+ const currentScanDiscounts = currentDiscountList.filter((discount) => discount == null ? void 0 : discount.isScan);
451
+ const currentScanDiscountIds = new Set(
452
+ currentScanDiscounts.map((discount) => discount == null ? void 0 : discount.id)
453
+ );
449
454
  const runtimeDiscountIds = /* @__PURE__ */ new Set();
450
455
  const runtimeDiscounts = discountList.filter((discount) => {
456
+ if (currentScanDiscountIds.has(discount == null ? void 0 : discount.id))
457
+ return false;
451
458
  if (runtimeDiscountIds.has(discount == null ? void 0 : discount.id))
452
459
  return false;
453
460
  runtimeDiscountIds.add(discount == null ? void 0 : discount.id);
@@ -455,6 +462,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
455
462
  });
456
463
  const mergedDiscountList = [
457
464
  ...currentEditDiscounts,
465
+ ...currentScanDiscounts,
458
466
  ...runtimeDiscounts
459
467
  ];
460
468
  await ((_d = this.store.discount) == null ? void 0 : _d.setOriginalDiscountList(mergedDiscountList));
@@ -2214,6 +2222,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2214
2222
  const type = (discount == null ? void 0 : discount.type) ?? (discount == null ? void 0 : discount.tag);
2215
2223
  return type === "good_pass" || type === "discount_card" || type === "product_discount_card";
2216
2224
  }
2225
+ shouldKeepCustomerBoundDiscountAfterCustomerChange(discount) {
2226
+ return Boolean((discount == null ? void 0 : discount.isScan) || (discount == null ? void 0 : discount.isEditMode));
2227
+ }
2217
2228
  productHasCustomerBoundDiscount(product) {
2218
2229
  if (((product == null ? void 0 : product.discount_list) || []).some((discount) => this.isCustomerBoundDiscount(discount))) {
2219
2230
  return true;
@@ -2269,12 +2280,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2269
2280
  const currentDiscounts = ((_a = discountModule.getDiscountList) == null ? void 0 : _a.call(discountModule)) || [];
2270
2281
  const currentOriginalDiscounts = ((_b = discountModule.getOriginalDiscountList) == null ? void 0 : _b.call(discountModule)) || [];
2271
2282
  const nextDiscounts = currentDiscounts.filter((discount) => {
2272
- if (discount == null ? void 0 : discount.isEditMode)
2283
+ if (this.shouldKeepCustomerBoundDiscountAfterCustomerChange(discount))
2273
2284
  return true;
2274
2285
  return !this.isCustomerBoundDiscount(discount);
2275
2286
  });
2276
2287
  const nextOriginalDiscounts = currentOriginalDiscounts.filter((discount) => {
2277
- if (discount == null ? void 0 : discount.isEditMode)
2288
+ if (this.shouldKeepCustomerBoundDiscountAfterCustomerChange(discount))
2278
2289
  return true;
2279
2290
  return !this.isCustomerBoundDiscount(discount);
2280
2291
  });
@@ -2986,6 +2997,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2986
2997
  return bundle;
2987
2998
  return {
2988
2999
  ...bundle,
3000
+ ...(bundle.cover === void 0 || bundle.cover === null || bundle.cover === "") && previous.cover !== void 0 && previous.cover !== null && previous.cover !== "" ? { cover: previous.cover } : {},
2989
3001
  price: previous.price,
2990
3002
  custom_price: previous.custom_price,
2991
3003
  bundle_payment_price: previous.bundle_payment_price,
@@ -67,8 +67,8 @@ export declare function sumOptionUnitPrice(options?: Array<{
67
67
  /**
68
68
  * 仅基于 tempOrder.products 重算整单定金。
69
69
  *
70
- * 对齐 Checkout relation_products 分支:商品定金先按商品规则计算,
71
- * 再扣减商品券/折扣卡抵扣金额;tempOrder.bookings 不参与这里的计算。
70
+ * 商品折扣在进入定金计算前已体现在商品行价格字段中,
71
+ * 因此这里只按商品定金规则汇总,不再扣减 discount_list;tempOrder.bookings 不参与这里的计算。
72
72
  */
73
73
  export declare function calculateOrderProductsDeposit(products?: OrderProduct[], options?: {
74
74
  productsByUid?: Record<string, Record<string, any>>;
@@ -286,9 +286,6 @@ function calculateOrderProductsDeposit(products = [], options) {
286
286
  if (!(deposit == null ? void 0 : deposit.total) || Number(deposit.total) <= 0)
287
287
  continue;
288
288
  total = total.plus(deposit.total);
289
- for (const discount of product.discount_list || []) {
290
- total = total.minus((discount == null ? void 0 : discount.amount) || 0);
291
- }
292
289
  for (const protocol of deposit.protocols || []) {
293
290
  if (!protocolMap.has(protocol.id))
294
291
  protocolMap.set(protocol.id, protocol);
@@ -495,13 +492,17 @@ function createDefaultOrderRulesHooks() {
495
492
  const current = currentByIdentity.get(getBundleIdentity(bundle));
496
493
  if (!current)
497
494
  return bundle;
495
+ const bundleWithDisplayFields = {
496
+ ...bundle,
497
+ ...isEmptyOrderProductDisplayValue(bundle.cover) && !isEmptyOrderProductDisplayValue(current.cover) ? { cover: current.cover } : {}
498
+ };
498
499
  const isProductPriceBundle = (bundle.price_type_ext ?? current.price_type_ext) === "product_price";
499
500
  if (!isProductPriceBundle)
500
- return bundle;
501
+ return bundleWithDisplayFields;
501
502
  const sourcePrice = current.price ?? current.custom_price ?? current.original_price ?? current.bundle_selling_price;
502
503
  const originalPrice = current.original_price ?? current.product_price ?? current.price ?? current.custom_price ?? sourcePrice;
503
504
  return {
504
- ...bundle,
505
+ ...bundleWithDisplayFields,
505
506
  ...sourcePrice !== void 0 ? { price: sourcePrice } : {},
506
507
  ...originalPrice !== void 0 ? { original_price: originalPrice } : {},
507
508
  ...current.original_total !== void 0 ? { original_total: current.original_total } : {}
@@ -745,6 +746,7 @@ function formatSubmitBundleItems(bundle) {
745
746
  bundle_group_id: (rawBundle == null ? void 0 : rawBundle.bundle_group_id) ?? (rawBundle == null ? void 0 : rawBundle.group_id),
746
747
  bundle_id: (rawBundle == null ? void 0 : rawBundle.bundle_id) ?? (rawBundle == null ? void 0 : rawBundle.id),
747
748
  bundle_product_id: (rawBundle == null ? void 0 : rawBundle.bundle_product_id) ?? (rawBundle == null ? void 0 : rawBundle._bundle_product_id),
749
+ cover: rawBundle.cover,
748
750
  metadata: {
749
751
  ...submitMetadata,
750
752
  ...hasSubmitBundleDiscounts && bundleMapId !== void 0 ? { custom_product_bundle_map_id: bundleMapId } : {},
@@ -448,6 +448,7 @@ declare class Server {
448
448
  private collectSalesDetailProductIds;
449
449
  private buildSalesDetailProductSnapshotMap;
450
450
  private withProductCatalogSnapshots;
451
+ private withBundleCatalogSnapshots;
451
452
  private withSalesDetailProductSnapshots;
452
453
  private withPendingSyncProductTitles;
453
454
  private buildProductTitleSnapshot;
@@ -3236,13 +3236,20 @@ var Server = class {
3236
3236
  collectSalesDetailProductIds(order) {
3237
3237
  const products = Array.isArray(order == null ? void 0 : order.products) ? order.products : [];
3238
3238
  const productIds = /* @__PURE__ */ new Set();
3239
- products.forEach((product) => {
3240
- const rawProductId = (product == null ? void 0 : product.product_id) ?? (product == null ? void 0 : product.id);
3239
+ const addProductId = (rawProductId) => {
3241
3240
  if (rawProductId === void 0 || rawProductId === null || rawProductId === "")
3242
3241
  return;
3243
3242
  const productId = Number(rawProductId);
3244
3243
  if (Number.isFinite(productId))
3245
3244
  productIds.add(productId);
3245
+ };
3246
+ products.forEach((product) => {
3247
+ addProductId((product == null ? void 0 : product.product_id) ?? (product == null ? void 0 : product.id));
3248
+ if (Array.isArray(product == null ? void 0 : product.product_bundle)) {
3249
+ product.product_bundle.forEach((bundle) => {
3250
+ addProductId((bundle == null ? void 0 : bundle.bundle_product_id) ?? (bundle == null ? void 0 : bundle._bundle_product_id) ?? (bundle == null ? void 0 : bundle.product_id));
3251
+ });
3252
+ }
3246
3253
  });
3247
3254
  return Array.from(productIds);
3248
3255
  }
@@ -3290,6 +3297,36 @@ var Server = class {
3290
3297
  } : {}
3291
3298
  };
3292
3299
  }
3300
+ withBundleCatalogSnapshots(product, snapshotMap) {
3301
+ if (!Array.isArray(product == null ? void 0 : product.product_bundle))
3302
+ return product;
3303
+ let hasChanged = false;
3304
+ const productBundle = product.product_bundle.map((bundle) => {
3305
+ if (!bundle || typeof bundle !== "object")
3306
+ return bundle;
3307
+ const rawProductId = (bundle == null ? void 0 : bundle.bundle_product_id) ?? (bundle == null ? void 0 : bundle._bundle_product_id) ?? (bundle == null ? void 0 : bundle.product_id);
3308
+ if (rawProductId === void 0 || rawProductId === null || rawProductId === "")
3309
+ return bundle;
3310
+ const productId = Number(rawProductId);
3311
+ if (!Number.isFinite(productId))
3312
+ return bundle;
3313
+ const snapshot = snapshotMap[String(productId)];
3314
+ const shouldFillCover = (bundle.cover === void 0 || bundle.cover === null || bundle.cover === "") && (snapshot == null ? void 0 : snapshot.cover) !== void 0 && snapshot.cover !== null && snapshot.cover !== "";
3315
+ if (!shouldFillCover)
3316
+ return bundle;
3317
+ hasChanged = true;
3318
+ return {
3319
+ ...bundle,
3320
+ cover: snapshot.cover
3321
+ };
3322
+ });
3323
+ if (!hasChanged)
3324
+ return product;
3325
+ return {
3326
+ ...product,
3327
+ product_bundle: productBundle
3328
+ };
3329
+ }
3293
3330
  async withSalesDetailProductSnapshots(order) {
3294
3331
  const products = Array.isArray(order == null ? void 0 : order.products) ? order.products : null;
3295
3332
  if (!(products == null ? void 0 : products.length))
@@ -3299,7 +3336,8 @@ var Server = class {
3299
3336
  return order;
3300
3337
  let hasChanged = false;
3301
3338
  const enrichedProducts = products.map((product) => {
3302
- const nextProduct = this.withProductCatalogSnapshots(product, snapshotMap);
3339
+ const productWithBundleSnapshots = this.withBundleCatalogSnapshots(product, snapshotMap);
3340
+ const nextProduct = this.withProductCatalogSnapshots(productWithBundleSnapshots, snapshotMap);
3303
3341
  if (nextProduct !== product)
3304
3342
  hasChanged = true;
3305
3343
  return nextProduct;
@@ -63,6 +63,8 @@ export interface OrderProductBundleItem {
63
63
  bundle_group_id?: number;
64
64
  /** 套餐商品 ID */
65
65
  bundle_id?: number;
66
+ /** 套餐子商品封面图 */
67
+ cover?: string | null;
66
68
  /** 套餐商品规格 ID */
67
69
  bundle_variant_id?: number;
68
70
  /** 数量 */
@@ -52,6 +52,7 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
52
52
  private salesDetailLoadInFlight;
53
53
  private serverOrderChangeUnsubscribe;
54
54
  private serverOrderChangeHydrateInFlight;
55
+ private serverOrderChangeSyncEnabled;
55
56
  constructor(name?: string, version?: string);
56
57
  /**
57
58
  * 子类可覆盖此方法以追加/收敛要注册的子模块。
@@ -73,6 +74,7 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
73
74
  */
74
75
  private logError;
75
76
  private isCurrentSalesOrderRecord;
77
+ setServerOrderChangeSyncEnabled(enabled: boolean): void;
76
78
  private syncCurrentSalesDetailFromServerOrderChange;
77
79
  private registerServerOrderChangeSync;
78
80
  private hydrateOrderPaymentNames;
@@ -191,6 +193,16 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
191
193
  discountList: Discount[];
192
194
  }>;
193
195
  getDiscountList(): Discount[];
196
+ /** 读取 Discount 模块原始券列表(未经过 bookingTime 等过滤)。 */
197
+ getOriginalDiscountList(): Discount[];
198
+ /**
199
+ * 同步写入 Discount 模块的 discountList / originalDiscountList。
200
+ * 供 Holder 补全等场景在 OS store 层更新 machinecode holder 字段。
201
+ */
202
+ replaceDiscountStoreLists(params: {
203
+ discountList: Discount[];
204
+ originalDiscountList?: Discount[];
205
+ }): Promise<void>;
194
206
  scanPromotionCode(code: string, customerId?: number): Promise<BaseSalesScanCodeResult>;
195
207
  setDiscountSelected(params: {
196
208
  discountId: number;
@@ -193,6 +193,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
193
193
  this.salesDetailLoadInFlight = false;
194
194
  this.serverOrderChangeUnsubscribe = null;
195
195
  this.serverOrderChangeHydrateInFlight = null;
196
+ this.serverOrderChangeSyncEnabled = false;
196
197
  }
197
198
  /**
198
199
  * 子类可覆盖此方法以追加/收敛要注册的子模块。
@@ -266,9 +267,12 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
266
267
  ].filter(Boolean);
267
268
  return currentRecords.some((record) => isSameBaseSalesOrderRecord(record, order));
268
269
  }
270
+ setServerOrderChangeSyncEnabled(enabled) {
271
+ this.serverOrderChangeSyncEnabled = enabled;
272
+ }
269
273
  async syncCurrentSalesDetailFromServerOrderChange(payload) {
270
274
  const changedOrders = Array.isArray(payload) ? payload : Array.isArray(payload == null ? void 0 : payload.changedOrders) ? payload.changedOrders : (payload == null ? void 0 : payload.data) && typeof payload.data === "object" ? [payload.data] : [];
271
- if (this.salesDetailLoadInFlight || this.serverOrderChangeHydrateInFlight)
275
+ if (!this.serverOrderChangeSyncEnabled || this.salesDetailLoadInFlight || this.serverOrderChangeHydrateInFlight)
272
276
  return;
273
277
  const changedOrder = changedOrders.find(
274
278
  (order) => this.isCurrentSalesOrderRecord(order)
@@ -1305,6 +1309,30 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1305
1309
  return [];
1306
1310
  return this.store.order.getDiscountList();
1307
1311
  }
1312
+ /** 读取 Discount 模块原始券列表(未经过 bookingTime 等过滤)。 */
1313
+ getOriginalDiscountList() {
1314
+ var _a, _b;
1315
+ if (!this.store.order)
1316
+ return [];
1317
+ const discountModule = (_a = this.store.order.store) == null ? void 0 : _a.discount;
1318
+ return ((_b = discountModule == null ? void 0 : discountModule.getOriginalDiscountList) == null ? void 0 : _b.call(discountModule)) || [];
1319
+ }
1320
+ /**
1321
+ * 同步写入 Discount 模块的 discountList / originalDiscountList。
1322
+ * 供 Holder 补全等场景在 OS store 层更新 machinecode holder 字段。
1323
+ */
1324
+ async replaceDiscountStoreLists(params) {
1325
+ var _a;
1326
+ if (!this.store.order)
1327
+ throw new Error("order 模块未初始化");
1328
+ const discountModule = (_a = this.store.order.store) == null ? void 0 : _a.discount;
1329
+ if (!discountModule)
1330
+ return;
1331
+ if (params.originalDiscountList) {
1332
+ await discountModule.setOriginalDiscountList(params.originalDiscountList);
1333
+ }
1334
+ await discountModule.setDiscountList(params.discountList);
1335
+ }
1308
1336
  async scanPromotionCode(code, customerId) {
1309
1337
  try {
1310
1338
  if (!this.store.order)
@@ -1317,7 +1345,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1317
1345
  return {
1318
1346
  isAvailable: raw.isAvailable,
1319
1347
  type: raw.type,
1320
- unavailableReason: raw.unavailableReason
1348
+ unavailableReason: raw.unavailableReason,
1349
+ scannedDiscountList: raw.scannedDiscountList
1321
1350
  };
1322
1351
  } catch (error) {
1323
1352
  throw error;
@@ -1,3 +1,4 @@
1
+ import type { Discount } from '../../modules/Discount/types';
1
2
  import { OrderModule, ProductList, QuotationModule, SalesSummaryModule, ScanOrderLoggerModule as BaseSalesLoggerModule, ScheduleModule } from '../../modules';
2
3
  import type { ScanOrderLogInput as BaseSalesLogInput, ScanOrderLoggerProviderConfig as BaseSalesLoggerProviderConfig, ScanOrderLoggerProviderType as BaseSalesLoggerProviderType } from '../../modules/ScanOrderLogger/types';
3
4
  import type { QuantityCheckResult, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
@@ -383,9 +384,11 @@ export interface BaseSalesLoggerRuntimeConfig {
383
384
  }
384
385
  export interface BaseSalesAddLogParams extends BaseSalesLogInput {
385
386
  }
386
- /** BaseSales.scanPromotionCode 对外的轻量结果(不含 discountList,UI resolve 后调 getDiscountList) */
387
+ /** BaseSales.scanPromotionCode 对外的轻量结果(UI 可用 getDiscountList scannedDiscountList 补 Holder) */
387
388
  export interface BaseSalesScanCodeResult {
388
389
  isAvailable: boolean;
389
390
  type?: 'server' | string;
390
391
  unavailableReason?: 'time_limit' | string;
392
+ /** batchSearch 原始结果;isAvailable=false 时 discountList 可能未写入 store,Holder 补全需读此字段 */
393
+ scannedDiscountList?: Discount[];
391
394
  }
@@ -50,6 +50,12 @@ function toPriceString(value, fallback = "0.00") {
50
50
  return fallback;
51
51
  return parsedValue.toFixed(2);
52
52
  }
53
+ function isBlankValue(value) {
54
+ return value === void 0 || value === null || typeof value === "string" && value.trim() === "";
55
+ }
56
+ function firstNonBlank(...values) {
57
+ return values.find((value) => !isBlankValue(value));
58
+ }
53
59
  function normalizeOptionItems(optionItems) {
54
60
  if (!Array.isArray(optionItems))
55
61
  return [];
@@ -237,7 +243,7 @@ function transformBaseProductToOrderProduct(params) {
237
243
  metadata,
238
244
  note: payload.note != null ? String(payload.note) : "",
239
245
  product_title: productTitle,
240
- product_cover: sourceProduct == null ? void 0 : sourceProduct.cover,
246
+ product_cover: firstNonBlank(matchedVariant == null ? void 0 : matchedVariant.cover, sourceProduct == null ? void 0 : sourceProduct.cover),
241
247
  _origin: {
242
248
  ...sourceProduct || {},
243
249
  callbackData: payload
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
314
+ weekNum: 0 | 1 | 2 | 6 | 3 | 4 | 5;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;
@@ -358,7 +358,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
358
358
  };
359
359
  setOtherData(key: string, value: any): void;
360
360
  getOtherData(key: string): any;
361
- getProductTypeById(id: number): Promise<"duration" | "session" | "normal">;
361
+ getProductTypeById(id: number): Promise<"normal" | "duration" | "session">;
362
362
  /**
363
363
  * 提供给 UI 的方法,减轻 UI 层的计算压力,UI 层只需要传递 cartItemId 和 resourceCode 即返回对应的 renderList
364
364
  *