@pisell/pisellos 2.1.152 → 2.1.154

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.
@@ -815,6 +815,49 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
815
815
  combined_resource: isCombined ? combined : null
816
816
  };
817
817
  }
818
+ async prepareRetailAvailability(params) {
819
+ var _a, _b;
820
+ const { tempOrder, hasOrderId, resourceId, reason } = params;
821
+ this.enabledReservationRuleProducts = [];
822
+ tempOrder.bookings = [];
823
+ tempOrder.order_id = null;
824
+ delete tempOrder.relation_id;
825
+ delete tempOrder.table_form_id;
826
+ delete tempOrder.resource_id;
827
+ delete tempOrder.table_number;
828
+ tempOrder.metadata = { ...tempOrder.metadata || {} };
829
+ delete tempOrder.metadata.table_occupancy_duration;
830
+ const resourceState = {
831
+ mode: "idle",
832
+ deskmate_valid: false,
833
+ allowSnack: false,
834
+ deskmateValid: false,
835
+ isExclusive: false,
836
+ isFull: false,
837
+ raw: null
838
+ };
839
+ this.store.resource = resourceState;
840
+ (_a = this.store.order) == null ? void 0 : _a.persistTempOrder();
841
+ await this.addNewOrder();
842
+ await this.setItemRuleRuntimeConfig({
843
+ serviceType: (_b = this.otherParams) == null ? void 0 : _b.businessCode,
844
+ submissionIndex: hasOrderId ? 1 : 0,
845
+ historicalItems: []
846
+ });
847
+ const availabilityInfo = {
848
+ mode: "idle",
849
+ deskmate_valid: false
850
+ };
851
+ this.logMethodSuccess("checkResourceAvailable", {
852
+ resourceId,
853
+ mode: availabilityInfo.mode,
854
+ retailMode: true,
855
+ retailReason: reason,
856
+ persistedRelationId: tempOrder.relation_id,
857
+ persistedResourceId: tempOrder.resource_id
858
+ });
859
+ return availabilityInfo;
860
+ }
818
861
  // ScanOrder 提交 payload enhancer:
819
862
  // - 给所有 booking 注入 appointment_status: 'started'(扫码点餐语义)
820
863
  // - 给所有 booking 的 metadata 注入 resource_select_type(来自预约规则商品的 resource.type)
@@ -824,23 +867,33 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
824
867
  const ruleProduct = this.enabledReservationRuleProducts[0];
825
868
  const resourceState = this.store.resource;
826
869
  const resourceSelectType = resourceState == null ? void 0 : resourceState.resourceSelectType;
827
- const resolveResourceCapacity = () => {
870
+ const resolveBookingCapacityValue = () => {
828
871
  var _a;
829
872
  if (resourceSelectType === "single") {
830
873
  const raw = (_a = resourceState == null ? void 0 : resourceState.table_form_record) == null ? void 0 : _a.capacity;
831
874
  const num = Number(raw);
832
875
  if (Number.isFinite(num) && num > 0)
833
- return num;
876
+ return Math.max(1, Math.floor(num));
834
877
  return 1;
835
878
  }
836
879
  return 1;
837
880
  };
838
881
  return (payload, { bookingUuid, tempOrder }) => {
839
882
  var _a, _b;
840
- const resourceId = tempOrder.resource_id ?? (resourceState == null ? void 0 : resourceState.relationId);
883
+ const resourceId = String(tempOrder.resource_id ?? (resourceState == null ? void 0 : resourceState.relationId) ?? "").trim();
884
+ const hasReservationBookingContext = Boolean(
885
+ ruleProduct && resourceState && resourceId && (tempOrder.relation_id || resourceState.relationId) && (tempOrder.table_form_id || resourceState.tableFormId)
886
+ );
887
+ if (!hasReservationBookingContext) {
888
+ return {
889
+ ...payload,
890
+ bookings: [],
891
+ products: [...payload.products || []]
892
+ };
893
+ }
841
894
  const rawCollectPax = (_a = tempOrder.metadata) == null ? void 0 : _a.collect_pax;
842
- const hasCollectPaxForCapacity = rawCollectPax !== null && rawCollectPax !== void 0 && rawCollectPax !== "";
843
- const resourceCapacityValue = hasCollectPaxForCapacity ? (0, import_utils2.normalizeSubmitCollectPaxValue)(rawCollectPax) : resolveResourceCapacity();
895
+ const hasExplicitCollectPax = rawCollectPax !== null && rawCollectPax !== void 0 && rawCollectPax !== "";
896
+ const bookingCapacityValue = resolveBookingCapacityValue();
844
897
  const pickOriginal = (value) => {
845
898
  if (value && typeof value === "object" && !Array.isArray(value)) {
846
899
  const original = value.original;
@@ -856,35 +909,42 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
856
909
  main_field: mainField,
857
910
  form_id: resourceState.tableFormId,
858
911
  relation_id: resourceState.relationId ?? resourceId,
859
- capacity: resourceCapacityValue,
912
+ capacity: bookingCapacityValue,
860
913
  metadata: this.buildScanOrderResourceMetadata({
861
914
  resourceState,
862
915
  resourceName: mainField
863
916
  })
864
917
  } : void 0;
865
918
  const ruleProductUid = ruleProduct ? (0, import_utils2.createUuidV4)() : void 0;
866
- const bookingCapacityValue = resourceCapacityValue;
867
919
  const bookingCapacityDimensionId = (0, import_utils.pickFirstCustomCapacityDimensionId)(this.enabledReservationRuleProducts) ?? 0;
868
- const nextBookings = (payload.bookings || []).map((booking, idx) => ({
869
- ...booking,
870
- number: bookingCapacityValue,
871
- appointment_status: "started",
872
- metadata: {
873
- ...booking.metadata || {},
874
- ...resourceSelectType ? { resource_select_type: resourceSelectType } : {},
875
- ...resourceSelectType ? {
876
- capacity: [
877
- {
878
- id: bookingCapacityDimensionId,
879
- value: bookingCapacityValue,
880
- name: ""
881
- }
882
- ]
883
- } : {}
884
- },
885
- ...idx === 0 && resourceEntry ? { resources: [resourceEntry] } : {},
886
- ...idx === 0 && ruleProductUid ? { product_uid: ruleProductUid } : {}
887
- }));
920
+ const nextBookings = (payload.bookings || []).map((booking, idx) => {
921
+ const metadata = { ...booking.metadata || {} };
922
+ if (hasExplicitCollectPax) {
923
+ metadata.collect_pax = (0, import_utils2.normalizeSubmitCollectPaxValue)(rawCollectPax);
924
+ } else {
925
+ delete metadata.collect_pax;
926
+ }
927
+ return {
928
+ ...booking,
929
+ number: bookingCapacityValue,
930
+ appointment_status: "started",
931
+ metadata: {
932
+ ...metadata,
933
+ ...resourceSelectType ? { resource_select_type: resourceSelectType } : {},
934
+ ...resourceSelectType ? {
935
+ capacity: [
936
+ {
937
+ id: bookingCapacityDimensionId,
938
+ value: bookingCapacityValue,
939
+ name: ""
940
+ }
941
+ ]
942
+ } : {}
943
+ },
944
+ ...idx === 0 && resourceEntry ? { resources: [resourceEntry] } : {},
945
+ ...idx === 0 && ruleProductUid ? { product_uid: ruleProductUid } : {}
946
+ };
947
+ });
888
948
  const nextProducts = [...payload.products || []];
889
949
  if (ruleProduct && ruleProductUid && !tempOrder.order_id) {
890
950
  const sellingPrice = String(ruleProduct.price ?? "0.00");
@@ -921,10 +981,7 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
921
981
  if (!this.store.order) {
922
982
  throw new Error("scanOrder解决方案需要 order 模块支持");
923
983
  }
924
- const pax = (0, import_utils2.normalizeSubmitCollectPaxValue)(this.store.entryPaxNumber);
925
- this.store.entryPaxNumber = pax;
926
984
  const tempOrderForSubmit = this.store.order.ensureTempOrder();
927
- tempOrderForSubmit.metadata = { ...tempOrderForSubmit.metadata, collect_pax: pax };
928
985
  tempOrderForSubmit.delivery_type = "shop_service";
929
986
  const resourceTableName = (_b = (_a = this.store.resource) == null ? void 0 : _a.table_form_record) == null ? void 0 : _b.name;
930
987
  if (resourceTableName && typeof resourceTableName === "object") {
@@ -1471,8 +1528,8 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
1471
1528
  const matched = resources.find((r) => Number(r == null ? void 0 : r.id) === numericFormId);
1472
1529
  return matched == null ? void 0 : matched.type;
1473
1530
  }
1474
- async fetchResourceOccupyDetailByResourceId(resourceId) {
1475
- var _a, _b, _c, _d;
1531
+ async fetchResourceOccupyDetailsByResourceId(resourceId) {
1532
+ var _a, _b, _c;
1476
1533
  const formRecordId = Number(resourceId);
1477
1534
  if (!Number.isFinite(formRecordId) || formRecordId <= 0) {
1478
1535
  throw new Error(`[ScanOrder] 非法桌台 resourceId: ${resourceId}`);
@@ -1494,15 +1551,60 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
1494
1551
  if (!(response == null ? void 0 : response.status)) {
1495
1552
  throw new Error((response == null ? void 0 : response.message) || "获取资源占用详情失败");
1496
1553
  }
1497
- return ((_d = (_c = response == null ? void 0 : response.data) == null ? void 0 : _c.occupy_details) == null ? void 0 : _d[0]) ?? null;
1554
+ return ((_c = response == null ? void 0 : response.data) == null ? void 0 : _c.occupy_details) ?? [];
1555
+ }
1556
+ resolveAdditionalOrderFromOccupyDetail(detail, resourceSelectType, allowAddItems) {
1557
+ const currentOrderId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.order_id);
1558
+ if (currentOrderId) {
1559
+ return {
1560
+ matched: true,
1561
+ order_id: currentOrderId
1562
+ };
1563
+ }
1564
+ const orderListIds = (Array.isArray(detail == null ? void 0 : detail.order_list) ? (detail == null ? void 0 : detail.order_list) || [] : []).map((order) => (0, import_utils.toPositiveString)(order == null ? void 0 : order.id)).filter(Boolean);
1565
+ if (resourceSelectType !== "single") {
1566
+ return {
1567
+ matched: false,
1568
+ reason: "no_order"
1569
+ };
1570
+ }
1571
+ if (!orderListIds.length) {
1572
+ return {
1573
+ matched: false,
1574
+ reason: "no_order"
1575
+ };
1576
+ }
1577
+ if (!allowAddItems) {
1578
+ return {
1579
+ matched: false,
1580
+ reason: "add_items_disabled"
1581
+ };
1582
+ }
1583
+ if (orderListIds.length === 1) {
1584
+ return {
1585
+ matched: true,
1586
+ order_id: orderListIds[0]
1587
+ };
1588
+ }
1589
+ if (orderListIds.length > 1) {
1590
+ return {
1591
+ matched: false,
1592
+ reason: "multiple_orders"
1593
+ };
1594
+ }
1595
+ return {
1596
+ matched: false,
1597
+ reason: "no_order"
1598
+ };
1498
1599
  }
1499
1600
  // 检测当前链接是否可用
1500
1601
  // 通过 resource_id + 店铺配置
1501
1602
  // hasOrderId 表示 url 上是否有 orderid,如果是的话,后续的流程会走加单
1502
- async checkResourceAvailable(resourceId, hasOrderId) {
1503
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
1603
+ async checkResourceAvailable(resourceId, hasOrderId = false) {
1604
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
1605
+ const normalizedResourceId = String(resourceId ?? "").trim();
1504
1606
  this.logMethodStart("checkResourceAvailable", {
1505
- resourceId
1607
+ resourceId: normalizedResourceId
1506
1608
  });
1507
1609
  try {
1508
1610
  const businessCode = String(((_a = this.otherParams) == null ? void 0 : _a.businessCode) ?? "").trim();
@@ -1556,70 +1658,113 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
1556
1658
  const reservationLinkIds = (0, import_utils.collectLinkProductIdsFromReservationRules)(
1557
1659
  dineInConfig["fulfillment.enabled_resource_rules"]
1558
1660
  );
1661
+ if (!normalizedResourceId || reservationLinkIds.length === 0) {
1662
+ return await this.prepareRetailAvailability({
1663
+ tempOrder,
1664
+ hasOrderId,
1665
+ resourceId: normalizedResourceId,
1666
+ reason: !normalizedResourceId ? "missing_resource_id" : "missing_enabled_resource_rules"
1667
+ });
1668
+ }
1559
1669
  let pendingRequestEntryPax;
1560
1670
  let pendingRequestPaxMin;
1561
1671
  let pendingRequestPaxMax;
1562
- if (reservationLinkIds.length === 0) {
1563
- this.enabledReservationRuleProducts = [];
1672
+ tempOrder.metadata = { ...tempOrder.metadata || {} };
1673
+ delete tempOrder.metadata.table_occupancy_duration;
1674
+ const reservationProductList = new import_ProductList.ProductList(
1675
+ `${this.name}_reservationEnabledRules`,
1676
+ this.defaultVersion
1677
+ );
1678
+ await reservationProductList.initialize(this.core, {
1679
+ store: { list: [], selectProducts: [] },
1680
+ otherParams: {
1681
+ ...this.otherParams,
1682
+ fatherModule: this.name,
1683
+ openCache: Boolean(this.cacheId),
1684
+ cacheId: this.cacheId
1685
+ }
1686
+ });
1687
+ const scheduleDate = (0, import_dayjs.default)().format("YYYY-MM-DD");
1688
+ const scheduleDatetime = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1689
+ const loaded = await reservationProductList.loadProducts({
1690
+ product_ids: reservationLinkIds,
1691
+ schedule_date: scheduleDate,
1692
+ schedule_datetime: scheduleDatetime,
1693
+ cacheId: this.cacheId
1694
+ });
1695
+ if (Array.isArray(loaded)) {
1696
+ this.enabledReservationRuleProducts = loaded;
1697
+ const occupancyMinutes = (0, import_utils.pickFirstDurationMinutesFromProducts)(loaded);
1698
+ if (occupancyMinutes !== void 0) {
1699
+ tempOrder.metadata.table_occupancy_duration = occupancyMinutes;
1700
+ }
1701
+ if ((0, import_utils.hasCustomCapacityProduct)(loaded)) {
1702
+ pendingRequestEntryPax = 1;
1703
+ const paxBounds = (0, import_utils.pickFirstCustomCapacityPaxBounds)(loaded);
1704
+ if ((paxBounds == null ? void 0 : paxBounds.min) !== void 0)
1705
+ pendingRequestPaxMin = paxBounds.min;
1706
+ if ((paxBounds == null ? void 0 : paxBounds.max) !== void 0)
1707
+ pendingRequestPaxMax = paxBounds.max;
1708
+ }
1564
1709
  } else {
1565
- tempOrder.metadata = { ...tempOrder.metadata || {} };
1566
- delete tempOrder.metadata.table_occupancy_duration;
1567
- const reservationProductList = new import_ProductList.ProductList(
1568
- `${this.name}_reservationEnabledRules`,
1569
- this.defaultVersion
1570
- );
1571
- await reservationProductList.initialize(this.core, {
1572
- store: { list: [], selectProducts: [] },
1573
- otherParams: {
1574
- ...this.otherParams,
1575
- fatherModule: this.name,
1576
- openCache: Boolean(this.cacheId),
1577
- cacheId: this.cacheId
1578
- }
1579
- });
1580
- const scheduleDate = (0, import_dayjs.default)().format("YYYY-MM-DD");
1581
- const scheduleDatetime = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1582
- const loaded = await reservationProductList.loadProducts({
1583
- product_ids: reservationLinkIds,
1584
- schedule_date: scheduleDate,
1585
- schedule_datetime: scheduleDatetime,
1710
+ this.enabledReservationRuleProducts = [];
1711
+ const error = loaded instanceof Error ? loaded : new Error("预约规则商品列表接口返回异常");
1712
+ this.logMethodError("loadReservationRuleProducts", error, {
1713
+ resourceId: normalizedResourceId,
1714
+ reservationLinkIds,
1715
+ scheduleDate,
1716
+ scheduleDatetime,
1586
1717
  cacheId: this.cacheId
1587
1718
  });
1588
- if (Array.isArray(loaded)) {
1589
- this.enabledReservationRuleProducts = loaded;
1590
- const occupancyMinutes = (0, import_utils.pickFirstDurationMinutesFromProducts)(loaded);
1591
- if (occupancyMinutes !== void 0) {
1592
- tempOrder.metadata.table_occupancy_duration = occupancyMinutes;
1593
- }
1594
- if ((0, import_utils.hasCustomCapacityProduct)(loaded)) {
1595
- pendingRequestEntryPax = 1;
1596
- const paxBounds = (0, import_utils.pickFirstCustomCapacityPaxBounds)(loaded);
1597
- if ((paxBounds == null ? void 0 : paxBounds.min) !== void 0)
1598
- pendingRequestPaxMin = paxBounds.min;
1599
- if ((paxBounds == null ? void 0 : paxBounds.max) !== void 0)
1600
- pendingRequestPaxMax = paxBounds.max;
1601
- }
1602
- } else {
1603
- this.enabledReservationRuleProducts = [];
1604
- const error = loaded instanceof Error ? loaded : new Error("预约规则商品列表接口返回异常");
1605
- this.logMethodError("loadReservationRuleProducts", error, {
1606
- resourceId,
1607
- reservationLinkIds,
1608
- scheduleDate,
1609
- scheduleDatetime,
1610
- cacheId: this.cacheId
1611
- });
1612
- }
1613
1719
  }
1614
- const occupyDetail = await this.fetchResourceOccupyDetailByResourceId(resourceId);
1720
+ const occupyDetails = await this.fetchResourceOccupyDetailsByResourceId(normalizedResourceId);
1721
+ const occupyDetail = occupyDetails[0] ?? null;
1615
1722
  const resourceSelectType = this.resolveResourceSelectType(
1616
1723
  (0, import_utils.toPositiveString)(occupyDetail == null ? void 0 : occupyDetail.form_id)
1617
1724
  );
1725
+ const allowAddItems = (0, import_utils.toBoolean)(dineInConfig == null ? void 0 : dineInConfig["sale.allow_add_items"]);
1726
+ const additionalOrderResult = this.resolveAdditionalOrderFromOccupyDetail(
1727
+ occupyDetail,
1728
+ resourceSelectType,
1729
+ allowAddItems
1730
+ );
1731
+ if (additionalOrderResult.reason === "multiple_orders") {
1732
+ const multipleOrdersState = {
1733
+ ...this.normalizeResourceState(occupyDetail, resourceSelectType, hasOrderId),
1734
+ mode: "multiple_orders"
1735
+ };
1736
+ this.store.resource = multipleOrdersState;
1737
+ const availabilityInfo2 = {
1738
+ mode: "multiple_orders",
1739
+ deskmate_valid: multipleOrdersState.deskmate_valid,
1740
+ relation_id: multipleOrdersState.relationId,
1741
+ table_form_id: multipleOrdersState.tableFormId,
1742
+ table_form_record: multipleOrdersState.table_form_record
1743
+ };
1744
+ this.logMethodSuccess("checkResourceAvailable", {
1745
+ resourceId: normalizedResourceId,
1746
+ mode: availabilityInfo2.mode,
1747
+ orderListCount: ((_e = occupyDetail == null ? void 0 : occupyDetail.order_list) == null ? void 0 : _e.length) || 0,
1748
+ resourceSelectType
1749
+ });
1750
+ return availabilityInfo2;
1751
+ }
1618
1752
  const resourceState = this.normalizeResourceState(
1619
1753
  occupyDetail,
1620
1754
  resourceSelectType,
1621
1755
  hasOrderId
1622
1756
  );
1757
+ const additionalOrderId = additionalOrderResult.order_id;
1758
+ if (additionalOrderId) {
1759
+ resourceState.mode = "additional_order";
1760
+ resourceState.order_id = additionalOrderId;
1761
+ } else if (additionalOrderResult.reason === "add_items_disabled") {
1762
+ resourceState.mode = "resource_busy";
1763
+ resourceState.order_id = "0";
1764
+ } else if (resourceSelectType === "multiple" && resourceState.isFull) {
1765
+ resourceState.mode = "resource_busy";
1766
+ resourceState.order_id = "0";
1767
+ }
1623
1768
  this.store.resource = resourceState;
1624
1769
  if (pendingRequestEntryPax !== void 0) {
1625
1770
  this.store.resource.requestEntryPax = pendingRequestEntryPax;
@@ -1637,34 +1782,35 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
1637
1782
  table_form_id: resourceState.tableFormId,
1638
1783
  deskmate_valid: resourceState.deskmate_valid,
1639
1784
  table_form_record: resourceState.table_form_record,
1640
- policy: (_e = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _e.policy,
1641
- partyroom_booking: (_f = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _f.partyroom_booking,
1785
+ policy: (_f = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _f.policy,
1786
+ partyroom_booking: (_g = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _g.partyroom_booking,
1642
1787
  ...this.store.resource.requestEntryPax !== void 0 ? { requestEntryPax: this.store.resource.requestEntryPax } : {},
1643
1788
  ...this.store.resource.requestPaxMin !== void 0 ? { requestPaxMin: this.store.resource.requestPaxMin } : {},
1644
1789
  ...this.store.resource.requestPaxMax !== void 0 ? { requestPaxMax: this.store.resource.requestPaxMax } : {}
1645
1790
  };
1646
- tempOrder.relation_id = resourceId || ((_g = this.otherParams) == null ? void 0 : _g.relation_id);
1791
+ tempOrder.relation_id = normalizedResourceId || ((_h = this.otherParams) == null ? void 0 : _h.relation_id);
1647
1792
  tempOrder.table_form_id = resourceState.tableFormId;
1648
- tempOrder.resource_id = resourceId;
1649
- (_h = this.store.order) == null ? void 0 : _h.persistTempOrder();
1793
+ tempOrder.resource_id = normalizedResourceId;
1794
+ (_i = this.store.order) == null ? void 0 : _i.persistTempOrder();
1650
1795
  if (availabilityInfo.mode === "idle") {
1651
1796
  await this.addNewOrder();
1652
1797
  }
1653
- if (availabilityInfo.mode === "additional_order" || availabilityInfo.mode === "additional_order_with_code") {
1654
- tempOrder.order_id = resourceState.lastOrderId;
1798
+ const isAdditionalOrderMode = availabilityInfo.mode === "additional_order" || availabilityInfo.mode === "additional_order_with_code";
1799
+ if (isAdditionalOrderMode) {
1800
+ tempOrder.order_id = additionalOrderId;
1655
1801
  }
1656
1802
  if (tempOrder.order_id) {
1657
- const res = await ((_i = this.store.order) == null ? void 0 : _i.getOrderInfoByRemote(tempOrder.order_id));
1658
- const entryPaxNumber = (_m = (_l = (_k = (_j = res == null ? void 0 : res.data) == null ? void 0 : _j.bookings) == null ? void 0 : _k.find((p) => {
1803
+ const res = await ((_j = this.store.order) == null ? void 0 : _j.getOrderInfoByRemote(tempOrder.order_id));
1804
+ const entryPaxNumber = (_n = (_m = (_l = (_k = res == null ? void 0 : res.data) == null ? void 0 : _k.bookings) == null ? void 0 : _l.find((p) => {
1659
1805
  var _a2;
1660
1806
  return (_a2 = p.metadata) == null ? void 0 : _a2.collect_pax;
1661
- })) == null ? void 0 : _l.metadata) == null ? void 0 : _m.collect_pax;
1807
+ })) == null ? void 0 : _m.metadata) == null ? void 0 : _n.collect_pax;
1662
1808
  if (entryPaxNumber) {
1663
1809
  await this.setEntryPaxNumber(entryPaxNumber);
1664
1810
  }
1665
1811
  }
1666
- const lastOrderInfo = (_o = (_n = this.store.order) == null ? void 0 : _n.getLastOrderInfo) == null ? void 0 : _o.call(_n);
1667
- const historicalItems = hasOrderId && Array.isArray(lastOrderInfo == null ? void 0 : lastOrderInfo.products) ? lastOrderInfo.products.reduce((acc, p) => {
1812
+ const lastOrderInfo = (_p = (_o = this.store.order) == null ? void 0 : _o.getLastOrderInfo) == null ? void 0 : _p.call(_o);
1813
+ const historicalItems = isAdditionalOrderMode && Array.isArray(lastOrderInfo == null ? void 0 : lastOrderInfo.products) ? lastOrderInfo.products.reduce((acc, p) => {
1668
1814
  if (typeof (p == null ? void 0 : p.product_id) !== "number")
1669
1815
  return acc;
1670
1816
  acc.push({
@@ -1675,8 +1821,8 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
1675
1821
  return acc;
1676
1822
  }, []) : [];
1677
1823
  await this.setItemRuleRuntimeConfig({
1678
- serviceType: (_p = this.otherParams) == null ? void 0 : _p.businessCode,
1679
- submissionIndex: hasOrderId ? 1 : 0,
1824
+ serviceType: (_q = this.otherParams) == null ? void 0 : _q.businessCode,
1825
+ submissionIndex: isAdditionalOrderMode ? 1 : 0,
1680
1826
  historicalItems
1681
1827
  });
1682
1828
  if (outsideOperatingHours && closedBehaviorValue === "show_menu_disabled") {
@@ -1685,7 +1831,7 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
1685
1831
  availabilityInfo.closed_behavior = closedBehaviorValue;
1686
1832
  }
1687
1833
  this.logMethodSuccess("checkResourceAvailable", {
1688
- resourceId,
1834
+ resourceId: normalizedResourceId,
1689
1835
  mode: availabilityInfo.mode,
1690
1836
  orderId: availabilityInfo.order_id,
1691
1837
  relationId: availabilityInfo.relation_id,
@@ -1700,7 +1846,7 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
1700
1846
  return availabilityInfo;
1701
1847
  } catch (error) {
1702
1848
  this.logMethodError("checkResourceAvailable", error.message, {
1703
- resourceId
1849
+ resourceId: normalizedResourceId
1704
1850
  });
1705
1851
  throw error;
1706
1852
  }
@@ -1849,6 +1995,83 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
1849
1995
  getEntryPaxNumber() {
1850
1996
  return this.store.entryPaxNumber;
1851
1997
  }
1998
+ async syncAdditionalOrderFromResource(resourceId) {
1999
+ var _a, _b, _c, _d, _e, _f;
2000
+ const tempOrder = this.ensureTempOrder();
2001
+ const normalizedResourceId = String(
2002
+ resourceId ?? tempOrder.resource_id ?? ((_a = this.store.resource) == null ? void 0 : _a.relationId) ?? ((_b = this.store.resource) == null ? void 0 : _b.relation_id) ?? ""
2003
+ ).trim();
2004
+ this.logMethodStart("syncAdditionalOrderFromResource", {
2005
+ resourceId: normalizedResourceId
2006
+ });
2007
+ if (!normalizedResourceId) {
2008
+ const result2 = {
2009
+ matched: false,
2010
+ reason: "missing_resource_id"
2011
+ };
2012
+ this.logMethodSuccess("syncAdditionalOrderFromResource", result2);
2013
+ return result2;
2014
+ }
2015
+ const occupyDetails = await this.fetchResourceOccupyDetailsByResourceId(normalizedResourceId);
2016
+ const occupyDetail = occupyDetails[0] ?? null;
2017
+ const resourceSelectType = ((_c = this.store.resource) == null ? void 0 : _c.resourceSelectType) || this.resolveResourceSelectType((0, import_utils.toPositiveString)(occupyDetail == null ? void 0 : occupyDetail.form_id));
2018
+ const allowAddItems = (0, import_utils.toBoolean)(
2019
+ (_e = (_d = this.otherParams) == null ? void 0 : _d.dineInConfig) == null ? void 0 : _e["sale.allow_add_items"]
2020
+ );
2021
+ const result = this.resolveAdditionalOrderFromOccupyDetail(
2022
+ occupyDetail,
2023
+ resourceSelectType,
2024
+ allowAddItems
2025
+ );
2026
+ if (!result.matched || !result.order_id) {
2027
+ this.logMethodSuccess("syncAdditionalOrderFromResource", {
2028
+ ...result,
2029
+ resourceId: normalizedResourceId,
2030
+ resourceSelectType,
2031
+ allowAddItems
2032
+ });
2033
+ return result;
2034
+ }
2035
+ tempOrder.order_id = result.order_id;
2036
+ tempOrder.resource_id = normalizedResourceId;
2037
+ tempOrder.relation_id = (0, import_utils.toPositiveString)(occupyDetail == null ? void 0 : occupyDetail.form_record_id) || normalizedResourceId || tempOrder.relation_id;
2038
+ tempOrder.table_form_id = (0, import_utils.toPositiveString)(occupyDetail == null ? void 0 : occupyDetail.form_id) || tempOrder.table_form_id;
2039
+ (_f = this.store.order) == null ? void 0 : _f.persistTempOrder();
2040
+ this.logMethodSuccess("syncAdditionalOrderFromResource", {
2041
+ ...result,
2042
+ resourceId: normalizedResourceId,
2043
+ resourceSelectType,
2044
+ allowAddItems
2045
+ });
2046
+ return result;
2047
+ }
2048
+ // 读取预约规则商品的资源选择类型:single=单个预约,multiple=多个预约,capacity=容量型预约
2049
+ // 依赖 checkResourceAvailable 已根据预约规则商品与 occupy-detail 的 form_id 计算并缓存 store.resource
2050
+ getReservationResourceSelectType() {
2051
+ var _a;
2052
+ this.logMethodStart("getReservationResourceSelectType");
2053
+ const resourceSelectType = (_a = this.store.resource) == null ? void 0 : _a.resourceSelectType;
2054
+ const result = {
2055
+ ...resourceSelectType ? { resourceSelectType } : {},
2056
+ isSingleReservation: resourceSelectType === "single",
2057
+ isMultipleReservation: resourceSelectType === "multiple",
2058
+ isCapacityReservation: resourceSelectType === "capacity"
2059
+ };
2060
+ this.logMethodSuccess("getReservationResourceSelectType", result);
2061
+ return result;
2062
+ }
2063
+ // 判定后台是否开启允许加餐
2064
+ // 依赖 checkResourceAvailable 已缓存的 dineInConfig
2065
+ checkAllowAddItems() {
2066
+ var _a;
2067
+ this.logMethodStart("checkAllowAddItems");
2068
+ const dineInConfig = ((_a = this.otherParams) == null ? void 0 : _a.dineInConfig) || {};
2069
+ const result = {
2070
+ enabled: (0, import_utils.toBoolean)(dineInConfig["sale.allow_add_items"])
2071
+ };
2072
+ this.logMethodSuccess("checkAllowAddItems", result);
2073
+ return result;
2074
+ }
1852
2075
  // 读取取餐/送餐开关
1853
2076
  // 依赖 checkResourceAvailable 已缓存的 dineInConfig
1854
2077
  getFulfillmentModes() {
@@ -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;
@@ -193,6 +193,7 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
193
193
  setUIState(key: string, value: any): void;
194
194
  getUIState<T = any>(key: string): T | undefined;
195
195
  deleteUIState(key: string): void;
196
+ setBookingHolder(bookingUid: string, holder: any): void;
196
197
  checkOpenDataAvailability(): Promise<OpenDataAvailabilityResult>;
197
198
  setOtherParams(params: Record<string, any>, { cover }?: {
198
199
  cover?: boolean;
@@ -1896,6 +1896,17 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1896
1896
  this.writeUIStateBucket(bucket);
1897
1897
  }
1898
1898
  }
1899
+ setBookingHolder(bookingUid, holder) {
1900
+ var _a;
1901
+ const order = this.getTempOrder();
1902
+ const booking = (_a = order == null ? void 0 : order.bookings) == null ? void 0 : _a.find((b) => {
1903
+ var _a2;
1904
+ return ((_a2 = b.metadata) == null ? void 0 : _a2.unique_identification_number) === bookingUid;
1905
+ });
1906
+ if (booking) {
1907
+ booking.holder = holder;
1908
+ }
1909
+ }
1899
1910
  // ─── OpenData 可用性 ───
1900
1911
  async checkOpenDataAvailability() {
1901
1912
  if (!this.store.openData)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.1.152",
4
+ "version": "2.1.154",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",