@pisell/pisellos 2.3.38 → 2.3.40

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 (229) hide show
  1. package/dist/core/index.d.ts +0 -2
  2. package/dist/core/index.js +0 -7
  3. package/dist/model/strategy/adapter/promotion/adapter.d.ts +0 -4
  4. package/dist/model/strategy/adapter/promotion/adapter.js +0 -23
  5. package/dist/model/strategy/adapter/promotion/evaluator.d.ts +0 -17
  6. package/dist/model/strategy/adapter/promotion/evaluator.js +6 -279
  7. package/dist/model/strategy/adapter/promotion/examples.d.ts +0 -86
  8. package/dist/model/strategy/adapter/promotion/examples.js +0 -99
  9. package/dist/model/strategy/adapter/promotion/index.d.ts +1 -1
  10. package/dist/model/strategy/adapter/promotion/type.d.ts +2 -90
  11. package/dist/model/strategy/adapter/promotion/type.js +0 -45
  12. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +3 -5
  13. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +3 -6
  14. package/dist/modules/Discount/index.d.ts +1 -0
  15. package/dist/modules/Discount/index.js +40 -11
  16. package/dist/modules/Discount/types.d.ts +1 -0
  17. package/dist/modules/Holder/index.d.ts +48 -0
  18. package/dist/modules/Holder/index.js +640 -0
  19. package/dist/modules/Holder/types.d.ts +123 -0
  20. package/dist/modules/Holder/types.js +1 -0
  21. package/dist/modules/Holder/utils.d.ts +13 -0
  22. package/dist/modules/Holder/utils.js +34 -0
  23. package/dist/modules/OpenData/index.d.ts +0 -2
  24. package/dist/modules/OpenData/index.js +2 -10
  25. package/dist/modules/Order/index.d.ts +11 -28
  26. package/dist/modules/Order/index.js +509 -750
  27. package/dist/modules/Order/types.d.ts +10 -33
  28. package/dist/modules/Order/utils/orderCollectionIdentity.js +2 -7
  29. package/dist/modules/Order/utils.d.ts +10 -0
  30. package/dist/modules/Order/utils.js +41 -13
  31. package/dist/modules/Payment/index.d.ts +0 -2
  32. package/dist/modules/Payment/index.js +50 -79
  33. package/dist/modules/Payment/types.d.ts +28 -99
  34. package/dist/modules/Payment/types.js +3 -20
  35. package/dist/modules/Payment/walletpass.d.ts +1 -25
  36. package/dist/modules/Payment/walletpass.js +157 -707
  37. package/dist/modules/Product/types.d.ts +1 -0
  38. package/dist/modules/ProductList/index.js +33 -14
  39. package/dist/modules/Quotation/index.d.ts +1 -1
  40. package/dist/modules/Quotation/index.js +2 -2
  41. package/dist/modules/ResourcePlanner/index.d.ts +24 -0
  42. package/dist/modules/ResourcePlanner/index.js +181 -0
  43. package/dist/modules/ResourcePlanner/planner.d.ts +14 -0
  44. package/dist/modules/ResourcePlanner/planner.js +1069 -0
  45. package/dist/modules/ResourcePlanner/types.d.ts +227 -0
  46. package/dist/modules/ResourcePlanner/types.js +1 -0
  47. package/dist/modules/Rules/index.d.ts +0 -1
  48. package/dist/modules/Rules/index.js +96 -89
  49. package/dist/modules/SalesSummary/index.js +12 -13
  50. package/dist/modules/ScanOrderLogger/index.d.ts +2 -0
  51. package/dist/modules/ScanOrderLogger/index.js +15 -2
  52. package/dist/modules/ScanOrderLogger/providers/feishu.js +45 -27
  53. package/dist/modules/ScanOrderLogger/types.d.ts +1 -0
  54. package/dist/modules/Schedule/index.d.ts +3 -1
  55. package/dist/modules/Schedule/index.js +21 -16
  56. package/dist/modules/Summary/utils.js +38 -13
  57. package/dist/modules/index.d.ts +2 -0
  58. package/dist/modules/index.js +3 -1
  59. package/dist/plugins/window.d.ts +1 -0
  60. package/dist/server/index.d.ts +14 -16
  61. package/dist/server/index.js +1148 -1930
  62. package/dist/server/modules/order/index.d.ts +4 -54
  63. package/dist/server/modules/order/index.js +695 -1595
  64. package/dist/server/modules/order/types.d.ts +3 -11
  65. package/dist/server/modules/order/types.js +1 -1
  66. package/dist/solution/BaseSales/index.d.ts +20 -109
  67. package/dist/solution/BaseSales/index.js +481 -1797
  68. package/dist/solution/BaseSales/types.d.ts +0 -52
  69. package/dist/solution/BaseSales/types.js +1 -2
  70. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +1 -3
  71. package/dist/solution/BaseSales/utils/cartPromotion.js +31 -90
  72. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +1 -6
  73. package/dist/solution/BookingByStep/index.d.ts +17 -2
  74. package/dist/solution/BookingByStep/index.js +294 -215
  75. package/dist/solution/BookingByStep/types.d.ts +2 -1
  76. package/dist/solution/BookingByStep/types.js +3 -1
  77. package/dist/solution/BookingByStep/utils/capacity.js +17 -1
  78. package/dist/solution/BookingByStep/utils/timeslots.d.ts +3 -1
  79. package/dist/solution/BookingByStep/utils/timeslots.js +19 -12
  80. package/dist/solution/BookingTicket/index.d.ts +4 -8
  81. package/dist/solution/BookingTicket/index.js +51 -134
  82. package/dist/solution/BookingTicket/utils/addProductDecision.js +0 -6
  83. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +0 -8
  84. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +82 -172
  85. package/dist/solution/BookingTicket/utils/scan/handleScan.d.ts +3 -1
  86. package/dist/solution/BookingTicket/utils/scan/handleScan.js +10 -2
  87. package/dist/solution/Sales/index.d.ts +0 -1
  88. package/dist/solution/Sales/index.js +2 -10
  89. package/dist/solution/ScanOrder/index.d.ts +26 -14
  90. package/dist/solution/ScanOrder/index.js +1148 -756
  91. package/dist/solution/ScanOrder/types.d.ts +21 -1
  92. package/dist/solution/ScanOrder/utils.d.ts +8 -0
  93. package/dist/solution/ScanOrder/utils.js +66 -25
  94. package/dist/solution/ShopDiscount/index.d.ts +1 -0
  95. package/dist/solution/ShopDiscount/index.js +125 -87
  96. package/dist/solution/UnifiedBookingSales/index.d.ts +183 -0
  97. package/dist/solution/UnifiedBookingSales/index.js +1871 -0
  98. package/dist/solution/UnifiedBookingSales/types.d.ts +143 -0
  99. package/dist/solution/UnifiedBookingSales/types.js +11 -0
  100. package/dist/solution/VenueBooking/index.d.ts +39 -11
  101. package/dist/solution/VenueBooking/index.js +1176 -860
  102. package/dist/solution/VenueBooking/types.d.ts +3 -0
  103. package/dist/solution/VenueBooking/utils/resource.js +1 -0
  104. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +4 -4
  105. package/dist/solution/VenueBooking/utils/slotMerge.js +10 -5
  106. package/dist/solution/index.d.ts +1 -0
  107. package/dist/solution/index.js +2 -1
  108. package/dist/types/index.d.ts +1 -1
  109. package/lib/core/index.d.ts +0 -2
  110. package/lib/core/index.js +0 -4
  111. package/lib/model/strategy/adapter/promotion/adapter.d.ts +0 -4
  112. package/lib/model/strategy/adapter/promotion/adapter.js +0 -20
  113. package/lib/model/strategy/adapter/promotion/evaluator.d.ts +0 -17
  114. package/lib/model/strategy/adapter/promotion/evaluator.js +0 -235
  115. package/lib/model/strategy/adapter/promotion/examples.d.ts +0 -86
  116. package/lib/model/strategy/adapter/promotion/examples.js +0 -91
  117. package/lib/model/strategy/adapter/promotion/index.d.ts +1 -1
  118. package/lib/model/strategy/adapter/promotion/index.js +0 -2
  119. package/lib/model/strategy/adapter/promotion/type.d.ts +2 -90
  120. package/lib/model/strategy/adapter/promotion/type.js +0 -2
  121. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +1 -2
  122. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +1 -2
  123. package/lib/modules/Discount/index.d.ts +1 -0
  124. package/lib/modules/Discount/index.js +9 -0
  125. package/lib/modules/Discount/types.d.ts +1 -0
  126. package/lib/modules/Holder/index.d.ts +48 -0
  127. package/lib/modules/Holder/index.js +402 -0
  128. package/lib/modules/Holder/types.d.ts +123 -0
  129. package/lib/modules/Holder/types.js +17 -0
  130. package/lib/modules/Holder/utils.d.ts +13 -0
  131. package/lib/modules/Holder/utils.js +71 -0
  132. package/lib/modules/OpenData/index.d.ts +0 -2
  133. package/lib/modules/OpenData/index.js +1 -6
  134. package/lib/modules/Order/index.d.ts +11 -28
  135. package/lib/modules/Order/index.js +86 -196
  136. package/lib/modules/Order/types.d.ts +10 -33
  137. package/lib/modules/Order/utils/orderCollectionIdentity.js +0 -3
  138. package/lib/modules/Order/utils.d.ts +10 -0
  139. package/lib/modules/Order/utils.js +40 -16
  140. package/lib/modules/Payment/index.d.ts +0 -2
  141. package/lib/modules/Payment/index.js +13 -34
  142. package/lib/modules/Payment/types.d.ts +28 -99
  143. package/lib/modules/Payment/types.js +3 -4
  144. package/lib/modules/Payment/walletpass.d.ts +1 -25
  145. package/lib/modules/Payment/walletpass.js +21 -470
  146. package/lib/modules/Product/types.d.ts +1 -0
  147. package/lib/modules/ProductList/index.js +40 -31
  148. package/lib/modules/Quotation/index.d.ts +1 -1
  149. package/lib/modules/Quotation/index.js +2 -2
  150. package/lib/modules/ResourcePlanner/index.d.ts +24 -0
  151. package/lib/modules/ResourcePlanner/index.js +148 -0
  152. package/lib/modules/ResourcePlanner/planner.d.ts +14 -0
  153. package/lib/modules/ResourcePlanner/planner.js +933 -0
  154. package/lib/modules/ResourcePlanner/types.d.ts +227 -0
  155. package/lib/modules/ResourcePlanner/types.js +17 -0
  156. package/lib/modules/Rules/index.d.ts +0 -1
  157. package/lib/modules/Rules/index.js +40 -47
  158. package/lib/modules/SalesSummary/index.js +6 -7
  159. package/lib/modules/ScanOrderLogger/index.d.ts +2 -0
  160. package/lib/modules/ScanOrderLogger/index.js +13 -1
  161. package/lib/modules/ScanOrderLogger/providers/feishu.js +15 -6
  162. package/lib/modules/ScanOrderLogger/types.d.ts +1 -0
  163. package/lib/modules/Schedule/index.d.ts +3 -1
  164. package/lib/modules/Schedule/index.js +10 -8
  165. package/lib/modules/Summary/utils.js +21 -1
  166. package/lib/modules/index.d.ts +2 -0
  167. package/lib/modules/index.js +5 -1
  168. package/lib/plugins/window.d.ts +1 -0
  169. package/lib/server/index.d.ts +14 -16
  170. package/lib/server/index.js +83 -675
  171. package/lib/server/modules/order/index.d.ts +4 -54
  172. package/lib/server/modules/order/index.js +66 -679
  173. package/lib/server/modules/order/types.d.ts +3 -11
  174. package/lib/solution/BaseSales/index.d.ts +20 -109
  175. package/lib/solution/BaseSales/index.js +70 -881
  176. package/lib/solution/BaseSales/types.d.ts +0 -52
  177. package/lib/solution/BaseSales/types.js +1 -2
  178. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +1 -3
  179. package/lib/solution/BaseSales/utils/cartPromotion.js +12 -63
  180. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +1 -6
  181. package/lib/solution/BookingByStep/index.d.ts +17 -2
  182. package/lib/solution/BookingByStep/index.js +60 -18
  183. package/lib/solution/BookingByStep/types.d.ts +2 -1
  184. package/lib/solution/BookingByStep/types.js +5 -0
  185. package/lib/solution/BookingByStep/utils/capacity.js +20 -1
  186. package/lib/solution/BookingByStep/utils/timeslots.d.ts +3 -1
  187. package/lib/solution/BookingByStep/utils/timeslots.js +19 -11
  188. package/lib/solution/BookingTicket/index.d.ts +4 -8
  189. package/lib/solution/BookingTicket/index.js +19 -64
  190. package/lib/solution/BookingTicket/utils/addProductDecision.js +0 -4
  191. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +0 -8
  192. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +4 -36
  193. package/lib/solution/BookingTicket/utils/scan/handleScan.d.ts +3 -1
  194. package/lib/solution/BookingTicket/utils/scan/handleScan.js +2 -2
  195. package/lib/solution/Sales/index.d.ts +0 -1
  196. package/lib/solution/Sales/index.js +3 -5
  197. package/lib/solution/ScanOrder/index.d.ts +26 -14
  198. package/lib/solution/ScanOrder/index.js +449 -190
  199. package/lib/solution/ScanOrder/types.d.ts +21 -1
  200. package/lib/solution/ScanOrder/utils.d.ts +8 -0
  201. package/lib/solution/ScanOrder/utils.js +31 -0
  202. package/lib/solution/ShopDiscount/index.d.ts +1 -0
  203. package/lib/solution/ShopDiscount/index.js +14 -0
  204. package/lib/solution/UnifiedBookingSales/index.d.ts +183 -0
  205. package/lib/solution/UnifiedBookingSales/index.js +1076 -0
  206. package/lib/solution/UnifiedBookingSales/types.d.ts +143 -0
  207. package/lib/solution/UnifiedBookingSales/types.js +33 -0
  208. package/lib/solution/VenueBooking/index.d.ts +39 -11
  209. package/lib/solution/VenueBooking/index.js +328 -123
  210. package/lib/solution/VenueBooking/types.d.ts +3 -0
  211. package/lib/solution/VenueBooking/utils/resource.js +1 -0
  212. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +4 -4
  213. package/lib/solution/VenueBooking/utils/slotMerge.js +6 -4
  214. package/lib/solution/index.d.ts +1 -0
  215. package/lib/solution/index.js +3 -1
  216. package/lib/types/index.d.ts +1 -1
  217. package/package.json +1 -1
  218. package/dist/modules/Order/payment-utils.d.ts +0 -26
  219. package/dist/modules/Order/payment-utils.js +0 -225
  220. package/dist/solution/BookingTicket/utils/weighingProductSku.d.ts +0 -5
  221. package/dist/solution/BookingTicket/utils/weighingProductSku.js +0 -45
  222. package/dist/utils/payment-number.d.ts +0 -9
  223. package/dist/utils/payment-number.js +0 -69
  224. package/lib/modules/Order/payment-utils.d.ts +0 -26
  225. package/lib/modules/Order/payment-utils.js +0 -224
  226. package/lib/solution/BookingTicket/utils/weighingProductSku.d.ts +0 -5
  227. package/lib/solution/BookingTicket/utils/weighingProductSku.js +0 -63
  228. package/lib/utils/payment-number.d.ts +0 -9
  229. package/lib/utils/payment-number.js +0 -64
@@ -34,8 +34,6 @@ __export(server_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(server_exports);
36
36
  var import_dayjs = __toESM(require("dayjs"));
37
- var import_decimal = __toESM(require("decimal.js"));
38
- var import_lodash_es = require("lodash-es");
39
37
  var import_products = require("./modules/products");
40
38
  var import_menu = require("./modules/menu");
41
39
  var import_quotation = require("./modules/quotation");
@@ -52,8 +50,6 @@ var import_types3 = require("./modules/order/types");
52
50
  var import_filterOrders = require("./modules/order/utils/filterOrders");
53
51
  var import_filterBookings = require("./modules/order/utils/filterBookings");
54
52
  var import_small_ticket = require("./utils/small-ticket");
55
- var import_BaseSales = require("../solution/BaseSales");
56
- var import_payment_utils = require("../modules/Order/payment-utils");
57
53
  __reExport(server_exports, require("./modules"), module.exports);
58
54
  var PRODUCT_TITLE_SNAPSHOT_KEYS = [
59
55
  "en",
@@ -82,6 +78,10 @@ var Server = class {
82
78
  this.productQuerySubscribers = /* @__PURE__ */ new Map();
83
79
  /** subscriberId → 智能定价变价时间点定时器句柄(与 subscriber 分离存储,便于 clear) */
84
80
  this.productQueryScheduleTimers = /* @__PURE__ */ new Map();
81
+ /** 餐牌筛选为空时才触发的菜单/日程缓存自愈,避免每次商品查询都请求远端。 */
82
+ this.menuScheduleRefreshInFlight = null;
83
+ this.lastMenuScheduleRefreshAt = 0;
84
+ this.MENU_SCHEDULE_REFRESH_COOLDOWN_MS = 30 * 1e3;
85
85
  // ---- 订单 / 预约列表查询订阅者 ----
86
86
  this.orderQuerySubscribers = /* @__PURE__ */ new Map();
87
87
  this.bookingQuerySubscribers = /* @__PURE__ */ new Map();
@@ -91,7 +91,6 @@ var Server = class {
91
91
  this.BOOKING_REMOTE_CACHE_MAX_ENTRIES = 80;
92
92
  this.salesSearchSubscribers = /* @__PURE__ */ new Map();
93
93
  this.deviceTaskActionsRegistered = false;
94
- this.localPaymentUpdateQueues = /* @__PURE__ */ new Map();
95
94
  this.floorPlanQuerySubscribers = /* @__PURE__ */ new Map();
96
95
  // 模块注册表 - 定义所有可用的模块配置
97
96
  this.moduleRegistry = {
@@ -215,7 +214,11 @@ var Server = class {
215
214
  */
216
215
  this.handleProductQuery = async ({ url, method, data, config }) => {
217
216
  console.log("[Server] handleProductQuery:", url, method, data, config);
218
- const { menu_list_ids, schedule_datetime, schedule_date, customer_id, ids, extension_type, strategy_context } = data;
217
+ const { menu_list_ids, customer_id, ids, extension_type, strategy_context } = data;
218
+ const { schedule_date, schedule_datetime } = this.resolveProductQueryScheduleContext({
219
+ schedule_date: data.schedule_date,
220
+ schedule_datetime: data.schedule_datetime
221
+ });
219
222
  const { callback, subscriberId } = config || {};
220
223
  this.logInfo("handleProductQuery: 开始处理商品查询请求", {
221
224
  menu_list_ids,
@@ -580,128 +583,6 @@ var Server = class {
580
583
  title: "handleOrderSalesCheckout"
581
584
  });
582
585
  };
583
- this.handleOrderSalesDraft = async ({ data }) => {
584
- return this.handleOrderDraftSubmit({
585
- data,
586
- title: "handleOrderSalesDraft"
587
- });
588
- };
589
- this.handleGetLocalPayment = async ({ data }) => {
590
- const saleId = data == null ? void 0 : data.sale_id;
591
- const paymentNumber = data == null ? void 0 : data.payment_number;
592
- const operationId = this.createLocalPaymentOperationId("get");
593
- const requestContext = {
594
- operation_id: operationId,
595
- sale_id: saleId ?? null,
596
- payment_number: paymentNumber ?? null
597
- };
598
- this.logInfo("handleGetLocalPayment: 请求进入", requestContext);
599
- if (saleId === void 0 || saleId === null || saleId === "" || paymentNumber === void 0 || paymentNumber === null || paymentNumber === "") {
600
- this.logWarning("handleGetLocalPayment: 参数校验失败", {
601
- ...requestContext,
602
- missing_fields: [
603
- ...saleId === void 0 || saleId === null || saleId === "" ? ["sale_id"] : [],
604
- ...paymentNumber === void 0 || paymentNumber === null || paymentNumber === "" ? ["payment_number"] : []
605
- ]
606
- });
607
- return {
608
- code: 400,
609
- status: false,
610
- message: "sale_id 和 payment_number 必填",
611
- data: null
612
- };
613
- }
614
- if (!this.order) {
615
- this.logError("handleGetLocalPayment: Order 模块未注册", requestContext);
616
- return { code: 500, status: false, message: "Order 模块未注册", data: null };
617
- }
618
- const startedAt = Date.now();
619
- try {
620
- this.logInfo("handleGetLocalPayment: 开始查询本地支付项", requestContext);
621
- const found = await this.order.getLocalPayment({
622
- saleId,
623
- paymentNumber,
624
- operationId
625
- });
626
- if (!found) {
627
- this.logWarning("handleGetLocalPayment: 本地支付项不存在", {
628
- ...requestContext,
629
- duration_ms: Date.now() - startedAt
630
- });
631
- return { code: 404, status: false, message: "本地支付项不存在", data: null };
632
- }
633
- this.logInfo("handleGetLocalPayment: 查询命中", {
634
- ...requestContext,
635
- duration_ms: Date.now() - startedAt,
636
- matched_by: found.matchedBy,
637
- payment_index: found.paymentIndex,
638
- ...this.buildLocalPaymentOrderLogContext(found.order),
639
- payment: found.payment
640
- });
641
- return { code: 200, status: true, message: "", data: found.payment };
642
- } catch (error) {
643
- this.logError("handleGetLocalPayment: 查询异常", {
644
- ...requestContext,
645
- duration_ms: Date.now() - startedAt,
646
- error: error instanceof Error ? error.message : String(error),
647
- error_detail: this.normalizeUnknownError(error)
648
- });
649
- throw error;
650
- }
651
- };
652
- this.handleUpdateLocalPayment = async ({ data }) => {
653
- const saleId = data == null ? void 0 : data.sale_id;
654
- const paymentNumber = data == null ? void 0 : data.payment_number;
655
- const number = data == null ? void 0 : data.number;
656
- const status = data == null ? void 0 : data.status;
657
- const serviceCharge = data == null ? void 0 : data.service_charge;
658
- const cardReaderSurcharge = data == null ? void 0 : data.card_reader_surcharge;
659
- const hasSurchargeInput = serviceCharge !== void 0 || cardReaderSurcharge !== void 0;
660
- const invalidSurchargeFields = this.getInvalidLocalPaymentSurchargeFields(
661
- serviceCharge,
662
- cardReaderSurcharge
663
- );
664
- const operationId = this.createLocalPaymentOperationId("update");
665
- const requestContext = {
666
- operation_id: operationId,
667
- sale_id: saleId ?? null,
668
- payment_number: paymentNumber ?? null,
669
- transaction_number: number ?? null,
670
- requested_status: status ?? null,
671
- service_charge: serviceCharge ?? null,
672
- card_reader_surcharge: cardReaderSurcharge ?? null
673
- };
674
- this.logInfo("handleUpdateLocalPayment: 请求进入", requestContext);
675
- if (saleId === void 0 || saleId === null || saleId === "" || paymentNumber === void 0 || paymentNumber === null || paymentNumber === "" || number === void 0 || number === null || number === "" || status !== "success" && status !== "fail" || invalidSurchargeFields.length > 0) {
676
- this.logWarning("handleUpdateLocalPayment: 参数校验失败", {
677
- ...requestContext,
678
- missing_or_invalid_fields: [
679
- ...saleId === void 0 || saleId === null || saleId === "" ? ["sale_id"] : [],
680
- ...paymentNumber === void 0 || paymentNumber === null || paymentNumber === "" ? ["payment_number"] : [],
681
- ...number === void 0 || number === null || number === "" ? ["number"] : [],
682
- ...status !== "success" && status !== "fail" ? ["status"] : [],
683
- ...invalidSurchargeFields
684
- ]
685
- });
686
- return {
687
- code: 400,
688
- status: false,
689
- message: invalidSurchargeFields.length > 0 ? `手续费参数非法: ${invalidSurchargeFields.join(", ")}` : "sale_id、payment_number、number 必填,status 仅支持 success/fail",
690
- data: null
691
- };
692
- }
693
- const queueKey = `${String(saleId)}:${String(paymentNumber)}`;
694
- return this.runLocalPaymentUpdateInQueue(queueKey, () => this.processLocalPaymentUpdate({
695
- operationId,
696
- saleId,
697
- paymentNumber,
698
- number: String(number),
699
- status,
700
- serviceCharge,
701
- cardReaderSurcharge,
702
- hasSurchargeInput
703
- }), requestContext);
704
- };
705
586
  this.handleOrderCheckout = async ({ data }) => {
706
587
  return this.handleOrderCheckoutSubmit({
707
588
  backendPath: "/order/checkout",
@@ -1483,7 +1364,7 @@ var Server = class {
1483
1364
  const { backendPath, title } = params;
1484
1365
  const normalizedData = await this.normalizeCheckoutSubmitData(params.data, title);
1485
1366
  const checkoutData = await this.ensureCheckoutOrderNumbers(normalizedData, title);
1486
- const remoteCheckoutData = this.buildRemoteCheckoutData(checkoutData, title);
1367
+ const remoteCheckoutData = this.omitCheckoutSyncMode(checkoutData);
1487
1368
  if (!((_b = (_a = this.app) == null ? void 0 : _a.request) == null ? void 0 : _b.post)) {
1488
1369
  throw new Error("app.request 不可用");
1489
1370
  }
@@ -1499,20 +1380,20 @@ var Server = class {
1499
1380
  errorResponse: response,
1500
1381
  response,
1501
1382
  normalizedResponse: this.normalizeCheckoutResponse(response),
1502
- checkoutData
1383
+ checkoutData: remoteCheckoutData
1503
1384
  };
1504
1385
  }
1505
1386
  const fresh = this.extractOrderDataFromCheckoutResponse(response);
1506
1387
  const externalSaleNumber = this.getCheckoutExternalSaleNumber(
1507
- checkoutData,
1388
+ remoteCheckoutData,
1508
1389
  {
1509
1390
  external_sale_number: params.externalSaleNumber,
1510
- data: checkoutData
1391
+ data: remoteCheckoutData
1511
1392
  }
1512
1393
  );
1513
1394
  const syncedOrder = await this.persistSyncedCheckoutOrder({
1514
1395
  backendPath,
1515
- checkoutData,
1396
+ checkoutData: remoteCheckoutData,
1516
1397
  externalSaleNumber,
1517
1398
  fresh,
1518
1399
  title,
@@ -1523,11 +1404,11 @@ var Server = class {
1523
1404
  checkoutResponseOrder: fresh
1524
1405
  }) : void 0;
1525
1406
  if (printableSyncedOrder && this.shouldPrintSyncedOrder({
1526
- checkoutData,
1407
+ checkoutData: remoteCheckoutData,
1527
1408
  syncedOrder: printableSyncedOrder
1528
1409
  })) {
1529
1410
  await this.dispatchPrintOtherReceiptTask({
1530
- checkoutData,
1411
+ checkoutData: remoteCheckoutData,
1531
1412
  syncedOrder: printableSyncedOrder,
1532
1413
  response,
1533
1414
  deviceId: params.deviceId
@@ -1537,7 +1418,7 @@ var Server = class {
1537
1418
  rejected: false,
1538
1419
  response,
1539
1420
  normalizedResponse: this.normalizeCheckoutResponse(response),
1540
- checkoutData,
1421
+ checkoutData: remoteCheckoutData,
1541
1422
  syncedOrder,
1542
1423
  fresh
1543
1424
  };
@@ -1550,54 +1431,6 @@ var Server = class {
1550
1431
  delete next.syncMode;
1551
1432
  return next;
1552
1433
  }
1553
- buildRemoteCheckoutData(data, title) {
1554
- const next = (0, import_lodash_es.cloneDeep)(this.omitCheckoutSyncMode(data));
1555
- if (!next || typeof next !== "object")
1556
- return next;
1557
- const record = next;
1558
- if (!Array.isArray(record.payments))
1559
- return next;
1560
- const originalPayments = record.payments;
1561
- const filteredPayments = originalPayments.filter((payment) => !(0, import_payment_utils.isPendingOrderPayment)(payment));
1562
- const removedPayments = originalPayments.filter((payment) => (0, import_payment_utils.isPendingOrderPayment)(payment));
1563
- record.payments = filteredPayments;
1564
- this.logInfo(`${title}: checkout 云端支付项已过滤`, {
1565
- external_sale_number: record.external_sale_number,
1566
- original_payment_count: originalPayments.length,
1567
- remote_payment_count: filteredPayments.length,
1568
- filtered_pending_count: removedPayments.length,
1569
- filtered_payment_identities: removedPayments.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1570
- });
1571
- return next;
1572
- }
1573
- mergeCheckoutSyncPayments(checkoutData, fresh, title) {
1574
- const localPayments = Array.isArray(checkoutData == null ? void 0 : checkoutData.payments) ? checkoutData.payments : [];
1575
- const freshRecord = fresh;
1576
- if (!Array.isArray(freshRecord.payments)) {
1577
- return localPayments.length > 0 ? { ...freshRecord, payments: (0, import_lodash_es.cloneDeep)(localPayments) } : freshRecord;
1578
- }
1579
- const freshPayments = freshRecord.payments;
1580
- const mergedPayments = (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(
1581
- localPayments,
1582
- freshPayments,
1583
- { preserveUnmatchedExistingWhen: import_payment_utils.isIdentifiedPendingOrderPayment }
1584
- );
1585
- const remoteIdentityKeys = new Set(
1586
- freshPayments.flatMap((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1587
- );
1588
- const preservedPending = localPayments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment) && !(0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => remoteIdentityKeys.has(key)));
1589
- if (preservedPending.length > 0) {
1590
- this.logInfo(`${title}: checkout 响应合并保留本地 pending 支付项`, {
1591
- external_sale_number: checkoutData == null ? void 0 : checkoutData.external_sale_number,
1592
- preserved_pending_count: preservedPending.length,
1593
- preserved_payment_identities: preservedPending.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1594
- });
1595
- }
1596
- return {
1597
- ...freshRecord,
1598
- payments: mergedPayments
1599
- };
1600
- }
1601
1434
  async persistSyncedCheckoutOrder(params) {
1602
1435
  const {
1603
1436
  backendPath,
@@ -1612,17 +1445,15 @@ var Server = class {
1612
1445
  if (this.order && fresh && (shouldMergeRemoteOrder || persistCheckoutDataWithResponse)) {
1613
1446
  syncedOrder = persistCheckoutDataWithResponse ? {
1614
1447
  ...checkoutData,
1615
- ...this.mergeCheckoutSyncPayments(checkoutData, fresh, title),
1448
+ ...fresh,
1616
1449
  external_sale_number: fresh.external_sale_number ?? externalSaleNumber,
1617
- need_sync: 0,
1618
- is_draft_order: 0
1450
+ need_sync: 0
1619
1451
  } : {
1620
- ...this.mergeCheckoutSyncPayments(checkoutData, fresh, title),
1452
+ ...fresh,
1621
1453
  external_sale_number: fresh.external_sale_number ?? externalSaleNumber,
1622
- need_sync: 0,
1623
- is_draft_order: 0
1454
+ need_sync: 0
1624
1455
  };
1625
- await this.order.upsertOrdersFromRemote([syncedOrder], "checkoutSync");
1456
+ await this.order.upsertOrdersFromRemote([syncedOrder]);
1626
1457
  this.logInfo(`${title}: sync_sales 完整订单已同步到本地`, {
1627
1458
  order_id: fresh.order_id,
1628
1459
  external_sale_number: syncedOrder.external_sale_number,
@@ -1640,8 +1471,7 @@ var Server = class {
1640
1471
  ...checkoutData,
1641
1472
  ...patch,
1642
1473
  external_sale_number: externalSaleNumber,
1643
- need_sync: 0,
1644
- is_draft_order: 0
1474
+ need_sync: 0
1645
1475
  };
1646
1476
  this.logInfo(`${title}: sync_sales 已按 external_sale_number 标记本地订单`, {
1647
1477
  order_id: (syncedOrder == null ? void 0 : syncedOrder.order_id) ?? null,
@@ -2021,11 +1851,6 @@ var Server = class {
2021
1851
  path: "/shop/order/sales/checkout",
2022
1852
  handler: this.handleOrderSalesCheckout.bind(this)
2023
1853
  },
2024
- {
2025
- method: "post",
2026
- path: "/shop/order/sales/draft",
2027
- handler: this.handleOrderSalesDraft.bind(this)
2028
- },
2029
1854
  {
2030
1855
  method: "post",
2031
1856
  path: "/order/checkout",
@@ -2036,16 +1861,6 @@ var Server = class {
2036
1861
  path: "/shop/local/print-order",
2037
1862
  handler: this.handleLocalPrintOrder.bind(this)
2038
1863
  },
2039
- {
2040
- method: "post",
2041
- path: "/shop/local/getLocalPayment",
2042
- handler: this.handleGetLocalPayment.bind(this)
2043
- },
2044
- {
2045
- method: "post",
2046
- path: "/shop/local/updateLocalPayment",
2047
- handler: this.handleUpdateLocalPayment.bind(this)
2048
- },
2049
1864
  {
2050
1865
  method: "post",
2051
1866
  path: "/shop/machinecode/batch",
@@ -2277,6 +2092,43 @@ var Server = class {
2277
2092
  this.scheduleSubscriberTimePointReloads(subscriberId, timePoints);
2278
2093
  }
2279
2094
  }
2095
+ /**
2096
+ * ProductList callers such as standalone retail pages do not always have a selected schedule.
2097
+ * In that case query against the current local time so menu availability can still be evaluated.
2098
+ */
2099
+ resolveProductQueryScheduleContext(params) {
2100
+ const now = (0, import_dayjs.default)();
2101
+ const schedule_datetime = typeof params.schedule_datetime === "string" && params.schedule_datetime.trim() ? params.schedule_datetime : now.format("YYYY-MM-DD HH:mm:ss");
2102
+ const schedule_date = typeof params.schedule_date === "string" && params.schedule_date.trim() ? params.schedule_date : (0, import_dayjs.default)(schedule_datetime).isValid() ? (0, import_dayjs.default)(schedule_datetime).format("YYYY-MM-DD") : now.format("YYYY-MM-DD");
2103
+ return { schedule_date, schedule_datetime };
2104
+ }
2105
+ /**
2106
+ * OpenData 的关联餐牌可能已更新,而 server_menu/server_schedule 仍命中本地持久化缓存。
2107
+ * 仅在当前筛选没有任何生效餐牌时刷新一次,并由调用方重新计算筛选结果。
2108
+ */
2109
+ async refreshMenuScheduleCacheAfterEmptyResult() {
2110
+ if (!this.menu || !this.schedule)
2111
+ return false;
2112
+ const now = Date.now();
2113
+ if (now - this.lastMenuScheduleRefreshAt < this.MENU_SCHEDULE_REFRESH_COOLDOWN_MS) {
2114
+ return false;
2115
+ }
2116
+ if (!this.menuScheduleRefreshInFlight) {
2117
+ this.lastMenuScheduleRefreshAt = now;
2118
+ this.menuScheduleRefreshInFlight = Promise.all([
2119
+ this.menu.loadMenuList(),
2120
+ this.schedule.loadAllSchedule()
2121
+ ]).then(() => void 0).catch((error) => {
2122
+ this.logWarning("刷新菜单/日程缓存失败,继续使用现有缓存", {
2123
+ error: error instanceof Error ? error.message : String(error)
2124
+ });
2125
+ }).finally(() => {
2126
+ this.menuScheduleRefreshInFlight = null;
2127
+ });
2128
+ }
2129
+ await this.menuScheduleRefreshInFlight;
2130
+ return true;
2131
+ }
2280
2132
  /**
2281
2133
  * 执行 sales 搜索并登记可见订单号。
2282
2134
  * 搜索参数完全透传后端,OS 不做过滤、筛选、排序。
@@ -2887,405 +2739,6 @@ var Server = class {
2887
2739
  };
2888
2740
  }
2889
2741
  }
2890
- createLocalPaymentOperationId(action) {
2891
- return `local_payment_${action}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
2892
- }
2893
- buildLocalPaymentOrderLogContext(order) {
2894
- if (!order)
2895
- return {};
2896
- return {
2897
- order_id: order.order_id ?? null,
2898
- external_sale_number: order.external_sale_number ?? null,
2899
- order_number: order.order_number ?? null,
2900
- shop_order_number: order.shop_order_number ?? null,
2901
- shop_full_order_number: order.shop_full_order_number ?? null,
2902
- order_status: order.status ?? null,
2903
- payment_status: order.payment_status ?? null,
2904
- is_draft_order: Number(order.is_draft_order || 0),
2905
- need_sync: Number(order.need_sync || 0),
2906
- platform: order.platform ?? null,
2907
- business_code: order.business_code ?? null,
2908
- order_sales_channel: order.order_sales_channel ?? null,
2909
- sales_channel: order.sales_channel ?? null,
2910
- order_type: order.type ?? null,
2911
- payments_count: Array.isArray(order.payments) ? order.payments.length : 0
2912
- };
2913
- }
2914
- isValidLocalPaymentDecimal(value) {
2915
- if (typeof value !== "string" && typeof value !== "number")
2916
- return false;
2917
- if (typeof value === "string" && value.trim() === "")
2918
- return false;
2919
- try {
2920
- return new import_decimal.default(value).isFinite();
2921
- } catch {
2922
- return false;
2923
- }
2924
- }
2925
- getInvalidLocalPaymentSurchargeFields(serviceCharge, cardReaderSurcharge) {
2926
- const invalidFields = [];
2927
- if (serviceCharge !== void 0) {
2928
- if (serviceCharge === null || typeof serviceCharge !== "object" || Array.isArray(serviceCharge)) {
2929
- invalidFields.push("service_charge");
2930
- } else {
2931
- const input = serviceCharge;
2932
- if (input.fixed !== void 0 && !this.isValidLocalPaymentDecimal(input.fixed)) {
2933
- invalidFields.push("service_charge.fixed");
2934
- }
2935
- if (input.percentage !== void 0 && !this.isValidLocalPaymentDecimal(input.percentage)) {
2936
- invalidFields.push("service_charge.percentage");
2937
- }
2938
- }
2939
- }
2940
- if (cardReaderSurcharge !== void 0 && !this.isValidLocalPaymentDecimal(cardReaderSurcharge)) {
2941
- invalidFields.push("card_reader_surcharge");
2942
- }
2943
- return invalidFields;
2944
- }
2945
- buildLocalPaymentSurchargeUpdate(params) {
2946
- var _a, _b, _c;
2947
- const amount = new import_decimal.default(((_a = params.serviceCharge) == null ? void 0 : _a.fixed) || 0).plus(params.cardReaderSurcharge || 0).toFixed(2);
2948
- const serviceFee = new import_decimal.default(params.paymentAmount || 0).times(((_b = params.serviceCharge) == null ? void 0 : _b.percentage) || 0).plus(amount).toDecimalPlaces(2).toFixed(2);
2949
- return {
2950
- service_charge: {
2951
- amount,
2952
- ...((_c = params.serviceCharge) == null ? void 0 : _c.percentage) !== void 0 ? { percentage: params.serviceCharge.percentage } : {}
2953
- },
2954
- service_fee: serviceFee
2955
- };
2956
- }
2957
- async runLocalPaymentUpdateInQueue(key, task, context) {
2958
- var _a;
2959
- const queuedAt = Date.now();
2960
- const hasPreviousTask = this.localPaymentUpdateQueues.has(key);
2961
- const previous = this.localPaymentUpdateQueues.get(key) || Promise.resolve();
2962
- this.logInfo("handleUpdateLocalPayment: 串行队列入队", {
2963
- ...context,
2964
- queue_key: key,
2965
- waiting_for_previous: hasPreviousTask,
2966
- active_queue_count: this.localPaymentUpdateQueues.size
2967
- });
2968
- const current = previous.catch(() => void 0).then(async () => {
2969
- this.logInfo("handleUpdateLocalPayment: 串行队列开始执行", {
2970
- ...context,
2971
- queue_key: key,
2972
- queue_wait_ms: Date.now() - queuedAt
2973
- });
2974
- return task();
2975
- });
2976
- const tail = current.then(() => void 0, () => void 0);
2977
- this.localPaymentUpdateQueues.set(key, tail);
2978
- try {
2979
- const result = await current;
2980
- this.logInfo("handleUpdateLocalPayment: 串行队列执行完成", {
2981
- ...context,
2982
- queue_key: key,
2983
- total_duration_ms: Date.now() - queuedAt,
2984
- result_code: result == null ? void 0 : result.code,
2985
- result_status: result == null ? void 0 : result.status,
2986
- payment: (_a = result == null ? void 0 : result.data) == null ? void 0 : _a.payment
2987
- });
2988
- return result;
2989
- } catch (error) {
2990
- this.logError("handleUpdateLocalPayment: 串行队列执行失败", {
2991
- ...context,
2992
- queue_key: key,
2993
- total_duration_ms: Date.now() - queuedAt,
2994
- error: error instanceof Error ? error.message : String(error),
2995
- error_detail: this.normalizeUnknownError(error)
2996
- });
2997
- throw error;
2998
- } finally {
2999
- let released = false;
3000
- if (this.localPaymentUpdateQueues.get(key) === tail) {
3001
- this.localPaymentUpdateQueues.delete(key);
3002
- released = true;
3003
- }
3004
- this.logInfo("handleUpdateLocalPayment: 串行队列释放", {
3005
- ...context,
3006
- queue_key: key,
3007
- released,
3008
- active_queue_count: this.localPaymentUpdateQueues.size
3009
- });
3010
- }
3011
- }
3012
- async processLocalPaymentUpdate(params) {
3013
- var _a, _b, _c;
3014
- const requestContext = {
3015
- operation_id: params.operationId,
3016
- sale_id: params.saleId,
3017
- payment_number: params.paymentNumber,
3018
- transaction_number: params.number,
3019
- requested_status: params.status,
3020
- service_charge: params.serviceCharge ?? null,
3021
- card_reader_surcharge: params.cardReaderSurcharge ?? null
3022
- };
3023
- this.logInfo("processLocalPaymentUpdate: 开始处理", requestContext);
3024
- if (!this.order) {
3025
- this.logError("processLocalPaymentUpdate: Order 模块未注册", requestContext);
3026
- return { code: 500, status: false, message: "Order 模块未注册", data: null };
3027
- }
3028
- this.logInfo("processLocalPaymentUpdate: 开始查询本地支付项", requestContext);
3029
- const found = await this.order.getLocalPayment({
3030
- saleId: params.saleId,
3031
- paymentNumber: params.paymentNumber,
3032
- operationId: params.operationId
3033
- });
3034
- if (!found) {
3035
- this.logWarning("processLocalPaymentUpdate: 本地支付项不存在", requestContext);
3036
- return { code: 404, status: false, message: "本地支付项不存在", data: null };
3037
- }
3038
- const surchargeUpdate = params.status === "success" && params.hasSurchargeInput ? this.buildLocalPaymentSurchargeUpdate({
3039
- paymentAmount: (_a = found.payment) == null ? void 0 : _a.amount,
3040
- serviceCharge: params.serviceCharge,
3041
- cardReaderSurcharge: params.cardReaderSurcharge
3042
- }) : void 0;
3043
- const incomingPaymentUpdate = params.status === "success" ? {
3044
- status: "paid",
3045
- ...surchargeUpdate || {},
3046
- metadata: {
3047
- unique_payment_number: params.number,
3048
- transactions: [{ number: params.number, status: "success" }]
3049
- }
3050
- } : {
3051
- metadata: {
3052
- transactions: [{ number: params.number, status: "fail" }]
3053
- }
3054
- };
3055
- const transactions = Array.isArray((_c = (_b = found.payment) == null ? void 0 : _b.metadata) == null ? void 0 : _c.transactions) ? found.payment.metadata.transactions : [];
3056
- const existingTransaction = transactions.find((item) => String((item == null ? void 0 : item.number) || "") === params.number);
3057
- const hasRecordedSuccess = transactions.some((item) => (item == null ? void 0 : item.status) === "success");
3058
- const orderIsDraft = Number(found.order.is_draft_order || 0) === 1;
3059
- const foundContext = {
3060
- ...requestContext,
3061
- matched_by: found.matchedBy,
3062
- payment_index: found.paymentIndex,
3063
- ...this.buildLocalPaymentOrderLogContext(found.order),
3064
- payment: found.payment,
3065
- incoming_payment_update: incomingPaymentUpdate,
3066
- existing_transaction: existingTransaction || null,
3067
- has_recorded_success: hasRecordedSuccess
3068
- };
3069
- this.logInfo("processLocalPaymentUpdate: 查询命中", foundContext);
3070
- if (params.status === "fail" && (found.payment.status === "paid" || hasRecordedSuccess)) {
3071
- this.logInfo("processLocalPaymentUpdate: 幂等返回", {
3072
- ...foundContext,
3073
- idempotent_reason: "ignore_failure_after_success"
3074
- });
3075
- return {
3076
- code: 200,
3077
- status: true,
3078
- message: "",
3079
- data: { payment: found.payment, order: found.order, idempotent: true }
3080
- };
3081
- }
3082
- const alreadyRecordedFailure = params.status === "fail" && (existingTransaction == null ? void 0 : existingTransaction.status) === "fail";
3083
- if (alreadyRecordedFailure) {
3084
- this.logInfo("processLocalPaymentUpdate: 幂等返回", {
3085
- ...foundContext,
3086
- idempotent_reason: "failure_already_recorded"
3087
- });
3088
- return {
3089
- code: 200,
3090
- status: true,
3091
- message: "",
3092
- data: { payment: found.payment, order: found.order, idempotent: true }
3093
- };
3094
- }
3095
- if (params.status === "success" && (existingTransaction == null ? void 0 : existingTransaction.status) === "success" && found.payment.status === "paid" && !orderIsDraft) {
3096
- this.logInfo("processLocalPaymentUpdate: 幂等返回", {
3097
- ...foundContext,
3098
- idempotent_reason: "success_already_committed"
3099
- });
3100
- return {
3101
- code: 200,
3102
- status: true,
3103
- message: "",
3104
- data: { payment: found.payment, order: found.order, idempotent: true }
3105
- };
3106
- }
3107
- if (params.status === "success") {
3108
- this.logInfo("processLocalPaymentUpdate: 进入 success 恢复分支", {
3109
- ...foundContext,
3110
- force_submit_if_paid: found.payment.status === "paid" && orderIsDraft
3111
- });
3112
- return this.processSuccessfulLocalPayment({
3113
- ...params,
3114
- order: found.order,
3115
- payment: found.payment,
3116
- matchBy: found.matchedBy === "payment_number" ? "payment_number" : "compat",
3117
- forceSubmitIfPaid: found.payment.status === "paid" && orderIsDraft,
3118
- paymentUpdate: incomingPaymentUpdate
3119
- });
3120
- }
3121
- this.logInfo("processLocalPaymentUpdate: 进入 fail 本地更新分支", {
3122
- ...foundContext,
3123
- incoming_payment_update: incomingPaymentUpdate
3124
- });
3125
- let updated;
3126
- try {
3127
- updated = await this.order.updateLocalPayment({
3128
- saleId: params.saleId,
3129
- paymentNumber: params.paymentNumber,
3130
- operationId: params.operationId,
3131
- updates: incomingPaymentUpdate
3132
- });
3133
- } catch (error) {
3134
- this.logError("processLocalPaymentUpdate: fail 本地更新失败", {
3135
- ...foundContext,
3136
- incoming_payment_update: incomingPaymentUpdate,
3137
- error: error instanceof Error ? error.message : String(error),
3138
- error_detail: this.normalizeUnknownError(error)
3139
- });
3140
- throw error;
3141
- }
3142
- if (!updated) {
3143
- this.logWarning("processLocalPaymentUpdate: fail 本地更新未命中", foundContext);
3144
- return { code: 404, status: false, message: "本地支付项不存在", data: null };
3145
- }
3146
- this.logInfo("processLocalPaymentUpdate: fail 本地更新完成", {
3147
- ...requestContext,
3148
- ...this.buildLocalPaymentOrderLogContext(updated.order),
3149
- previous_payment: updated.previousPayment,
3150
- payment: updated.payment
3151
- });
3152
- return {
3153
- code: 200,
3154
- status: true,
3155
- message: "",
3156
- data: {
3157
- local_only: true,
3158
- payment: updated.payment,
3159
- order: updated.order
3160
- }
3161
- };
3162
- }
3163
- async processSuccessfulLocalPayment(params) {
3164
- var _a, _b, _c, _d, _e;
3165
- const moduleName = `local_payment_recovery_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
3166
- const baseSales = new import_BaseSales.BaseSalesImpl(moduleName);
3167
- const startedAt = Date.now();
3168
- const recoveryContext = {
3169
- operation_id: params.operationId,
3170
- sale_id: params.saleId,
3171
- payment_number: params.paymentNumber,
3172
- transaction_number: params.number,
3173
- requested_status: "success",
3174
- match_by: params.matchBy,
3175
- force_submit_if_paid: params.forceSubmitIfPaid,
3176
- incoming_payment_update: params.paymentUpdate,
3177
- base_sales_module_name: moduleName,
3178
- ...this.buildLocalPaymentOrderLogContext(params.order),
3179
- payment: params.payment
3180
- };
3181
- this.logInfo("processSuccessfulLocalPayment: 创建临时 BaseSales", recoveryContext);
3182
- try {
3183
- const order = this.sanitizeLocalRecoveryOrder(params.order);
3184
- this.logInfo("processSuccessfulLocalPayment: 本地订单清洗完成", {
3185
- ...recoveryContext,
3186
- sanitized_order_id: order.order_id ?? null,
3187
- removed_synthetic_order_id: params.order.order_id != null && order.order_id == null
3188
- });
3189
- await baseSales.initialize(this.core, {
3190
- otherParams: {
3191
- platform: order.platform,
3192
- businessCode: order.business_code,
3193
- business_code: order.business_code,
3194
- channel: order.order_sales_channel || order.sales_channel,
3195
- type: order.type,
3196
- enableTempOrderPersist: false
3197
- }
3198
- });
3199
- this.logInfo("processSuccessfulLocalPayment: BaseSales 初始化完成", recoveryContext);
3200
- await baseSales.replaceTempOrder(order);
3201
- this.logInfo("processSuccessfulLocalPayment: 本地订单 tempOrder 恢复完成", recoveryContext);
3202
- this.logInfo("processSuccessfulLocalPayment: 开始更新支付项并提交", {
3203
- ...recoveryContext,
3204
- incoming_payment_update: params.paymentUpdate
3205
- });
3206
- const result = await baseSales.updateOrderPayment(
3207
- params.paymentNumber,
3208
- params.paymentUpdate,
3209
- {
3210
- submitWhenPaid: true,
3211
- matchBy: params.matchBy,
3212
- forceSubmitIfPaid: params.forceSubmitIfPaid,
3213
- applyUpdatesWhenPaid: params.forceSubmitIfPaid,
3214
- smallTicketDataFlag: 1
3215
- }
3216
- );
3217
- this.logInfo("processSuccessfulLocalPayment: 支付恢复完成", {
3218
- ...recoveryContext,
3219
- duration_ms: Date.now() - startedAt,
3220
- payment: result.payment,
3221
- payments_count: ((_a = result.payments) == null ? void 0 : _a.length) || 0,
3222
- summary: result.summary,
3223
- sync_result: result.syncResult ? {
3224
- is_fully_paid: result.syncResult.isFullyPaid,
3225
- is_order_fully_paid: result.syncResult.isOrderFullyPaid,
3226
- is_deposit_fully_paid: result.syncResult.isDepositFullyPaid,
3227
- payment_stage: result.syncResult.paymentStage,
3228
- deposit_amount: result.syncResult.depositAmount,
3229
- order_expected_amount: result.syncResult.orderExpectedAmount,
3230
- submit_result_code: (_b = result.syncResult.submitResult) == null ? void 0 : _b.code,
3231
- submit_result_status: (_c = result.syncResult.submitResult) == null ? void 0 : _c.status
3232
- } : null,
3233
- draft_result: result.draftResult ? {
3234
- code: (_d = result.draftResult) == null ? void 0 : _d.code,
3235
- status: (_e = result.draftResult) == null ? void 0 : _e.status
3236
- } : null,
3237
- draft_error: result.draftError instanceof Error ? result.draftError.message : result.draftError
3238
- });
3239
- return {
3240
- code: 200,
3241
- status: true,
3242
- message: "",
3243
- data: {
3244
- payment: result.payment,
3245
- payments: result.payments,
3246
- summary: result.summary,
3247
- sync_result: result.syncResult
3248
- }
3249
- };
3250
- } catch (error) {
3251
- const message = error instanceof Error ? error.message : String(error);
3252
- this.logError("processSuccessfulLocalPayment: 支付恢复失败", {
3253
- ...recoveryContext,
3254
- duration_ms: Date.now() - startedAt,
3255
- error: message,
3256
- error_detail: this.normalizeUnknownError(error)
3257
- });
3258
- return { code: 500, status: false, message, data: null };
3259
- } finally {
3260
- try {
3261
- await baseSales.destroy();
3262
- this.logInfo("processSuccessfulLocalPayment: 临时 BaseSales 销毁完成", {
3263
- ...recoveryContext,
3264
- duration_ms: Date.now() - startedAt
3265
- });
3266
- } catch (error) {
3267
- this.logError("processSuccessfulLocalPayment: 临时 BaseSales 销毁失败", {
3268
- ...recoveryContext,
3269
- duration_ms: Date.now() - startedAt,
3270
- error: error instanceof Error ? error.message : String(error),
3271
- error_detail: this.normalizeUnknownError(error)
3272
- });
3273
- }
3274
- }
3275
- }
3276
- sanitizeLocalRecoveryOrder(order) {
3277
- const next = {
3278
- ...order,
3279
- country_calling_code: String(order.country_calling_code ?? ""),
3280
- phone: String(order.phone ?? ""),
3281
- email: String(order.email ?? "")
3282
- };
3283
- const externalSaleNumber = next.external_sale_number;
3284
- if (Number(next.is_draft_order || 0) === 1 && next.order_id !== void 0 && externalSaleNumber !== void 0 && String(next.order_id) === String(externalSaleNumber)) {
3285
- delete next.order_id;
3286
- }
3287
- return next;
3288
- }
3289
2742
  getDeviceTaskPlugin() {
3290
2743
  var _a, _b;
3291
2744
  return ((_b = (_a = this.app) == null ? void 0 : _a.getPlugin) == null ? void 0 : _b.call(_a, "deviceTask")) || null;
@@ -3779,10 +3232,22 @@ var Server = class {
3779
3232
  data: (normalized == null ? void 0 : normalized.data) ?? null
3780
3233
  };
3781
3234
  }
3782
- return this.withSyncedOrderIdInCheckoutResponse(
3235
+ const response = this.withSyncedOrderIdInCheckoutResponse(
3783
3236
  syncResult.normalizedResponse,
3784
3237
  syncResult.syncedOrder
3785
3238
  );
3239
+ const syncedOrder = syncResult.syncedOrder;
3240
+ if (syncedOrder && this.shouldBuildSmallTicketData(syncResult.checkoutData) && this.isSalesOrderFullyPaid(syncedOrder)) {
3241
+ await this.dispatchLocalReceiptPrint({
3242
+ checkoutData: syncResult.checkoutData,
3243
+ order: syncedOrder,
3244
+ response: syncResult.normalizedResponse,
3245
+ requireFullyPaid: true,
3246
+ // print_all 的 type=0 是收据打印;不要沿用同步成功后的券/手环打印 type=99。
3247
+ isManualPrint: true
3248
+ });
3249
+ }
3250
+ return response;
3786
3251
  } catch (error) {
3787
3252
  const backendError = this.extractBackendErrorResponse(error);
3788
3253
  if (backendError) {
@@ -3808,59 +3273,6 @@ var Server = class {
3808
3273
  };
3809
3274
  }
3810
3275
  }
3811
- async handleOrderDraftSubmit(params) {
3812
- var _a, _b, _c;
3813
- const { data, title } = params;
3814
- this.logInfo(`${title}: 开始处理`, {
3815
- order_id: data == null ? void 0 : data.order_id,
3816
- external_sale_number: data == null ? void 0 : data.external_sale_number,
3817
- order_number: data == null ? void 0 : data.order_number
3818
- });
3819
- const normalizedData = await this.normalizeCheckoutSubmitData(data, title);
3820
- const createdAt = normalizedData.created_at || normalizedData.create_date || (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
3821
- const draftOrder = {
3822
- ...normalizedData,
3823
- external_sale_number: normalizedData.external_sale_number || `LOCAL_DRAFT_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`,
3824
- created_at: createdAt,
3825
- schedule_date: normalizedData.schedule_date || createdAt,
3826
- need_sync: 0,
3827
- is_draft_order: 1
3828
- };
3829
- if (!this.order || typeof this.order.upsertLocalDraftOrders !== "function") {
3830
- this.logError(`${title}: Order 模块不支持本地草稿写入`);
3831
- return {
3832
- code: 500,
3833
- status: false,
3834
- message: "Order 模块不支持本地草稿写入",
3835
- data: null
3836
- };
3837
- }
3838
- try {
3839
- await this.order.upsertLocalDraftOrders([draftOrder]);
3840
- this.logInfo(`${title}: 草稿订单已写入本地`, {
3841
- order_id: draftOrder.order_id,
3842
- external_sale_number: draftOrder.external_sale_number
3843
- });
3844
- return {
3845
- code: 200,
3846
- status: true,
3847
- message: "",
3848
- data: {
3849
- ...draftOrder,
3850
- amount_gap: (_a = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _a.amount_gap,
3851
- expect_amount: (_b = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _b.expect_amount,
3852
- total_amount: (_c = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _c.total_amount,
3853
- payment_status: draftOrder == null ? void 0 : draftOrder.payment_status
3854
- }
3855
- };
3856
- } catch (error) {
3857
- const errorMessage = error instanceof Error ? error.message : String(error);
3858
- this.logError(`${title}: 写入本地草稿订单失败`, {
3859
- error: errorMessage
3860
- });
3861
- return { code: 500, status: false, message: errorMessage, data: null };
3862
- }
3863
- }
3864
3276
  async handlePendingSyncCheckoutOrder(params) {
3865
3277
  var _a, _b, _c, _d;
3866
3278
  const { backendPath, data, title, reason } = params;
@@ -3936,8 +3348,7 @@ var Server = class {
3936
3348
  return null;
3937
3349
  const pendingOrder = {
3938
3350
  ...data,
3939
- need_sync: 1,
3940
- is_draft_order: 0
3351
+ need_sync: 1
3941
3352
  };
3942
3353
  const productMap = await this.buildSmallTicketProductMap(pendingOrder);
3943
3354
  const orderWithProductTitles = this.withPendingSyncProductTitles(
@@ -3990,7 +3401,7 @@ var Server = class {
3990
3401
  return 0;
3991
3402
  return payments.reduce((sum, payment) => {
3992
3403
  const status = String((payment == null ? void 0 : payment.status) || "").toLowerCase();
3993
- if (status !== "paid")
3404
+ if (status === "voided" || status === "failed" || status === "cancelled")
3994
3405
  return sum;
3995
3406
  return sum + this.toAmountNumber((payment == null ? void 0 : payment.amount) ?? (payment == null ? void 0 : payment.origin_amount));
3996
3407
  }, 0);
@@ -4557,11 +3968,9 @@ var Server = class {
4557
3968
  return value === void 0 ? void 0 : String(value);
4558
3969
  }
4559
3970
  buildCheckoutSyncSuccessPatch(fresh) {
4560
- const patch = {
4561
- is_draft_order: 0
4562
- };
4563
3971
  if (!fresh)
4564
- return patch;
3972
+ return {};
3973
+ const patch = {};
4565
3974
  if (fresh.order_id !== void 0 && fresh.order_id !== null)
4566
3975
  patch.order_id = fresh.order_id;
4567
3976
  if (fresh.order_number !== void 0 && fresh.order_number !== null) {
@@ -4842,10 +4251,6 @@ var Server = class {
4842
4251
  const rawList = this.order.getOrders();
4843
4252
  this.logInfo("computeOrderQueryResult: 本地订单数量", { rawCount: rawList.length });
4844
4253
  const result = (0, import_filterOrders.filterOrders)(rawList, data);
4845
- result.list.forEach((order) => {
4846
- var _a;
4847
- order.payments = (_a = order.payments) == null ? void 0 : _a.filter((payment) => !(0, import_payment_utils.isPendingOrderPayment)(payment));
4848
- });
4849
4254
  this.logInfo("computeOrderQueryResult: 过滤结果", {
4850
4255
  rawCount: rawList.length,
4851
4256
  filteredCount: result.count,
@@ -5072,13 +4477,16 @@ var Server = class {
5072
4477
  let activeMenuList = [];
5073
4478
  if (menu_list_ids && Array.isArray(menu_list_ids) && menu_list_ids.length > 0) {
5074
4479
  const tMenu = performance.now();
5075
- const menuList = this.menu.getMenuByIds(menu_list_ids);
5076
- activeMenuList = menuList.filter((menu) => {
4480
+ const getActiveMenus = () => this.menu.getMenuByIds(menu_list_ids).filter((menu) => {
5077
4481
  var _a;
5078
4482
  return ((_a = this.schedule) == null ? void 0 : _a.getDateIsInSchedule(schedule_datetime, menu.schedule)) || false;
5079
4483
  });
4484
+ activeMenuList = getActiveMenus();
4485
+ if (!activeMenuList.length && await this.refreshMenuScheduleCacheAfterEmptyResult()) {
4486
+ activeMenuList = getActiveMenus();
4487
+ }
5080
4488
  (0, import_product.perfMark)("computeQuery.filterActiveMenu", performance.now() - tMenu, {
5081
- totalMenu: menuList.length,
4489
+ totalMenu: menu_list_ids.length,
5082
4490
  activeMenu: activeMenuList.length
5083
4491
  });
5084
4492
  }