@pisell/pisellos 2.2.259 → 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 (103) 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 +1 -32
  15. package/dist/modules/Order/index.js +288 -615
  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/modules/SalesSummary/index.d.ts +3 -7
  28. package/dist/modules/SalesSummary/index.js +39 -67
  29. package/dist/modules/SalesSummary/types.d.ts +0 -1
  30. package/dist/modules/SalesSummary/utils.js +1 -2
  31. package/dist/modules/SurchargeList/index.d.ts +4 -6
  32. package/dist/modules/SurchargeList/index.js +39 -62
  33. package/dist/modules/SurchargeList/types.d.ts +2 -6
  34. package/dist/server/index.d.ts +50 -3
  35. package/dist/server/index.js +1040 -1075
  36. package/dist/server/modules/order/index.d.ts +3 -22
  37. package/dist/server/modules/order/index.js +316 -398
  38. package/dist/server/modules/products/index.d.ts +26 -7
  39. package/dist/server/modules/products/index.js +166 -76
  40. package/dist/server/modules/products/types.d.ts +14 -0
  41. package/dist/solution/BaseSales/index.d.ts +2 -22
  42. package/dist/solution/BaseSales/index.js +701 -995
  43. package/dist/solution/BaseSales/types.d.ts +0 -1
  44. package/dist/solution/BaseSales/types.js +1 -2
  45. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +3 -6
  46. package/dist/solution/BookingByStep/index.d.ts +1 -1
  47. package/dist/solution/BookingTicket/index.d.ts +0 -8
  48. package/dist/solution/BookingTicket/index.js +6 -153
  49. package/dist/solution/BookingTicket/types.d.ts +2 -0
  50. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +49 -0
  51. package/lib/model/strategy/adapter/dataVariant/adapter.js +139 -0
  52. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +87 -0
  53. package/lib/model/strategy/adapter/dataVariant/evaluator.js +564 -0
  54. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  55. package/lib/model/strategy/adapter/dataVariant/examples.js +295 -0
  56. package/lib/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  57. package/lib/model/strategy/adapter/dataVariant/index.js +38 -0
  58. package/lib/model/strategy/adapter/dataVariant/type.d.ts +146 -0
  59. package/lib/model/strategy/adapter/dataVariant/type.js +31 -0
  60. package/lib/model/strategy/adapter/index.d.ts +4 -0
  61. package/lib/model/strategy/adapter/index.js +13 -2
  62. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +1 -11
  63. package/lib/modules/Order/index.d.ts +1 -32
  64. package/lib/modules/Order/index.js +64 -402
  65. package/lib/modules/Order/types.d.ts +2 -20
  66. package/lib/modules/Order/utils.d.ts +0 -4
  67. package/lib/modules/Order/utils.js +2 -84
  68. package/lib/modules/Product/index.d.ts +1 -1
  69. package/lib/modules/Product/types.d.ts +22 -0
  70. package/lib/modules/ProductList/index.d.ts +1 -1
  71. package/lib/modules/ProductList/index.js +4 -2
  72. package/lib/modules/ProductList/types.d.ts +2 -0
  73. package/lib/modules/Rules/index.d.ts +3 -3
  74. package/lib/modules/Rules/index.js +3 -4
  75. package/lib/modules/Rules/types.d.ts +1 -2
  76. package/lib/modules/SalesSummary/index.d.ts +3 -7
  77. package/lib/modules/SalesSummary/index.js +11 -28
  78. package/lib/modules/SalesSummary/types.d.ts +0 -1
  79. package/lib/modules/SalesSummary/utils.js +0 -2
  80. package/lib/modules/SurchargeList/index.d.ts +4 -6
  81. package/lib/modules/SurchargeList/index.js +21 -41
  82. package/lib/modules/SurchargeList/types.d.ts +2 -6
  83. package/lib/server/index.d.ts +50 -3
  84. package/lib/server/index.js +215 -244
  85. package/lib/server/modules/order/index.d.ts +3 -22
  86. package/lib/server/modules/order/index.js +53 -103
  87. package/lib/server/modules/products/index.d.ts +26 -7
  88. package/lib/server/modules/products/index.js +113 -35
  89. package/lib/server/modules/products/types.d.ts +14 -0
  90. package/lib/solution/BaseSales/index.d.ts +2 -22
  91. package/lib/solution/BaseSales/index.js +60 -246
  92. package/lib/solution/BaseSales/types.d.ts +0 -1
  93. package/lib/solution/BaseSales/types.js +1 -2
  94. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +6 -6
  95. package/lib/solution/BookingByStep/index.d.ts +1 -1
  96. package/lib/solution/BookingTicket/index.d.ts +0 -8
  97. package/lib/solution/BookingTicket/index.js +0 -101
  98. package/lib/solution/BookingTicket/types.d.ts +2 -0
  99. package/package.json +1 -1
  100. package/dist/modules/Order/utils/bundleDiscountHydration.d.ts +0 -5
  101. package/dist/modules/Order/utils/bundleDiscountHydration.js +0 -144
  102. package/lib/modules/Order/utils/bundleDiscountHydration.d.ts +0 -5
  103. 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,97 +676,6 @@ var Server = class {
662
676
  };
663
677
  }
664
678
  };
665
- this.handleMachinecodeBatchMeta = async ({ data }) => {
666
- var _a, _b;
667
- const title = "handleMachinecodeBatchMeta";
668
- const backendPath = "/shop/machinecode/batch";
669
- const ids = Array.isArray(data == null ? void 0 : data.ids) ? data.ids : [];
670
- const status = data == null ? void 0 : data.status;
671
- this.logInfo(`${title}: 开始处理`, {
672
- backendPath,
673
- batchSize: ids.length,
674
- status,
675
- order_lookup: this.resolveMachinecodeBatchMetadataLookup(data) ?? null
676
- });
677
- if (ids.length === 0) {
678
- return {
679
- code: 200,
680
- status: true,
681
- message: "",
682
- data: []
683
- };
684
- }
685
- if (status !== "used" && status !== "unused") {
686
- return {
687
- code: 400,
688
- status: false,
689
- message: "无效的核销状态",
690
- data: null
691
- };
692
- }
693
- try {
694
- await this.syncMachinecodeRedeemStatusToLocalOrder(data, ids, status);
695
- } catch (error) {
696
- const message = this.getUnknownErrorMessage(error);
697
- this.logError(`${title}: 本地订单核销状态更新失败`, {
698
- error: message,
699
- error_detail: this.normalizeUnknownError(error)
700
- });
701
- return {
702
- code: 500,
703
- status: false,
704
- message,
705
- data: null
706
- };
707
- }
708
- if (!((_b = (_a = this.app) == null ? void 0 : _a.request) == null ? void 0 : _b.post)) {
709
- this.logError(`${title}: app.request 不可用`, { backendPath });
710
- return {
711
- code: 500,
712
- status: false,
713
- message: "app.request 不可用",
714
- data: null
715
- };
716
- }
717
- try {
718
- const response = await this.app.request.post(backendPath, {
719
- ids,
720
- status
721
- }, {
722
- isShopApi: true,
723
- customToast: () => {
724
- }
725
- });
726
- return {
727
- code: (response == null ? void 0 : response.code) ?? 200,
728
- status: (response == null ? void 0 : response.status) ?? true,
729
- message: (response == null ? void 0 : response.message) ?? "",
730
- data: (response == null ? void 0 : response.data) ?? response
731
- };
732
- } catch (error) {
733
- const backendError = this.extractBackendErrorResponse(error);
734
- if (backendError) {
735
- return {
736
- code: backendError.code ?? 500,
737
- status: backendError.status ?? false,
738
- message: backendError.message ?? "后端拒绝 batch-metadata",
739
- data: backendError.data ?? null
740
- };
741
- }
742
- const message = this.getUnknownErrorMessage(error);
743
- this.logError(`${title}: 请求失败`, {
744
- backendPath,
745
- error: message,
746
- error_detail: this.normalizeUnknownError(error)
747
- });
748
- return {
749
- code: 500,
750
- status: false,
751
- message,
752
- data: null
753
- };
754
- }
755
- };
756
679
  this.handleOrderSalesDetail = async ({ url, data, path }) => {
757
680
  var _a;
758
681
  const requestPath = this.parseRequestPath(url, path);
@@ -829,7 +752,7 @@ var Server = class {
829
752
  };
830
753
  } catch (error) {
831
754
  const errorMessage = error instanceof Error ? error.message : String(error);
832
- this.logInfo("handleOrderSalesDetail: 请求失败", {
755
+ this.logError("handleOrderSalesDetail: 请求失败", {
833
756
  lookup,
834
757
  backendPath,
835
758
  error: errorMessage
@@ -1835,16 +1758,6 @@ var Server = class {
1835
1758
  method: "post",
1836
1759
  path: "/shop/local/print-order",
1837
1760
  handler: this.handleLocalPrintOrder.bind(this)
1838
- },
1839
- {
1840
- method: "post",
1841
- path: "/shop/machinecode/batch",
1842
- handler: this.handleMachinecodeBatchMeta.bind(this)
1843
- },
1844
- {
1845
- method: "post",
1846
- path: "/machinecode/batch",
1847
- handler: this.handleMachinecodeBatchMeta.bind(this)
1848
1761
  }
1849
1762
  ]);
1850
1763
  this.registerPrefixRoutes([
@@ -1909,6 +1822,7 @@ var Server = class {
1909
1822
  */
1910
1823
  removeProductQuerySubscriber(subscriberId) {
1911
1824
  if (subscriberId) {
1825
+ this.clearSubscriberScheduleTimers(subscriberId);
1912
1826
  this.productQuerySubscribers.delete(subscriberId);
1913
1827
  this.logInfo("removeProductQuerySubscriber: 已移除订阅者", {
1914
1828
  subscriberId,
@@ -1916,6 +1830,156 @@ var Server = class {
1916
1830
  });
1917
1831
  }
1918
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
+ }
1919
1983
  /**
1920
1984
  * 执行 sales 搜索并登记可见订单号。
1921
1985
  * 搜索参数完全透传后端,OS 不做过滤、筛选、排序。
@@ -2758,12 +2822,10 @@ var Server = class {
2758
2822
  action: "print_all",
2759
2823
  device_id: params.deviceId ?? deviceId,
2760
2824
  payload: {
2761
- type: params.isManualPrint ? "0" : "99",
2825
+ type: params.receiptOnly ? "0" : "99",
2762
2826
  data: params.receiptOnly ? {
2763
2827
  order_id: printIdentity,
2764
- small_ticket_data: (_b = (_a = params.syncedOrder) == null ? void 0 : _a.payment_info) == null ? void 0 : _b.small_ticket_data,
2765
- skip_wristband: true,
2766
- skip_voucher: true
2828
+ small_ticket_data: (_b = (_a = params.syncedOrder) == null ? void 0 : _a.payment_info) == null ? void 0 : _b.small_ticket_data
2767
2829
  } : {
2768
2830
  order_id: printIdentity,
2769
2831
  machine_code_print_info: (_d = (_c = params.syncedOrder) == null ? void 0 : _c.payment_info) == null ? void 0 : _d.machine_code_print_info,
@@ -2774,7 +2836,7 @@ var Server = class {
2774
2836
  idempotency_key: this.buildPrintOtherReceiptIdempotencyKey(params.syncedOrder, {
2775
2837
  receiptOnly: params.receiptOnly
2776
2838
  }),
2777
- name: "PRINT_V1",
2839
+ name: "打印转发",
2778
2840
  source: "server",
2779
2841
  source_type: "order",
2780
2842
  source_id: printIdentity
@@ -2814,8 +2876,7 @@ var Server = class {
2814
2876
  checkoutData: params.checkoutData,
2815
2877
  syncedOrder: printableOrder,
2816
2878
  response: params.response,
2817
- receiptOnly: true,
2818
- isManualPrint: params.isManualPrint
2879
+ receiptOnly: true
2819
2880
  });
2820
2881
  return { printed: true, order: printableOrder };
2821
2882
  }
@@ -2833,110 +2894,6 @@ var Server = class {
2833
2894
  }
2834
2895
  return void 0;
2835
2896
  }
2836
- resolveMachinecodeBatchMetadataLookup(data) {
2837
- const candidates = [
2838
- data == null ? void 0 : data.order_lookup,
2839
- data == null ? void 0 : data.orderLookup,
2840
- data == null ? void 0 : data.external_sale_number,
2841
- data == null ? void 0 : data.externalSaleNumber,
2842
- data == null ? void 0 : data.order_id,
2843
- data == null ? void 0 : data.orderId,
2844
- data == null ? void 0 : data.order_number,
2845
- data == null ? void 0 : data.orderNumber,
2846
- data == null ? void 0 : data.shop_order_number,
2847
- data == null ? void 0 : data.shopOrderNumber,
2848
- data == null ? void 0 : data.shop_full_order_number,
2849
- data == null ? void 0 : data.shopFullOrderNumber
2850
- ];
2851
- return candidates.find((candidate) => candidate !== void 0 && candidate !== null && candidate !== "");
2852
- }
2853
- async syncMachinecodeRedeemStatusToLocalOrder(data, ids, status) {
2854
- var _a;
2855
- const title = "handleMachinecodeBatchMetadata";
2856
- const lookup = this.resolveMachinecodeBatchMetadataLookup(data);
2857
- if (lookup === void 0) {
2858
- this.logWarning(`${title}: order lookup 缺失,跳过本地订单核销状态更新`, {
2859
- batchSize: ids.length,
2860
- status
2861
- });
2862
- return;
2863
- }
2864
- if (!((_a = this.order) == null ? void 0 : _a.getLocalOrderByLookup)) {
2865
- this.logWarning(`${title}: Order 模块未注册,跳过本地订单核销状态更新`, {
2866
- lookup,
2867
- status
2868
- });
2869
- return;
2870
- }
2871
- const localOrder = await this.order.getLocalOrderByLookup(lookup);
2872
- if (!localOrder) {
2873
- this.logWarning(`${title}: 本地订单不存在,跳过核销状态更新`, {
2874
- lookup,
2875
- status
2876
- });
2877
- return;
2878
- }
2879
- const voucherIdSet = new Set(
2880
- ids.filter((id) => id !== void 0 && id !== null && id !== "").map((id) => String(id))
2881
- );
2882
- if (voucherIdSet.size === 0) {
2883
- this.logWarning(`${title}: voucher ids 缺失,跳过本地订单核销状态更新`, {
2884
- lookup,
2885
- status
2886
- });
2887
- return;
2888
- }
2889
- const vouchers = Array.isArray(localOrder.vouchers) ? localOrder.vouchers : [];
2890
- let hasUpdatedVoucher = false;
2891
- const nextVouchers = vouchers.map((voucher) => {
2892
- const voucherId = voucher == null ? void 0 : voucher.voucher_id;
2893
- if (voucherId === void 0 || voucherId === null)
2894
- return voucher;
2895
- if (!voucherIdSet.has(String(voucherId)))
2896
- return voucher;
2897
- hasUpdatedVoucher = true;
2898
- return {
2899
- ...voucher,
2900
- status
2901
- };
2902
- });
2903
- if (!hasUpdatedVoucher) {
2904
- this.logWarning(`${title}: 本地订单未命中任何 voucher,跳过核销状态更新`, {
2905
- lookup,
2906
- voucher_ids: Array.from(voucherIdSet),
2907
- status
2908
- });
2909
- return;
2910
- }
2911
- if (typeof this.order.overwriteExistingOrder === "function") {
2912
- await this.order.overwriteExistingOrder({
2913
- ...localOrder,
2914
- vouchers: nextVouchers
2915
- });
2916
- this.logInfo(`${title}: 本地订单 vouchers 核销状态已更新`, {
2917
- lookup,
2918
- updatedCount: voucherIdSet.size,
2919
- status
2920
- });
2921
- return;
2922
- }
2923
- if ((data == null ? void 0 : data.external_sale_number) && typeof this.order.markOrderSyncedByExternalSaleNumber === "function") {
2924
- await this.order.markOrderSyncedByExternalSaleNumber({
2925
- externalSaleNumber: data.external_sale_number,
2926
- patch: { vouchers: nextVouchers }
2927
- });
2928
- this.logInfo(`${title}: 本地订单 vouchers 核销状态已更新`, {
2929
- lookup,
2930
- updatedCount: voucherIdSet.size,
2931
- status
2932
- });
2933
- return;
2934
- }
2935
- this.logWarning(`${title}: Order 模块不支持本地订单覆盖,跳过核销状态更新`, {
2936
- lookup,
2937
- status
2938
- });
2939
- }
2940
2897
  async handleOrderCheckoutSubmit(params) {
2941
2898
  const { backendPath, data, title } = params;
2942
2899
  this.logInfo(`${title}: 开始处理`, {
@@ -3134,8 +3091,11 @@ var Server = class {
3134
3091
  );
3135
3092
  }
3136
3093
  shouldBuildSmallTicketData(order) {
3094
+ var _a;
3137
3095
  if (!order || typeof order !== "object")
3138
3096
  return false;
3097
+ if ((0, import_small_ticket.hasSmallTicketData)((_a = order.payment_info) == null ? void 0 : _a.small_ticket_data))
3098
+ return false;
3139
3099
  return Number(order.small_ticket_data_flag ?? order.smallTicketDataFlag ?? 0) === 1;
3140
3100
  }
3141
3101
  shouldPrintSyncedOrder(params) {
@@ -3992,8 +3952,14 @@ var Server = class {
3992
3952
  */
3993
3953
  async computeProductQueryResult(context, options) {
3994
3954
  const tTotal = performance.now();
3995
- 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;
3996
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
+ });
3997
3963
  this.logInfo("computeProductQueryResult 开始", {
3998
3964
  menuListIdsCount: (menu_list_ids == null ? void 0 : menu_list_ids.length) ?? 0,
3999
3965
  ids: queryIds,
@@ -4002,20 +3968,17 @@ var Server = class {
4002
3968
  customer_id,
4003
3969
  extension_type,
4004
3970
  product_id,
3971
+ strategyContextKeys: strategy_context ? Object.keys(strategy_context) : [],
4005
3972
  changedIds: options == null ? void 0 : options.changedIds
4006
3973
  });
4007
3974
  if (!this.products) {
4008
3975
  this.logError("computeProductQueryResult: Products 模块未注册");
4009
- return { message: "Products 模块未注册", data: { list: [], count: 0 } };
3976
+ return { message: "Products 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
4010
3977
  }
4011
3978
  if (queryIds.length > 0) {
4012
3979
  const uniqueIds = Array.from(new Set(queryIds));
4013
3980
  const tPrice2 = performance.now();
4014
- const productsWithPrice = await this.products.getProductsWithPrice(schedule_date, {
4015
- scheduleModule: this.getSchedule(),
4016
- schedule_datetime,
4017
- customer_id
4018
- }, {
3981
+ const productsWithPrice = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4019
3982
  changedIds: options == null ? void 0 : options.changedIds,
4020
3983
  productIds: uniqueIds
4021
3984
  });
@@ -4036,7 +3999,7 @@ var Server = class {
4036
3999
  });
4037
4000
  return {
4038
4001
  code: 200,
4039
- data: { list: extensionFilteredProducts, count: extensionFilteredProducts.length },
4002
+ data: this.buildProductQueryResultPayload(extensionFilteredProducts),
4040
4003
  message: "",
4041
4004
  status: true
4042
4005
  };
@@ -4044,9 +4007,7 @@ var Server = class {
4044
4007
  if (product_id != null && Number.isFinite(Number(product_id))) {
4045
4008
  const pid = Number(product_id);
4046
4009
  const tPrice2 = performance.now();
4047
- const allProductsWithPrice = await this.products.getProductsWithPrice(schedule_date, {
4048
- scheduleModule: this.getSchedule()
4049
- }, {
4010
+ const allProductsWithPrice = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4050
4011
  changedIds: options == null ? void 0 : options.changedIds
4051
4012
  });
4052
4013
  (0, import_product.perfMark)("computeQuery.getProductsWithPrice(single)", performance.now() - tPrice2, {
@@ -4076,11 +4037,7 @@ var Server = class {
4076
4037
  }
4077
4038
  if (this.shouldQueryProductsByExtensionTypes(extension_type)) {
4078
4039
  const tPrice2 = performance.now();
4079
- let filteredProducts2 = await this.products.getProductsWithPrice(schedule_date, {
4080
- scheduleModule: this.getSchedule(),
4081
- schedule_datetime,
4082
- customer_id
4083
- }, {
4040
+ let filteredProducts2 = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4084
4041
  changedIds: options == null ? void 0 : options.changedIds
4085
4042
  });
4086
4043
  (0, import_product.perfMark)("computeQuery.getProductsWithPrice(extensionType)", performance.now() - tPrice2, {
@@ -4120,18 +4077,18 @@ var Server = class {
4120
4077
  });
4121
4078
  return {
4122
4079
  code: 200,
4123
- data: { list: filteredProducts2, count: filteredProducts2.length },
4080
+ data: this.buildProductQueryResultPayload(filteredProducts2),
4124
4081
  message: "",
4125
4082
  status: true
4126
4083
  };
4127
4084
  }
4128
4085
  if (!this.menu) {
4129
4086
  this.logError("computeProductQueryResult: Menu 模块未注册");
4130
- return { message: "Menu 模块未注册", data: { list: [], count: 0 } };
4087
+ return { message: "Menu 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
4131
4088
  }
4132
4089
  if (!this.schedule) {
4133
4090
  this.logError("computeProductQueryResult: Schedule 模块未注册");
4134
- return { message: "Schedule 模块未注册", data: { list: [], count: 0 } };
4091
+ return { message: "Schedule 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
4135
4092
  }
4136
4093
  let activeMenuList = [];
4137
4094
  if (menu_list_ids && Array.isArray(menu_list_ids) && menu_list_ids.length > 0) {
@@ -4155,11 +4112,7 @@ var Server = class {
4155
4112
  isAllProducts: !!productScope.isAllProducts
4156
4113
  });
4157
4114
  const tPrice = performance.now();
4158
- let filteredProducts = scopedProductIds.length > 0 ? await this.products.getProductsWithPrice(schedule_date, {
4159
- scheduleModule: this.getSchedule(),
4160
- schedule_datetime,
4161
- customer_id
4162
- }, {
4115
+ let filteredProducts = scopedProductIds.length > 0 ? await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4163
4116
  changedIds: options == null ? void 0 : options.changedIds,
4164
4117
  productIds: productScope.isAllProducts ? void 0 : scopedProductIds
4165
4118
  }) : [];
@@ -4202,11 +4155,29 @@ var Server = class {
4202
4155
  });
4203
4156
  return {
4204
4157
  code: 200,
4205
- data: { list: filteredProducts, count: filteredProducts.length },
4158
+ data: this.buildProductQueryResultPayload(filteredProducts),
4206
4159
  message: "",
4207
4160
  status: true
4208
4161
  };
4209
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
+ }
4210
4181
  /**
4211
4182
  * 数据变更后,遍历所有订阅者重新计算查询结果并通过 callback 推送
4212
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;