@pisell/pisellos 2.2.258 → 2.2.260

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +49 -0
  2. package/dist/model/strategy/adapter/dataVariant/adapter.js +152 -0
  3. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +87 -0
  4. package/dist/model/strategy/adapter/dataVariant/evaluator.js +755 -0
  5. package/dist/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  6. package/dist/model/strategy/adapter/dataVariant/examples.js +282 -0
  7. package/dist/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  8. package/dist/model/strategy/adapter/dataVariant/index.js +4 -0
  9. package/dist/model/strategy/adapter/dataVariant/type.d.ts +146 -0
  10. package/dist/model/strategy/adapter/dataVariant/type.js +54 -0
  11. package/dist/model/strategy/adapter/index.d.ts +4 -0
  12. package/dist/model/strategy/adapter/index.js +5 -1
  13. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +13 -17
  14. package/dist/modules/Order/index.d.ts +2 -30
  15. package/dist/modules/Order/index.js +241 -508
  16. package/dist/modules/Order/types.d.ts +2 -20
  17. package/dist/modules/Order/utils.d.ts +0 -4
  18. package/dist/modules/Order/utils.js +28 -114
  19. package/dist/modules/Product/index.d.ts +1 -1
  20. package/dist/modules/Product/types.d.ts +22 -0
  21. package/dist/modules/ProductList/index.d.ts +1 -1
  22. package/dist/modules/ProductList/index.js +4 -2
  23. package/dist/modules/ProductList/types.d.ts +2 -0
  24. package/dist/modules/Rules/index.d.ts +3 -3
  25. package/dist/modules/Rules/index.js +3 -8
  26. package/dist/modules/Rules/types.d.ts +1 -2
  27. package/dist/server/index.d.ts +50 -3
  28. package/dist/server/index.js +958 -1000
  29. package/dist/server/modules/order/index.d.ts +3 -22
  30. package/dist/server/modules/order/index.js +314 -397
  31. package/dist/server/modules/products/index.d.ts +26 -7
  32. package/dist/server/modules/products/index.js +166 -76
  33. package/dist/server/modules/products/types.d.ts +14 -0
  34. package/dist/solution/BaseSales/index.d.ts +2 -16
  35. package/dist/solution/BaseSales/index.js +314 -484
  36. package/dist/solution/BaseSales/types.d.ts +0 -1
  37. package/dist/solution/BaseSales/types.js +1 -2
  38. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +2 -4
  39. package/dist/solution/BookingByStep/index.d.ts +1 -1
  40. package/dist/solution/BookingTicket/index.d.ts +1 -9
  41. package/dist/solution/BookingTicket/index.js +6 -162
  42. package/dist/solution/BookingTicket/types.d.ts +2 -0
  43. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +49 -0
  44. package/lib/model/strategy/adapter/dataVariant/adapter.js +139 -0
  45. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +87 -0
  46. package/lib/model/strategy/adapter/dataVariant/evaluator.js +564 -0
  47. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  48. package/lib/model/strategy/adapter/dataVariant/examples.js +295 -0
  49. package/lib/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  50. package/lib/model/strategy/adapter/dataVariant/index.js +38 -0
  51. package/lib/model/strategy/adapter/dataVariant/type.d.ts +146 -0
  52. package/lib/model/strategy/adapter/dataVariant/type.js +31 -0
  53. package/lib/model/strategy/adapter/index.d.ts +4 -0
  54. package/lib/model/strategy/adapter/index.js +13 -2
  55. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  56. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +1 -11
  57. package/lib/modules/Order/index.d.ts +2 -30
  58. package/lib/modules/Order/index.js +57 -340
  59. package/lib/modules/Order/types.d.ts +2 -20
  60. package/lib/modules/Order/utils.d.ts +0 -4
  61. package/lib/modules/Order/utils.js +2 -84
  62. package/lib/modules/Product/index.d.ts +1 -1
  63. package/lib/modules/Product/types.d.ts +22 -0
  64. package/lib/modules/ProductList/index.d.ts +1 -1
  65. package/lib/modules/ProductList/index.js +4 -2
  66. package/lib/modules/ProductList/types.d.ts +2 -0
  67. package/lib/modules/Rules/index.d.ts +3 -3
  68. package/lib/modules/Rules/index.js +3 -4
  69. package/lib/modules/Rules/types.d.ts +1 -2
  70. package/lib/server/index.d.ts +50 -3
  71. package/lib/server/index.js +215 -230
  72. package/lib/server/modules/order/index.d.ts +3 -22
  73. package/lib/server/modules/order/index.js +51 -102
  74. package/lib/server/modules/products/index.d.ts +26 -7
  75. package/lib/server/modules/products/index.js +113 -35
  76. package/lib/server/modules/products/types.d.ts +14 -0
  77. package/lib/solution/BaseSales/index.d.ts +2 -16
  78. package/lib/solution/BaseSales/index.js +31 -143
  79. package/lib/solution/BaseSales/types.d.ts +0 -1
  80. package/lib/solution/BaseSales/types.js +1 -2
  81. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +5 -4
  82. package/lib/solution/BookingByStep/index.d.ts +1 -1
  83. package/lib/solution/BookingTicket/index.d.ts +1 -9
  84. package/lib/solution/BookingTicket/index.js +0 -112
  85. package/lib/solution/BookingTicket/types.d.ts +2 -0
  86. package/package.json +1 -1
  87. package/dist/modules/Order/utils/bundleDiscountHydration.d.ts +0 -5
  88. package/dist/modules/Order/utils/bundleDiscountHydration.js +0 -144
  89. package/lib/modules/Order/utils/bundleDiscountHydration.d.ts +0 -5
  90. package/lib/modules/Order/utils/bundleDiscountHydration.js +0 -139
@@ -76,6 +76,8 @@ var Server = class {
76
76
  };
77
77
  // ---- 商品查询订阅者 ----
78
78
  this.productQuerySubscribers = /* @__PURE__ */ new Map();
79
+ /** subscriberId → 智能定价变价时间点定时器句柄(与 subscriber 分离存储,便于 clear) */
80
+ this.productQueryScheduleTimers = /* @__PURE__ */ new Map();
79
81
  // ---- 订单 / 预约列表查询订阅者 ----
80
82
  this.orderQuerySubscribers = /* @__PURE__ */ new Map();
81
83
  this.bookingQuerySubscribers = /* @__PURE__ */ new Map();
@@ -208,7 +210,7 @@ var Server = class {
208
210
  */
209
211
  this.handleProductQuery = async ({ url, method, data, config }) => {
210
212
  console.log("[Server] handleProductQuery:", url, method, data, config);
211
- const { menu_list_ids, schedule_datetime, schedule_date, customer_id, ids, extension_type } = data;
213
+ const { menu_list_ids, schedule_datetime, schedule_date, customer_id, ids, extension_type, strategy_context } = data;
212
214
  const { callback, subscriberId } = config || {};
213
215
  this.logInfo("handleProductQuery: 开始处理商品查询请求", {
214
216
  menu_list_ids,
@@ -216,19 +218,32 @@ var Server = class {
216
218
  schedule_datetime,
217
219
  schedule_date,
218
220
  customer_id,
219
- extension_type
221
+ extension_type,
222
+ strategyContextKeys: strategy_context ? Object.keys(strategy_context) : []
220
223
  });
221
224
  if (subscriberId && typeof callback === "function") {
222
225
  this.productQuerySubscribers.set(subscriberId, {
223
226
  callback,
224
- context: { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type }
227
+ context: { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type, strategy_context }
225
228
  });
226
229
  this.logInfo("handleProductQuery: 已注册订阅者", {
227
230
  subscriberId,
228
231
  totalSubscribers: this.productQuerySubscribers.size
229
232
  });
230
233
  }
231
- return this.computeProductQueryResult({ menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type });
234
+ const result = await this.computeProductQueryResult({
235
+ menu_list_ids,
236
+ ids,
237
+ schedule_date,
238
+ schedule_datetime,
239
+ customer_id,
240
+ extension_type,
241
+ strategy_context
242
+ });
243
+ if (subscriberId && typeof callback === "function") {
244
+ this.syncProductQueryScheduleTimers(subscriberId, strategy_context);
245
+ }
246
+ return result;
232
247
  };
233
248
  /**
234
249
  * 按商品 id 查询单条(GET /shop/product/query/:productId)
@@ -639,8 +654,7 @@ var Server = class {
639
654
  checkoutData,
640
655
  order: printableOrder,
641
656
  response: null,
642
- requireFullyPaid: false,
643
- isManualPrint: true
657
+ requireFullyPaid: false
644
658
  });
645
659
  return {
646
660
  code: 200,
@@ -662,86 +676,6 @@ var Server = class {
662
676
  };
663
677
  }
664
678
  };
665
- this.handleMachinecodeBatchMetadata = async ({ data }) => {
666
- var _a, _b;
667
- const title = "handleMachinecodeBatchMetadata";
668
- const backendPath = "/shop/machinecode/batch-metadata";
669
- const batchMetadata = Array.isArray(data == null ? void 0 : data.data) ? data.data : [];
670
- this.logInfo(`${title}: 开始处理`, {
671
- backendPath,
672
- batchSize: batchMetadata.length,
673
- order_lookup: this.resolveMachinecodeBatchMetadataLookup(data) ?? null
674
- });
675
- if (batchMetadata.length === 0) {
676
- return {
677
- code: 200,
678
- status: true,
679
- message: "",
680
- data: []
681
- };
682
- }
683
- try {
684
- await this.syncMachinecodeBatchMetadataToLocalOrder(data, batchMetadata);
685
- } catch (error) {
686
- const message = this.getUnknownErrorMessage(error);
687
- this.logError(`${title}: 本地订单 metadata 更新失败`, {
688
- error: message,
689
- error_detail: this.normalizeUnknownError(error)
690
- });
691
- return {
692
- code: 500,
693
- status: false,
694
- message,
695
- data: null
696
- };
697
- }
698
- if (!((_b = (_a = this.app) == null ? void 0 : _a.request) == null ? void 0 : _b.post)) {
699
- this.logError(`${title}: app.request 不可用`, { backendPath });
700
- return {
701
- code: 500,
702
- status: false,
703
- message: "app.request 不可用",
704
- data: null
705
- };
706
- }
707
- try {
708
- const response = await this.app.request.post(backendPath, {
709
- data: batchMetadata
710
- }, {
711
- isShopApi: true,
712
- customToast: () => {
713
- }
714
- });
715
- return {
716
- code: (response == null ? void 0 : response.code) ?? 200,
717
- status: (response == null ? void 0 : response.status) ?? true,
718
- message: (response == null ? void 0 : response.message) ?? "",
719
- data: (response == null ? void 0 : response.data) ?? response
720
- };
721
- } catch (error) {
722
- const backendError = this.extractBackendErrorResponse(error);
723
- if (backendError) {
724
- return {
725
- code: backendError.code ?? 500,
726
- status: backendError.status ?? false,
727
- message: backendError.message ?? "后端拒绝 batch-metadata",
728
- data: backendError.data ?? null
729
- };
730
- }
731
- const message = this.getUnknownErrorMessage(error);
732
- this.logError(`${title}: 请求失败`, {
733
- backendPath,
734
- error: message,
735
- error_detail: this.normalizeUnknownError(error)
736
- });
737
- return {
738
- code: 500,
739
- status: false,
740
- message,
741
- data: null
742
- };
743
- }
744
- };
745
679
  this.handleOrderSalesDetail = async ({ url, data, path }) => {
746
680
  var _a;
747
681
  const requestPath = this.parseRequestPath(url, path);
@@ -818,7 +752,7 @@ var Server = class {
818
752
  };
819
753
  } catch (error) {
820
754
  const errorMessage = error instanceof Error ? error.message : String(error);
821
- this.logInfo("handleOrderSalesDetail: 请求失败", {
755
+ this.logError("handleOrderSalesDetail: 请求失败", {
822
756
  lookup,
823
757
  backendPath,
824
758
  error: errorMessage
@@ -1824,16 +1758,6 @@ var Server = class {
1824
1758
  method: "post",
1825
1759
  path: "/shop/local/print-order",
1826
1760
  handler: this.handleLocalPrintOrder.bind(this)
1827
- },
1828
- {
1829
- method: "post",
1830
- path: "/shop/machinecode/batch-metadata",
1831
- handler: this.handleMachinecodeBatchMetadata.bind(this)
1832
- },
1833
- {
1834
- method: "post",
1835
- path: "/machinecode/batch-metadata",
1836
- handler: this.handleMachinecodeBatchMetadata.bind(this)
1837
1761
  }
1838
1762
  ]);
1839
1763
  this.registerPrefixRoutes([
@@ -1898,6 +1822,7 @@ var Server = class {
1898
1822
  */
1899
1823
  removeProductQuerySubscriber(subscriberId) {
1900
1824
  if (subscriberId) {
1825
+ this.clearSubscriberScheduleTimers(subscriberId);
1901
1826
  this.productQuerySubscribers.delete(subscriberId);
1902
1827
  this.logInfo("removeProductQuerySubscriber: 已移除订阅者", {
1903
1828
  subscriberId,
@@ -1905,6 +1830,156 @@ var Server = class {
1905
1830
  });
1906
1831
  }
1907
1832
  }
1833
+ /**
1834
+ * 构建商品 query 响应 data 段,附带智能定价 schedule_time_points 元数据。
1835
+ */
1836
+ buildProductQueryResultPayload(list, count) {
1837
+ var _a, _b;
1838
+ return {
1839
+ list,
1840
+ count: count ?? list.length,
1841
+ schedule_time_points: ((_b = (_a = this.products) == null ? void 0 : _a.getLastScheduleTimePoints) == null ? void 0 : _b.call(_a)) ?? []
1842
+ };
1843
+ }
1844
+ /**
1845
+ * 是否启用商品 query 订阅的 schedule 时间点定时重算。
1846
+ * strategy_context.enable_schedule_reload === false 时关闭。
1847
+ */
1848
+ shouldScheduleProductQueryReload(strategy_context) {
1849
+ return (strategy_context == null ? void 0 : strategy_context.enable_schedule_reload) !== false;
1850
+ }
1851
+ /**
1852
+ * 清除指定 subscriber 的全部 schedule 定时器,防止重复 query 或 unsubscribe 后泄漏。
1853
+ */
1854
+ clearSubscriberScheduleTimers(subscriberId) {
1855
+ const timers = this.productQueryScheduleTimers.get(subscriberId);
1856
+ if (timers == null ? void 0 : timers.length) {
1857
+ timers.forEach((timerId) => clearTimeout(timerId));
1858
+ }
1859
+ this.productQueryScheduleTimers.delete(subscriberId);
1860
+ const subscriber = this.productQuerySubscribers.get(subscriberId);
1861
+ if (subscriber) {
1862
+ subscriber.scheduleTimerIds = [];
1863
+ }
1864
+ }
1865
+ /**
1866
+ * 从 productQueryScheduleTimers 移除已触发的 timer 引用。
1867
+ */
1868
+ removeScheduleTimerRef(subscriberId, timerId) {
1869
+ const timers = this.productQueryScheduleTimers.get(subscriberId);
1870
+ if (!(timers == null ? void 0 : timers.length))
1871
+ return;
1872
+ const next = timers.filter((id) => id !== timerId);
1873
+ if (next.length === 0) {
1874
+ this.productQueryScheduleTimers.delete(subscriberId);
1875
+ } else {
1876
+ this.productQueryScheduleTimers.set(subscriberId, next);
1877
+ }
1878
+ const subscriber = this.productQuerySubscribers.get(subscriberId);
1879
+ if (subscriber) {
1880
+ subscriber.scheduleTimerIds = next;
1881
+ }
1882
+ }
1883
+ /**
1884
+ * 计算 schedule 变价时间点到当前时刻的延迟(ms)。已过期返回 -1。
1885
+ */
1886
+ computeScheduleTimePointDelayMs(scheduleDate, timePoint) {
1887
+ const parts = timePoint.split(":");
1888
+ if (parts.length < 2)
1889
+ return -1;
1890
+ const hours = parseInt(parts[0], 10);
1891
+ const minutes = parseInt(parts[1], 10);
1892
+ if (!Number.isFinite(hours) || !Number.isFinite(minutes))
1893
+ return -1;
1894
+ const target = (0, import_dayjs.default)(scheduleDate).hour(hours).minute(minutes).second(4).millisecond(0);
1895
+ const delayMs = target.diff((0, import_dayjs.default)());
1896
+ return delayMs >= 0 ? delayMs : -1;
1897
+ }
1898
+ /**
1899
+ * 定时重算前刷新 subscriber schedule 上下文:使用执行瞬间时间,禁止沿用首次 query 的 schedule_datetime。
1900
+ */
1901
+ refreshSubscriberScheduleAtExecution(subscriber) {
1902
+ const executedAt = (0, import_dayjs.default)();
1903
+ const bookingDate = subscriber.context.schedule_date || executedAt.format("YYYY-MM-DD");
1904
+ subscriber.context.schedule_date = bookingDate;
1905
+ subscriber.context.schedule_datetime = `${bookingDate} ${executedAt.format("HH:mm:ss")}`;
1906
+ }
1907
+ /**
1908
+ * 为 subscriber 注册智能定价 scheduleTimePoints 定时重算。
1909
+ * 必须先 clearSubscriberScheduleTimers,再调用本方法。
1910
+ */
1911
+ scheduleSubscriberTimePointReloads(subscriberId, timePoints) {
1912
+ const subscriber = this.productQuerySubscribers.get(subscriberId);
1913
+ if (!subscriber || !timePoints.length)
1914
+ return;
1915
+ const scheduleDate = subscriber.context.schedule_date || (0, import_dayjs.default)().format("YYYY-MM-DD");
1916
+ const timerIds = [];
1917
+ for (const timePoint of timePoints) {
1918
+ const delayMs = this.computeScheduleTimePointDelayMs(scheduleDate, timePoint);
1919
+ if (delayMs < 0)
1920
+ continue;
1921
+ const timerId = setTimeout(() => {
1922
+ void this.onScheduleTimePointTimerFire(subscriberId, timerId);
1923
+ }, delayMs);
1924
+ timerIds.push(timerId);
1925
+ }
1926
+ if (timerIds.length > 0) {
1927
+ this.productQueryScheduleTimers.set(subscriberId, timerIds);
1928
+ subscriber.scheduleTimerIds = timerIds;
1929
+ this.logInfo("scheduleSubscriberTimePointReloads: 已注册定时器", {
1930
+ subscriberId,
1931
+ timerCount: timerIds.length,
1932
+ timePoints
1933
+ });
1934
+ }
1935
+ }
1936
+ /**
1937
+ * schedule 变价时间点定时器触发:刷新 schedule_datetime 后重算并 callback。
1938
+ */
1939
+ async onScheduleTimePointTimerFire(subscriberId, timerId) {
1940
+ this.removeScheduleTimerRef(subscriberId, timerId);
1941
+ if (!this.productQuerySubscribers.has(subscriberId))
1942
+ return;
1943
+ const subscriber = this.productQuerySubscribers.get(subscriberId);
1944
+ this.refreshSubscriberScheduleAtExecution(subscriber);
1945
+ await this.recomputeAndNotifySubscriber(subscriberId);
1946
+ }
1947
+ /**
1948
+ * 对单个商品 query 订阅者重算并推送(定时路径;不新建 schedule timer)。
1949
+ */
1950
+ async recomputeAndNotifySubscriber(subscriberId) {
1951
+ const subscriber = this.productQuerySubscribers.get(subscriberId);
1952
+ if (!subscriber)
1953
+ return;
1954
+ try {
1955
+ const result = await this.computeProductQueryResult(subscriber.context);
1956
+ subscriber.callback(result);
1957
+ this.logInfo("recomputeAndNotifySubscriber: 已推送", {
1958
+ subscriberId,
1959
+ schedule_datetime: subscriber.context.schedule_datetime
1960
+ });
1961
+ } catch (error) {
1962
+ const errorMessage = error instanceof Error ? error.message : String(error);
1963
+ this.logError("recomputeAndNotifySubscriber: 推送失败", {
1964
+ subscriberId,
1965
+ error: errorMessage
1966
+ });
1967
+ }
1968
+ }
1969
+ /**
1970
+ * query 完成后为 subscriber 同步 schedule 定时器(先 clear 再 schedule)。
1971
+ */
1972
+ syncProductQueryScheduleTimers(subscriberId, strategy_context) {
1973
+ var _a, _b;
1974
+ this.clearSubscriberScheduleTimers(subscriberId);
1975
+ if (!this.shouldScheduleProductQueryReload(strategy_context)) {
1976
+ return;
1977
+ }
1978
+ const timePoints = ((_b = (_a = this.products) == null ? void 0 : _a.getLastScheduleTimePoints) == null ? void 0 : _b.call(_a)) ?? [];
1979
+ if (timePoints.length > 0) {
1980
+ this.scheduleSubscriberTimePointReloads(subscriberId, timePoints);
1981
+ }
1982
+ }
1908
1983
  /**
1909
1984
  * 执行 sales 搜索并登记可见订单号。
1910
1985
  * 搜索参数完全透传后端,OS 不做过滤、筛选、排序。
@@ -2747,12 +2822,10 @@ var Server = class {
2747
2822
  action: "print_all",
2748
2823
  device_id: params.deviceId ?? deviceId,
2749
2824
  payload: {
2750
- type: params.isManualPrint ? "0" : "99",
2825
+ type: params.receiptOnly ? "0" : "99",
2751
2826
  data: params.receiptOnly ? {
2752
2827
  order_id: printIdentity,
2753
- small_ticket_data: (_b = (_a = params.syncedOrder) == null ? void 0 : _a.payment_info) == null ? void 0 : _b.small_ticket_data,
2754
- skip_wristband: true,
2755
- skip_voucher: true
2828
+ small_ticket_data: (_b = (_a = params.syncedOrder) == null ? void 0 : _a.payment_info) == null ? void 0 : _b.small_ticket_data
2756
2829
  } : {
2757
2830
  order_id: printIdentity,
2758
2831
  machine_code_print_info: (_d = (_c = params.syncedOrder) == null ? void 0 : _c.payment_info) == null ? void 0 : _d.machine_code_print_info,
@@ -2763,7 +2836,7 @@ var Server = class {
2763
2836
  idempotency_key: this.buildPrintOtherReceiptIdempotencyKey(params.syncedOrder, {
2764
2837
  receiptOnly: params.receiptOnly
2765
2838
  }),
2766
- name: "PRINT_V1",
2839
+ name: "打印转发",
2767
2840
  source: "server",
2768
2841
  source_type: "order",
2769
2842
  source_id: printIdentity
@@ -2803,8 +2876,7 @@ var Server = class {
2803
2876
  checkoutData: params.checkoutData,
2804
2877
  syncedOrder: printableOrder,
2805
2878
  response: params.response,
2806
- receiptOnly: true,
2807
- isManualPrint: params.isManualPrint
2879
+ receiptOnly: true
2808
2880
  });
2809
2881
  return { printed: true, order: printableOrder };
2810
2882
  }
@@ -2822,107 +2894,6 @@ var Server = class {
2822
2894
  }
2823
2895
  return void 0;
2824
2896
  }
2825
- resolveMachinecodeBatchMetadataLookup(data) {
2826
- const candidates = [
2827
- data == null ? void 0 : data.order_lookup,
2828
- data == null ? void 0 : data.orderLookup,
2829
- data == null ? void 0 : data.external_sale_number,
2830
- data == null ? void 0 : data.externalSaleNumber,
2831
- data == null ? void 0 : data.order_id,
2832
- data == null ? void 0 : data.orderId,
2833
- data == null ? void 0 : data.order_number,
2834
- data == null ? void 0 : data.orderNumber,
2835
- data == null ? void 0 : data.shop_order_number,
2836
- data == null ? void 0 : data.shopOrderNumber,
2837
- data == null ? void 0 : data.shop_full_order_number,
2838
- data == null ? void 0 : data.shopFullOrderNumber
2839
- ];
2840
- return candidates.find((candidate) => candidate !== void 0 && candidate !== null && candidate !== "");
2841
- }
2842
- async syncMachinecodeBatchMetadataToLocalOrder(data, batchMetadata) {
2843
- var _a;
2844
- const title = "handleMachinecodeBatchMetadata";
2845
- const lookup = this.resolveMachinecodeBatchMetadataLookup(data);
2846
- if (lookup === void 0) {
2847
- this.logWarning(`${title}: order lookup 缺失,跳过本地订单 metadata 更新`, {
2848
- batchSize: batchMetadata.length
2849
- });
2850
- return;
2851
- }
2852
- if (!((_a = this.order) == null ? void 0 : _a.getLocalOrderByLookup)) {
2853
- this.logWarning(`${title}: Order 模块未注册,跳过本地订单 metadata 更新`, {
2854
- lookup
2855
- });
2856
- return;
2857
- }
2858
- const localOrder = await this.order.getLocalOrderByLookup(lookup);
2859
- if (!localOrder) {
2860
- this.logWarning(`${title}: 本地订单不存在,跳过 metadata 更新`, {
2861
- lookup
2862
- });
2863
- return;
2864
- }
2865
- const metadataByVoucherId = /* @__PURE__ */ new Map();
2866
- for (const item of batchMetadata) {
2867
- const voucherId = (item == null ? void 0 : item.voucher_id) ?? (item == null ? void 0 : item.voucherId);
2868
- if (voucherId === void 0 || voucherId === null || voucherId === "")
2869
- continue;
2870
- metadataByVoucherId.set(String(voucherId), (item == null ? void 0 : item.metadata) || {});
2871
- }
2872
- if (metadataByVoucherId.size === 0) {
2873
- this.logWarning(`${title}: voucher metadata 缺失,跳过本地订单 metadata 更新`, {
2874
- lookup
2875
- });
2876
- return;
2877
- }
2878
- const vouchers = Array.isArray(localOrder.vouchers) ? localOrder.vouchers : [];
2879
- let hasUpdatedVoucher = false;
2880
- const nextVouchers = vouchers.map((voucher) => {
2881
- const voucherId = voucher == null ? void 0 : voucher.voucher_id;
2882
- if (voucherId === void 0 || voucherId === null)
2883
- return voucher;
2884
- const metadata = metadataByVoucherId.get(String(voucherId));
2885
- if (!metadata)
2886
- return voucher;
2887
- hasUpdatedVoucher = true;
2888
- return {
2889
- ...voucher,
2890
- metadata
2891
- };
2892
- });
2893
- if (!hasUpdatedVoucher) {
2894
- this.logWarning(`${title}: 本地订单未命中任何 voucher,跳过 metadata 更新`, {
2895
- lookup,
2896
- voucher_ids: Array.from(metadataByVoucherId.keys())
2897
- });
2898
- return;
2899
- }
2900
- if (typeof this.order.overwriteExistingOrder === "function") {
2901
- await this.order.overwriteExistingOrder({
2902
- ...localOrder,
2903
- vouchers: nextVouchers
2904
- });
2905
- this.logInfo(`${title}: 本地订单 vouchers metadata 已更新`, {
2906
- lookup,
2907
- updatedCount: metadataByVoucherId.size
2908
- });
2909
- return;
2910
- }
2911
- if ((data == null ? void 0 : data.external_sale_number) && typeof this.order.markOrderSyncedByExternalSaleNumber === "function") {
2912
- await this.order.markOrderSyncedByExternalSaleNumber({
2913
- externalSaleNumber: data.external_sale_number,
2914
- patch: { vouchers: nextVouchers }
2915
- });
2916
- this.logInfo(`${title}: 本地订单 vouchers metadata 已更新`, {
2917
- lookup,
2918
- updatedCount: metadataByVoucherId.size
2919
- });
2920
- return;
2921
- }
2922
- this.logWarning(`${title}: Order 模块不支持本地订单覆盖,跳过 metadata 更新`, {
2923
- lookup
2924
- });
2925
- }
2926
2897
  async handleOrderCheckoutSubmit(params) {
2927
2898
  const { backendPath, data, title } = params;
2928
2899
  this.logInfo(`${title}: 开始处理`, {
@@ -3120,8 +3091,11 @@ var Server = class {
3120
3091
  );
3121
3092
  }
3122
3093
  shouldBuildSmallTicketData(order) {
3094
+ var _a;
3123
3095
  if (!order || typeof order !== "object")
3124
3096
  return false;
3097
+ if ((0, import_small_ticket.hasSmallTicketData)((_a = order.payment_info) == null ? void 0 : _a.small_ticket_data))
3098
+ return false;
3125
3099
  return Number(order.small_ticket_data_flag ?? order.smallTicketDataFlag ?? 0) === 1;
3126
3100
  }
3127
3101
  shouldPrintSyncedOrder(params) {
@@ -3978,8 +3952,14 @@ var Server = class {
3978
3952
  */
3979
3953
  async computeProductQueryResult(context, options) {
3980
3954
  const tTotal = performance.now();
3981
- const { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type, product_id } = context;
3955
+ const { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type, product_id, strategy_context } = context;
3982
3956
  const queryIds = Array.isArray(ids) ? ids.map((id) => Number(id)).filter((id) => Number.isFinite(id)) : [];
3957
+ const formatterContext = this.buildProductFormatterContext({
3958
+ schedule_date,
3959
+ schedule_datetime,
3960
+ customer_id,
3961
+ strategy_context
3962
+ });
3983
3963
  this.logInfo("computeProductQueryResult 开始", {
3984
3964
  menuListIdsCount: (menu_list_ids == null ? void 0 : menu_list_ids.length) ?? 0,
3985
3965
  ids: queryIds,
@@ -3988,20 +3968,17 @@ var Server = class {
3988
3968
  customer_id,
3989
3969
  extension_type,
3990
3970
  product_id,
3971
+ strategyContextKeys: strategy_context ? Object.keys(strategy_context) : [],
3991
3972
  changedIds: options == null ? void 0 : options.changedIds
3992
3973
  });
3993
3974
  if (!this.products) {
3994
3975
  this.logError("computeProductQueryResult: Products 模块未注册");
3995
- return { message: "Products 模块未注册", data: { list: [], count: 0 } };
3976
+ return { message: "Products 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
3996
3977
  }
3997
3978
  if (queryIds.length > 0) {
3998
3979
  const uniqueIds = Array.from(new Set(queryIds));
3999
3980
  const tPrice2 = performance.now();
4000
- const productsWithPrice = await this.products.getProductsWithPrice(schedule_date, {
4001
- scheduleModule: this.getSchedule(),
4002
- schedule_datetime,
4003
- customer_id
4004
- }, {
3981
+ const productsWithPrice = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4005
3982
  changedIds: options == null ? void 0 : options.changedIds,
4006
3983
  productIds: uniqueIds
4007
3984
  });
@@ -4022,7 +3999,7 @@ var Server = class {
4022
3999
  });
4023
4000
  return {
4024
4001
  code: 200,
4025
- data: { list: extensionFilteredProducts, count: extensionFilteredProducts.length },
4002
+ data: this.buildProductQueryResultPayload(extensionFilteredProducts),
4026
4003
  message: "",
4027
4004
  status: true
4028
4005
  };
@@ -4030,9 +4007,7 @@ var Server = class {
4030
4007
  if (product_id != null && Number.isFinite(Number(product_id))) {
4031
4008
  const pid = Number(product_id);
4032
4009
  const tPrice2 = performance.now();
4033
- const allProductsWithPrice = await this.products.getProductsWithPrice(schedule_date, {
4034
- scheduleModule: this.getSchedule()
4035
- }, {
4010
+ const allProductsWithPrice = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4036
4011
  changedIds: options == null ? void 0 : options.changedIds
4037
4012
  });
4038
4013
  (0, import_product.perfMark)("computeQuery.getProductsWithPrice(single)", performance.now() - tPrice2, {
@@ -4062,11 +4037,7 @@ var Server = class {
4062
4037
  }
4063
4038
  if (this.shouldQueryProductsByExtensionTypes(extension_type)) {
4064
4039
  const tPrice2 = performance.now();
4065
- let filteredProducts2 = await this.products.getProductsWithPrice(schedule_date, {
4066
- scheduleModule: this.getSchedule(),
4067
- schedule_datetime,
4068
- customer_id
4069
- }, {
4040
+ let filteredProducts2 = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4070
4041
  changedIds: options == null ? void 0 : options.changedIds
4071
4042
  });
4072
4043
  (0, import_product.perfMark)("computeQuery.getProductsWithPrice(extensionType)", performance.now() - tPrice2, {
@@ -4106,18 +4077,18 @@ var Server = class {
4106
4077
  });
4107
4078
  return {
4108
4079
  code: 200,
4109
- data: { list: filteredProducts2, count: filteredProducts2.length },
4080
+ data: this.buildProductQueryResultPayload(filteredProducts2),
4110
4081
  message: "",
4111
4082
  status: true
4112
4083
  };
4113
4084
  }
4114
4085
  if (!this.menu) {
4115
4086
  this.logError("computeProductQueryResult: Menu 模块未注册");
4116
- return { message: "Menu 模块未注册", data: { list: [], count: 0 } };
4087
+ return { message: "Menu 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
4117
4088
  }
4118
4089
  if (!this.schedule) {
4119
4090
  this.logError("computeProductQueryResult: Schedule 模块未注册");
4120
- return { message: "Schedule 模块未注册", data: { list: [], count: 0 } };
4091
+ return { message: "Schedule 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
4121
4092
  }
4122
4093
  let activeMenuList = [];
4123
4094
  if (menu_list_ids && Array.isArray(menu_list_ids) && menu_list_ids.length > 0) {
@@ -4141,11 +4112,7 @@ var Server = class {
4141
4112
  isAllProducts: !!productScope.isAllProducts
4142
4113
  });
4143
4114
  const tPrice = performance.now();
4144
- let filteredProducts = scopedProductIds.length > 0 ? await this.products.getProductsWithPrice(schedule_date, {
4145
- scheduleModule: this.getSchedule(),
4146
- schedule_datetime,
4147
- customer_id
4148
- }, {
4115
+ let filteredProducts = scopedProductIds.length > 0 ? await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4149
4116
  changedIds: options == null ? void 0 : options.changedIds,
4150
4117
  productIds: productScope.isAllProducts ? void 0 : scopedProductIds
4151
4118
  }) : [];
@@ -4188,11 +4155,29 @@ var Server = class {
4188
4155
  });
4189
4156
  return {
4190
4157
  code: 200,
4191
- data: { list: filteredProducts, count: filteredProducts.length },
4158
+ data: this.buildProductQueryResultPayload(filteredProducts),
4192
4159
  message: "",
4193
4160
  status: true
4194
4161
  };
4195
4162
  }
4163
+ /**
4164
+ * 构建商品格式化上下文。
4165
+ *
4166
+ * 智能定价条件使用全量 menuList/scheduleList;Product Query 顶层参数只保留筛选商品集合所需字段。
4167
+ */
4168
+ buildProductFormatterContext(context) {
4169
+ var _a, _b, _c, _d;
4170
+ const scheduleModule = this.getSchedule();
4171
+ return {
4172
+ scheduleModule,
4173
+ schedule_datetime: context.schedule_datetime,
4174
+ customer_id: context.customer_id,
4175
+ strategy_context: context.strategy_context,
4176
+ menuList: ((_b = (_a = this.menu) == null ? void 0 : _a.getMenuList) == null ? void 0 : _b.call(_a)) || [],
4177
+ scheduleList: ((_c = scheduleModule == null ? void 0 : scheduleModule.getScheduleList) == null ? void 0 : _c.call(scheduleModule)) || [],
4178
+ dataVariantEvaluator: (_d = this.core.context) == null ? void 0 : _d.dataVariantEvaluator
4179
+ };
4180
+ }
4196
4181
  /**
4197
4182
  * 数据变更后,遍历所有订阅者重新计算查询结果并通过 callback 推送
4198
4183
  * 由 ProductsModule 的 onProductsSyncCompleted 事件触发
@@ -15,6 +15,7 @@ export declare class OrderModule extends BaseModule implements Module {
15
15
  private syncTimer?;
16
16
  private isProcessingSyncBatch;
17
17
  private isIdlePhase;
18
+ private resourceIdIndex;
18
19
  private logger;
19
20
  private storage;
20
21
  private orderSQLiteSaveQueue; /** 按 storageKey 记录最近一次 SQLite 写入来源与时间,用于去重 */
@@ -88,6 +89,7 @@ export declare class OrderModule extends BaseModule implements Module {
88
89
  * @returns 刷新后的订单列表
89
90
  */
90
91
  silentRefresh(): Promise<OrderData[]>;
92
+ getOrdersByResourceId(resourceId: string | number): OrderData[];
91
93
  private normalizeOrderForMemoryList;
92
94
  /**
93
95
  * 仅覆盖本地已存在的订单;不存在则直接跳过,不落库、不 emit。
@@ -124,6 +126,7 @@ export declare class OrderModule extends BaseModule implements Module {
124
126
  private isBlankIdentityValue;
125
127
  private getOrderIdentityEntries;
126
128
  private getOrderIdentityKeys;
129
+ private extractResourceIds;
127
130
  private getOrderDateKey;
128
131
  /**
129
132
  * 初始化 OrderDataSource 实例
@@ -172,28 +175,6 @@ export declare class OrderModule extends BaseModule implements Module {
172
175
  * 将增量订单合并到 store
173
176
  */
174
177
  private mergeOrdersToStore;
175
- /**
176
- * 在身份索引中查找与目标订单共享任一身份键的已存在订单下标。
177
- * 返回所有命中键里最小的下标,等价于原 findOrderIndexByIdentity 的「取首个匹配」语义。
178
- *
179
- * @example
180
- * const idx = this.lookupOrderIndexByIdentityKeys(identityKeyToIndex, freshIdentityKeys)
181
- */
182
- private lookupOrderIndexByIdentityKeys;
183
- private isRemoteEchoMergeSource;
184
- /**
185
- * 将订单的全部身份键登记到索引并指向其在列表中的下标。
186
- * 合并后订单新增的身份字段(如挂单同步后拿到 order_id)也会被登记。
187
- *
188
- * @example
189
- * this.registerOrderIdentityKeys(identityKeyToIndex, mergedOrder, matchIndex)
190
- */
191
- private registerOrderIdentityKeys;
192
- /**
193
- * 合并热路径去重兜底:默认直接返回原列表(增量索引已保证无重复)。
194
- * 仅当 ORDER_MERGE_SELF_CHECK 开启时,额外做一次全表压缩并在发现残留重复时告警。
195
- */
196
- private runOrderStoreSelfCheck;
197
178
  private normalizeOrderSyncMessage;
198
179
  private normalizeOrderSyncPayload;
199
180
  private uniqueOrderIds;