@pisell/pisellos 2.2.260 → 2.2.261

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 (129) hide show
  1. package/dist/model/strategy/adapter/index.d.ts +0 -4
  2. package/dist/model/strategy/adapter/index.js +1 -5
  3. package/dist/model/strategy/adapter/promotion/adapter.d.ts +4 -0
  4. package/dist/model/strategy/adapter/promotion/adapter.js +23 -0
  5. package/dist/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
  6. package/dist/model/strategy/adapter/promotion/evaluator.js +279 -6
  7. package/dist/model/strategy/adapter/promotion/examples.d.ts +86 -0
  8. package/dist/model/strategy/adapter/promotion/examples.js +99 -0
  9. package/dist/model/strategy/adapter/promotion/index.d.ts +1 -1
  10. package/dist/model/strategy/adapter/promotion/index.js +1 -1
  11. package/dist/model/strategy/adapter/promotion/type.d.ts +90 -2
  12. package/dist/model/strategy/adapter/promotion/type.js +45 -0
  13. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +17 -13
  14. package/dist/modules/Order/index.d.ts +33 -2
  15. package/dist/modules/Order/index.js +615 -288
  16. package/dist/modules/Order/types.d.ts +20 -2
  17. package/dist/modules/Order/utils/bundleDiscountHydration.d.ts +5 -0
  18. package/dist/modules/Order/utils/bundleDiscountHydration.js +144 -0
  19. package/dist/modules/Order/utils.d.ts +4 -0
  20. package/dist/modules/Order/utils.js +116 -29
  21. package/dist/modules/Product/types.d.ts +0 -22
  22. package/dist/modules/ProductList/index.d.ts +1 -1
  23. package/dist/modules/ProductList/index.js +2 -4
  24. package/dist/modules/ProductList/types.d.ts +0 -2
  25. package/dist/modules/Rules/index.d.ts +4 -3
  26. package/dist/modules/Rules/index.js +42 -17
  27. package/dist/modules/Rules/types.d.ts +2 -1
  28. package/dist/modules/SalesSummary/index.d.ts +7 -3
  29. package/dist/modules/SalesSummary/index.js +67 -39
  30. package/dist/modules/SalesSummary/types.d.ts +1 -0
  31. package/dist/modules/SalesSummary/utils.js +2 -1
  32. package/dist/modules/SurchargeList/index.d.ts +6 -4
  33. package/dist/modules/SurchargeList/index.js +62 -39
  34. package/dist/modules/SurchargeList/types.d.ts +6 -2
  35. package/dist/server/index.d.ts +3 -50
  36. package/dist/server/index.js +1075 -1040
  37. package/dist/server/modules/order/index.d.ts +22 -3
  38. package/dist/server/modules/order/index.js +398 -316
  39. package/dist/server/modules/products/index.d.ts +7 -26
  40. package/dist/server/modules/products/index.js +76 -166
  41. package/dist/server/modules/products/types.d.ts +0 -14
  42. package/dist/solution/BaseSales/index.d.ts +22 -2
  43. package/dist/solution/BaseSales/index.js +995 -701
  44. package/dist/solution/BaseSales/types.d.ts +1 -0
  45. package/dist/solution/BaseSales/types.js +2 -1
  46. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
  47. package/dist/solution/BaseSales/utils/cartPromotion.js +74 -29
  48. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +6 -3
  49. package/dist/solution/BookingByStep/index.d.ts +1 -1
  50. package/dist/solution/BookingTicket/index.d.ts +9 -1
  51. package/dist/solution/BookingTicket/index.js +153 -6
  52. package/dist/solution/BookingTicket/types.d.ts +0 -2
  53. package/dist/solution/ScanOrder/index.js +31 -20
  54. package/dist/solution/VenueBooking/index.js +30 -19
  55. package/lib/model/strategy/adapter/index.d.ts +0 -4
  56. package/lib/model/strategy/adapter/index.js +2 -13
  57. package/lib/model/strategy/adapter/promotion/adapter.d.ts +4 -0
  58. package/lib/model/strategy/adapter/promotion/adapter.js +20 -0
  59. package/lib/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
  60. package/lib/model/strategy/adapter/promotion/evaluator.js +235 -0
  61. package/lib/model/strategy/adapter/promotion/examples.d.ts +86 -0
  62. package/lib/model/strategy/adapter/promotion/examples.js +91 -0
  63. package/lib/model/strategy/adapter/promotion/index.d.ts +1 -1
  64. package/lib/model/strategy/adapter/promotion/index.js +2 -0
  65. package/lib/model/strategy/adapter/promotion/type.d.ts +90 -2
  66. package/lib/model/strategy/adapter/promotion/type.js +2 -0
  67. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +11 -1
  68. package/lib/modules/Order/index.d.ts +33 -2
  69. package/lib/modules/Order/index.js +402 -64
  70. package/lib/modules/Order/types.d.ts +20 -2
  71. package/lib/modules/Order/utils/bundleDiscountHydration.d.ts +5 -0
  72. package/lib/modules/Order/utils/bundleDiscountHydration.js +139 -0
  73. package/lib/modules/Order/utils.d.ts +4 -0
  74. package/lib/modules/Order/utils.js +90 -3
  75. package/lib/modules/Product/types.d.ts +0 -22
  76. package/lib/modules/ProductList/index.d.ts +1 -1
  77. package/lib/modules/ProductList/index.js +2 -4
  78. package/lib/modules/ProductList/types.d.ts +0 -2
  79. package/lib/modules/Rules/index.d.ts +4 -3
  80. package/lib/modules/Rules/index.js +27 -7
  81. package/lib/modules/Rules/types.d.ts +2 -1
  82. package/lib/modules/SalesSummary/index.d.ts +7 -3
  83. package/lib/modules/SalesSummary/index.js +28 -11
  84. package/lib/modules/SalesSummary/types.d.ts +1 -0
  85. package/lib/modules/SalesSummary/utils.js +2 -0
  86. package/lib/modules/SurchargeList/index.d.ts +6 -4
  87. package/lib/modules/SurchargeList/index.js +41 -21
  88. package/lib/modules/SurchargeList/types.d.ts +6 -2
  89. package/lib/server/index.d.ts +3 -50
  90. package/lib/server/index.js +244 -215
  91. package/lib/server/modules/order/index.d.ts +22 -3
  92. package/lib/server/modules/order/index.js +103 -53
  93. package/lib/server/modules/products/index.d.ts +7 -26
  94. package/lib/server/modules/products/index.js +35 -113
  95. package/lib/server/modules/products/types.d.ts +0 -14
  96. package/lib/solution/BaseSales/index.d.ts +22 -2
  97. package/lib/solution/BaseSales/index.js +246 -60
  98. package/lib/solution/BaseSales/types.d.ts +1 -0
  99. package/lib/solution/BaseSales/types.js +2 -1
  100. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
  101. package/lib/solution/BaseSales/utils/cartPromotion.js +59 -16
  102. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +6 -6
  103. package/lib/solution/BookingByStep/index.d.ts +1 -1
  104. package/lib/solution/BookingTicket/index.d.ts +9 -1
  105. package/lib/solution/BookingTicket/index.js +101 -0
  106. package/lib/solution/BookingTicket/types.d.ts +0 -2
  107. package/lib/solution/ScanOrder/index.js +8 -0
  108. package/lib/solution/VenueBooking/index.js +8 -0
  109. package/package.json +1 -1
  110. package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +0 -49
  111. package/dist/model/strategy/adapter/dataVariant/adapter.js +0 -152
  112. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -87
  113. package/dist/model/strategy/adapter/dataVariant/evaluator.js +0 -755
  114. package/dist/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
  115. package/dist/model/strategy/adapter/dataVariant/examples.js +0 -282
  116. package/dist/model/strategy/adapter/dataVariant/index.d.ts +0 -4
  117. package/dist/model/strategy/adapter/dataVariant/index.js +0 -4
  118. package/dist/model/strategy/adapter/dataVariant/type.d.ts +0 -146
  119. package/dist/model/strategy/adapter/dataVariant/type.js +0 -54
  120. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +0 -49
  121. package/lib/model/strategy/adapter/dataVariant/adapter.js +0 -139
  122. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -87
  123. package/lib/model/strategy/adapter/dataVariant/evaluator.js +0 -564
  124. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
  125. package/lib/model/strategy/adapter/dataVariant/examples.js +0 -295
  126. package/lib/model/strategy/adapter/dataVariant/index.d.ts +0 -4
  127. package/lib/model/strategy/adapter/dataVariant/index.js +0 -38
  128. package/lib/model/strategy/adapter/dataVariant/type.d.ts +0 -146
  129. package/lib/model/strategy/adapter/dataVariant/type.js +0 -31
@@ -76,8 +76,6 @@ var Server = class {
76
76
  };
77
77
  // ---- 商品查询订阅者 ----
78
78
  this.productQuerySubscribers = /* @__PURE__ */ new Map();
79
- /** subscriberId → 智能定价变价时间点定时器句柄(与 subscriber 分离存储,便于 clear) */
80
- this.productQueryScheduleTimers = /* @__PURE__ */ new Map();
81
79
  // ---- 订单 / 预约列表查询订阅者 ----
82
80
  this.orderQuerySubscribers = /* @__PURE__ */ new Map();
83
81
  this.bookingQuerySubscribers = /* @__PURE__ */ new Map();
@@ -210,7 +208,7 @@ var Server = class {
210
208
  */
211
209
  this.handleProductQuery = async ({ url, method, data, config }) => {
212
210
  console.log("[Server] handleProductQuery:", url, method, data, config);
213
- const { menu_list_ids, schedule_datetime, schedule_date, customer_id, ids, extension_type, strategy_context } = data;
211
+ const { menu_list_ids, schedule_datetime, schedule_date, customer_id, ids, extension_type } = data;
214
212
  const { callback, subscriberId } = config || {};
215
213
  this.logInfo("handleProductQuery: 开始处理商品查询请求", {
216
214
  menu_list_ids,
@@ -218,32 +216,19 @@ var Server = class {
218
216
  schedule_datetime,
219
217
  schedule_date,
220
218
  customer_id,
221
- extension_type,
222
- strategyContextKeys: strategy_context ? Object.keys(strategy_context) : []
219
+ extension_type
223
220
  });
224
221
  if (subscriberId && typeof callback === "function") {
225
222
  this.productQuerySubscribers.set(subscriberId, {
226
223
  callback,
227
- context: { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type, strategy_context }
224
+ context: { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type }
228
225
  });
229
226
  this.logInfo("handleProductQuery: 已注册订阅者", {
230
227
  subscriberId,
231
228
  totalSubscribers: this.productQuerySubscribers.size
232
229
  });
233
230
  }
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;
231
+ return this.computeProductQueryResult({ menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type });
247
232
  };
248
233
  /**
249
234
  * 按商品 id 查询单条(GET /shop/product/query/:productId)
@@ -654,7 +639,8 @@ var Server = class {
654
639
  checkoutData,
655
640
  order: printableOrder,
656
641
  response: null,
657
- requireFullyPaid: false
642
+ requireFullyPaid: false,
643
+ isManualPrint: true
658
644
  });
659
645
  return {
660
646
  code: 200,
@@ -676,6 +662,97 @@ var Server = class {
676
662
  };
677
663
  }
678
664
  };
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
+ };
679
756
  this.handleOrderSalesDetail = async ({ url, data, path }) => {
680
757
  var _a;
681
758
  const requestPath = this.parseRequestPath(url, path);
@@ -752,7 +829,7 @@ var Server = class {
752
829
  };
753
830
  } catch (error) {
754
831
  const errorMessage = error instanceof Error ? error.message : String(error);
755
- this.logError("handleOrderSalesDetail: 请求失败", {
832
+ this.logInfo("handleOrderSalesDetail: 请求失败", {
756
833
  lookup,
757
834
  backendPath,
758
835
  error: errorMessage
@@ -1758,6 +1835,16 @@ var Server = class {
1758
1835
  method: "post",
1759
1836
  path: "/shop/local/print-order",
1760
1837
  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)
1761
1848
  }
1762
1849
  ]);
1763
1850
  this.registerPrefixRoutes([
@@ -1822,7 +1909,6 @@ var Server = class {
1822
1909
  */
1823
1910
  removeProductQuerySubscriber(subscriberId) {
1824
1911
  if (subscriberId) {
1825
- this.clearSubscriberScheduleTimers(subscriberId);
1826
1912
  this.productQuerySubscribers.delete(subscriberId);
1827
1913
  this.logInfo("removeProductQuerySubscriber: 已移除订阅者", {
1828
1914
  subscriberId,
@@ -1830,156 +1916,6 @@ var Server = class {
1830
1916
  });
1831
1917
  }
1832
1918
  }
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
- }
1983
1919
  /**
1984
1920
  * 执行 sales 搜索并登记可见订单号。
1985
1921
  * 搜索参数完全透传后端,OS 不做过滤、筛选、排序。
@@ -2822,10 +2758,12 @@ var Server = class {
2822
2758
  action: "print_all",
2823
2759
  device_id: params.deviceId ?? deviceId,
2824
2760
  payload: {
2825
- type: params.receiptOnly ? "0" : "99",
2761
+ type: params.isManualPrint ? "0" : "99",
2826
2762
  data: params.receiptOnly ? {
2827
2763
  order_id: printIdentity,
2828
- small_ticket_data: (_b = (_a = params.syncedOrder) == null ? void 0 : _a.payment_info) == null ? void 0 : _b.small_ticket_data
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
2829
2767
  } : {
2830
2768
  order_id: printIdentity,
2831
2769
  machine_code_print_info: (_d = (_c = params.syncedOrder) == null ? void 0 : _c.payment_info) == null ? void 0 : _d.machine_code_print_info,
@@ -2836,7 +2774,7 @@ var Server = class {
2836
2774
  idempotency_key: this.buildPrintOtherReceiptIdempotencyKey(params.syncedOrder, {
2837
2775
  receiptOnly: params.receiptOnly
2838
2776
  }),
2839
- name: "打印转发",
2777
+ name: "PRINT_V1",
2840
2778
  source: "server",
2841
2779
  source_type: "order",
2842
2780
  source_id: printIdentity
@@ -2876,7 +2814,8 @@ var Server = class {
2876
2814
  checkoutData: params.checkoutData,
2877
2815
  syncedOrder: printableOrder,
2878
2816
  response: params.response,
2879
- receiptOnly: true
2817
+ receiptOnly: true,
2818
+ isManualPrint: params.isManualPrint
2880
2819
  });
2881
2820
  return { printed: true, order: printableOrder };
2882
2821
  }
@@ -2894,6 +2833,110 @@ var Server = class {
2894
2833
  }
2895
2834
  return void 0;
2896
2835
  }
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
+ }
2897
2940
  async handleOrderCheckoutSubmit(params) {
2898
2941
  const { backendPath, data, title } = params;
2899
2942
  this.logInfo(`${title}: 开始处理`, {
@@ -3091,11 +3134,8 @@ var Server = class {
3091
3134
  );
3092
3135
  }
3093
3136
  shouldBuildSmallTicketData(order) {
3094
- var _a;
3095
3137
  if (!order || typeof order !== "object")
3096
3138
  return false;
3097
- if ((0, import_small_ticket.hasSmallTicketData)((_a = order.payment_info) == null ? void 0 : _a.small_ticket_data))
3098
- return false;
3099
3139
  return Number(order.small_ticket_data_flag ?? order.smallTicketDataFlag ?? 0) === 1;
3100
3140
  }
3101
3141
  shouldPrintSyncedOrder(params) {
@@ -3952,14 +3992,8 @@ var Server = class {
3952
3992
  */
3953
3993
  async computeProductQueryResult(context, options) {
3954
3994
  const tTotal = performance.now();
3955
- const { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type, product_id, strategy_context } = context;
3995
+ const { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type, product_id } = context;
3956
3996
  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
- });
3963
3997
  this.logInfo("computeProductQueryResult 开始", {
3964
3998
  menuListIdsCount: (menu_list_ids == null ? void 0 : menu_list_ids.length) ?? 0,
3965
3999
  ids: queryIds,
@@ -3968,17 +4002,20 @@ var Server = class {
3968
4002
  customer_id,
3969
4003
  extension_type,
3970
4004
  product_id,
3971
- strategyContextKeys: strategy_context ? Object.keys(strategy_context) : [],
3972
4005
  changedIds: options == null ? void 0 : options.changedIds
3973
4006
  });
3974
4007
  if (!this.products) {
3975
4008
  this.logError("computeProductQueryResult: Products 模块未注册");
3976
- return { message: "Products 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
4009
+ return { message: "Products 模块未注册", data: { list: [], count: 0 } };
3977
4010
  }
3978
4011
  if (queryIds.length > 0) {
3979
4012
  const uniqueIds = Array.from(new Set(queryIds));
3980
4013
  const tPrice2 = performance.now();
3981
- const productsWithPrice = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4014
+ const productsWithPrice = await this.products.getProductsWithPrice(schedule_date, {
4015
+ scheduleModule: this.getSchedule(),
4016
+ schedule_datetime,
4017
+ customer_id
4018
+ }, {
3982
4019
  changedIds: options == null ? void 0 : options.changedIds,
3983
4020
  productIds: uniqueIds
3984
4021
  });
@@ -3999,7 +4036,7 @@ var Server = class {
3999
4036
  });
4000
4037
  return {
4001
4038
  code: 200,
4002
- data: this.buildProductQueryResultPayload(extensionFilteredProducts),
4039
+ data: { list: extensionFilteredProducts, count: extensionFilteredProducts.length },
4003
4040
  message: "",
4004
4041
  status: true
4005
4042
  };
@@ -4007,7 +4044,9 @@ var Server = class {
4007
4044
  if (product_id != null && Number.isFinite(Number(product_id))) {
4008
4045
  const pid = Number(product_id);
4009
4046
  const tPrice2 = performance.now();
4010
- const allProductsWithPrice = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4047
+ const allProductsWithPrice = await this.products.getProductsWithPrice(schedule_date, {
4048
+ scheduleModule: this.getSchedule()
4049
+ }, {
4011
4050
  changedIds: options == null ? void 0 : options.changedIds
4012
4051
  });
4013
4052
  (0, import_product.perfMark)("computeQuery.getProductsWithPrice(single)", performance.now() - tPrice2, {
@@ -4037,7 +4076,11 @@ var Server = class {
4037
4076
  }
4038
4077
  if (this.shouldQueryProductsByExtensionTypes(extension_type)) {
4039
4078
  const tPrice2 = performance.now();
4040
- let filteredProducts2 = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4079
+ let filteredProducts2 = await this.products.getProductsWithPrice(schedule_date, {
4080
+ scheduleModule: this.getSchedule(),
4081
+ schedule_datetime,
4082
+ customer_id
4083
+ }, {
4041
4084
  changedIds: options == null ? void 0 : options.changedIds
4042
4085
  });
4043
4086
  (0, import_product.perfMark)("computeQuery.getProductsWithPrice(extensionType)", performance.now() - tPrice2, {
@@ -4077,18 +4120,18 @@ var Server = class {
4077
4120
  });
4078
4121
  return {
4079
4122
  code: 200,
4080
- data: this.buildProductQueryResultPayload(filteredProducts2),
4123
+ data: { list: filteredProducts2, count: filteredProducts2.length },
4081
4124
  message: "",
4082
4125
  status: true
4083
4126
  };
4084
4127
  }
4085
4128
  if (!this.menu) {
4086
4129
  this.logError("computeProductQueryResult: Menu 模块未注册");
4087
- return { message: "Menu 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
4130
+ return { message: "Menu 模块未注册", data: { list: [], count: 0 } };
4088
4131
  }
4089
4132
  if (!this.schedule) {
4090
4133
  this.logError("computeProductQueryResult: Schedule 模块未注册");
4091
- return { message: "Schedule 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
4134
+ return { message: "Schedule 模块未注册", data: { list: [], count: 0 } };
4092
4135
  }
4093
4136
  let activeMenuList = [];
4094
4137
  if (menu_list_ids && Array.isArray(menu_list_ids) && menu_list_ids.length > 0) {
@@ -4112,7 +4155,11 @@ var Server = class {
4112
4155
  isAllProducts: !!productScope.isAllProducts
4113
4156
  });
4114
4157
  const tPrice = performance.now();
4115
- let filteredProducts = scopedProductIds.length > 0 ? await this.products.getProductsWithPrice(schedule_date, formatterContext, {
4158
+ let filteredProducts = scopedProductIds.length > 0 ? await this.products.getProductsWithPrice(schedule_date, {
4159
+ scheduleModule: this.getSchedule(),
4160
+ schedule_datetime,
4161
+ customer_id
4162
+ }, {
4116
4163
  changedIds: options == null ? void 0 : options.changedIds,
4117
4164
  productIds: productScope.isAllProducts ? void 0 : scopedProductIds
4118
4165
  }) : [];
@@ -4155,29 +4202,11 @@ var Server = class {
4155
4202
  });
4156
4203
  return {
4157
4204
  code: 200,
4158
- data: this.buildProductQueryResultPayload(filteredProducts),
4205
+ data: { list: filteredProducts, count: filteredProducts.length },
4159
4206
  message: "",
4160
4207
  status: true
4161
4208
  };
4162
4209
  }
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
- }
4181
4210
  /**
4182
4211
  * 数据变更后,遍历所有订阅者重新计算查询结果并通过 callback 推送
4183
4212
  * 由 ProductsModule 的 onProductsSyncCompleted 事件触发
@@ -15,7 +15,6 @@ export declare class OrderModule extends BaseModule implements Module {
15
15
  private syncTimer?;
16
16
  private isProcessingSyncBatch;
17
17
  private isIdlePhase;
18
- private resourceIdIndex;
19
18
  private logger;
20
19
  private storage;
21
20
  private orderSQLiteSaveQueue; /** 按 storageKey 记录最近一次 SQLite 写入来源与时间,用于去重 */
@@ -89,7 +88,6 @@ export declare class OrderModule extends BaseModule implements Module {
89
88
  * @returns 刷新后的订单列表
90
89
  */
91
90
  silentRefresh(): Promise<OrderData[]>;
92
- getOrdersByResourceId(resourceId: string | number): OrderData[];
93
91
  private normalizeOrderForMemoryList;
94
92
  /**
95
93
  * 仅覆盖本地已存在的订单;不存在则直接跳过,不落库、不 emit。
@@ -126,7 +124,6 @@ export declare class OrderModule extends BaseModule implements Module {
126
124
  private isBlankIdentityValue;
127
125
  private getOrderIdentityEntries;
128
126
  private getOrderIdentityKeys;
129
- private extractResourceIds;
130
127
  private getOrderDateKey;
131
128
  /**
132
129
  * 初始化 OrderDataSource 实例
@@ -175,6 +172,28 @@ export declare class OrderModule extends BaseModule implements Module {
175
172
  * 将增量订单合并到 store
176
173
  */
177
174
  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;
178
197
  private normalizeOrderSyncMessage;
179
198
  private normalizeOrderSyncPayload;
180
199
  private uniqueOrderIds;