@pisell/pisellos 2.1.153 → 2.1.155

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,6 +1,6 @@
1
1
  import { Module, ModuleOptions, PisellCore } from '../../types';
2
2
  import { BaseModule } from '../../modules/BaseModule';
3
- import { ScanOrderAddLogParams, ScanOrderAvailabilityInfo, ScanOrderOrderProduct, ScanOrderOrderProductIdentity, ScanOrderScanCodeResult, ScanOrderTempOrder } from './types';
3
+ import { ScanOrderAddLogParams, ScanOrderAvailabilityInfo, ScanOrderAllowAddItemsInfo, ScanOrderOrderProduct, ScanOrderOrderProductIdentity, ScanOrderReservationResourceSelectInfo, ScanOrderScanCodeResult, ScanOrderSyncAdditionalOrderResult, ScanOrderTempOrder } from './types';
4
4
  import type { UpdateProductInOrderParams } from '../../modules/Order/types';
5
5
  import type { Discount } from '../../modules/Discount/types';
6
6
  import { type CartItemSummary, type PaxInfo, type QuantityCheckResult, type QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
@@ -118,7 +118,8 @@ export declare class ScanOrderImpl extends BaseModule implements Module {
118
118
  setItemRuleRuntimeConfig(config?: ScanOrderItemRuleRuntimeConfig): Promise<void>;
119
119
  private normalizeResourceState;
120
120
  private resolveResourceSelectType;
121
- private fetchResourceOccupyDetailByResourceId;
121
+ private fetchResourceOccupyDetailsByResourceId;
122
+ private resolveAdditionalOrderFromOccupyDetail;
122
123
  checkResourceAvailable(resourceId?: string | null, hasOrderId?: boolean): Promise<ScanOrderAvailabilityInfo>;
123
124
  getAdditionalOrderInfo(): Promise<{
124
125
  orderId: string;
@@ -142,6 +143,9 @@ export declare class ScanOrderImpl extends BaseModule implements Module {
142
143
  clearUIState(): void;
143
144
  setEntryPaxNumber(number: number): Promise<void>;
144
145
  getEntryPaxNumber(): number | null;
146
+ syncAdditionalOrderFromResource(resourceId?: string | null): Promise<ScanOrderSyncAdditionalOrderResult>;
147
+ getReservationResourceSelectType(): ScanOrderReservationResourceSelectInfo;
148
+ checkAllowAddItems(): ScanOrderAllowAddItemsInfo;
145
149
  getFulfillmentModes(): {
146
150
  enablePickup: boolean;
147
151
  enableTableService: boolean;
@@ -32,7 +32,7 @@ import { OrderModule } from "../../modules/Order";
32
32
  import { AccountHooks } from "../../modules/Account/types";
33
33
  import { RegisterAndLoginHooks } from "../RegisterAndLogin/types";
34
34
  import Decimal from 'decimal.js';
35
- import { attachItemRuleLimitsToTopLevelProducts, buildProductKey, buildItemRuleBusinessData, collectLinkProductIdsFromReservationRules, computeResourceIsFull, createEmptySummary, getProductIdentityIndex, getSafeProductNum, hasCustomCapacityProduct, pickFirstCustomCapacityDimensionId, pickFirstCustomCapacityPaxBounds, normalizeEnabledItemRuleIds, normalizeOrderProduct, normalizeItemRuleStrategies, pickFirstDurationMinutesFromProducts, toNonNegativeInt, toPriceString, toBoolean, toPositiveString } from "./utils";
35
+ import { attachItemRuleLimitsToTopLevelProducts, buildProductKey, buildItemRuleBusinessData, collectLinkProductIdsFromReservationRules, computeResourceIsFull, createEmptySummary, findReservationRuleProductByResourceId, getProductIdentityIndex, getSafeProductNum, hasCustomCapacityProduct, pickFirstCustomCapacityDimensionId, pickFirstCustomCapacityPaxBounds, normalizeEnabledItemRuleIds, normalizeOrderProduct, normalizeItemRuleStrategies, pickFirstDurationMinutesFromProducts, toNonNegativeInt, toPriceString, toBoolean, toPositiveString } from "./utils";
36
36
  import { createModule } from "../BookingByStep/types";
37
37
  import { ProductList } from "../../modules/ProductList";
38
38
  import { ScheduleModule } from "../../modules/Schedule";
@@ -1411,13 +1411,13 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1411
1411
  var resourceState = this.store.resource;
1412
1412
  var resourceSelectType = resourceState === null || resourceState === void 0 ? void 0 : resourceState.resourceSelectType;
1413
1413
 
1414
- // collect_pax 时的资源占用兜底:single 独占整张桌台,其余模式占 1 个容量位。
1415
- var resolveResourceCapacity = function resolveResourceCapacity() {
1414
+ // ScanOrder booking 容量只由预约规则决定:single 占用整张桌台,multiple 占用 1 个容量位。
1415
+ var resolveBookingCapacityValue = function resolveBookingCapacityValue() {
1416
1416
  if (resourceSelectType === 'single') {
1417
1417
  var _resourceState$table_;
1418
1418
  var raw = resourceState === null || resourceState === void 0 || (_resourceState$table_ = resourceState.table_form_record) === null || _resourceState$table_ === void 0 ? void 0 : _resourceState$table_.capacity;
1419
1419
  var num = Number(raw);
1420
- if (Number.isFinite(num) && num > 0) return num;
1420
+ if (Number.isFinite(num) && num > 0) return Math.max(1, Math.floor(num));
1421
1421
  return 1;
1422
1422
  }
1423
1423
  return 1;
@@ -1435,8 +1435,8 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1435
1435
  });
1436
1436
  }
1437
1437
  var rawCollectPax = (_tempOrder$metadata = tempOrder.metadata) === null || _tempOrder$metadata === void 0 ? void 0 : _tempOrder$metadata.collect_pax;
1438
- var hasCollectPaxForCapacity = rawCollectPax !== null && rawCollectPax !== undefined && rawCollectPax !== '';
1439
- var resourceCapacityValue = hasCollectPaxForCapacity ? normalizeSubmitCollectPaxValue(rawCollectPax) : resolveResourceCapacity();
1438
+ var hasExplicitCollectPax = rawCollectPax !== null && rawCollectPax !== undefined && rawCollectPax !== '';
1439
+ var bookingCapacityValue = resolveBookingCapacityValue();
1440
1440
  var pickOriginal = function pickOriginal(value) {
1441
1441
  if (value && _typeof(value) === 'object' && !Array.isArray(value)) {
1442
1442
  var original = value.original;
@@ -1452,21 +1452,25 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1452
1452
  main_field: mainField,
1453
1453
  form_id: resourceState.tableFormId,
1454
1454
  relation_id: (_resourceState$relati = resourceState.relationId) !== null && _resourceState$relati !== void 0 ? _resourceState$relati : resourceId,
1455
- capacity: resourceCapacityValue,
1455
+ capacity: bookingCapacityValue,
1456
1456
  metadata: _this5.buildScanOrderResourceMetadata({
1457
1457
  resourceState: resourceState,
1458
1458
  resourceName: mainField
1459
1459
  })
1460
1460
  } : undefined;
1461
1461
  var ruleProductUid = ruleProduct ? createUuidV4() : undefined;
1462
- // 有 collect_pax 时 booking/resource capacity 与 number 都代表本次 pax;否则使用资源占用兜底值。
1463
- var bookingCapacityValue = resourceCapacityValue;
1464
1462
  var bookingCapacityDimensionId = (_pickFirstCustomCapac = pickFirstCustomCapacityDimensionId(_this5.enabledReservationRuleProducts)) !== null && _pickFirstCustomCapac !== void 0 ? _pickFirstCustomCapac : 0;
1465
1463
  var nextBookings = (payload.bookings || []).map(function (booking, idx) {
1464
+ var metadata = _objectSpread({}, booking.metadata || {});
1465
+ if (hasExplicitCollectPax) {
1466
+ metadata.collect_pax = normalizeSubmitCollectPaxValue(rawCollectPax);
1467
+ } else {
1468
+ delete metadata.collect_pax;
1469
+ }
1466
1470
  return _objectSpread(_objectSpread(_objectSpread({}, booking), {}, {
1467
1471
  number: bookingCapacityValue,
1468
1472
  appointment_status: 'started',
1469
- metadata: _objectSpread(_objectSpread(_objectSpread({}, booking.metadata || {}), resourceSelectType ? {
1473
+ metadata: _objectSpread(_objectSpread(_objectSpread({}, metadata), resourceSelectType ? {
1470
1474
  resource_select_type: resourceSelectType
1471
1475
  } : {}), resourceSelectType ? {
1472
1476
  capacity: [{
@@ -1516,7 +1520,7 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1516
1520
  key: "submitScanOrder",
1517
1521
  value: function () {
1518
1522
  var _submitScanOrder = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee18() {
1519
- var _this$store$resource, _this$otherParams5, _this$otherParams6, _this$otherParams7, _this$otherParams8, _tempOrder$products, pax, tempOrderForSubmit, resourceTableName, enhancePayload, result, tempOrder;
1523
+ var _this$store$resource, _this$otherParams5, _this$otherParams6, _this$otherParams7, _this$otherParams8, _tempOrder$products, tempOrderForSubmit, resourceTableName, enhancePayload, result, tempOrder;
1520
1524
  return _regeneratorRuntime().wrap(function _callee18$(_context18) {
1521
1525
  while (1) switch (_context18.prev = _context18.next) {
1522
1526
  case 0:
@@ -1531,12 +1535,7 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1531
1535
  }
1532
1536
  throw new Error('scanOrder解决方案需要 order 模块支持');
1533
1537
  case 6:
1534
- pax = normalizeSubmitCollectPaxValue(this.store.entryPaxNumber);
1535
- this.store.entryPaxNumber = pax;
1536
1538
  tempOrderForSubmit = this.store.order.ensureTempOrder();
1537
- tempOrderForSubmit.metadata = _objectSpread(_objectSpread({}, tempOrderForSubmit.metadata), {}, {
1538
- collect_pax: pax
1539
- });
1540
1539
  tempOrderForSubmit.delivery_type = 'shop_service';
1541
1540
  resourceTableName = (_this$store$resource = this.store.resource) === null || _this$store$resource === void 0 || (_this$store$resource = _this$store$resource.table_form_record) === null || _this$store$resource === void 0 ? void 0 : _this$store$resource.name;
1542
1541
  if (resourceTableName && _typeof(resourceTableName) === 'object') {
@@ -1546,7 +1545,7 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1546
1545
  }
1547
1546
  this.store.order.persistTempOrder();
1548
1547
  enhancePayload = this.buildSubmitPayloadEnhancer();
1549
- _context18.next = 17;
1548
+ _context18.next = 14;
1550
1549
  return this.store.order.submitTempOrder({
1551
1550
  cacheId: this.cacheId,
1552
1551
  platform: (_this$otherParams5 = this.otherParams) === null || _this$otherParams5 === void 0 ? void 0 : _this$otherParams5.platform,
@@ -1555,23 +1554,23 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1555
1554
  type: (_this$otherParams8 = this.otherParams) === null || _this$otherParams8 === void 0 ? void 0 : _this$otherParams8.type,
1556
1555
  enhancePayload: enhancePayload
1557
1556
  });
1558
- case 17:
1557
+ case 14:
1559
1558
  result = _context18.sent;
1560
1559
  tempOrder = this.store.order.getTempOrder();
1561
1560
  this.logMethodSuccess('submitScanOrder', {
1562
1561
  productCount: (tempOrder === null || tempOrder === void 0 || (_tempOrder$products = tempOrder.products) === null || _tempOrder$products === void 0 ? void 0 : _tempOrder$products.length) || 0
1563
1562
  });
1564
1563
  return _context18.abrupt("return", result);
1565
- case 23:
1566
- _context18.prev = 23;
1564
+ case 20:
1565
+ _context18.prev = 20;
1567
1566
  _context18.t0 = _context18["catch"](1);
1568
1567
  this.logMethodError('submitScanOrder', _context18.t0);
1569
1568
  throw _context18.t0;
1570
- case 27:
1569
+ case 24:
1571
1570
  case "end":
1572
1571
  return _context18.stop();
1573
1572
  }
1574
- }, _callee18, this, [[1, 23]]);
1573
+ }, _callee18, this, [[1, 20]]);
1575
1574
  }));
1576
1575
  function submitScanOrder() {
1577
1576
  return _submitScanOrder.apply(this, arguments);
@@ -2569,9 +2568,9 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
2569
2568
  return matched === null || matched === void 0 ? void 0 : matched.type;
2570
2569
  }
2571
2570
  }, {
2572
- key: "fetchResourceOccupyDetailByResourceId",
2571
+ key: "fetchResourceOccupyDetailsByResourceId",
2573
2572
  value: function () {
2574
- var _fetchResourceOccupyDetailByResourceId = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee36(resourceId) {
2573
+ var _fetchResourceOccupyDetailsByResourceId = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee36(resourceId) {
2575
2574
  var _this$otherParams10, _this$otherParams10$g, _response$data$occupy, _response$data;
2576
2575
  var formRecordId, shopId, response;
2577
2576
  return _regeneratorRuntime().wrap(function _callee36$(_context36) {
@@ -2607,18 +2606,68 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
2607
2606
  }
2608
2607
  throw new Error((response === null || response === void 0 ? void 0 : response.message) || '获取资源占用详情失败');
2609
2608
  case 11:
2610
- return _context36.abrupt("return", (_response$data$occupy = response === null || response === void 0 || (_response$data = response.data) === null || _response$data === void 0 || (_response$data = _response$data.occupy_details) === null || _response$data === void 0 ? void 0 : _response$data[0]) !== null && _response$data$occupy !== void 0 ? _response$data$occupy : null);
2609
+ return _context36.abrupt("return", (_response$data$occupy = response === null || response === void 0 || (_response$data = response.data) === null || _response$data === void 0 ? void 0 : _response$data.occupy_details) !== null && _response$data$occupy !== void 0 ? _response$data$occupy : []);
2611
2610
  case 12:
2612
2611
  case "end":
2613
2612
  return _context36.stop();
2614
2613
  }
2615
2614
  }, _callee36, this);
2616
2615
  }));
2617
- function fetchResourceOccupyDetailByResourceId(_x18) {
2618
- return _fetchResourceOccupyDetailByResourceId.apply(this, arguments);
2616
+ function fetchResourceOccupyDetailsByResourceId(_x18) {
2617
+ return _fetchResourceOccupyDetailsByResourceId.apply(this, arguments);
2618
+ }
2619
+ return fetchResourceOccupyDetailsByResourceId;
2620
+ }()
2621
+ }, {
2622
+ key: "resolveAdditionalOrderFromOccupyDetail",
2623
+ value: function resolveAdditionalOrderFromOccupyDetail(detail, resourceSelectType, allowAddItems) {
2624
+ var currentOrderId = toPositiveString(detail === null || detail === void 0 ? void 0 : detail.order_id);
2625
+ if (currentOrderId) {
2626
+ return {
2627
+ matched: true,
2628
+ order_id: currentOrderId
2629
+ };
2630
+ }
2631
+ var orderListIds = (Array.isArray(detail === null || detail === void 0 ? void 0 : detail.order_list) ? (detail === null || detail === void 0 ? void 0 : detail.order_list) || [] : []).map(function (order) {
2632
+ return toPositiveString(order === null || order === void 0 ? void 0 : order.id);
2633
+ }).filter(Boolean);
2634
+ if (resourceSelectType !== 'single') {
2635
+ return {
2636
+ matched: false,
2637
+ reason: 'no_order'
2638
+ };
2639
+ }
2640
+ if (!orderListIds.length) {
2641
+ return {
2642
+ matched: false,
2643
+ reason: 'no_order'
2644
+ };
2619
2645
  }
2620
- return fetchResourceOccupyDetailByResourceId;
2621
- }() // 检测当前链接是否可用
2646
+ if (!allowAddItems) {
2647
+ return {
2648
+ matched: false,
2649
+ reason: 'add_items_disabled'
2650
+ };
2651
+ }
2652
+ if (orderListIds.length === 1) {
2653
+ return {
2654
+ matched: true,
2655
+ order_id: orderListIds[0]
2656
+ };
2657
+ }
2658
+ if (orderListIds.length > 1) {
2659
+ return {
2660
+ matched: false,
2661
+ reason: 'multiple_orders'
2662
+ };
2663
+ }
2664
+ return {
2665
+ matched: false,
2666
+ reason: 'no_order'
2667
+ };
2668
+ }
2669
+
2670
+ // 检测当前链接是否可用
2622
2671
  // 通过 resource_id + 店铺配置
2623
2672
  // hasOrderId 表示 url 上是否有 orderid,如果是的话,后续的流程会走加单
2624
2673
  }, {
@@ -2633,6 +2682,7 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
2633
2682
  _this$otherParams12,
2634
2683
  _this$otherParams13,
2635
2684
  _this$otherParams13$g,
2685
+ _occupyDetails$,
2636
2686
  _occupyDetail$form_re,
2637
2687
  _occupyDetail$form_re2,
2638
2688
  _this$otherParams14,
@@ -2663,13 +2713,23 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
2663
2713
  scheduleDate,
2664
2714
  scheduleDatetime,
2665
2715
  loaded,
2716
+ matchedRuleProduct,
2717
+ ruleProductsForResource,
2666
2718
  occupancyMinutes,
2667
2719
  paxBounds,
2668
2720
  error,
2721
+ occupyDetails,
2669
2722
  occupyDetail,
2670
2723
  resourceSelectType,
2724
+ allowAddItems,
2725
+ additionalOrderResult,
2726
+ _occupyDetail$order_l,
2727
+ multipleOrdersState,
2728
+ _availabilityInfo,
2671
2729
  resourceState,
2730
+ additionalOrderId,
2672
2731
  availabilityInfo,
2732
+ isAdditionalOrderMode,
2673
2733
  _this$store$order7,
2674
2734
  _res$data,
2675
2735
  res,
@@ -2805,14 +2865,16 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
2805
2865
  case 46:
2806
2866
  loaded = _context37.sent;
2807
2867
  if (Array.isArray(loaded)) {
2808
- this.enabledReservationRuleProducts = loaded;
2809
- occupancyMinutes = pickFirstDurationMinutesFromProducts(loaded);
2868
+ matchedRuleProduct = findReservationRuleProductByResourceId(loaded, normalizedResourceId);
2869
+ ruleProductsForResource = matchedRuleProduct ? [matchedRuleProduct] : [];
2870
+ this.enabledReservationRuleProducts = ruleProductsForResource;
2871
+ occupancyMinutes = pickFirstDurationMinutesFromProducts(ruleProductsForResource);
2810
2872
  if (occupancyMinutes !== undefined) {
2811
2873
  tempOrder.metadata.table_occupancy_duration = occupancyMinutes;
2812
2874
  }
2813
- if (hasCustomCapacityProduct(loaded)) {
2875
+ if (hasCustomCapacityProduct(ruleProductsForResource)) {
2814
2876
  pendingRequestEntryPax = 1;
2815
- paxBounds = pickFirstCustomCapacityPaxBounds(loaded);
2877
+ paxBounds = pickFirstCustomCapacityPaxBounds(ruleProductsForResource);
2816
2878
  if ((paxBounds === null || paxBounds === void 0 ? void 0 : paxBounds.min) !== undefined) pendingRequestPaxMin = paxBounds.min;
2817
2879
  if ((paxBounds === null || paxBounds === void 0 ? void 0 : paxBounds.max) !== undefined) pendingRequestPaxMax = paxBounds.max;
2818
2880
  }
@@ -2828,15 +2890,52 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
2828
2890
  });
2829
2891
  }
2830
2892
 
2831
- // Step2: 请求新的资源占用详情接口
2893
+ // Step2: 请求新的资源占用详情接口。occupy_details 第一维是资源,不是订单。
2832
2894
  _context37.next = 50;
2833
- return this.fetchResourceOccupyDetailByResourceId(normalizedResourceId);
2895
+ return this.fetchResourceOccupyDetailsByResourceId(normalizedResourceId);
2834
2896
  case 50:
2835
- occupyDetail = _context37.sent;
2836
- // Step3: 结合预约规则商品的 product_resource.resources 与占用接口返回的 form_id,
2897
+ occupyDetails = _context37.sent;
2898
+ occupyDetail = (_occupyDetails$ = occupyDetails[0]) !== null && _occupyDetails$ !== void 0 ? _occupyDetails$ : null; // Step3: 结合预约规则商品的 product_resource.resources 与占用接口返回的 form_id,
2837
2899
  // 计算当前桌台的 resourceSelectType(single/multiple/capacity)
2838
- resourceSelectType = this.resolveResourceSelectType(toPositiveString(occupyDetail === null || occupyDetail === void 0 ? void 0 : occupyDetail.form_id)); // Step4: 用 occupyDetail + resourceSelectType 规整为 resourceState
2900
+ resourceSelectType = this.resolveResourceSelectType(toPositiveString(occupyDetail === null || occupyDetail === void 0 ? void 0 : occupyDetail.form_id));
2901
+ allowAddItems = toBoolean(dineInConfig === null || dineInConfig === void 0 ? void 0 : dineInConfig['sale.allow_add_items']);
2902
+ additionalOrderResult = this.resolveAdditionalOrderFromOccupyDetail(occupyDetail, resourceSelectType, allowAddItems);
2903
+ if (!(additionalOrderResult.reason === 'multiple_orders')) {
2904
+ _context37.next = 61;
2905
+ break;
2906
+ }
2907
+ multipleOrdersState = _objectSpread(_objectSpread({}, this.normalizeResourceState(occupyDetail, resourceSelectType, hasOrderId)), {}, {
2908
+ mode: 'multiple_orders'
2909
+ });
2910
+ this.store.resource = multipleOrdersState;
2911
+ _availabilityInfo = {
2912
+ mode: 'multiple_orders',
2913
+ deskmate_valid: multipleOrdersState.deskmate_valid,
2914
+ relation_id: multipleOrdersState.relationId,
2915
+ table_form_id: multipleOrdersState.tableFormId,
2916
+ table_form_record: multipleOrdersState.table_form_record
2917
+ };
2918
+ this.logMethodSuccess('checkResourceAvailable', {
2919
+ resourceId: normalizedResourceId,
2920
+ mode: _availabilityInfo.mode,
2921
+ orderListCount: (occupyDetail === null || occupyDetail === void 0 || (_occupyDetail$order_l = occupyDetail.order_list) === null || _occupyDetail$order_l === void 0 ? void 0 : _occupyDetail$order_l.length) || 0,
2922
+ resourceSelectType: resourceSelectType
2923
+ });
2924
+ return _context37.abrupt("return", _availabilityInfo);
2925
+ case 61:
2926
+ // Step4: 用 occupyDetail + resourceSelectType 规整为 resourceState
2839
2927
  resourceState = this.normalizeResourceState(occupyDetail, resourceSelectType, hasOrderId);
2928
+ additionalOrderId = additionalOrderResult.order_id;
2929
+ if (additionalOrderId) {
2930
+ resourceState.mode = 'additional_order';
2931
+ resourceState.order_id = additionalOrderId;
2932
+ } else if (additionalOrderResult.reason === 'add_items_disabled') {
2933
+ resourceState.mode = 'resource_busy';
2934
+ resourceState.order_id = '0';
2935
+ } else if (resourceSelectType === 'multiple' && resourceState.isFull) {
2936
+ resourceState.mode = 'resource_busy';
2937
+ resourceState.order_id = '0';
2938
+ }
2840
2939
  this.store.resource = resourceState;
2841
2940
 
2842
2941
  // Step5: 把预约规则商品阶段暂存的 requestEntryPax 等注入 store.resource
@@ -2872,23 +2971,23 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
2872
2971
 
2873
2972
  // 空闲状态下自动准备本地临时订单,供后续“购物车式”商品操作使用
2874
2973
  if (!(availabilityInfo.mode === 'idle')) {
2875
- _context37.next = 65;
2974
+ _context37.next = 76;
2876
2975
  break;
2877
2976
  }
2878
- _context37.next = 65;
2977
+ _context37.next = 76;
2879
2978
  return this.addNewOrder();
2880
- case 65:
2881
- // 如果是加单模式,tempOrder 需要记录 lastOrderId,提交的时候走加单接口
2882
- if (availabilityInfo.mode === 'additional_order' || availabilityInfo.mode === 'additional_order_with_code') {
2883
- tempOrder.order_id = resourceState.lastOrderId;
2979
+ case 76:
2980
+ isAdditionalOrderMode = availabilityInfo.mode === 'additional_order' || availabilityInfo.mode === 'additional_order_with_code'; // 如果是加单模式,tempOrder 里需要记录目标订单 id,提交的时候走加单接口
2981
+ if (isAdditionalOrderMode) {
2982
+ tempOrder.order_id = additionalOrderId;
2884
2983
  }
2885
2984
  if (!tempOrder.order_id) {
2886
- _context37.next = 74;
2985
+ _context37.next = 86;
2887
2986
  break;
2888
2987
  }
2889
- _context37.next = 69;
2988
+ _context37.next = 81;
2890
2989
  return (_this$store$order7 = this.store.order) === null || _this$store$order7 === void 0 ? void 0 : _this$store$order7.getOrderInfoByRemote(tempOrder.order_id);
2891
- case 69:
2990
+ case 81:
2892
2991
  res = _context37.sent;
2893
2992
  // 找到下单的时候输入的 entryPaxNumber
2894
2993
  entryPaxNumber = res === null || res === void 0 || (_res$data = res.data) === null || _res$data === void 0 || (_res$data = _res$data.bookings) === null || _res$data === void 0 || (_res$data = _res$data.find(function (p) {
@@ -2896,14 +2995,14 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
2896
2995
  return (_p$metadata = p.metadata) === null || _p$metadata === void 0 ? void 0 : _p$metadata.collect_pax;
2897
2996
  })) === null || _res$data === void 0 || (_res$data = _res$data.metadata) === null || _res$data === void 0 ? void 0 : _res$data.collect_pax;
2898
2997
  if (!entryPaxNumber) {
2899
- _context37.next = 74;
2998
+ _context37.next = 86;
2900
2999
  break;
2901
3000
  }
2902
- _context37.next = 74;
3001
+ _context37.next = 86;
2903
3002
  return this.setEntryPaxNumber(entryPaxNumber);
2904
- case 74:
3003
+ case 86:
2905
3004
  lastOrderInfo = (_this$store$order8 = this.store.order) === null || _this$store$order8 === void 0 || (_this$store$order8$ge = _this$store$order8.getLastOrderInfo) === null || _this$store$order8$ge === void 0 ? void 0 : _this$store$order8$ge.call(_this$store$order8);
2906
- historicalItems = hasOrderId && Array.isArray(lastOrderInfo === null || lastOrderInfo === void 0 ? void 0 : lastOrderInfo.products) ? lastOrderInfo.products.reduce(function (acc, p) {
3005
+ historicalItems = isAdditionalOrderMode && Array.isArray(lastOrderInfo === null || lastOrderInfo === void 0 ? void 0 : lastOrderInfo.products) ? lastOrderInfo.products.reduce(function (acc, p) {
2907
3006
  if (typeof (p === null || p === void 0 ? void 0 : p.product_id) !== 'number') return acc;
2908
3007
  acc.push(_objectSpread({
2909
3008
  product_id: p.product_id,
@@ -2913,13 +3012,13 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
2913
3012
  } : {}));
2914
3013
  return acc;
2915
3014
  }, []) : []; // pax 由 setEntryPaxNumber 负责写入 itemRuleRuntimeConfig.pax
2916
- _context37.next = 78;
3015
+ _context37.next = 90;
2917
3016
  return this.setItemRuleRuntimeConfig({
2918
3017
  serviceType: (_this$otherParams15 = this.otherParams) === null || _this$otherParams15 === void 0 ? void 0 : _this$otherParams15.businessCode,
2919
- submissionIndex: hasOrderId ? 1 : 0,
3018
+ submissionIndex: isAdditionalOrderMode ? 1 : 0,
2920
3019
  historicalItems: historicalItems
2921
3020
  });
2922
- case 78:
3021
+ case 90:
2923
3022
  // operating_hours 超出营业时段 + closed_behavior=show_menu_disabled:
2924
3023
  // 允许浏览商品但 UI 层需拦截“下一步”,这里覆盖最终 mode 并回传错误提示
2925
3024
  if (outsideOperatingHours && closedBehaviorValue === 'show_menu_disabled') {
@@ -2941,18 +3040,18 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
2941
3040
  isFull: resourceState.isFull
2942
3041
  });
2943
3042
  return _context37.abrupt("return", availabilityInfo);
2944
- case 83:
2945
- _context37.prev = 83;
3043
+ case 95:
3044
+ _context37.prev = 95;
2946
3045
  _context37.t0 = _context37["catch"](3);
2947
3046
  this.logMethodError('checkResourceAvailable', _context37.t0.message, {
2948
3047
  resourceId: normalizedResourceId
2949
3048
  });
2950
3049
  throw _context37.t0;
2951
- case 87:
3050
+ case 99:
2952
3051
  case "end":
2953
3052
  return _context37.stop();
2954
3053
  }
2955
- }, _callee37, this, [[3, 83]]);
3054
+ }, _callee37, this, [[3, 95]]);
2956
3055
  }));
2957
3056
  function checkResourceAvailable(_x19) {
2958
3057
  return _checkResourceAvailable.apply(this, arguments);
@@ -3214,15 +3313,113 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
3214
3313
  value: function getEntryPaxNumber() {
3215
3314
  return this.store.entryPaxNumber;
3216
3315
  }
3316
+ }, {
3317
+ key: "syncAdditionalOrderFromResource",
3318
+ value: function () {
3319
+ var _syncAdditionalOrderFromResource = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee42(resourceId) {
3320
+ var _ref10, _ref11, _ref12, _this$store$resource2, _this$store$resource3, _occupyDetails$2, _this$store$resource4, _this$otherParams17, _this$store$order9;
3321
+ var tempOrder, normalizedResourceId, _result, occupyDetails, occupyDetail, resourceSelectType, allowAddItems, result;
3322
+ return _regeneratorRuntime().wrap(function _callee42$(_context42) {
3323
+ while (1) switch (_context42.prev = _context42.next) {
3324
+ case 0:
3325
+ tempOrder = this.ensureTempOrder();
3326
+ normalizedResourceId = String((_ref10 = (_ref11 = (_ref12 = resourceId !== null && resourceId !== void 0 ? resourceId : tempOrder.resource_id) !== null && _ref12 !== void 0 ? _ref12 : (_this$store$resource2 = this.store.resource) === null || _this$store$resource2 === void 0 ? void 0 : _this$store$resource2.relationId) !== null && _ref11 !== void 0 ? _ref11 : (_this$store$resource3 = this.store.resource) === null || _this$store$resource3 === void 0 ? void 0 : _this$store$resource3.relation_id) !== null && _ref10 !== void 0 ? _ref10 : '').trim();
3327
+ this.logMethodStart('syncAdditionalOrderFromResource', {
3328
+ resourceId: normalizedResourceId
3329
+ });
3330
+ if (normalizedResourceId) {
3331
+ _context42.next = 7;
3332
+ break;
3333
+ }
3334
+ _result = {
3335
+ matched: false,
3336
+ reason: 'missing_resource_id'
3337
+ };
3338
+ this.logMethodSuccess('syncAdditionalOrderFromResource', _result);
3339
+ return _context42.abrupt("return", _result);
3340
+ case 7:
3341
+ _context42.next = 9;
3342
+ return this.fetchResourceOccupyDetailsByResourceId(normalizedResourceId);
3343
+ case 9:
3344
+ occupyDetails = _context42.sent;
3345
+ occupyDetail = (_occupyDetails$2 = occupyDetails[0]) !== null && _occupyDetails$2 !== void 0 ? _occupyDetails$2 : null;
3346
+ resourceSelectType = ((_this$store$resource4 = this.store.resource) === null || _this$store$resource4 === void 0 ? void 0 : _this$store$resource4.resourceSelectType) || this.resolveResourceSelectType(toPositiveString(occupyDetail === null || occupyDetail === void 0 ? void 0 : occupyDetail.form_id));
3347
+ allowAddItems = toBoolean((_this$otherParams17 = this.otherParams) === null || _this$otherParams17 === void 0 || (_this$otherParams17 = _this$otherParams17.dineInConfig) === null || _this$otherParams17 === void 0 ? void 0 : _this$otherParams17['sale.allow_add_items']);
3348
+ result = this.resolveAdditionalOrderFromOccupyDetail(occupyDetail, resourceSelectType, allowAddItems);
3349
+ if (!(!result.matched || !result.order_id)) {
3350
+ _context42.next = 17;
3351
+ break;
3352
+ }
3353
+ this.logMethodSuccess('syncAdditionalOrderFromResource', _objectSpread(_objectSpread({}, result), {}, {
3354
+ resourceId: normalizedResourceId,
3355
+ resourceSelectType: resourceSelectType,
3356
+ allowAddItems: allowAddItems
3357
+ }));
3358
+ return _context42.abrupt("return", result);
3359
+ case 17:
3360
+ tempOrder.order_id = result.order_id;
3361
+ tempOrder.resource_id = normalizedResourceId;
3362
+ tempOrder.relation_id = toPositiveString(occupyDetail === null || occupyDetail === void 0 ? void 0 : occupyDetail.form_record_id) || normalizedResourceId || tempOrder.relation_id;
3363
+ tempOrder.table_form_id = toPositiveString(occupyDetail === null || occupyDetail === void 0 ? void 0 : occupyDetail.form_id) || tempOrder.table_form_id;
3364
+ (_this$store$order9 = this.store.order) === null || _this$store$order9 === void 0 || _this$store$order9.persistTempOrder();
3365
+ this.logMethodSuccess('syncAdditionalOrderFromResource', _objectSpread(_objectSpread({}, result), {}, {
3366
+ resourceId: normalizedResourceId,
3367
+ resourceSelectType: resourceSelectType,
3368
+ allowAddItems: allowAddItems
3369
+ }));
3370
+ return _context42.abrupt("return", result);
3371
+ case 24:
3372
+ case "end":
3373
+ return _context42.stop();
3374
+ }
3375
+ }, _callee42, this);
3376
+ }));
3377
+ function syncAdditionalOrderFromResource(_x22) {
3378
+ return _syncAdditionalOrderFromResource.apply(this, arguments);
3379
+ }
3380
+ return syncAdditionalOrderFromResource;
3381
+ }() // 读取预约规则商品的资源选择类型:single=单个预约,multiple=多个预约,capacity=容量型预约
3382
+ // 依赖 checkResourceAvailable 已根据预约规则商品与 occupy-detail 的 form_id 计算并缓存 store.resource
3383
+ }, {
3384
+ key: "getReservationResourceSelectType",
3385
+ value: function getReservationResourceSelectType() {
3386
+ var _this$store$resource5;
3387
+ this.logMethodStart('getReservationResourceSelectType');
3388
+ var resourceSelectType = (_this$store$resource5 = this.store.resource) === null || _this$store$resource5 === void 0 ? void 0 : _this$store$resource5.resourceSelectType;
3389
+ var result = _objectSpread(_objectSpread({}, resourceSelectType ? {
3390
+ resourceSelectType: resourceSelectType
3391
+ } : {}), {}, {
3392
+ isSingleReservation: resourceSelectType === 'single',
3393
+ isMultipleReservation: resourceSelectType === 'multiple',
3394
+ isCapacityReservation: resourceSelectType === 'capacity'
3395
+ });
3396
+ this.logMethodSuccess('getReservationResourceSelectType', result);
3397
+ return result;
3398
+ }
3399
+
3400
+ // 判定后台是否开启允许加餐
3401
+ // 依赖 checkResourceAvailable 已缓存的 dineInConfig
3402
+ }, {
3403
+ key: "checkAllowAddItems",
3404
+ value: function checkAllowAddItems() {
3405
+ var _this$otherParams18;
3406
+ this.logMethodStart('checkAllowAddItems');
3407
+ var dineInConfig = ((_this$otherParams18 = this.otherParams) === null || _this$otherParams18 === void 0 ? void 0 : _this$otherParams18.dineInConfig) || {};
3408
+ var result = {
3409
+ enabled: toBoolean(dineInConfig['sale.allow_add_items'])
3410
+ };
3411
+ this.logMethodSuccess('checkAllowAddItems', result);
3412
+ return result;
3413
+ }
3217
3414
 
3218
3415
  // 读取取餐/送餐开关
3219
3416
  // 依赖 checkResourceAvailable 已缓存的 dineInConfig
3220
3417
  }, {
3221
3418
  key: "getFulfillmentModes",
3222
3419
  value: function getFulfillmentModes() {
3223
- var _this$otherParams17;
3420
+ var _this$otherParams19;
3224
3421
  this.logMethodStart('getFulfillmentModes');
3225
- var dineInConfig = ((_this$otherParams17 = this.otherParams) === null || _this$otherParams17 === void 0 ? void 0 : _this$otherParams17.dineInConfig) || {};
3422
+ var dineInConfig = ((_this$otherParams19 = this.otherParams) === null || _this$otherParams19 === void 0 ? void 0 : _this$otherParams19.dineInConfig) || {};
3226
3423
  var result = {
3227
3424
  enablePickup: Boolean(dineInConfig['fulfillment.enable_pickup']),
3228
3425
  enableTableService: Boolean(dineInConfig['fulfillment.enable_table_service'])
@@ -3236,9 +3433,9 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
3236
3433
  }, {
3237
3434
  key: "checkManualPickupRef",
3238
3435
  value: function checkManualPickupRef() {
3239
- var _this$otherParams18;
3436
+ var _this$otherParams20;
3240
3437
  this.logMethodStart('checkManualPickupRef');
3241
- var dineInConfig = ((_this$otherParams18 = this.otherParams) === null || _this$otherParams18 === void 0 ? void 0 : _this$otherParams18.dineInConfig) || {};
3438
+ var dineInConfig = ((_this$otherParams20 = this.otherParams) === null || _this$otherParams20 === void 0 ? void 0 : _this$otherParams20.dineInConfig) || {};
3242
3439
  var refMode = dineInConfig['fulfillment.fulfillment_ref_mode'];
3243
3440
  var manualInputType = dineInConfig['fulfillment.manual_input_type'];
3244
3441
  var enabled = refMode === 'manual_input';
@@ -185,7 +185,7 @@ export interface ScanOrderSubmitPayload extends Omit<ScanOrderTempOrder, 'platfo
185
185
  }>;
186
186
  products: ScanOrderSubmitProduct[];
187
187
  }
188
- export type ScanOrderAvailabilityMode = 'idle' | 'shop_closed' | 'submit_disabled' | 'resource_busy' | 'additional_order_with_code' | 'additional_order';
188
+ export type ScanOrderAvailabilityMode = 'idle' | 'shop_closed' | 'submit_disabled' | 'resource_busy' | 'multiple_orders' | 'additional_order_with_code' | 'additional_order';
189
189
  export interface ScanOrderTableFormRecord {
190
190
  policy?: string | null;
191
191
  partyroom_booking?: string | null;
@@ -228,6 +228,10 @@ export interface ScanOrderResourceOccupyDetail {
228
228
  form_id?: number | string | null;
229
229
  order_id?: number | string | null;
230
230
  last_order_id?: number | string | null;
231
+ order_list?: Array<{
232
+ id?: number | string | null;
233
+ [key: string]: any;
234
+ }> | null;
231
235
  resource_capacity?: ScanOrderResourceCapacity[] | null;
232
236
  form_record?: ScanOrderTableFormRecord | null;
233
237
  [key: string]: any;
@@ -241,6 +245,21 @@ export interface ScanOrderResourceOccupyDetailApiResponse {
241
245
  } | null;
242
246
  }
243
247
  export type ScanOrderResourceSelectType = 'single' | 'multiple' | 'capacity';
248
+ export interface ScanOrderReservationResourceSelectInfo {
249
+ resourceSelectType?: ScanOrderResourceSelectType;
250
+ isSingleReservation: boolean;
251
+ isMultipleReservation: boolean;
252
+ isCapacityReservation: boolean;
253
+ }
254
+ export interface ScanOrderAllowAddItemsInfo {
255
+ enabled: boolean;
256
+ }
257
+ export type ScanOrderSyncAdditionalOrderReason = 'missing_resource_id' | 'no_order' | 'multiple_orders' | 'add_items_disabled' | 'invalid_order_id';
258
+ export interface ScanOrderSyncAdditionalOrderResult {
259
+ matched: boolean;
260
+ order_id?: string;
261
+ reason?: ScanOrderSyncAdditionalOrderReason;
262
+ }
244
263
  export interface ScanOrderResourceState extends ScanOrderAvailabilityInfo {
245
264
  relationId?: string;
246
265
  tableFormId?: string;
@@ -134,6 +134,11 @@ export declare function normalizeOrderProduct(product: Partial<ScanOrderOrderPro
134
134
  * 从 reservation.enabled_reservation_rules 中收集 type=link 的商品 id。
135
135
  */
136
136
  export declare function collectLinkProductIdsFromReservationRules(rules: unknown): number[];
137
+ /**
138
+ * 找到第一个归属指定桌台的预约规则商品。
139
+ * 归属判断基于商品资源中的 default_resource / optional_resource。
140
+ */
141
+ export declare function findReservationRuleProductByResourceId(products: ProductData[], resourceId: string | number | null | undefined): ProductData | undefined;
137
142
  /**
138
143
  * 返回列表中第一个带有效 duration.value(分钟)的商品时长。
139
144
  */