@pisell/pisellos 2.1.122 → 2.1.123

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.
@@ -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";
@@ -112,4 +112,6 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
112
112
  createOrderByCheckout(params: CheckoutOrderParams): Promise<any>;
113
113
  submitScanOrder<T = any>(params: SubmitScanOrderParams): Promise<T>;
114
114
  scanOrderMore<T = any>(params: ScanOrderMoreParams): Promise<T>;
115
+ getOrderInfoByRemote(order_id: number): Promise<void>;
116
+ getLastOrderInfo(): Record<string, any> | undefined;
115
117
  }
@@ -1099,7 +1099,41 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1099
1099
  return _scanOrderMore.apply(this, arguments);
1100
1100
  }
1101
1101
  return scanOrderMore;
1102
+ }() // TODO 获取详情的接口
1103
+ }, {
1104
+ key: "getOrderInfoByRemote",
1105
+ value: function () {
1106
+ var _getOrderInfoByRemote = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee15(order_id) {
1107
+ var res;
1108
+ return _regeneratorRuntime().wrap(function _callee15$(_context15) {
1109
+ while (1) switch (_context15.prev = _context15.next) {
1110
+ case 0:
1111
+ _context15.next = 2;
1112
+ return this.request.get("/order/sales/".concat(order_id), {
1113
+ with: ['products', 'scheduleEvents']
1114
+ });
1115
+ case 2:
1116
+ res = _context15.sent;
1117
+ if (res.data.code === 200 && this.store.tempOrder) {
1118
+ this.store.tempOrder.lastOrderInfo = res.data.data;
1119
+ }
1120
+ case 4:
1121
+ case "end":
1122
+ return _context15.stop();
1123
+ }
1124
+ }, _callee15, this);
1125
+ }));
1126
+ function getOrderInfoByRemote(_x15) {
1127
+ return _getOrderInfoByRemote.apply(this, arguments);
1128
+ }
1129
+ return getOrderInfoByRemote;
1102
1130
  }()
1131
+ }, {
1132
+ key: "getLastOrderInfo",
1133
+ value: function getLastOrderInfo() {
1134
+ var _this$store;
1135
+ return (_this$store = this.store) === null || _this$store === void 0 || (_this$store = _this$store.tempOrder) === null || _this$store === void 0 ? void 0 : _this$store.lastOrderInfo;
1136
+ }
1103
1137
  }], [{
1104
1138
  key: "populateSavedAmounts",
1105
1139
  value:
@@ -78,18 +78,21 @@ export var QuotationModule = /*#__PURE__*/function (_BaseModule) {
78
78
  case 0:
79
79
  query = {};
80
80
  if (params !== null && params !== void 0 && params.channel) query.channel = params.channel;
81
- _context2.next = 4;
81
+ if ((params === null || params === void 0 ? void 0 : params.channel) === 'online-store') {
82
+ query.channel = 'online_store';
83
+ }
84
+ _context2.next = 5;
82
85
  return this.request.get('/quotation/available', query, {
83
86
  useCache: false
84
87
  });
85
- case 4:
88
+ case 5:
86
89
  res = _context2.sent;
87
90
  list = (res === null || res === void 0 || (_data = res.data) === null || _data === void 0 ? void 0 : _data.list) || (res === null || res === void 0 ? void 0 : res.list) || [];
88
91
  list.sort(function (a, b) {
89
92
  return a.sort - b.sort;
90
93
  });
91
94
  this.store.list = list;
92
- case 8:
95
+ case 9:
93
96
  case "end":
94
97
  return _context2.stop();
95
98
  }
@@ -27,6 +27,8 @@ export declare class ScanOrderImpl extends BaseModule implements Module {
27
27
  private itemRuleConfigsPromise;
28
28
  private itemRulePrefillApplied;
29
29
  private itemRuleRuntimeConfig;
30
+ /** 最近一次 checkResourceAvailable 从预约规则 link 拉取的商品快照 */
31
+ private enabledReservationRuleProducts;
30
32
  private getScanOrderLoggerContext;
31
33
  private serializeError;
32
34
  private addScanOrderLog;
@@ -22,8 +22,9 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
22
22
  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); }
23
23
  import { BaseModule } from "../../modules/BaseModule";
24
24
  import { ScanOrderHooks } from "./types";
25
- import { attachItemRuleLimitsToTopLevelProducts, buildProductKey, buildItemRuleBusinessData, createEmptySummary, getProductIdentityIndex, getSafeProductNum, normalizeEnabledItemRuleIds, normalizeOrderProduct, normalizeItemRuleStrategies, toNonNegativeInt, toNonNegativeNumber, toPriceString, toBoolean, toPositiveString } from "./utils";
25
+ import { attachItemRuleLimitsToTopLevelProducts, buildProductKey, buildItemRuleBusinessData, collectLinkProductIdsFromReservationRules, createEmptySummary, getProductIdentityIndex, getSafeProductNum, hasCustomCapacityProduct, normalizeEnabledItemRuleIds, normalizeOrderProduct, normalizeItemRuleStrategies, pickFirstDurationMinutesFromProducts, toNonNegativeInt, toNonNegativeNumber, toPriceString, toBoolean, toPositiveString } from "./utils";
26
26
  import { createModule } from "../BookingByStep/types";
27
+ import { ProductList } from "../../modules/ProductList";
27
28
  import dayjs from 'dayjs';
28
29
  import { ItemRuleEvaluator } from "../../model/strategy/adapter/itemRule";
29
30
  export * from "./types";
@@ -61,6 +62,8 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
61
62
  _defineProperty(_assertThisInitialized(_this), "itemRuleConfigsPromise", null);
62
63
  _defineProperty(_assertThisInitialized(_this), "itemRulePrefillApplied", false);
63
64
  _defineProperty(_assertThisInitialized(_this), "itemRuleRuntimeConfig", {});
65
+ /** 最近一次 checkResourceAvailable 从预约规则 link 拉取的商品快照 */
66
+ _defineProperty(_assertThisInitialized(_this), "enabledReservationRuleProducts", []);
64
67
  return _this;
65
68
  }
66
69
  _createClass(ScanOrderImpl, [{
@@ -1651,7 +1654,7 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1651
1654
  key: "checkResourceAvailable",
1652
1655
  value: function () {
1653
1656
  var _checkResourceAvailable = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee27(resourceId, hasOrderId) {
1654
- var _this$otherParams9, _this$otherParams9$ge, _config$table_form_re, _config$table_form_re2, _this$otherParams10, _this$store$order4, openData, dineInConfig, shopClosedInfo, config, resourceState, availabilityInfo, tempOrder;
1657
+ var _this$otherParams9, _this$otherParams9$ge, _config$table_form_re, _config$table_form_re2, _this$otherParams10, _this$store$order4, openData, dineInConfig, shopClosedInfo, config, resourceState, availabilityInfo, tempOrder, reservationLinkIds, reservationProductList, scheduleDate, scheduleDatetime, loaded, occupancyMinutes, _this$store$order5;
1655
1658
  return _regeneratorRuntime().wrap(function _callee27$(_context27) {
1656
1659
  while (1) switch (_context27.prev = _context27.next) {
1657
1660
  case 0:
@@ -1717,26 +1720,95 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1717
1720
  tempOrder.relation_id = resourceId || ((_this$otherParams10 = this.otherParams) === null || _this$otherParams10 === void 0 ? void 0 : _this$otherParams10.relation_id);
1718
1721
  tempOrder.table_form_id = resourceState.tableFormId;
1719
1722
  tempOrder.resource_id = resourceId;
1723
+ reservationLinkIds = collectLinkProductIdsFromReservationRules(dineInConfig['reservation.enabled_reservation_rules']);
1724
+ if (!(reservationLinkIds.length === 0)) {
1725
+ _context27.next = 31;
1726
+ break;
1727
+ }
1728
+ this.enabledReservationRuleProducts = [];
1729
+ if (this.store.resource) delete this.store.resource.requestEntryPax;
1730
+ _context27.next = 42;
1731
+ break;
1732
+ case 31:
1733
+ tempOrder.metadata = _objectSpread({}, tempOrder.metadata || {});
1734
+ delete tempOrder.metadata.table_occupancy_duration;
1735
+ reservationProductList = new ProductList("".concat(this.name, "_reservationEnabledRules"), this.defaultVersion);
1736
+ _context27.next = 36;
1737
+ return reservationProductList.initialize(this.core, {
1738
+ store: {
1739
+ list: [],
1740
+ selectProducts: []
1741
+ },
1742
+ otherParams: _objectSpread(_objectSpread({}, this.otherParams), {}, {
1743
+ fatherModule: this.name,
1744
+ openCache: Boolean(this.cacheId),
1745
+ cacheId: this.cacheId
1746
+ })
1747
+ });
1748
+ case 36:
1749
+ scheduleDate = dayjs().format('YYYY-MM-DD');
1750
+ scheduleDatetime = dayjs().format('YYYY-MM-DD HH:mm:ss');
1751
+ _context27.next = 40;
1752
+ return reservationProductList.loadProducts({
1753
+ product_ids: reservationLinkIds,
1754
+ schedule_date: scheduleDate,
1755
+ schedule_datetime: scheduleDatetime,
1756
+ cacheId: this.cacheId
1757
+ });
1758
+ case 40:
1759
+ loaded = _context27.sent;
1760
+ if (Array.isArray(loaded)) {
1761
+ this.enabledReservationRuleProducts = loaded;
1762
+ occupancyMinutes = pickFirstDurationMinutesFromProducts(loaded);
1763
+ if (occupancyMinutes !== undefined) {
1764
+ tempOrder.metadata.table_occupancy_duration = occupancyMinutes;
1765
+ }
1766
+ if (hasCustomCapacityProduct(loaded)) {
1767
+ availabilityInfo.requestEntryPax = 1;
1768
+ if (this.store.resource) this.store.resource.requestEntryPax = 1;
1769
+ } else if (this.store.resource) {
1770
+ delete this.store.resource.requestEntryPax;
1771
+ }
1772
+ } else {
1773
+ this.enabledReservationRuleProducts = [];
1774
+ if (this.store.resource) delete this.store.resource.requestEntryPax;
1775
+ void this.addScanOrderLog({
1776
+ level: 'error',
1777
+ title: '[ScanOrder] enabled_reservation_rules product query failed',
1778
+ payload: {
1779
+ linkIds: reservationLinkIds,
1780
+ error: this.serializeError(loaded)
1781
+ }
1782
+ });
1783
+ }
1784
+ case 42:
1720
1785
  (_this$store$order4 = this.store.order) === null || _this$store$order4 === void 0 || _this$store$order4.persistTempOrder();
1721
1786
 
1722
1787
  // 空闲状态下自动准备本地临时订单,供后续“购物车式”商品操作使用
1723
1788
  if (!(availabilityInfo.mode === 'idle')) {
1724
- _context27.next = 29;
1789
+ _context27.next = 46;
1725
1790
  break;
1726
1791
  }
1727
- _context27.next = 29;
1792
+ _context27.next = 46;
1728
1793
  return this.addNewOrder();
1729
- case 29:
1794
+ case 46:
1730
1795
  // 如果是加单模式,tempOrder 里 需要记录 lastOrderId,提交的时候走加单接口
1731
1796
  if (availabilityInfo.mode === 'additional_order' || availabilityInfo.mode === 'additional_order_with_code') {
1732
1797
  tempOrder.order_id = resourceState.lastOrderId;
1733
1798
  }
1734
- _context27.next = 32;
1799
+ if (!tempOrder.order_id) {
1800
+ _context27.next = 50;
1801
+ break;
1802
+ }
1803
+ _context27.next = 50;
1804
+ return (_this$store$order5 = this.store.order) === null || _this$store$order5 === void 0 ? void 0 : _this$store$order5.getOrderInfoByRemote(tempOrder.order_id);
1805
+ case 50:
1806
+ _context27.next = 52;
1735
1807
  return this.refreshItemRuleQuantityLimits();
1736
- case 32:
1737
- _context27.next = 34;
1808
+ case 52:
1809
+ _context27.next = 54;
1738
1810
  return this.refreshCartValidationPassed();
1739
- case 34:
1811
+ case 54:
1740
1812
  this.logMethodSuccess('checkResourceAvailable', {
1741
1813
  resourceId: resourceId,
1742
1814
  mode: availabilityInfo.mode,
@@ -1752,18 +1824,18 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1752
1824
  isFull: resourceState.isFull
1753
1825
  });
1754
1826
  return _context27.abrupt("return", availabilityInfo);
1755
- case 38:
1756
- _context27.prev = 38;
1827
+ case 58:
1828
+ _context27.prev = 58;
1757
1829
  _context27.t0 = _context27["catch"](1);
1758
1830
  this.logMethodError('checkResourceAvailable', _context27.t0, {
1759
1831
  resourceId: resourceId
1760
1832
  });
1761
1833
  throw _context27.t0;
1762
- case 42:
1834
+ case 62:
1763
1835
  case "end":
1764
1836
  return _context27.stop();
1765
1837
  }
1766
- }, _callee27, this, [[1, 38]]);
1838
+ }, _callee27, this, [[1, 58]]);
1767
1839
  }));
1768
1840
  function checkResourceAvailable(_x10, _x11) {
1769
1841
  return _checkResourceAvailable.apply(this, arguments);
@@ -121,6 +121,7 @@ export interface ScanOrderTempOrder {
121
121
  holder: Record<string, any> | null;
122
122
  summary: ScanOrderSummary;
123
123
  metadata: Record<string, any>;
124
+ lastOrderInfo?: Record<string, any>;
124
125
  }
125
126
  export interface ScanOrderSubmitPayload extends Omit<ScanOrderTempOrder, 'platform' | 'products' | 'created_at' | 'summary' | 'surcharges'> {
126
127
  platform: 'H5' | 'PC';
@@ -141,6 +142,8 @@ export interface ScanOrderAvailabilityInfo {
141
142
  errorTips?: string;
142
143
  policy?: string | null;
143
144
  partyroom_booking?: string | null;
145
+ /** 预约规则关联商品存在 custom 容量时,由 checkResourceAvailable 置为 1 */
146
+ requestEntryPax?: number;
144
147
  }
145
148
  export interface ScanOrderTableSnackConfig {
146
149
  snack?: boolean | number | string;
@@ -1,6 +1,7 @@
1
1
  import { ScanOrderOrderProduct, ScanOrderOrderProductIdentity, ScanOrderSummary, ScanOrderTempOrder } from './types';
2
2
  import type { CartItemSummary, ItemRuleBusinessData, PaxInfo, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
3
3
  import type { StrategyConfig } from '../../model/strategy/type';
4
+ import type { ProductData } from '../../modules/Product/types';
4
5
  /**
5
6
  * 构建金额全为 0 的空 summary。
6
7
  * 作为尚未计算金额时的兜底默认值,避免下游因 undefined 报错。
@@ -91,3 +92,13 @@ export declare function getProductIdentityIndex(products: ScanOrderOrderProduct[
91
92
  * - 保留 _origin 供后续业务流程(如促销规则)使用
92
93
  */
93
94
  export declare function normalizeOrderProduct(product: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity): ScanOrderOrderProduct;
95
+ /**
96
+ * 从 reservation.enabled_reservation_rules 中收集 type=link 的商品 id。
97
+ */
98
+ export declare function collectLinkProductIdsFromReservationRules(rules: unknown): number[];
99
+ /**
100
+ * 返回列表中第一个带有效 duration.value(分钟)的商品时长。
101
+ */
102
+ export declare function pickFirstDurationMinutesFromProducts(products: ProductData[]): number | undefined;
103
+ /** 是否存在 capacity.type === 'custom' 的商品 */
104
+ export declare function hasCustomCapacityProduct(products: ProductData[]): boolean;
@@ -394,4 +394,71 @@ export function normalizeOrderProduct(product) {
394
394
  metadata: metadata,
395
395
  _origin: product._origin
396
396
  };
397
+ }
398
+
399
+ /**
400
+ * 从 reservation.enabled_reservation_rules 中收集 type=link 的商品 id。
401
+ */
402
+ export function collectLinkProductIdsFromReservationRules(rules) {
403
+ if (!Array.isArray(rules)) return [];
404
+ var ids = [];
405
+ var _iterator6 = _createForOfIteratorHelper(rules),
406
+ _step6;
407
+ try {
408
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
409
+ var entry = _step6.value;
410
+ if (!entry || _typeof(entry) !== 'object') continue;
411
+ var rec = entry;
412
+ if (rec.type !== 'link') continue;
413
+ if (!Array.isArray(rec.value)) continue;
414
+ var _iterator7 = _createForOfIteratorHelper(rec.value),
415
+ _step7;
416
+ try {
417
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
418
+ var v = _step7.value;
419
+ var n = Number(v);
420
+ if (Number.isFinite(n) && n > 0) ids.push(Math.floor(n));
421
+ }
422
+ } catch (err) {
423
+ _iterator7.e(err);
424
+ } finally {
425
+ _iterator7.f();
426
+ }
427
+ }
428
+ } catch (err) {
429
+ _iterator6.e(err);
430
+ } finally {
431
+ _iterator6.f();
432
+ }
433
+ return _toConsumableArray(new Set(ids));
434
+ }
435
+
436
+ /**
437
+ * 返回列表中第一个带有效 duration.value(分钟)的商品时长。
438
+ */
439
+ export function pickFirstDurationMinutesFromProducts(products) {
440
+ var _iterator8 = _createForOfIteratorHelper(products),
441
+ _step8;
442
+ try {
443
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
444
+ var _product$duration;
445
+ var product = _step8.value;
446
+ var value = product === null || product === void 0 || (_product$duration = product.duration) === null || _product$duration === void 0 ? void 0 : _product$duration.value;
447
+ var n = Number(value);
448
+ if (Number.isFinite(n) && n > 0) return Math.floor(n);
449
+ }
450
+ } catch (err) {
451
+ _iterator8.e(err);
452
+ } finally {
453
+ _iterator8.f();
454
+ }
455
+ return undefined;
456
+ }
457
+
458
+ /** 是否存在 capacity.type === 'custom' 的商品 */
459
+ export function hasCustomCapacityProduct(products) {
460
+ return products.some(function (p) {
461
+ var _p$capacity;
462
+ return (p === null || p === void 0 || (_p$capacity = p.capacity) === null || _p$capacity === void 0 ? void 0 : _p$capacity.type) === 'custom';
463
+ });
397
464
  }
@@ -112,4 +112,6 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
112
112
  createOrderByCheckout(params: CheckoutOrderParams): Promise<any>;
113
113
  submitScanOrder<T = any>(params: SubmitScanOrderParams): Promise<T>;
114
114
  scanOrderMore<T = any>(params: ScanOrderMoreParams): Promise<T>;
115
+ getOrderInfoByRemote(order_id: number): Promise<void>;
116
+ getLastOrderInfo(): Record<string, any> | undefined;
115
117
  }
@@ -732,6 +732,19 @@ var OrderModule = class extends import_BaseModule.BaseModule {
732
732
  };
733
733
  return this.request.put(fetchUrl, requestBody);
734
734
  }
735
+ // TODO 获取详情的接口
736
+ async getOrderInfoByRemote(order_id) {
737
+ const res = await this.request.get(`/order/sales/${order_id}`, {
738
+ with: ["products", "scheduleEvents"]
739
+ });
740
+ if (res.data.code === 200 && this.store.tempOrder) {
741
+ this.store.tempOrder.lastOrderInfo = res.data.data;
742
+ }
743
+ }
744
+ getLastOrderInfo() {
745
+ var _a, _b;
746
+ return (_b = (_a = this.store) == null ? void 0 : _a.tempOrder) == null ? void 0 : _b.lastOrderInfo;
747
+ }
735
748
  };
736
749
  // Annotate the CommonJS export names for ESM import in node:
737
750
  0 && (module.exports = {
@@ -43,6 +43,9 @@ var QuotationModule = class extends import_BaseModule.BaseModule {
43
43
  const query = {};
44
44
  if (params == null ? void 0 : params.channel)
45
45
  query.channel = params.channel;
46
+ if ((params == null ? void 0 : params.channel) === "online-store") {
47
+ query.channel = "online_store";
48
+ }
46
49
  const res = await this.request.get(
47
50
  "/quotation/available",
48
51
  query,
@@ -27,6 +27,8 @@ export declare class ScanOrderImpl extends BaseModule implements Module {
27
27
  private itemRuleConfigsPromise;
28
28
  private itemRulePrefillApplied;
29
29
  private itemRuleRuntimeConfig;
30
+ /** 最近一次 checkResourceAvailable 从预约规则 link 拉取的商品快照 */
31
+ private enabledReservationRuleProducts;
30
32
  private getScanOrderLoggerContext;
31
33
  private serializeError;
32
34
  private addScanOrderLog;
@@ -37,6 +37,7 @@ var import_BaseModule = require("../../modules/BaseModule");
37
37
  var import_types = require("./types");
38
38
  var import_utils = require("./utils");
39
39
  var import_types2 = require("../BookingByStep/types");
40
+ var import_ProductList = require("../../modules/ProductList");
40
41
  var import_dayjs = __toESM(require("dayjs"));
41
42
  var import_itemRule = require("../../model/strategy/adapter/itemRule");
42
43
  __reExport(ScanOrder_exports, require("./types"), module.exports);
@@ -67,6 +68,8 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
67
68
  this.itemRuleConfigsPromise = null;
68
69
  this.itemRulePrefillApplied = false;
69
70
  this.itemRuleRuntimeConfig = {};
71
+ /** 最近一次 checkResourceAvailable 从预约规则 link 拉取的商品快照 */
72
+ this.enabledReservationRuleProducts = [];
70
73
  }
71
74
  getScanOrderLoggerContext() {
72
75
  return {
@@ -947,7 +950,7 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
947
950
  // 通过 resource_id + 店铺配置
948
951
  // hasOrderId 表示 url 上是否有 orderid,如果是的话,后续的流程会走加单
949
952
  async checkResourceAvailable(resourceId, hasOrderId) {
950
- var _a, _b, _c, _d, _e, _f;
953
+ var _a, _b, _c, _d, _e, _f, _g;
951
954
  this.logMethodStart("checkResourceAvailable", {
952
955
  resourceId
953
956
  });
@@ -992,6 +995,64 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
992
995
  tempOrder.relation_id = resourceId || ((_e = this.otherParams) == null ? void 0 : _e.relation_id);
993
996
  tempOrder.table_form_id = resourceState.tableFormId;
994
997
  tempOrder.resource_id = resourceId;
998
+ const reservationLinkIds = (0, import_utils.collectLinkProductIdsFromReservationRules)(
999
+ dineInConfig["reservation.enabled_reservation_rules"]
1000
+ );
1001
+ if (reservationLinkIds.length === 0) {
1002
+ this.enabledReservationRuleProducts = [];
1003
+ if (this.store.resource)
1004
+ delete this.store.resource.requestEntryPax;
1005
+ } else {
1006
+ tempOrder.metadata = { ...tempOrder.metadata || {} };
1007
+ delete tempOrder.metadata.table_occupancy_duration;
1008
+ const reservationProductList = new import_ProductList.ProductList(
1009
+ `${this.name}_reservationEnabledRules`,
1010
+ this.defaultVersion
1011
+ );
1012
+ await reservationProductList.initialize(this.core, {
1013
+ store: { list: [], selectProducts: [] },
1014
+ otherParams: {
1015
+ ...this.otherParams,
1016
+ fatherModule: this.name,
1017
+ openCache: Boolean(this.cacheId),
1018
+ cacheId: this.cacheId
1019
+ }
1020
+ });
1021
+ const scheduleDate = (0, import_dayjs.default)().format("YYYY-MM-DD");
1022
+ const scheduleDatetime = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1023
+ const loaded = await reservationProductList.loadProducts({
1024
+ product_ids: reservationLinkIds,
1025
+ schedule_date: scheduleDate,
1026
+ schedule_datetime: scheduleDatetime,
1027
+ cacheId: this.cacheId
1028
+ });
1029
+ if (Array.isArray(loaded)) {
1030
+ this.enabledReservationRuleProducts = loaded;
1031
+ const occupancyMinutes = (0, import_utils.pickFirstDurationMinutesFromProducts)(loaded);
1032
+ if (occupancyMinutes !== void 0) {
1033
+ tempOrder.metadata.table_occupancy_duration = occupancyMinutes;
1034
+ }
1035
+ if ((0, import_utils.hasCustomCapacityProduct)(loaded)) {
1036
+ availabilityInfo.requestEntryPax = 1;
1037
+ if (this.store.resource)
1038
+ this.store.resource.requestEntryPax = 1;
1039
+ } else if (this.store.resource) {
1040
+ delete this.store.resource.requestEntryPax;
1041
+ }
1042
+ } else {
1043
+ this.enabledReservationRuleProducts = [];
1044
+ if (this.store.resource)
1045
+ delete this.store.resource.requestEntryPax;
1046
+ void this.addScanOrderLog({
1047
+ level: "error",
1048
+ title: "[ScanOrder] enabled_reservation_rules product query failed",
1049
+ payload: {
1050
+ linkIds: reservationLinkIds,
1051
+ error: this.serializeError(loaded)
1052
+ }
1053
+ });
1054
+ }
1055
+ }
995
1056
  (_f = this.store.order) == null ? void 0 : _f.persistTempOrder();
996
1057
  if (availabilityInfo.mode === "idle") {
997
1058
  await this.addNewOrder();
@@ -999,6 +1060,9 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
999
1060
  if (availabilityInfo.mode === "additional_order" || availabilityInfo.mode === "additional_order_with_code") {
1000
1061
  tempOrder.order_id = resourceState.lastOrderId;
1001
1062
  }
1063
+ if (tempOrder.order_id) {
1064
+ await ((_g = this.store.order) == null ? void 0 : _g.getOrderInfoByRemote(tempOrder.order_id));
1065
+ }
1002
1066
  await this.refreshItemRuleQuantityLimits();
1003
1067
  await this.refreshCartValidationPassed();
1004
1068
  this.logMethodSuccess("checkResourceAvailable", {
@@ -121,6 +121,7 @@ export interface ScanOrderTempOrder {
121
121
  holder: Record<string, any> | null;
122
122
  summary: ScanOrderSummary;
123
123
  metadata: Record<string, any>;
124
+ lastOrderInfo?: Record<string, any>;
124
125
  }
125
126
  export interface ScanOrderSubmitPayload extends Omit<ScanOrderTempOrder, 'platform' | 'products' | 'created_at' | 'summary' | 'surcharges'> {
126
127
  platform: 'H5' | 'PC';
@@ -141,6 +142,8 @@ export interface ScanOrderAvailabilityInfo {
141
142
  errorTips?: string;
142
143
  policy?: string | null;
143
144
  partyroom_booking?: string | null;
145
+ /** 预约规则关联商品存在 custom 容量时,由 checkResourceAvailable 置为 1 */
146
+ requestEntryPax?: number;
144
147
  }
145
148
  export interface ScanOrderTableSnackConfig {
146
149
  snack?: boolean | number | string;
@@ -1,6 +1,7 @@
1
1
  import { ScanOrderOrderProduct, ScanOrderOrderProductIdentity, ScanOrderSummary, ScanOrderTempOrder } from './types';
2
2
  import type { CartItemSummary, ItemRuleBusinessData, PaxInfo, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
3
3
  import type { StrategyConfig } from '../../model/strategy/type';
4
+ import type { ProductData } from '../../modules/Product/types';
4
5
  /**
5
6
  * 构建金额全为 0 的空 summary。
6
7
  * 作为尚未计算金额时的兜底默认值,避免下游因 undefined 报错。
@@ -91,3 +92,13 @@ export declare function getProductIdentityIndex(products: ScanOrderOrderProduct[
91
92
  * - 保留 _origin 供后续业务流程(如促销规则)使用
92
93
  */
93
94
  export declare function normalizeOrderProduct(product: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity): ScanOrderOrderProduct;
95
+ /**
96
+ * 从 reservation.enabled_reservation_rules 中收集 type=link 的商品 id。
97
+ */
98
+ export declare function collectLinkProductIdsFromReservationRules(rules: unknown): number[];
99
+ /**
100
+ * 返回列表中第一个带有效 duration.value(分钟)的商品时长。
101
+ */
102
+ export declare function pickFirstDurationMinutesFromProducts(products: ProductData[]): number | undefined;
103
+ /** 是否存在 capacity.type === 'custom' 的商品 */
104
+ export declare function hasCustomCapacityProduct(products: ProductData[]): boolean;
@@ -24,16 +24,19 @@ __export(utils_exports, {
24
24
  buildItemRuleBusinessData: () => buildItemRuleBusinessData,
25
25
  buildProductKey: () => buildProductKey,
26
26
  buildQuantityLimitIndex: () => buildQuantityLimitIndex,
27
+ collectLinkProductIdsFromReservationRules: () => collectLinkProductIdsFromReservationRules,
27
28
  createEmptySummary: () => createEmptySummary,
28
29
  extractStrategyModelIdsFromTableConfig: () => extractStrategyModelIdsFromTableConfig,
29
30
  getProductIdentityIndex: () => getProductIdentityIndex,
30
31
  getSafeProductNum: () => getSafeProductNum,
31
32
  getTopLevelProductId: () => getTopLevelProductId,
32
33
  getTopLevelVariantId: () => getTopLevelVariantId,
34
+ hasCustomCapacityProduct: () => hasCustomCapacityProduct,
33
35
  isIdentityMatch: () => isIdentityMatch,
34
36
  normalizeEnabledItemRuleIds: () => normalizeEnabledItemRuleIds,
35
37
  normalizeItemRuleStrategies: () => normalizeItemRuleStrategies,
36
38
  normalizeOrderProduct: () => normalizeOrderProduct,
39
+ pickFirstDurationMinutesFromProducts: () => pickFirstDurationMinutesFromProducts,
37
40
  resolveSkuMatchedQuantityLimits: () => resolveSkuMatchedQuantityLimits,
38
41
  toBoolean: () => toBoolean,
39
42
  toNonNegativeInt: () => toNonNegativeInt,
@@ -333,6 +336,42 @@ function normalizeOrderProduct(product) {
333
336
  _origin: product._origin
334
337
  };
335
338
  }
339
+ function collectLinkProductIdsFromReservationRules(rules) {
340
+ if (!Array.isArray(rules))
341
+ return [];
342
+ const ids = [];
343
+ for (const entry of rules) {
344
+ if (!entry || typeof entry !== "object")
345
+ continue;
346
+ const rec = entry;
347
+ if (rec.type !== "link")
348
+ continue;
349
+ if (!Array.isArray(rec.value))
350
+ continue;
351
+ for (const v of rec.value) {
352
+ const n = Number(v);
353
+ if (Number.isFinite(n) && n > 0)
354
+ ids.push(Math.floor(n));
355
+ }
356
+ }
357
+ return [...new Set(ids)];
358
+ }
359
+ function pickFirstDurationMinutesFromProducts(products) {
360
+ var _a;
361
+ for (const product of products) {
362
+ const value = (_a = product == null ? void 0 : product.duration) == null ? void 0 : _a.value;
363
+ const n = Number(value);
364
+ if (Number.isFinite(n) && n > 0)
365
+ return Math.floor(n);
366
+ }
367
+ return void 0;
368
+ }
369
+ function hasCustomCapacityProduct(products) {
370
+ return products.some((p) => {
371
+ var _a;
372
+ return ((_a = p == null ? void 0 : p.capacity) == null ? void 0 : _a.type) === "custom";
373
+ });
374
+ }
336
375
  // Annotate the CommonJS export names for ESM import in node:
337
376
  0 && (module.exports = {
338
377
  aggregateItemRuleLimit,
@@ -340,16 +379,19 @@ function normalizeOrderProduct(product) {
340
379
  buildItemRuleBusinessData,
341
380
  buildProductKey,
342
381
  buildQuantityLimitIndex,
382
+ collectLinkProductIdsFromReservationRules,
343
383
  createEmptySummary,
344
384
  extractStrategyModelIdsFromTableConfig,
345
385
  getProductIdentityIndex,
346
386
  getSafeProductNum,
347
387
  getTopLevelProductId,
348
388
  getTopLevelVariantId,
389
+ hasCustomCapacityProduct,
349
390
  isIdentityMatch,
350
391
  normalizeEnabledItemRuleIds,
351
392
  normalizeItemRuleStrategies,
352
393
  normalizeOrderProduct,
394
+ pickFirstDurationMinutesFromProducts,
353
395
  resolveSkuMatchedQuantityLimits,
354
396
  toBoolean,
355
397
  toNonNegativeInt,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.1.122",
4
+ "version": "2.1.123",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",