@pisell/pisellos 2.2.148 → 2.2.149

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 (247) hide show
  1. package/dist/apis/picoding.d.ts +0 -0
  2. package/dist/apis/picoding.js +1 -0
  3. package/dist/model/strategy/adapter/index.d.ts +2 -0
  4. package/dist/model/strategy/adapter/index.js +3 -1
  5. package/dist/model/strategy/adapter/itemRule/adapter.d.ts +67 -0
  6. package/dist/model/strategy/adapter/itemRule/adapter.js +483 -0
  7. package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +43 -0
  8. package/dist/model/strategy/adapter/itemRule/evaluator.js +169 -0
  9. package/dist/model/strategy/adapter/itemRule/examples.d.ts +79 -0
  10. package/dist/model/strategy/adapter/itemRule/examples.js +382 -0
  11. package/dist/model/strategy/adapter/itemRule/index.d.ts +5 -0
  12. package/dist/model/strategy/adapter/itemRule/index.js +5 -0
  13. package/dist/model/strategy/adapter/itemRule/type.d.ts +225 -0
  14. package/dist/model/strategy/adapter/itemRule/type.js +101 -0
  15. package/dist/modules/Cart/types.d.ts +2 -0
  16. package/dist/modules/Cart/utils/cartProduct.js +22 -1
  17. package/dist/modules/Cart/utils/changePrice.js +6 -0
  18. package/dist/modules/Date/index.d.ts +1 -1
  19. package/dist/modules/Date/index.js +16 -8
  20. package/dist/modules/Date/types.d.ts +3 -1
  21. package/dist/modules/OpenData/index.d.ts +24 -0
  22. package/dist/modules/OpenData/index.js +173 -0
  23. package/dist/modules/OpenData/types.d.ts +73 -0
  24. package/dist/modules/OpenData/types.js +1 -0
  25. package/dist/modules/OpenData/utils.d.ts +2 -0
  26. package/dist/modules/OpenData/utils.js +75 -0
  27. package/dist/modules/Order/index.d.ts +171 -1
  28. package/dist/modules/Order/index.js +2052 -112
  29. package/dist/modules/Order/types.d.ts +441 -20
  30. package/dist/modules/Order/types.js +23 -0
  31. package/dist/modules/Order/utils.d.ts +120 -0
  32. package/dist/modules/Order/utils.js +653 -2
  33. package/dist/modules/Product/utils.js +2 -2
  34. package/dist/modules/ProductList/index.js +2 -1
  35. package/dist/modules/Quotation/index.d.ts +8 -1
  36. package/dist/modules/Quotation/index.js +40 -10
  37. package/dist/modules/Quotation/types.d.ts +5 -0
  38. package/dist/modules/Rules/index.d.ts +3 -1
  39. package/dist/modules/Rules/index.js +136 -50
  40. package/dist/modules/Rules/types.d.ts +6 -0
  41. package/dist/modules/Rules/types.js +8 -0
  42. package/dist/modules/SalesSummary/index.d.ts +70 -0
  43. package/dist/modules/SalesSummary/index.js +175 -0
  44. package/dist/modules/SalesSummary/types.d.ts +64 -0
  45. package/dist/modules/SalesSummary/types.js +1 -0
  46. package/dist/modules/SalesSummary/utils.d.ts +34 -0
  47. package/dist/modules/SalesSummary/utils.js +488 -0
  48. package/dist/modules/ScanOrderLogger/index.d.ts +21 -0
  49. package/dist/modules/ScanOrderLogger/index.js +161 -0
  50. package/dist/modules/ScanOrderLogger/providers/feishu.d.ts +2 -0
  51. package/dist/modules/ScanOrderLogger/providers/feishu.js +203 -0
  52. package/dist/modules/ScanOrderLogger/providers/grafana.d.ts +2 -0
  53. package/dist/modules/ScanOrderLogger/providers/grafana.js +50 -0
  54. package/dist/modules/ScanOrderLogger/types.d.ts +52 -0
  55. package/dist/modules/ScanOrderLogger/types.js +1 -0
  56. package/dist/modules/Schedule/getDateIsInSchedule.js +7 -7
  57. package/dist/modules/Schedule/index.d.ts +4 -13
  58. package/dist/modules/Schedule/index.js +6 -23
  59. package/dist/modules/Schedule/utils.d.ts +1 -1
  60. package/dist/modules/Summary/index.d.ts +3 -0
  61. package/dist/modules/Summary/index.js +134 -15
  62. package/dist/modules/Summary/types.d.ts +7 -0
  63. package/dist/modules/Summary/utils.d.ts +104 -1
  64. package/dist/modules/Summary/utils.js +1116 -13
  65. package/dist/modules/index.d.ts +4 -0
  66. package/dist/modules/index.js +5 -1
  67. package/dist/server/index.d.ts +41 -4
  68. package/dist/server/index.js +900 -405
  69. package/dist/server/modules/order/index.d.ts +10 -2
  70. package/dist/server/modules/order/index.js +246 -193
  71. package/dist/server/modules/products/index.d.ts +26 -0
  72. package/dist/server/modules/products/index.js +618 -338
  73. package/dist/server/modules/products/types.d.ts +5 -1
  74. package/dist/solution/BaseSales/index.d.ts +175 -0
  75. package/dist/solution/BaseSales/index.js +1293 -0
  76. package/dist/solution/BaseSales/types.d.ts +305 -0
  77. package/dist/solution/BaseSales/types.js +38 -0
  78. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +143 -0
  79. package/dist/solution/BaseSales/utils/parseSalesResponse.js +159 -0
  80. package/dist/solution/BaseSales/utils.d.ts +40 -0
  81. package/dist/solution/BaseSales/utils.js +222 -0
  82. package/dist/solution/BookingByStep/index.d.ts +14 -0
  83. package/dist/solution/BookingByStep/index.js +699 -212
  84. package/dist/solution/BookingByStep/types.d.ts +3 -1
  85. package/dist/solution/BookingByStep/types.js +5 -1
  86. package/dist/solution/BookingByStep/utils/capacity.js +1 -1
  87. package/dist/solution/BookingByStep/utils/resources.js +6 -1
  88. package/dist/solution/BookingTicket/index.d.ts +113 -15
  89. package/dist/solution/BookingTicket/index.js +534 -196
  90. package/dist/solution/BookingTicket/types.d.ts +69 -6
  91. package/dist/solution/BookingTicket/types.js +40 -9
  92. package/dist/solution/BookingTicket/utils/bookingStatus.d.ts +37 -0
  93. package/dist/solution/BookingTicket/utils/bookingStatus.js +66 -0
  94. package/dist/solution/BookingTicket/utils/cartView.d.ts +26 -0
  95. package/dist/solution/BookingTicket/utils/cartView.js +84 -0
  96. package/dist/solution/Sales/index.d.ts +1 -0
  97. package/dist/solution/Sales/index.js +1 -0
  98. package/dist/solution/ScanOrder/index.d.ts +146 -0
  99. package/dist/solution/ScanOrder/index.js +3029 -0
  100. package/dist/solution/ScanOrder/types.d.ts +305 -0
  101. package/dist/solution/ScanOrder/types.js +35 -0
  102. package/dist/solution/ScanOrder/utils.d.ts +167 -0
  103. package/dist/solution/ScanOrder/utils.js +768 -0
  104. package/dist/solution/ShopDiscount/index.d.ts +2 -0
  105. package/dist/solution/ShopDiscount/index.js +9 -5
  106. package/dist/solution/ShopDiscount/types.d.ts +4 -0
  107. package/dist/solution/VenueBooking/index.d.ts +197 -0
  108. package/dist/solution/VenueBooking/index.js +3411 -0
  109. package/dist/solution/VenueBooking/sales-section-4-annotated.json +343 -0
  110. package/dist/solution/VenueBooking/types.d.ts +153 -0
  111. package/dist/solution/VenueBooking/types.js +21 -0
  112. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +11 -0
  113. package/dist/solution/VenueBooking/utils/dateSummary.js +104 -0
  114. package/dist/solution/VenueBooking/utils/resource.d.ts +14 -0
  115. package/dist/solution/VenueBooking/utils/resource.js +130 -0
  116. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +34 -0
  117. package/dist/solution/VenueBooking/utils/slotMerge.js +224 -0
  118. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +32 -0
  119. package/dist/solution/VenueBooking/utils/timeSlot.js +453 -0
  120. package/dist/solution/VenueBooking/utils.d.ts +1 -0
  121. package/dist/solution/VenueBooking/utils.js +1 -0
  122. package/dist/solution/index.d.ts +3 -0
  123. package/dist/solution/index.js +4 -1
  124. package/lib/apis/picoding.d.ts +0 -0
  125. package/lib/apis/picoding.js +0 -0
  126. package/lib/model/strategy/adapter/index.d.ts +2 -0
  127. package/lib/model/strategy/adapter/index.js +6 -0
  128. package/lib/model/strategy/adapter/itemRule/adapter.d.ts +67 -0
  129. package/lib/model/strategy/adapter/itemRule/adapter.js +377 -0
  130. package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +43 -0
  131. package/lib/model/strategy/adapter/itemRule/evaluator.js +124 -0
  132. package/lib/model/strategy/adapter/itemRule/examples.d.ts +79 -0
  133. package/lib/model/strategy/adapter/itemRule/examples.js +316 -0
  134. package/lib/model/strategy/adapter/itemRule/index.d.ts +5 -0
  135. package/lib/model/strategy/adapter/itemRule/index.js +60 -0
  136. package/lib/model/strategy/adapter/itemRule/type.d.ts +225 -0
  137. package/lib/model/strategy/adapter/itemRule/type.js +46 -0
  138. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  139. package/lib/modules/Cart/types.d.ts +2 -0
  140. package/lib/modules/Cart/utils/cartProduct.js +17 -1
  141. package/lib/modules/Cart/utils/changePrice.js +5 -0
  142. package/lib/modules/Date/index.d.ts +1 -1
  143. package/lib/modules/Date/index.js +7 -1
  144. package/lib/modules/Date/types.d.ts +3 -1
  145. package/lib/modules/OpenData/index.d.ts +24 -0
  146. package/lib/modules/OpenData/index.js +119 -0
  147. package/lib/modules/OpenData/types.d.ts +73 -0
  148. package/lib/modules/OpenData/types.js +17 -0
  149. package/lib/modules/OpenData/utils.d.ts +2 -0
  150. package/lib/modules/OpenData/utils.js +111 -0
  151. package/lib/modules/Order/index.d.ts +171 -1
  152. package/lib/modules/Order/index.js +1396 -5
  153. package/lib/modules/Order/types.d.ts +441 -20
  154. package/lib/modules/Order/types.js +1 -0
  155. package/lib/modules/Order/utils.d.ts +120 -0
  156. package/lib/modules/Order/utils.js +562 -2
  157. package/lib/modules/Product/utils.js +2 -2
  158. package/lib/modules/ProductList/index.js +2 -1
  159. package/lib/modules/Quotation/index.d.ts +8 -1
  160. package/lib/modules/Quotation/index.js +33 -4
  161. package/lib/modules/Quotation/types.d.ts +5 -0
  162. package/lib/modules/Rules/index.d.ts +3 -1
  163. package/lib/modules/Rules/index.js +46 -6
  164. package/lib/modules/Rules/types.d.ts +6 -0
  165. package/lib/modules/Rules/types.js +11 -2
  166. package/lib/modules/SalesSummary/index.d.ts +70 -0
  167. package/lib/modules/SalesSummary/index.js +106 -0
  168. package/lib/modules/SalesSummary/types.d.ts +64 -0
  169. package/lib/modules/SalesSummary/types.js +17 -0
  170. package/lib/modules/SalesSummary/utils.d.ts +34 -0
  171. package/lib/modules/SalesSummary/utils.js +430 -0
  172. package/lib/modules/ScanOrderLogger/index.d.ts +21 -0
  173. package/lib/modules/ScanOrderLogger/index.js +135 -0
  174. package/lib/modules/ScanOrderLogger/providers/feishu.d.ts +2 -0
  175. package/lib/modules/ScanOrderLogger/providers/feishu.js +148 -0
  176. package/lib/modules/ScanOrderLogger/providers/grafana.d.ts +2 -0
  177. package/lib/modules/ScanOrderLogger/providers/grafana.js +52 -0
  178. package/lib/modules/ScanOrderLogger/types.d.ts +52 -0
  179. package/lib/modules/ScanOrderLogger/types.js +17 -0
  180. package/lib/modules/Schedule/getDateIsInSchedule.js +5 -5
  181. package/lib/modules/Schedule/index.d.ts +4 -13
  182. package/lib/modules/Schedule/index.js +4 -15
  183. package/lib/modules/Schedule/utils.d.ts +1 -1
  184. package/lib/modules/Summary/index.d.ts +3 -0
  185. package/lib/modules/Summary/index.js +61 -2
  186. package/lib/modules/Summary/types.d.ts +7 -0
  187. package/lib/modules/Summary/utils.d.ts +104 -1
  188. package/lib/modules/Summary/utils.js +659 -8
  189. package/lib/modules/index.d.ts +4 -0
  190. package/lib/modules/index.js +9 -1
  191. package/lib/server/index.d.ts +41 -4
  192. package/lib/server/index.js +272 -10
  193. package/lib/server/modules/order/index.d.ts +10 -2
  194. package/lib/server/modules/order/index.js +26 -1
  195. package/lib/server/modules/products/index.d.ts +26 -0
  196. package/lib/server/modules/products/index.js +174 -22
  197. package/lib/server/modules/products/types.d.ts +5 -1
  198. package/lib/solution/BaseSales/index.d.ts +175 -0
  199. package/lib/solution/BaseSales/index.js +655 -0
  200. package/lib/solution/BaseSales/types.d.ts +305 -0
  201. package/lib/solution/BaseSales/types.js +40 -0
  202. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +143 -0
  203. package/lib/solution/BaseSales/utils/parseSalesResponse.js +160 -0
  204. package/lib/solution/BaseSales/utils.d.ts +40 -0
  205. package/lib/solution/BaseSales/utils.js +200 -0
  206. package/lib/solution/BookingByStep/index.d.ts +14 -0
  207. package/lib/solution/BookingByStep/index.js +469 -91
  208. package/lib/solution/BookingByStep/types.d.ts +3 -1
  209. package/lib/solution/BookingByStep/types.js +10 -0
  210. package/lib/solution/BookingByStep/utils/capacity.js +1 -1
  211. package/lib/solution/BookingByStep/utils/resources.js +5 -2
  212. package/lib/solution/BookingTicket/index.d.ts +113 -15
  213. package/lib/solution/BookingTicket/index.js +253 -61
  214. package/lib/solution/BookingTicket/types.d.ts +69 -6
  215. package/lib/solution/BookingTicket/types.js +16 -14
  216. package/lib/solution/BookingTicket/utils/bookingStatus.d.ts +37 -0
  217. package/lib/solution/BookingTicket/utils/bookingStatus.js +65 -0
  218. package/lib/solution/BookingTicket/utils/cartView.d.ts +26 -0
  219. package/lib/solution/BookingTicket/utils/cartView.js +103 -0
  220. package/lib/solution/Sales/index.d.ts +1 -0
  221. package/lib/solution/ScanOrder/index.d.ts +146 -0
  222. package/lib/solution/ScanOrder/index.js +1820 -0
  223. package/lib/solution/ScanOrder/types.d.ts +305 -0
  224. package/lib/solution/ScanOrder/types.js +36 -0
  225. package/lib/solution/ScanOrder/utils.d.ts +167 -0
  226. package/lib/solution/ScanOrder/utils.js +639 -0
  227. package/lib/solution/ShopDiscount/index.d.ts +2 -0
  228. package/lib/solution/ShopDiscount/index.js +9 -4
  229. package/lib/solution/ShopDiscount/types.d.ts +4 -0
  230. package/lib/solution/VenueBooking/index.d.ts +197 -0
  231. package/lib/solution/VenueBooking/index.js +1892 -0
  232. package/lib/solution/VenueBooking/sales-section-4-annotated.json +343 -0
  233. package/lib/solution/VenueBooking/types.d.ts +153 -0
  234. package/lib/solution/VenueBooking/types.js +44 -0
  235. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +11 -0
  236. package/lib/solution/VenueBooking/utils/dateSummary.js +110 -0
  237. package/lib/solution/VenueBooking/utils/resource.d.ts +14 -0
  238. package/lib/solution/VenueBooking/utils/resource.js +91 -0
  239. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +34 -0
  240. package/lib/solution/VenueBooking/utils/slotMerge.js +225 -0
  241. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +32 -0
  242. package/lib/solution/VenueBooking/utils/timeSlot.js +339 -0
  243. package/lib/solution/VenueBooking/utils.d.ts +1 -0
  244. package/lib/solution/VenueBooking/utils.js +69 -0
  245. package/lib/solution/index.d.ts +3 -0
  246. package/lib/solution/index.js +7 -1
  247. package/package.json +1 -1
@@ -0,0 +1,1820 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/solution/ScanOrder/index.ts
31
+ var ScanOrder_exports = {};
32
+ __export(ScanOrder_exports, {
33
+ ScanOrderImpl: () => ScanOrderImpl
34
+ });
35
+ module.exports = __toCommonJS(ScanOrder_exports);
36
+ var import_BaseModule = require("../../modules/BaseModule");
37
+ var import_types = require("./types");
38
+ var import_Order = require("../../modules/Order");
39
+ var import_types2 = require("../../modules/Account/types");
40
+ var import_types3 = require("../RegisterAndLogin/types");
41
+ var import_decimal = __toESM(require("decimal.js"));
42
+ var import_utils = require("./utils");
43
+ var import_types4 = require("../BookingByStep/types");
44
+ var import_ProductList = require("../../modules/ProductList");
45
+ var import_Schedule = require("../../modules/Schedule");
46
+ var import_getDateIsInSchedule = require("../../modules/Schedule/getDateIsInSchedule");
47
+ var import_utils2 = require("../../modules/Order/utils");
48
+ var import_dayjs = __toESM(require("dayjs"));
49
+ var import_itemRule = require("../../model/strategy/adapter/itemRule");
50
+ __reExport(ScanOrder_exports, require("./types"), module.exports);
51
+ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
52
+ constructor(name, version) {
53
+ super(name, version);
54
+ this.defaultName = "scanOrder";
55
+ this.defaultVersion = "1.0.0";
56
+ this.isSolution = true;
57
+ this.initializeOptions = {};
58
+ this.store = {
59
+ entryContext: null,
60
+ status: "idle",
61
+ config: null,
62
+ resource: null,
63
+ flow: {},
64
+ error: null,
65
+ products: void 0,
66
+ itemRuleQuantityLimits: [],
67
+ cartValidation: {
68
+ passed: null,
69
+ failures: []
70
+ },
71
+ entryPaxNumber: 1
72
+ };
73
+ this.otherParams = {};
74
+ this.itemRuleEvaluator = new import_itemRule.ItemRuleEvaluator();
75
+ this.itemRuleConfigs = [];
76
+ this.itemRuleConfigsPromise = null;
77
+ this.itemRulePrefillApplied = false;
78
+ this.itemRuleRuntimeConfig = {};
79
+ /** 最近一次 checkResourceAvailable 从预约规则 link 拉取的商品快照 */
80
+ this.enabledReservationRuleProducts = [];
81
+ this.loginEffectDisposers = [];
82
+ this.customerLoginRefreshInFlight = null;
83
+ this.customerLoginRefreshIdInFlight = null;
84
+ }
85
+ getScanOrderLoggerContext() {
86
+ return {
87
+ cacheId: this.cacheId,
88
+ solutionName: this.name,
89
+ moduleName: "scanOrder"
90
+ };
91
+ }
92
+ serializeError(error) {
93
+ if (error instanceof Error) {
94
+ return JSON.stringify({
95
+ name: error.name,
96
+ message: error.message,
97
+ stack: error.stack
98
+ });
99
+ }
100
+ return {
101
+ message: String(error)
102
+ };
103
+ }
104
+ async addScanOrderLog(params) {
105
+ const payload = {
106
+ cacheId: this.cacheId,
107
+ ...params.payload || {}
108
+ };
109
+ const extra = {
110
+ ...params.extra || {}
111
+ };
112
+ const logger = this.store.scanOrderLogger;
113
+ if (!logger) {
114
+ if ((params.level || "info") === "error") {
115
+ console.error("[ScanOrder][log-fallback]", params.title, { payload, extra });
116
+ } else {
117
+ console.log("[ScanOrder][log-fallback]", params.title, { payload, extra });
118
+ }
119
+ return;
120
+ }
121
+ await logger.addLog({
122
+ ...params,
123
+ payload,
124
+ extra
125
+ });
126
+ }
127
+ logMethodStart(method, payload = {}) {
128
+ void this.addScanOrderLog({
129
+ level: "info",
130
+ title: `[ScanOrder] ${method} start`,
131
+ payload: {
132
+ method,
133
+ ...payload
134
+ }
135
+ });
136
+ }
137
+ logMethodSuccess(method, payload = {}) {
138
+ void this.addScanOrderLog({
139
+ level: "info",
140
+ title: `[ScanOrder] ${method} success`,
141
+ payload: {
142
+ method,
143
+ ...payload
144
+ }
145
+ });
146
+ }
147
+ logMethodError(method, error, payload = {}) {
148
+ void this.addScanOrderLog({
149
+ level: "error",
150
+ title: `[ScanOrder] ${method} failed`,
151
+ payload: {
152
+ method,
153
+ ...payload,
154
+ error: this.serializeError(error)
155
+ }
156
+ });
157
+ }
158
+ async addLog(params) {
159
+ await this.addScanOrderLog({
160
+ ...params,
161
+ payload: {
162
+ source: "ui-bridge",
163
+ ...params.payload || {}
164
+ }
165
+ });
166
+ }
167
+ normalizeCustomerId(value) {
168
+ const customerId = Number(value);
169
+ if (!Number.isFinite(customerId) || customerId <= 0)
170
+ return null;
171
+ return customerId;
172
+ }
173
+ resolveCustomerIdFromLoginPayload(payload) {
174
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
175
+ const candidates = [
176
+ payload == null ? void 0 : payload.customerId,
177
+ payload == null ? void 0 : payload.customer_id,
178
+ payload == null ? void 0 : payload.id,
179
+ (_a = payload == null ? void 0 : payload.user) == null ? void 0 : _a.customerId,
180
+ (_b = payload == null ? void 0 : payload.user) == null ? void 0 : _b.customer_id,
181
+ (_c = payload == null ? void 0 : payload.user) == null ? void 0 : _c.id,
182
+ (_e = (_d = payload == null ? void 0 : payload.user) == null ? void 0 : _d._origin) == null ? void 0 : _e.customer_id,
183
+ (_f = payload == null ? void 0 : payload.account) == null ? void 0 : _f.customerId,
184
+ (_g = payload == null ? void 0 : payload.account) == null ? void 0 : _g.customer_id,
185
+ (_h = payload == null ? void 0 : payload.account) == null ? void 0 : _h.id,
186
+ (_i = payload == null ? void 0 : payload._origin) == null ? void 0 : _i.customer_id
187
+ ];
188
+ for (const candidate of candidates) {
189
+ const customerId = this.normalizeCustomerId(candidate);
190
+ if (customerId)
191
+ return customerId;
192
+ }
193
+ return null;
194
+ }
195
+ clearLoginEffectListeners() {
196
+ for (const dispose of this.loginEffectDisposers) {
197
+ dispose();
198
+ }
199
+ this.loginEffectDisposers = [];
200
+ }
201
+ registerLoginEffect(event, callback) {
202
+ var _a;
203
+ const effects = (_a = this.core) == null ? void 0 : _a.effects;
204
+ if (!(effects == null ? void 0 : effects.on))
205
+ return;
206
+ effects.on(event, callback);
207
+ this.loginEffectDisposers.push(() => {
208
+ if (typeof effects.off === "function") {
209
+ effects.off(event, callback);
210
+ }
211
+ });
212
+ }
213
+ registerCustomerLoginListeners() {
214
+ this.clearLoginEffectListeners();
215
+ const createHandleLogin = () => async (payload) => {
216
+ const customerId = this.resolveCustomerIdFromLoginPayload(payload);
217
+ if (!customerId)
218
+ return;
219
+ await this.refreshOrderMarketingAfterLogin({ customerId });
220
+ };
221
+ this.registerLoginEffect(
222
+ _ScanOrderImpl.PISELL1_LOGIN_SUCCESS,
223
+ createHandleLogin()
224
+ );
225
+ this.registerLoginEffect(import_types2.AccountHooks.OnLogin, createHandleLogin());
226
+ this.registerLoginEffect(
227
+ import_types3.RegisterAndLoginHooks.onLoginSuccess,
228
+ createHandleLogin()
229
+ );
230
+ }
231
+ async refreshOrderMarketingAfterLogin(params) {
232
+ if (!this.store.order)
233
+ throw new Error("order 模块未初始化");
234
+ if (this.customerLoginRefreshInFlight) {
235
+ if (this.customerLoginRefreshIdInFlight === params.customerId) {
236
+ await this.customerLoginRefreshInFlight;
237
+ return;
238
+ }
239
+ await this.customerLoginRefreshInFlight;
240
+ }
241
+ this.customerLoginRefreshIdInFlight = params.customerId;
242
+ const refreshTask = (async () => {
243
+ await this.store.order.loadDiscountConfig({
244
+ customerId: params.customerId
245
+ });
246
+ await this.store.order.recalculateSummary({ createIfMissing: true });
247
+ this.store.order.persistTempOrder();
248
+ await this.refreshItemRuleQuantityLimits();
249
+ await this.refreshCartValidationPassed();
250
+ })();
251
+ this.customerLoginRefreshInFlight = refreshTask;
252
+ try {
253
+ await refreshTask;
254
+ } catch (error) {
255
+ throw error;
256
+ } finally {
257
+ if (this.customerLoginRefreshInFlight === refreshTask) {
258
+ this.customerLoginRefreshInFlight = null;
259
+ this.customerLoginRefreshIdInFlight = null;
260
+ }
261
+ }
262
+ }
263
+ /** 与 `otherParams.cacheId` 一致,供宿主在 URL 变化时判断是否需要重新注册模块 */
264
+ getCacheId() {
265
+ return this.cacheId;
266
+ }
267
+ async destroyRegisteredChildModules() {
268
+ const modules = [
269
+ this.store.schedule,
270
+ this.store.salesSummary,
271
+ this.store.order,
272
+ this.store.products,
273
+ this.store.scanOrderLogger
274
+ ];
275
+ for (const mod of modules) {
276
+ if (mod && typeof mod.destroy === "function")
277
+ await Promise.resolve(mod.destroy());
278
+ }
279
+ }
280
+ async initialize(core, options = {}) {
281
+ var _a, _b, _c, _d, _e, _f;
282
+ this.logMethodStart("initialize");
283
+ this.core = core;
284
+ this.initializeOptions = options || {};
285
+ this.store = { ...this.store, ...options.store };
286
+ this.store.entryContext = ((_a = options.otherParams) == null ? void 0 : _a.entryContext) || this.store.entryContext;
287
+ this.store.status = "initializing";
288
+ this.store.error = null;
289
+ this.otherParams = options.otherParams || {};
290
+ this.cacheId = (_b = this.otherParams) == null ? void 0 : _b.cacheId;
291
+ this.itemRuleRuntimeConfig = ((_c = this.otherParams) == null ? void 0 : _c.scanOrderItemRule) || ((_d = this.otherParams) == null ? void 0 : _d.itemRule) || {};
292
+ this.itemRuleConfigs = [];
293
+ this.itemRuleConfigsPromise = null;
294
+ this.itemRulePrefillApplied = false;
295
+ this.store.itemRuleQuantityLimits = [];
296
+ this.store.cartValidation = {
297
+ passed: null,
298
+ failures: []
299
+ };
300
+ this.window = core.getPlugin("window");
301
+ this.request = core.getPlugin("request");
302
+ if (!this.window) {
303
+ this.logMethodError("initialize", "window plugin missing");
304
+ throw new Error("scanOrder解决方案需要 window 插件支持");
305
+ }
306
+ if (!this.request) {
307
+ this.logMethodError("initialize", "request plugin missing");
308
+ throw new Error("scanOrder解决方案需要 request 插件支持");
309
+ }
310
+ const moduleArr = [
311
+ "scanOrderLogger",
312
+ "products",
313
+ "order",
314
+ "salesSummary"
315
+ ];
316
+ moduleArr.forEach((step) => {
317
+ var _a2, _b2, _c2, _d2, _e2, _f2;
318
+ const targetModule = (0, import_types4.createModule)(step, this.name);
319
+ if (targetModule) {
320
+ this.store[step] = targetModule;
321
+ const initialState = step === "salesSummary" ? {
322
+ // TODO(Order types): ScanOrder runtime should read OrderState.summary instead of tempOrder.summary.
323
+ summary: ((_b2 = (_a2 = this.store.order) == null ? void 0 : _a2.getTempOrder()) == null ? void 0 : _b2.summary) || (0, import_utils.createEmptySummary)()
324
+ } : {};
325
+ const loggerProvider = ((_c2 = this.otherParams) == null ? void 0 : _c2.scanOrderLoggerProvider) || "feishu";
326
+ const loggerConfig = ((_d2 = this.otherParams) == null ? void 0 : _d2.scanOrderLoggerConfig) || {
327
+ feishu: {
328
+ webhook: "https://open.feishu.cn/open-apis/bot/v2/hook/216b3fe6-af98-424e-8706-f0471241a7ed"
329
+ }
330
+ };
331
+ this.core.registerModule(targetModule, {
332
+ initialState,
333
+ otherParams: {
334
+ ...this.otherParams,
335
+ fatherModule: this.name,
336
+ openCache: ((_e2 = this.otherParams) == null ? void 0 : _e2.cacheId) ? true : false,
337
+ cacheId: (_f2 = this.otherParams) == null ? void 0 : _f2.cacheId,
338
+ salesSummaryModuleName: `${this.name}_salesSummary`,
339
+ provider: loggerProvider,
340
+ providerConfig: loggerConfig,
341
+ context: this.getScanOrderLoggerContext()
342
+ }
343
+ });
344
+ } else {
345
+ this.logMethodError("initialize", `module ${step} missing`);
346
+ throw new Error(`模块 ${step} 不存在`);
347
+ }
348
+ });
349
+ if (this.store.scanOrderLogger) {
350
+ this.store.scanOrderLogger.setContext(this.getScanOrderLoggerContext());
351
+ }
352
+ const scheduleModule = new import_Schedule.ScheduleModule(`${this.name}_schedule`);
353
+ this.store.schedule = scheduleModule;
354
+ this.core.registerModule(scheduleModule, {
355
+ otherParams: {
356
+ ...this.otherParams,
357
+ fatherModule: this.name
358
+ }
359
+ });
360
+ this.registerCustomerLoginListeners();
361
+ console.log("[ScanOrder] 初始化开始");
362
+ try {
363
+ await ((_e = this.store.order) == null ? void 0 : _e.recalculateSummary({ createIfMissing: false }));
364
+ (_f = this.store.order) == null ? void 0 : _f.persistTempOrder();
365
+ await this.loadRuntimeConfigs();
366
+ if (this.store.schedule) {
367
+ try {
368
+ await this.store.schedule.loadAllSchedule();
369
+ } catch (scheduleError) {
370
+ console.warn("[ScanOrder] loadAllSchedule 失败,operating_hours 判定将跳过", scheduleError);
371
+ }
372
+ }
373
+ await this.refreshItemRuleQuantityLimits();
374
+ this.store.status = "ready";
375
+ console.log("[ScanOrder] 初始化完成");
376
+ await this.core.effects.emit(import_types.ScanOrderHooks.onInited, {
377
+ status: this.store.status
378
+ });
379
+ this.logMethodSuccess("initialize", {
380
+ status: this.store.status
381
+ });
382
+ } catch (error) {
383
+ this.store.status = "error";
384
+ this.store.error = error instanceof Error ? error.message : "初始化失败";
385
+ console.error("[ScanOrder] 初始化失败", error);
386
+ this.logMethodError("initialize", error, {
387
+ status: this.store.status
388
+ });
389
+ throw error;
390
+ }
391
+ }
392
+ async destroy() {
393
+ this.logMethodStart("destroy");
394
+ this.clearLoginEffectListeners();
395
+ await this.core.effects.emit(import_types.ScanOrderHooks.onDestroy, {});
396
+ await this.destroyRegisteredChildModules();
397
+ super.destroy();
398
+ console.log("[ScanOrder] 已销毁");
399
+ this.logMethodSuccess("destroy");
400
+ }
401
+ async retryInit() {
402
+ this.logMethodStart("retryInit");
403
+ console.log("[ScanOrder] retryInit 调用");
404
+ await this.core.effects.emit(import_types.ScanOrderHooks.onRetryInit, {});
405
+ try {
406
+ await this.initialize(this.core, this.initializeOptions);
407
+ this.logMethodSuccess("retryInit");
408
+ } catch (error) {
409
+ this.logMethodError("retryInit", error);
410
+ throw error;
411
+ }
412
+ }
413
+ async refresh() {
414
+ this.logMethodStart("refresh");
415
+ console.log("[ScanOrder] refresh 调用");
416
+ try {
417
+ this.store.status = "initializing";
418
+ await this.loadRuntimeConfigs();
419
+ await this.refreshItemRuleQuantityLimits();
420
+ this.store.status = "ready";
421
+ await this.core.effects.emit(import_types.ScanOrderHooks.onRefresh, {
422
+ status: this.store.status
423
+ });
424
+ this.logMethodSuccess("refresh", {
425
+ status: this.store.status
426
+ });
427
+ } catch (error) {
428
+ this.logMethodError("refresh", error);
429
+ throw error;
430
+ }
431
+ }
432
+ getStatus() {
433
+ this.logMethodStart("getStatus");
434
+ const result = this.store.status;
435
+ this.logMethodSuccess("getStatus", {
436
+ status: result
437
+ });
438
+ return result;
439
+ }
440
+ getEntryContext() {
441
+ this.logMethodStart("getEntryContext");
442
+ const result = this.store.entryContext;
443
+ this.logMethodSuccess("getEntryContext", {
444
+ hasEntryContext: Boolean(result)
445
+ });
446
+ return result;
447
+ }
448
+ getConfig() {
449
+ this.logMethodStart("getConfig");
450
+ const result = this.store.config || {};
451
+ this.logMethodSuccess("getConfig", {
452
+ configKeys: Object.keys(result || {})
453
+ });
454
+ return result;
455
+ }
456
+ getItemRuleQuantityLimits() {
457
+ this.logMethodStart("getItemRuleQuantityLimits");
458
+ const result = this.store.itemRuleQuantityLimits || [];
459
+ this.logMethodSuccess("getItemRuleQuantityLimits", {
460
+ limitCount: result.length
461
+ });
462
+ return result;
463
+ }
464
+ getCartValidationPassed() {
465
+ var _a;
466
+ this.logMethodStart("getCartValidationPassed");
467
+ const result = ((_a = this.store.cartValidation) == null ? void 0 : _a.passed) ?? null;
468
+ this.logMethodSuccess("getCartValidationPassed", {
469
+ cartValidationPassed: result
470
+ });
471
+ return result;
472
+ }
473
+ getCartValidation() {
474
+ this.logMethodStart("getCartValidation");
475
+ const result = this.store.cartValidation || {
476
+ passed: null,
477
+ failures: []
478
+ };
479
+ this.logMethodSuccess("getCartValidation", {
480
+ cartValidationPassed: result.passed,
481
+ failureCount: Array.isArray(result.failures) ? result.failures.length : 0
482
+ });
483
+ return result;
484
+ }
485
+ getTempOrder() {
486
+ var _a, _b, _c;
487
+ this.logMethodStart("getTempOrder");
488
+ const result = ((_a = this.store.order) == null ? void 0 : _a.getTempOrder()) || null;
489
+ this.logMethodSuccess("getTempOrder", {
490
+ hasTempOrder: Boolean(result),
491
+ productCount: ((_b = result == null ? void 0 : result.products) == null ? void 0 : _b.length) || 0,
492
+ noteLength: ((_c = result == null ? void 0 : result.note) == null ? void 0 : _c.length) || 0
493
+ });
494
+ return result;
495
+ }
496
+ updateTempOrderNote(note) {
497
+ this.logMethodStart("updateTempOrderNote", {
498
+ noteLength: String(note || "").length
499
+ });
500
+ try {
501
+ if (!this.store.order)
502
+ throw new Error("order 模块未初始化");
503
+ const result = this.store.order.updateTempOrderNote(note);
504
+ this.logMethodSuccess("updateTempOrderNote", {
505
+ noteLength: result.length
506
+ });
507
+ return result;
508
+ } catch (error) {
509
+ this.logMethodError("updateTempOrderNote", error);
510
+ throw error;
511
+ }
512
+ }
513
+ // 存储 UI 层选择的取餐方式到 tempOrder.metadata.shop_service_data
514
+ // service_type 在扫码点餐场景固定为 dine_in
515
+ setPickupReferenceMode(mode) {
516
+ this.logMethodStart("setPickupReferenceMode", { mode });
517
+ try {
518
+ if (!this.store.order)
519
+ throw new Error("order 模块未初始化");
520
+ const tempOrder = this.store.order.ensureTempOrder();
521
+ tempOrder.metadata = {
522
+ ...tempOrder.metadata || {},
523
+ shop_service_data: {
524
+ ...(tempOrder.metadata || {}).shop_service_data || {},
525
+ service_type: "dine_in",
526
+ pickup_reference_mode: mode
527
+ }
528
+ };
529
+ this.store.order.persistTempOrder();
530
+ this.logMethodSuccess("setPickupReferenceMode", {
531
+ mode
532
+ });
533
+ return tempOrder.metadata.shop_service_data;
534
+ } catch (error) {
535
+ this.logMethodError("setPickupReferenceMode", error, { mode });
536
+ throw error;
537
+ }
538
+ }
539
+ // 存储用户自定义取餐标识到 tempOrder.buzzer
540
+ setPickupRef(buzzer) {
541
+ this.logMethodStart("setPickupRef", {
542
+ buzzerLength: String(buzzer || "").length
543
+ });
544
+ try {
545
+ if (!this.store.order)
546
+ throw new Error("order 模块未初始化");
547
+ const result = this.store.order.updateTempOrderBuzzer(buzzer);
548
+ this.logMethodSuccess("setPickupRef", {
549
+ buzzerLength: result.length
550
+ });
551
+ return result;
552
+ } catch (error) {
553
+ this.logMethodError("setPickupRef", error);
554
+ throw error;
555
+ }
556
+ }
557
+ ensureTempOrder() {
558
+ if (!this.store.order)
559
+ throw new Error("order 模块未初始化");
560
+ return this.store.order.ensureTempOrder();
561
+ }
562
+ // 主动创建临时订单;若已存在则直接返回已有订单
563
+ async addNewOrder() {
564
+ this.logMethodStart("addNewOrder");
565
+ try {
566
+ if (!this.store.order)
567
+ throw new Error("order 模块未初始化");
568
+ const tempOrder = await this.store.order.addNewOrder();
569
+ this.logMethodSuccess("addNewOrder", {
570
+ productCount: tempOrder.products.length
571
+ });
572
+ return tempOrder;
573
+ } catch (error) {
574
+ this.logMethodError("addNewOrder", error);
575
+ throw error;
576
+ }
577
+ }
578
+ // 重置 tempOrder 与与上一单强相关的运行态(resource/entryPaxNumber/enabledReservationRuleProducts),
579
+ // 适用于从支付页通过 react-router 跳回继续下单时清理残留数据
580
+ async restoreOrder() {
581
+ this.logMethodStart("restoreOrder");
582
+ try {
583
+ if (!this.store.order) {
584
+ throw new Error("scanOrder 解决方案需要 order 模块支持");
585
+ }
586
+ this.store.resource = null;
587
+ this.store.entryPaxNumber = 1;
588
+ this.enabledReservationRuleProducts = [];
589
+ const tempOrder = this.store.order.restoreOrder();
590
+ this.logMethodSuccess("restoreOrder");
591
+ return tempOrder;
592
+ } catch (error) {
593
+ this.logMethodError("restoreOrder", error);
594
+ throw error;
595
+ }
596
+ }
597
+ getOrderProducts() {
598
+ this.logMethodStart("getOrderProducts");
599
+ if (!this.store.order)
600
+ throw new Error("order 模块未初始化");
601
+ const products = this.store.order.getOrderProducts();
602
+ this.logMethodSuccess("getOrderProducts", {
603
+ productCount: products.length
604
+ });
605
+ return products;
606
+ }
607
+ async getSummary() {
608
+ this.logMethodStart("getSummary");
609
+ try {
610
+ if (!this.store.order)
611
+ throw new Error("order 模块未初始化");
612
+ const summary = await this.store.order.getOrderSummary();
613
+ this.logMethodSuccess("getSummary", {
614
+ totalAmount: summary.total_amount
615
+ });
616
+ return summary;
617
+ } catch (error) {
618
+ this.logMethodError("getSummary", error);
619
+ throw error;
620
+ }
621
+ }
622
+ getDiscountList() {
623
+ if (!this.store.order)
624
+ return [];
625
+ return this.store.order.getDiscountList();
626
+ }
627
+ async scanCode(code, customerId) {
628
+ this.logMethodStart("scanCode", { code });
629
+ try {
630
+ if (!this.store.order)
631
+ throw new Error("order 模块未初始化");
632
+ const raw = await this.store.order.scanCode(code, customerId);
633
+ if (raw.isAvailable) {
634
+ await this.store.order.recalculateSummary({ createIfMissing: true });
635
+ this.store.order.persistTempOrder();
636
+ }
637
+ this.logMethodSuccess("scanCode", { isAvailable: raw.isAvailable });
638
+ return {
639
+ isAvailable: raw.isAvailable,
640
+ type: raw.type,
641
+ unavailableReason: raw.unavailableReason
642
+ };
643
+ } catch (error) {
644
+ this.logMethodError("scanCode", error);
645
+ throw error;
646
+ }
647
+ }
648
+ async setDiscountSelected(params) {
649
+ var _a, _b, _c, _d, _e;
650
+ this.logMethodStart("setDiscountSelected", params);
651
+ try {
652
+ if (!this.store.order)
653
+ throw new Error("order 模块未初始化");
654
+ const list = this.store.order.getDiscountList();
655
+ const updated = list.map(
656
+ (d) => d.id === params.discountId ? {
657
+ ...d,
658
+ isSelected: params.isSelected,
659
+ isManualSelect: !params.isSelected
660
+ } : d
661
+ );
662
+ const tempOrder = this.store.order.ensureTempOrder();
663
+ const orderStore = this.store.order.store || {};
664
+ const discountModule = orderStore.discount;
665
+ const rulesModule = orderStore.rules;
666
+ const holders = ((_a = tempOrder.holder) == null ? void 0 : _a.form_record_id) ? [{ form_record_id: tempOrder.holder.form_record_id }] : [];
667
+ let nextDiscountList = updated;
668
+ await (discountModule == null ? void 0 : discountModule.setDiscountList(updated));
669
+ if (rulesModule) {
670
+ const result = rulesModule.calcDiscount(
671
+ {
672
+ productList: tempOrder.products,
673
+ discountList: updated,
674
+ holders,
675
+ isFormSubject: !!((_b = tempOrder.holder) == null ? void 0 : _b.type) && tempOrder.holder.type === "form"
676
+ },
677
+ {
678
+ discountId: params.discountId,
679
+ isSelected: params.isSelected
680
+ }
681
+ ) || { productList: tempOrder.products, discountList: updated };
682
+ if (result == null ? void 0 : result.productList) {
683
+ tempOrder.products = result.productList;
684
+ }
685
+ if (result == null ? void 0 : result.discountList) {
686
+ nextDiscountList = result.discountList;
687
+ if (!params.isSelected) {
688
+ const beforeSelectedIds = new Set(
689
+ updated.filter((d) => d.isSelected).map((d) => d.id)
690
+ );
691
+ for (const d of nextDiscountList) {
692
+ if (d.isSelected && !beforeSelectedIds.has(d.id)) {
693
+ d.isSelected = false;
694
+ }
695
+ }
696
+ }
697
+ }
698
+ }
699
+ const selectedResourceIds = new Set(
700
+ nextDiscountList.filter((d) => d.isSelected).map((d) => d.id)
701
+ );
702
+ for (const product of tempOrder.products) {
703
+ if ((_c = product._origin) == null ? void 0 : _c.isManualDiscount)
704
+ continue;
705
+ product.discount_list = (product.discount_list || []).filter((pd) => {
706
+ var _a2;
707
+ const rid = ((_a2 = pd.discount) == null ? void 0 : _a2.resource_id) ?? pd.id;
708
+ return rid != null && selectedResourceIds.has(rid);
709
+ });
710
+ const totalPerUnitDiscount = (product.discount_list || []).reduce(
711
+ (sum, pd) => sum + (pd.amount || 0),
712
+ 0
713
+ );
714
+ const optionSum = (0, import_utils2.sumOptionUnitPrice)(product.product_option_item);
715
+ const sourcePrice = ((_d = product.metadata) == null ? void 0 : _d.source_product_price) ?? (((_e = product.metadata) == null ? void 0 : _e.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
716
+ const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
717
+ const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
718
+ if (product.metadata) {
719
+ product.metadata.main_product_selling_price = newMainSellingPrice;
720
+ product.metadata.price_schema_version = 2;
721
+ }
722
+ product.selling_price = (0, import_utils2.composeLinePrice)({
723
+ mainPrice: newMainSellingPrice,
724
+ bundle: product.product_bundle
725
+ });
726
+ }
727
+ import_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
728
+ await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
729
+ tempOrder.discount_list = (nextDiscountList || []).filter((d) => d.isSelected);
730
+ await this.store.order.recalculateSummary({ createIfMissing: true });
731
+ this.store.order.persistTempOrder();
732
+ this.logMethodSuccess("setDiscountSelected", params);
733
+ } catch (error) {
734
+ this.logMethodError("setDiscountSelected", error);
735
+ throw error;
736
+ }
737
+ }
738
+ async onCustomerLogin(params) {
739
+ this.logMethodStart("onCustomerLogin", { customerId: params.customerId });
740
+ try {
741
+ await this.refreshOrderMarketingAfterLogin({
742
+ customerId: params.customerId
743
+ });
744
+ this.logMethodSuccess("onCustomerLogin", { customerId: params.customerId });
745
+ } catch (error) {
746
+ this.logMethodError("onCustomerLogin", error);
747
+ throw error;
748
+ }
749
+ }
750
+ // ScanOrder 提交 payload enhancer:
751
+ // - 给所有 booking 注入 appointment_status: 'started'(扫码点餐语义)
752
+ // - 给所有 booking 的 metadata 注入 resource_select_type(来自预约规则商品的 resource.type)
753
+ // - 给第一条 booking 补 resources 与 product_uid(仅当存在 resource / rule product)
754
+ // - 追加一条 is_rule=true 的 rule product,与 booking 互相关联
755
+ buildSubmitPayloadEnhancer() {
756
+ const ruleProduct = this.enabledReservationRuleProducts[0];
757
+ const resourceState = this.store.resource;
758
+ const resourceSelectType = resourceState == null ? void 0 : resourceState.resourceSelectType;
759
+ const resolveResourceCapacity = () => {
760
+ var _a;
761
+ if (resourceSelectType === "single") {
762
+ const raw = (_a = resourceState == null ? void 0 : resourceState.table_form_record) == null ? void 0 : _a.capacity;
763
+ const num = Number(raw);
764
+ if (Number.isFinite(num) && num > 0)
765
+ return num;
766
+ return 1;
767
+ }
768
+ return 1;
769
+ };
770
+ return (payload, { bookingUuid, tempOrder }) => {
771
+ var _a, _b;
772
+ const resourceId = tempOrder.resource_id ?? (resourceState == null ? void 0 : resourceState.relationId);
773
+ const pickOriginal = (value) => {
774
+ if (value && typeof value === "object" && !Array.isArray(value)) {
775
+ const original = value.original;
776
+ return typeof original === "string" && original.length > 0 ? original : void 0;
777
+ }
778
+ return void 0;
779
+ };
780
+ const mainField = pickOriginal(tempOrder.table_number) ?? pickOriginal((_a = resourceState == null ? void 0 : resourceState.table_form_record) == null ? void 0 : _a.name) ?? "";
781
+ const resourceEntry = resourceState && resourceId ? {
782
+ relation_type: "form",
783
+ like_status: "common",
784
+ id: Number(resourceId),
785
+ main_field: mainField,
786
+ form_id: resourceState.tableFormId,
787
+ relation_id: resourceState.relationId ?? resourceId,
788
+ capacity: resolveResourceCapacity(),
789
+ metadata: {}
790
+ } : void 0;
791
+ const ruleProductUid = ruleProduct ? (0, import_utils2.createUuidV4)() : void 0;
792
+ const rawCollectPax = (_b = tempOrder.metadata) == null ? void 0 : _b.collect_pax;
793
+ const hasCollectPaxForCapacity = rawCollectPax !== null && rawCollectPax !== void 0 && rawCollectPax !== "";
794
+ const bookingCapacityValue = hasCollectPaxForCapacity ? (0, import_utils2.normalizeSubmitCollectPaxValue)(rawCollectPax) : resolveResourceCapacity();
795
+ const bookingCapacityDimensionId = (0, import_utils.pickFirstCustomCapacityDimensionId)(this.enabledReservationRuleProducts) ?? 0;
796
+ const nextBookings = (payload.bookings || []).map((booking, idx) => {
797
+ var _a2;
798
+ return {
799
+ ...booking,
800
+ appointment_status: "started",
801
+ metadata: {
802
+ ...booking.metadata || {},
803
+ holder_id: ((_a2 = booking.metadata) == null ? void 0 : _a2.holder_id) ?? null,
804
+ ...resourceSelectType ? { resource_select_type: resourceSelectType } : {},
805
+ ...resourceSelectType ? {
806
+ capacity: [
807
+ {
808
+ id: bookingCapacityDimensionId,
809
+ value: bookingCapacityValue,
810
+ name: ""
811
+ }
812
+ ]
813
+ } : {}
814
+ },
815
+ ...idx === 0 && resourceEntry ? { resources: [resourceEntry] } : {},
816
+ ...idx === 0 && ruleProductUid ? { product_uid: ruleProductUid } : {}
817
+ };
818
+ });
819
+ const nextProducts = [...payload.products || []];
820
+ if (ruleProduct && ruleProductUid && !tempOrder.order_id) {
821
+ const sellingPrice = String(ruleProduct.price ?? "0.00");
822
+ const originalPrice = String(
823
+ ruleProduct.original_price ?? ruleProduct.price ?? "0.00"
824
+ );
825
+ nextProducts.push({
826
+ product_id: ruleProduct.id,
827
+ product_variant_id: 0,
828
+ num: 1,
829
+ selling_price: sellingPrice,
830
+ original_price: originalPrice,
831
+ payment_price: sellingPrice,
832
+ is_charge_tax: ruleProduct.is_gst ?? 0,
833
+ product_option_item: [],
834
+ discount_list: [],
835
+ product_bundle: [],
836
+ booking_uid: bookingUuid,
837
+ metadata: {
838
+ is_rule: true,
839
+ unique_identification_number: ruleProductUid,
840
+ booking_uid: bookingUuid
841
+ }
842
+ });
843
+ }
844
+ return { ...payload, bookings: nextBookings, products: nextProducts };
845
+ };
846
+ }
847
+ async submitScanOrder() {
848
+ var _a, _b, _c, _d, _e, _f, _g;
849
+ this.logMethodStart("submitScanOrder");
850
+ try {
851
+ await this.validateBeforeSubmitByItemRule();
852
+ if (!this.store.order) {
853
+ throw new Error("scanOrder解决方案需要 order 模块支持");
854
+ }
855
+ const pax = (0, import_utils2.normalizeSubmitCollectPaxValue)(this.store.entryPaxNumber);
856
+ this.store.entryPaxNumber = pax;
857
+ const tempOrderForSubmit = this.store.order.ensureTempOrder();
858
+ tempOrderForSubmit.metadata = { ...tempOrderForSubmit.metadata, collect_pax: pax };
859
+ tempOrderForSubmit.delivery_type = "shop_service";
860
+ const resourceTableName = (_b = (_a = this.store.resource) == null ? void 0 : _a.table_form_record) == null ? void 0 : _b.name;
861
+ if (resourceTableName && typeof resourceTableName === "object") {
862
+ tempOrderForSubmit.table_number = resourceTableName;
863
+ } else {
864
+ delete tempOrderForSubmit.table_number;
865
+ }
866
+ this.store.order.persistTempOrder();
867
+ const enhancePayload = this.buildSubmitPayloadEnhancer();
868
+ const result = await this.store.order.submitTempOrder({
869
+ cacheId: this.cacheId,
870
+ platform: (_c = this.otherParams) == null ? void 0 : _c.platform,
871
+ businessCode: (_d = this.otherParams) == null ? void 0 : _d.businessCode,
872
+ channel: (_e = this.otherParams) == null ? void 0 : _e.channel,
873
+ type: (_f = this.otherParams) == null ? void 0 : _f.type,
874
+ enhancePayload
875
+ });
876
+ const tempOrder = this.store.order.getTempOrder();
877
+ this.logMethodSuccess("submitScanOrder", {
878
+ productCount: ((_g = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _g.length) || 0
879
+ });
880
+ return result;
881
+ } catch (error) {
882
+ this.logMethodError("submitScanOrder", error);
883
+ throw error;
884
+ }
885
+ }
886
+ async addProductToOrder(product) {
887
+ this.logMethodStart("addProductToOrder", {
888
+ product_id: product.product_id,
889
+ product_variant_id: product.product_variant_id
890
+ });
891
+ try {
892
+ if (!this.store.order)
893
+ throw new Error("order 模块未初始化");
894
+ const products = await this.store.order.addProductToOrder(product);
895
+ await this.refreshItemRuleQuantityLimits();
896
+ await this.refreshCartValidationPassed();
897
+ this.logMethodSuccess("addProductToOrder", {
898
+ productCount: products.length
899
+ });
900
+ return products;
901
+ } catch (error) {
902
+ this.logMethodError("addProductToOrder", error);
903
+ throw error;
904
+ }
905
+ }
906
+ async updateProductInOrder(params) {
907
+ this.logMethodStart("updateProductInOrder", {
908
+ product_id: params.product_id,
909
+ product_variant_id: params.product_variant_id
910
+ });
911
+ try {
912
+ if (!this.store.order)
913
+ throw new Error("order 模块未初始化");
914
+ const products = await this.store.order.updateProductInOrder(params);
915
+ await this.refreshItemRuleQuantityLimits();
916
+ await this.refreshCartValidationPassed();
917
+ this.logMethodSuccess("updateProductInOrder", {
918
+ productCount: products.length
919
+ });
920
+ return products;
921
+ } catch (error) {
922
+ this.logMethodError("updateProductInOrder", error);
923
+ throw error;
924
+ }
925
+ }
926
+ /**
927
+ * 设置单行商品备注(与整单 `updateTempOrderNote` 区分)。
928
+ * 多行同 SKU 时必须传入与删除/更新一致的 identity(如 `identity_key`)。
929
+ */
930
+ async setOrderProductLineNote(identity, note) {
931
+ this.logMethodStart("setOrderProductLineNote", {
932
+ product_id: identity.product_id,
933
+ product_variant_id: identity.product_variant_id
934
+ });
935
+ try {
936
+ const params = {
937
+ product_id: identity.product_id,
938
+ product_variant_id: identity.product_variant_id,
939
+ updates: { note: String(note || "") }
940
+ };
941
+ if (identity.identity_key !== void 0) {
942
+ params.identity_key = identity.identity_key;
943
+ }
944
+ if (identity.product_option_item !== void 0) {
945
+ params.product_option_item = identity.product_option_item;
946
+ }
947
+ if (identity.product_bundle !== void 0)
948
+ params.product_bundle = identity.product_bundle;
949
+ const products = await this.updateProductInOrder(params);
950
+ this.logMethodSuccess("setOrderProductLineNote", { productCount: products.length });
951
+ return products;
952
+ } catch (error) {
953
+ this.logMethodError("setOrderProductLineNote", error);
954
+ throw error;
955
+ }
956
+ }
957
+ async removeProductFromOrder(identity) {
958
+ this.logMethodStart("removeProductFromOrder", {
959
+ product_id: identity.product_id,
960
+ product_variant_id: identity.product_variant_id
961
+ });
962
+ try {
963
+ if (!this.store.order)
964
+ throw new Error("order 模块未初始化");
965
+ const products = await this.store.order.removeProductFromOrder(identity);
966
+ await this.refreshItemRuleQuantityLimits();
967
+ await this.refreshCartValidationPassed();
968
+ this.logMethodSuccess("removeProductFromOrder", {
969
+ productCount: products.length
970
+ });
971
+ return products;
972
+ } catch (error) {
973
+ this.logMethodError("removeProductFromOrder", error);
974
+ throw error;
975
+ }
976
+ }
977
+ async loadRuntimeConfigs() {
978
+ const itemRuleConfigs = await this.ensureItemRuleConfigsLoaded();
979
+ this.logMethodSuccess("loadRuntimeConfigs", {
980
+ itemRuleCount: itemRuleConfigs.length
981
+ });
982
+ return {
983
+ itemRuleConfigs
984
+ };
985
+ }
986
+ async syncItemRuleConfigsFromDineInConfig(dineInConfig) {
987
+ const enableItemRules = (0, import_utils.toBoolean)(dineInConfig == null ? void 0 : dineInConfig["sale.enable_item_rules"]);
988
+ const strategyModelIds = (0, import_utils.normalizeEnabledItemRuleIds)(
989
+ dineInConfig == null ? void 0 : dineInConfig["sale.enabled_item_rules"]
990
+ );
991
+ if (!enableItemRules || !strategyModelIds.length) {
992
+ this.itemRuleConfigs = [];
993
+ this.itemRuleConfigsPromise = Promise.resolve([]);
994
+ this.itemRuleEvaluator.setStrategyConfigs([]);
995
+ this.logMethodSuccess("syncItemRuleConfigsFromDineInConfig", {
996
+ enabled: enableItemRules,
997
+ strategyModelIds: [],
998
+ itemRuleCount: 0
999
+ });
1000
+ return [];
1001
+ }
1002
+ const itemRuleConfigs = await this.fetchItemRuleConfigsByModelIds(
1003
+ strategyModelIds
1004
+ );
1005
+ this.itemRuleConfigs = itemRuleConfigs;
1006
+ this.itemRuleConfigsPromise = Promise.resolve(itemRuleConfigs);
1007
+ this.itemRuleEvaluator.setStrategyConfigs(itemRuleConfigs);
1008
+ this.logMethodSuccess("syncItemRuleConfigsFromDineInConfig", {
1009
+ enabled: enableItemRules,
1010
+ strategyModelIds,
1011
+ itemRuleCount: itemRuleConfigs.length
1012
+ });
1013
+ return itemRuleConfigs;
1014
+ }
1015
+ async fetchItemRuleConfigsByModelIds(strategyModelIds) {
1016
+ this.logMethodStart("fetchItemRuleConfigsByModelIds", {
1017
+ strategyModelIds
1018
+ });
1019
+ if (!strategyModelIds.length)
1020
+ return [];
1021
+ try {
1022
+ const result = await this.request.get("/promotion", {
1023
+ skip: 1,
1024
+ num: 99,
1025
+ status: "active",
1026
+ ids: strategyModelIds
1027
+ });
1028
+ let configs = [];
1029
+ if (result.code === 200) {
1030
+ configs = result.data.list.map((item) => {
1031
+ return item.metadata;
1032
+ });
1033
+ }
1034
+ this.logMethodSuccess("fetchItemRuleConfigsByModelIds", {
1035
+ strategyModelIds,
1036
+ strategyCount: configs.length
1037
+ });
1038
+ return configs;
1039
+ } catch (error) {
1040
+ this.logMethodError("fetchItemRuleConfigsByModelIds", error, {
1041
+ strategyModelIds
1042
+ });
1043
+ return [];
1044
+ }
1045
+ }
1046
+ async buildPrefillProductSourceMap() {
1047
+ const sourceMap = /* @__PURE__ */ new Map();
1048
+ try {
1049
+ const productList = await this.getProductList();
1050
+ if (!Array.isArray(productList))
1051
+ return sourceMap;
1052
+ const visited = /* @__PURE__ */ new Set();
1053
+ const collectFromValue = (value) => {
1054
+ if (!value || typeof value !== "object")
1055
+ return;
1056
+ if (visited.has(value))
1057
+ return;
1058
+ visited.add(value);
1059
+ if (Array.isArray(value)) {
1060
+ for (const item of value)
1061
+ collectFromValue(item);
1062
+ return;
1063
+ }
1064
+ const node = value;
1065
+ const rawProductId = node.product_id ?? node.id;
1066
+ const productId = Number(rawProductId);
1067
+ if (Number.isFinite(productId) && productId > 0) {
1068
+ const productVariantId = Number(
1069
+ node.product_variant_id ?? node.variant_id ?? 0
1070
+ );
1071
+ const normalizedVariantId = Number.isNaN(productVariantId) ? 0 : productVariantId;
1072
+ const key = (0, import_utils.buildProductKey)(productId, normalizedVariantId);
1073
+ if (!sourceMap.has(key)) {
1074
+ sourceMap.set(key, node);
1075
+ }
1076
+ }
1077
+ for (const childValue of Object.values(node)) {
1078
+ if (childValue && typeof childValue === "object") {
1079
+ collectFromValue(childValue);
1080
+ }
1081
+ }
1082
+ };
1083
+ collectFromValue(productList);
1084
+ } catch (error) {
1085
+ this.logMethodError("buildPrefillProductSourceMap", error);
1086
+ }
1087
+ return sourceMap;
1088
+ }
1089
+ getItemRuleRuntimeConfig() {
1090
+ return this.itemRuleRuntimeConfig || {};
1091
+ }
1092
+ async ensureItemRuleConfigsLoaded() {
1093
+ if (this.itemRuleConfigs.length > 0)
1094
+ return this.itemRuleConfigs;
1095
+ if (this.itemRuleConfigsPromise)
1096
+ return this.itemRuleConfigsPromise;
1097
+ this.itemRuleConfigsPromise = (async () => {
1098
+ const runtimeConfig = this.getItemRuleRuntimeConfig();
1099
+ const staticConfigs = (0, import_utils.normalizeItemRuleStrategies)(runtimeConfig.strategyConfigs);
1100
+ if (staticConfigs.length > 0) {
1101
+ this.itemRuleConfigs = staticConfigs;
1102
+ this.itemRuleEvaluator.setStrategyConfigs(staticConfigs);
1103
+ return this.itemRuleConfigs;
1104
+ }
1105
+ this.itemRuleConfigs = [];
1106
+ this.itemRuleEvaluator.setStrategyConfigs([]);
1107
+ return this.itemRuleConfigs;
1108
+ })();
1109
+ const loadedConfigs = await this.itemRuleConfigsPromise;
1110
+ return loadedConfigs;
1111
+ }
1112
+ async refreshItemRuleQuantityLimits() {
1113
+ try {
1114
+ const strategyConfigs = await this.ensureItemRuleConfigsLoaded();
1115
+ if (!strategyConfigs.length) {
1116
+ this.store.itemRuleQuantityLimits = [];
1117
+ return [];
1118
+ }
1119
+ const businessData = (0, import_utils.buildItemRuleBusinessData)({
1120
+ tempOrder: this.ensureTempOrder(),
1121
+ runtimeConfig: this.getItemRuleRuntimeConfig(),
1122
+ itemRuleConfigs: this.itemRuleConfigs
1123
+ });
1124
+ const limits = this.itemRuleEvaluator.getQuantityLimits(businessData);
1125
+ this.store.itemRuleQuantityLimits = limits;
1126
+ this.logMethodSuccess("refreshItemRuleQuantityLimits", {
1127
+ limitCount: limits.length
1128
+ });
1129
+ return limits;
1130
+ } catch (error) {
1131
+ this.store.itemRuleQuantityLimits = [];
1132
+ this.logMethodError("refreshItemRuleQuantityLimits", error);
1133
+ return [];
1134
+ }
1135
+ }
1136
+ async applyPrefillByItemRule() {
1137
+ var _a, _b, _c;
1138
+ if (this.itemRulePrefillApplied)
1139
+ return;
1140
+ if (!this.store.order)
1141
+ return;
1142
+ const strategyConfigs = await this.ensureItemRuleConfigsLoaded();
1143
+ if (!strategyConfigs.length)
1144
+ return;
1145
+ const businessData = (0, import_utils.buildItemRuleBusinessData)({
1146
+ tempOrder: this.ensureTempOrder(),
1147
+ runtimeConfig: this.getItemRuleRuntimeConfig(),
1148
+ itemRuleConfigs: this.itemRuleConfigs
1149
+ });
1150
+ const prefillItems = this.itemRuleEvaluator.getPrefillItems(businessData);
1151
+ if (!prefillItems.length) {
1152
+ this.itemRulePrefillApplied = true;
1153
+ return;
1154
+ }
1155
+ const productSourceMap = await this.buildPrefillProductSourceMap();
1156
+ const tempOrder = this.ensureTempOrder();
1157
+ let hasChanges = false;
1158
+ for (const prefillItem of prefillItems) {
1159
+ const productId = Number(prefillItem.product_id);
1160
+ const productVariantId = Number(prefillItem.product_variant_id ?? 0);
1161
+ const targetQuantity = (0, import_utils.toNonNegativeInt)(prefillItem.quantity);
1162
+ if (!Number.isFinite(productId) || targetQuantity <= 0)
1163
+ continue;
1164
+ if (Number.isNaN(productVariantId))
1165
+ continue;
1166
+ const sourceItem = productSourceMap.get(
1167
+ (0, import_utils.buildProductKey)(productId, productVariantId)
1168
+ ) || productSourceMap.get((0, import_utils.buildProductKey)(productId, 0)) || null;
1169
+ const productIndex = (0, import_utils.getProductIdentityIndex)(tempOrder.products, {
1170
+ product_id: productId,
1171
+ product_variant_id: productVariantId
1172
+ });
1173
+ if (productIndex === -1) {
1174
+ const sellingPrice = (0, import_utils.toPriceString)(
1175
+ (sourceItem == null ? void 0 : sourceItem.price) ?? (sourceItem == null ? void 0 : sourceItem.selling_price),
1176
+ "0.00"
1177
+ );
1178
+ tempOrder.products.push(
1179
+ (0, import_utils.normalizeOrderProduct)({
1180
+ ...sourceItem,
1181
+ product_id: productId,
1182
+ product_variant_id: productVariantId,
1183
+ num: targetQuantity,
1184
+ selling_price: sellingPrice,
1185
+ original_price: sellingPrice,
1186
+ metadata: {
1187
+ item_rule_prefill: true,
1188
+ item_rule_id: prefillItem.ruleId
1189
+ },
1190
+ _origin: {
1191
+ ...sourceItem || {},
1192
+ item_rule_prefill: true,
1193
+ item_rule_id: prefillItem.ruleId
1194
+ }
1195
+ })
1196
+ );
1197
+ hasChanges = true;
1198
+ continue;
1199
+ }
1200
+ const targetProduct = tempOrder.products[productIndex];
1201
+ const existedQuantity = (0, import_utils.toNonNegativeInt)(targetProduct.num);
1202
+ const delta = targetQuantity - existedQuantity;
1203
+ const nextProduct = {
1204
+ ...targetProduct,
1205
+ ...delta > 0 ? { num: (0, import_utils.getSafeProductNum)(existedQuantity + delta) } : {},
1206
+ metadata: {
1207
+ ...targetProduct.metadata || {},
1208
+ item_rule_prefill: true,
1209
+ item_rule_id: prefillItem.ruleId
1210
+ },
1211
+ // TODO(Order types): migrate ScanOrder prefill origin runtime into tempOrder._extend.
1212
+ _origin: sourceItem ? {
1213
+ ...targetProduct._origin || {},
1214
+ ...sourceItem
1215
+ } : targetProduct._origin
1216
+ };
1217
+ const hasQuantityChanged = delta > 0;
1218
+ const hasOriginChanged = Boolean(
1219
+ sourceItem && (!targetProduct._origin || ((_a = targetProduct._origin) == null ? void 0 : _a.name) !== (sourceItem == null ? void 0 : sourceItem.name) || ((_b = targetProduct._origin) == null ? void 0 : _b.title) !== (sourceItem == null ? void 0 : sourceItem.title) || ((_c = targetProduct._origin) == null ? void 0 : _c.price) !== (sourceItem == null ? void 0 : sourceItem.price))
1220
+ );
1221
+ if (hasQuantityChanged || hasOriginChanged) {
1222
+ tempOrder.products[productIndex] = nextProduct;
1223
+ hasChanges = true;
1224
+ }
1225
+ }
1226
+ if (hasChanges) {
1227
+ this.store.order.applyDiscount();
1228
+ await this.store.order.recalculateSummary({ createIfMissing: true });
1229
+ this.store.order.persistTempOrder();
1230
+ }
1231
+ await this.refreshItemRuleQuantityLimits();
1232
+ this.itemRulePrefillApplied = true;
1233
+ this.logMethodSuccess("applyPrefillByItemRule", {
1234
+ prefillCount: prefillItems.length,
1235
+ hasChanges
1236
+ });
1237
+ }
1238
+ async applyItemRulePrefill() {
1239
+ var _a, _b;
1240
+ if ((_b = (_a = this.store.order) == null ? void 0 : _a.getLastOrderInfo) == null ? void 0 : _b.call(_a)) {
1241
+ return;
1242
+ }
1243
+ this.logMethodStart("applyItemRulePrefill");
1244
+ await this.applyPrefillByItemRule();
1245
+ await this.refreshItemRuleQuantityLimits();
1246
+ await this.refreshCartValidationPassed();
1247
+ }
1248
+ async evaluateCartValidationByItemRule() {
1249
+ const strategyConfigs = await this.ensureItemRuleConfigsLoaded();
1250
+ if (!strategyConfigs.length) {
1251
+ return {
1252
+ passed: true,
1253
+ failures: []
1254
+ };
1255
+ }
1256
+ const businessData = (0, import_utils.buildItemRuleBusinessData)({
1257
+ tempOrder: this.ensureTempOrder(),
1258
+ runtimeConfig: this.getItemRuleRuntimeConfig(),
1259
+ itemRuleConfigs: this.itemRuleConfigs
1260
+ });
1261
+ return this.itemRuleEvaluator.validateCart(businessData);
1262
+ }
1263
+ async validateBeforeSubmitByItemRule() {
1264
+ const validationResult = await this.evaluateCartValidationByItemRule();
1265
+ if (validationResult.passed)
1266
+ return;
1267
+ const firstFailure = validationResult.failures[0];
1268
+ const errorMessage = (firstFailure == null ? void 0 : firstFailure.validationMessage) || "当前购物车未满足商品规则,请调整后再提交";
1269
+ const error = new Error(String(errorMessage));
1270
+ error.failures = validationResult.failures;
1271
+ throw error;
1272
+ }
1273
+ async refreshCartValidationPassed() {
1274
+ const previous = this.store.cartValidation || {
1275
+ passed: null,
1276
+ failures: []
1277
+ };
1278
+ let nextState = {
1279
+ passed: null,
1280
+ failures: []
1281
+ };
1282
+ try {
1283
+ const validationResult = await this.evaluateCartValidationByItemRule();
1284
+ nextState = {
1285
+ passed: validationResult.passed,
1286
+ failures: validationResult.failures || []
1287
+ };
1288
+ } catch (error) {
1289
+ nextState = {
1290
+ passed: false,
1291
+ failures: []
1292
+ };
1293
+ }
1294
+ this.store.cartValidation = nextState;
1295
+ const changed = previous.passed !== nextState.passed || previous.failures !== nextState.failures;
1296
+ if (changed) {
1297
+ await this.core.effects.emit(import_types.ScanOrderHooks.onCartValidationChanged, {
1298
+ cartValidation: nextState,
1299
+ cartValidationPassed: nextState.passed
1300
+ });
1301
+ }
1302
+ return nextState.passed;
1303
+ }
1304
+ async setItemRuleRuntimeConfig(config = {}) {
1305
+ var _a, _b;
1306
+ this.logMethodStart("setItemRuleRuntimeConfig");
1307
+ this.itemRuleRuntimeConfig = {
1308
+ ...this.itemRuleRuntimeConfig,
1309
+ ...config,
1310
+ pax: {
1311
+ ...((_a = this.itemRuleRuntimeConfig) == null ? void 0 : _a.pax) || {},
1312
+ ...(config == null ? void 0 : config.pax) || {}
1313
+ },
1314
+ custom: {
1315
+ ...((_b = this.itemRuleRuntimeConfig) == null ? void 0 : _b.custom) || {},
1316
+ ...(config == null ? void 0 : config.custom) || {}
1317
+ }
1318
+ };
1319
+ if ("strategyConfigs" in config) {
1320
+ this.itemRuleConfigs = [];
1321
+ this.itemRuleConfigsPromise = null;
1322
+ this.itemRuleEvaluator.setStrategyConfigs([]);
1323
+ }
1324
+ this.itemRulePrefillApplied = false;
1325
+ await this.refreshItemRuleQuantityLimits();
1326
+ await this.refreshCartValidationPassed();
1327
+ this.logMethodSuccess("setItemRuleRuntimeConfig", {
1328
+ strategyCount: Array.isArray(this.itemRuleRuntimeConfig.strategyConfigs) ? this.itemRuleRuntimeConfig.strategyConfigs.length : 0
1329
+ });
1330
+ }
1331
+ normalizeResourceState(detail, resourceSelectType, hasOrderId) {
1332
+ var _a, _b, _c, _d;
1333
+ const currentOrderId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.order_id);
1334
+ const lastOrderId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.last_order_id);
1335
+ const relationId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.form_record_id);
1336
+ const tableFormId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.form_id);
1337
+ const formRecord = (detail == null ? void 0 : detail.form_record) ?? null;
1338
+ const allowSnack = ((_b = (_a = this.otherParams) == null ? void 0 : _a.dineInConfig) == null ? void 0 : _b["sale.allow_add_items"]) || false;
1339
+ const deskmateValid = false;
1340
+ const isExclusive = resourceSelectType === "single";
1341
+ const isFull = (0, import_utils.computeResourceIsFull)({
1342
+ resourceSelectType,
1343
+ lastOrderId,
1344
+ capacityList: ((_d = (_c = detail == null ? void 0 : detail.resource_capacity) == null ? void 0 : _c[0]) == null ? void 0 : _d.capacity_list) ?? [],
1345
+ capacity: formRecord == null ? void 0 : formRecord.capacity
1346
+ });
1347
+ let availabilityInfo = {
1348
+ mode: "idle",
1349
+ deskmate_valid: deskmateValid
1350
+ };
1351
+ if (currentOrderId) {
1352
+ if (!hasOrderId) {
1353
+ availabilityInfo = {
1354
+ mode: "resource_busy",
1355
+ order_id: currentOrderId,
1356
+ relation_id: relationId,
1357
+ table_form_id: tableFormId,
1358
+ deskmate_valid: deskmateValid
1359
+ };
1360
+ } else {
1361
+ availabilityInfo = {
1362
+ mode: allowSnack ? "additional_order" : "resource_busy",
1363
+ order_id: currentOrderId,
1364
+ relation_id: relationId,
1365
+ table_form_id: tableFormId,
1366
+ deskmate_valid: deskmateValid
1367
+ };
1368
+ }
1369
+ } else if (lastOrderId) {
1370
+ const canFallthroughToIdle = resourceSelectType === "multiple" && !isFull;
1371
+ if (!canFallthroughToIdle) {
1372
+ availabilityInfo = {
1373
+ mode: "resource_busy",
1374
+ order_id: "0",
1375
+ relation_id: relationId,
1376
+ table_form_id: tableFormId,
1377
+ deskmate_valid: deskmateValid
1378
+ };
1379
+ }
1380
+ }
1381
+ return {
1382
+ ...availabilityInfo,
1383
+ currentOrderId,
1384
+ lastOrderId,
1385
+ relationId,
1386
+ tableFormId,
1387
+ allowSnack,
1388
+ deskmateValid,
1389
+ isExclusive,
1390
+ isFull,
1391
+ resourceSelectType,
1392
+ raw: detail,
1393
+ table_form_record: formRecord
1394
+ };
1395
+ }
1396
+ // 从首个预约规则商品的 product_resource.resources 中,按 form_id 匹配返回 type
1397
+ resolveResourceSelectType(formId) {
1398
+ var _a;
1399
+ const firstProduct = this.enabledReservationRuleProducts[0];
1400
+ const resources = ((_a = firstProduct == null ? void 0 : firstProduct.product_resource) == null ? void 0 : _a.resources) || [];
1401
+ const numericFormId = Number(formId);
1402
+ if (!Number.isFinite(numericFormId) || numericFormId <= 0)
1403
+ return void 0;
1404
+ const matched = resources.find((r) => Number(r == null ? void 0 : r.id) === numericFormId);
1405
+ return matched == null ? void 0 : matched.type;
1406
+ }
1407
+ async fetchResourceOccupyDetailByResourceId(resourceId) {
1408
+ var _a, _b, _c, _d;
1409
+ const formRecordId = Number(resourceId);
1410
+ if (!Number.isFinite(formRecordId) || formRecordId <= 0) {
1411
+ throw new Error(`[ScanOrder] 非法桌台 resourceId: ${resourceId}`);
1412
+ }
1413
+ const shopId = (_b = (_a = this.otherParams) == null ? void 0 : _a.getStateData) == null ? void 0 : _b.call(_a, "shop_id");
1414
+ if (!shopId) {
1415
+ throw new Error("[ScanOrder] 无法获取 shop_id");
1416
+ }
1417
+ const response = await this.request.get(
1418
+ "/order/resource/occupy-detail",
1419
+ {
1420
+ shop_id: shopId,
1421
+ "form_record_ids[]": formRecordId,
1422
+ with_resource_capacity_info: 1,
1423
+ with_resource_order_info: 1,
1424
+ with_resource_form_info: 1
1425
+ }
1426
+ );
1427
+ if (!(response == null ? void 0 : response.status)) {
1428
+ throw new Error((response == null ? void 0 : response.message) || "获取资源占用详情失败");
1429
+ }
1430
+ return ((_d = (_c = response == null ? void 0 : response.data) == null ? void 0 : _c.occupy_details) == null ? void 0 : _d[0]) ?? null;
1431
+ }
1432
+ // 检测当前链接是否可用
1433
+ // 通过 resource_id + 店铺配置
1434
+ // hasOrderId 表示 url 上是否有 orderid,如果是的话,后续的流程会走加单
1435
+ async checkResourceAvailable(resourceId, hasOrderId) {
1436
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
1437
+ this.logMethodStart("checkResourceAvailable", {
1438
+ resourceId
1439
+ });
1440
+ try {
1441
+ const openData = await ((_b = (_a = this.otherParams) == null ? void 0 : _a.getOpenData) == null ? void 0 : _b.call(_a, {
1442
+ scope: "board",
1443
+ target: "dine_in+scan_to_order",
1444
+ section_code: ["basic", "fulfillment", "reservation", "sale", "menu", "availability", "workflow"]
1445
+ }));
1446
+ if ((openData == null ? void 0 : openData.status) === false) {
1447
+ throw new Error((openData == null ? void 0 : openData.message) || "获取店铺配置失败");
1448
+ }
1449
+ const dineInConfig = (openData == null ? void 0 : openData.data) || {};
1450
+ this.otherParams.dineInConfig = dineInConfig;
1451
+ await this.syncItemRuleConfigsFromDineInConfig(dineInConfig);
1452
+ const closedBehaviorValue = dineInConfig == null ? void 0 : dineInConfig["availability.closed_behavior"];
1453
+ const closedMessage = (dineInConfig == null ? void 0 : dineInConfig["availability.closed_message"]) || (dineInConfig == null ? void 0 : dineInConfig["availability.message"]) || (dineInConfig == null ? void 0 : dineInConfig["basic.closed_message"]);
1454
+ const basicUnavailableMessage = (dineInConfig == null ? void 0 : dineInConfig["basic.unavailable_message"]) || closedMessage;
1455
+ const pauseMessage = (dineInConfig == null ? void 0 : dineInConfig["availability.pause_message"]) || closedMessage;
1456
+ const makeShopClosed = (errorTips, closed_behavior) => ({
1457
+ mode: "shop_closed",
1458
+ order_id: void 0,
1459
+ relation_id: void 0,
1460
+ table_form_id: void 0,
1461
+ deskmate_valid: false,
1462
+ errorTips,
1463
+ closed_behavior
1464
+ });
1465
+ if ((dineInConfig == null ? void 0 : dineInConfig["basic.enable"]) === false) {
1466
+ return makeShopClosed(basicUnavailableMessage);
1467
+ }
1468
+ if ((0, import_utils.toBoolean)(dineInConfig == null ? void 0 : dineInConfig["availability.paused"])) {
1469
+ if ((dineInConfig == null ? void 0 : dineInConfig["availability.pause_behavior"]) === "hide_all") {
1470
+ return makeShopClosed(pauseMessage);
1471
+ }
1472
+ }
1473
+ const operatingHourIds = Array.isArray(dineInConfig == null ? void 0 : dineInConfig["availability.operating_hours"]) ? dineInConfig["availability.operating_hours"].map((id) => Number(id)).filter((id) => Number.isFinite(id) && id > 0) : [];
1474
+ let outsideOperatingHours = false;
1475
+ if (operatingHourIds.length && this.store.schedule) {
1476
+ const scheduleList = this.store.schedule.getScheduleListByIds(operatingHourIds);
1477
+ if (scheduleList.length) {
1478
+ const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1479
+ outsideOperatingHours = !(0, import_getDateIsInSchedule.getDateIsInSchedule)(now, scheduleList);
1480
+ }
1481
+ }
1482
+ if (outsideOperatingHours && closedBehaviorValue !== "show_menu_disabled") {
1483
+ return makeShopClosed(closedMessage, closedBehaviorValue);
1484
+ }
1485
+ const tempOrder = this.ensureTempOrder();
1486
+ const reservationLinkIds = (0, import_utils.collectLinkProductIdsFromReservationRules)(
1487
+ dineInConfig["fulfillment.enabled_resource_rules"]
1488
+ );
1489
+ let pendingRequestEntryPax;
1490
+ let pendingRequestPaxMin;
1491
+ let pendingRequestPaxMax;
1492
+ if (reservationLinkIds.length === 0) {
1493
+ this.enabledReservationRuleProducts = [];
1494
+ } else {
1495
+ tempOrder.metadata = { ...tempOrder.metadata || {} };
1496
+ delete tempOrder.metadata.table_occupancy_duration;
1497
+ const reservationProductList = new import_ProductList.ProductList(
1498
+ `${this.name}_reservationEnabledRules`,
1499
+ this.defaultVersion
1500
+ );
1501
+ await reservationProductList.initialize(this.core, {
1502
+ store: { list: [], selectProducts: [] },
1503
+ otherParams: {
1504
+ ...this.otherParams,
1505
+ fatherModule: this.name,
1506
+ openCache: Boolean(this.cacheId),
1507
+ cacheId: this.cacheId
1508
+ }
1509
+ });
1510
+ const scheduleDate = (0, import_dayjs.default)().format("YYYY-MM-DD");
1511
+ const scheduleDatetime = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1512
+ const loaded = await reservationProductList.loadProducts({
1513
+ product_ids: reservationLinkIds,
1514
+ schedule_date: scheduleDate,
1515
+ schedule_datetime: scheduleDatetime,
1516
+ cacheId: this.cacheId
1517
+ });
1518
+ if (Array.isArray(loaded)) {
1519
+ this.enabledReservationRuleProducts = loaded;
1520
+ const occupancyMinutes = (0, import_utils.pickFirstDurationMinutesFromProducts)(loaded);
1521
+ if (occupancyMinutes !== void 0) {
1522
+ tempOrder.metadata.table_occupancy_duration = occupancyMinutes;
1523
+ }
1524
+ if ((0, import_utils.hasCustomCapacityProduct)(loaded)) {
1525
+ pendingRequestEntryPax = 1;
1526
+ const paxBounds = (0, import_utils.pickFirstCustomCapacityPaxBounds)(loaded);
1527
+ if ((paxBounds == null ? void 0 : paxBounds.min) !== void 0)
1528
+ pendingRequestPaxMin = paxBounds.min;
1529
+ if ((paxBounds == null ? void 0 : paxBounds.max) !== void 0)
1530
+ pendingRequestPaxMax = paxBounds.max;
1531
+ }
1532
+ } else {
1533
+ this.enabledReservationRuleProducts = [];
1534
+ void this.addScanOrderLog({
1535
+ level: "error",
1536
+ title: "[ScanOrder] enabled_reservation_rules product query failed",
1537
+ payload: {
1538
+ linkIds: reservationLinkIds,
1539
+ error: this.serializeError(loaded)
1540
+ }
1541
+ });
1542
+ }
1543
+ }
1544
+ const occupyDetail = await this.fetchResourceOccupyDetailByResourceId(resourceId);
1545
+ const resourceSelectType = this.resolveResourceSelectType(
1546
+ (0, import_utils.toPositiveString)(occupyDetail == null ? void 0 : occupyDetail.form_id)
1547
+ );
1548
+ const resourceState = this.normalizeResourceState(
1549
+ occupyDetail,
1550
+ resourceSelectType,
1551
+ hasOrderId
1552
+ );
1553
+ this.store.resource = resourceState;
1554
+ if (pendingRequestEntryPax !== void 0) {
1555
+ this.store.resource.requestEntryPax = pendingRequestEntryPax;
1556
+ }
1557
+ if (pendingRequestPaxMin !== void 0) {
1558
+ this.store.resource.requestPaxMin = pendingRequestPaxMin;
1559
+ }
1560
+ if (pendingRequestPaxMax !== void 0) {
1561
+ this.store.resource.requestPaxMax = pendingRequestPaxMax;
1562
+ }
1563
+ const availabilityInfo = {
1564
+ mode: resourceState.mode,
1565
+ order_id: resourceState.order_id,
1566
+ relation_id: resourceState.relationId,
1567
+ table_form_id: resourceState.tableFormId,
1568
+ deskmate_valid: resourceState.deskmate_valid,
1569
+ table_form_record: resourceState.table_form_record,
1570
+ policy: (_c = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _c.policy,
1571
+ partyroom_booking: (_d = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _d.partyroom_booking,
1572
+ ...this.store.resource.requestEntryPax !== void 0 ? { requestEntryPax: this.store.resource.requestEntryPax } : {},
1573
+ ...this.store.resource.requestPaxMin !== void 0 ? { requestPaxMin: this.store.resource.requestPaxMin } : {},
1574
+ ...this.store.resource.requestPaxMax !== void 0 ? { requestPaxMax: this.store.resource.requestPaxMax } : {}
1575
+ };
1576
+ tempOrder.relation_id = resourceId || ((_e = this.otherParams) == null ? void 0 : _e.relation_id);
1577
+ tempOrder.table_form_id = resourceState.tableFormId;
1578
+ tempOrder.resource_id = resourceId;
1579
+ (_f = this.store.order) == null ? void 0 : _f.persistTempOrder();
1580
+ if (availabilityInfo.mode === "idle") {
1581
+ await this.addNewOrder();
1582
+ }
1583
+ if (availabilityInfo.mode === "additional_order" || availabilityInfo.mode === "additional_order_with_code") {
1584
+ tempOrder.order_id = resourceState.lastOrderId;
1585
+ }
1586
+ if (tempOrder.order_id) {
1587
+ const res = await ((_g = this.store.order) == null ? void 0 : _g.getOrderInfoByRemote(tempOrder.order_id));
1588
+ const entryPaxNumber = (_k = (_j = (_i = (_h = res == null ? void 0 : res.data) == null ? void 0 : _h.bookings) == null ? void 0 : _i.find((p) => {
1589
+ var _a2;
1590
+ return (_a2 = p.metadata) == null ? void 0 : _a2.collect_pax;
1591
+ })) == null ? void 0 : _j.metadata) == null ? void 0 : _k.collect_pax;
1592
+ if (entryPaxNumber) {
1593
+ await this.setEntryPaxNumber(entryPaxNumber);
1594
+ }
1595
+ }
1596
+ const lastOrderInfo = (_m = (_l = this.store.order) == null ? void 0 : _l.getLastOrderInfo) == null ? void 0 : _m.call(_l);
1597
+ const historicalItems = hasOrderId && Array.isArray(lastOrderInfo == null ? void 0 : lastOrderInfo.products) ? lastOrderInfo.products.reduce((acc, p) => {
1598
+ if (typeof (p == null ? void 0 : p.product_id) !== "number")
1599
+ return acc;
1600
+ acc.push({
1601
+ product_id: p.product_id,
1602
+ quantity: Number(p.product_quantity) || 0,
1603
+ ...typeof p.product_variant_id === "number" ? { product_variant_id: p.product_variant_id } : {}
1604
+ });
1605
+ return acc;
1606
+ }, []) : [];
1607
+ await this.setItemRuleRuntimeConfig({
1608
+ serviceType: (_n = this.otherParams) == null ? void 0 : _n.businessCode,
1609
+ submissionIndex: hasOrderId ? 1 : 0,
1610
+ historicalItems
1611
+ });
1612
+ if (outsideOperatingHours && closedBehaviorValue === "show_menu_disabled") {
1613
+ availabilityInfo.mode = "submit_disabled";
1614
+ availabilityInfo.errorTips = closedMessage;
1615
+ availabilityInfo.closed_behavior = closedBehaviorValue;
1616
+ }
1617
+ this.logMethodSuccess("checkResourceAvailable", {
1618
+ resourceId,
1619
+ mode: availabilityInfo.mode,
1620
+ orderId: availabilityInfo.order_id,
1621
+ relationId: availabilityInfo.relation_id,
1622
+ tableFormId: availabilityInfo.table_form_id,
1623
+ persistedRelationId: tempOrder.relation_id,
1624
+ persistedResourceId: tempOrder.resource_id,
1625
+ deskmateValid: availabilityInfo.deskmate_valid,
1626
+ resourceSelectType: resourceState.resourceSelectType,
1627
+ isExclusive: resourceState.isExclusive,
1628
+ isFull: resourceState.isFull
1629
+ });
1630
+ return availabilityInfo;
1631
+ } catch (error) {
1632
+ this.logMethodError("checkResourceAvailable", error.message, {
1633
+ resourceId
1634
+ });
1635
+ throw error;
1636
+ }
1637
+ }
1638
+ // 如果是加单的情况,提供返回当前订单相关信息的能力
1639
+ async getAdditionalOrderInfo() {
1640
+ this.logMethodStart("getAdditionalOrderInfo");
1641
+ const result = {
1642
+ orderId: "123567890",
1643
+ orderStatus: "pending",
1644
+ orderTime: "2026-03-31 10:00:00",
1645
+ orderAmount: 100,
1646
+ orderItems: []
1647
+ };
1648
+ this.logMethodSuccess("getAdditionalOrderInfo", {
1649
+ orderId: result.orderId,
1650
+ orderStatus: result.orderStatus
1651
+ });
1652
+ return result;
1653
+ }
1654
+ // 获取商品列表
1655
+ async getProductList() {
1656
+ var _a, _b, _c;
1657
+ this.logMethodStart("getProductList");
1658
+ const menu_list_ids = ((_b = (_a = this.otherParams) == null ? void 0 : _a.dineInConfig) == null ? void 0 : _b["menu.associated_menus"].map((n) => Number(n.value))) || [];
1659
+ try {
1660
+ const res = await ((_c = this.store.products) == null ? void 0 : _c.loadProducts({
1661
+ menu_list_ids,
1662
+ cacheId: this.cacheId,
1663
+ schedule_date: (0, import_dayjs.default)().format("YYYY-MM-DD"),
1664
+ schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
1665
+ }));
1666
+ const formattedRes = (0, import_utils.attachItemRuleLimitsToTopLevelProducts)(
1667
+ res,
1668
+ this.store.itemRuleQuantityLimits || []
1669
+ );
1670
+ this.logMethodSuccess("getProductList", {
1671
+ menuCount: menu_list_ids.length
1672
+ });
1673
+ return formattedRes;
1674
+ } catch (error) {
1675
+ this.logMethodError("getProductList", error.message);
1676
+ throw error;
1677
+ }
1678
+ }
1679
+ getOtherParams() {
1680
+ return this.otherParams;
1681
+ }
1682
+ async setOtherParams(params, { cover = false } = {}) {
1683
+ if (cover) {
1684
+ this.otherParams = params;
1685
+ } else {
1686
+ this.otherParams = { ...this.otherParams, ...params };
1687
+ }
1688
+ }
1689
+ getUIStateBucketKey() {
1690
+ if (!this.cacheId)
1691
+ return null;
1692
+ return `${_ScanOrderImpl.UI_STATE_KEY_PREFIX}${this.cacheId}`;
1693
+ }
1694
+ readUIStateBucket() {
1695
+ var _a;
1696
+ const key = this.getUIStateBucketKey();
1697
+ if (!key || !((_a = this.window) == null ? void 0 : _a.localStorage))
1698
+ return {};
1699
+ try {
1700
+ const raw = this.window.localStorage.getItem(key) || "{}";
1701
+ const parsed = JSON.parse(raw);
1702
+ return parsed && typeof parsed === "object" ? parsed : {};
1703
+ } catch {
1704
+ return {};
1705
+ }
1706
+ }
1707
+ writeUIStateBucket(bucket) {
1708
+ var _a;
1709
+ const key = this.getUIStateBucketKey();
1710
+ if (!key || !((_a = this.window) == null ? void 0 : _a.localStorage))
1711
+ return;
1712
+ try {
1713
+ this.window.localStorage.setItem(key, JSON.stringify(bucket));
1714
+ } catch (error) {
1715
+ console.warn("[ScanOrder] writeUIStateBucket failed", error);
1716
+ }
1717
+ }
1718
+ setUIState(key, value) {
1719
+ if (!this.getUIStateBucketKey())
1720
+ return;
1721
+ const bucket = this.readUIStateBucket();
1722
+ bucket[key] = value;
1723
+ this.writeUIStateBucket(bucket);
1724
+ }
1725
+ getUIState(key) {
1726
+ if (!this.getUIStateBucketKey())
1727
+ return void 0;
1728
+ const bucket = this.readUIStateBucket();
1729
+ return bucket[key];
1730
+ }
1731
+ deleteUIState(key) {
1732
+ if (!this.getUIStateBucketKey())
1733
+ return;
1734
+ const bucket = this.readUIStateBucket();
1735
+ if (key in bucket) {
1736
+ delete bucket[key];
1737
+ this.writeUIStateBucket(bucket);
1738
+ }
1739
+ }
1740
+ // 整桶清空(用于扫新桌、提交成功、restoreOrder 等场景)
1741
+ clearUIState() {
1742
+ var _a;
1743
+ const key = this.getUIStateBucketKey();
1744
+ if (!key || !((_a = this.window) == null ? void 0 : _a.localStorage))
1745
+ return;
1746
+ try {
1747
+ this.window.localStorage.removeItem(key);
1748
+ } catch (error) {
1749
+ console.warn("[ScanOrder] clearUIState failed", error);
1750
+ }
1751
+ }
1752
+ async setEntryPaxNumber(number) {
1753
+ const pax = (0, import_utils2.normalizeSubmitCollectPaxValue)(number);
1754
+ this.store.entryPaxNumber = pax;
1755
+ if (this.store.order) {
1756
+ const t = this.store.order.ensureTempOrder();
1757
+ t.metadata = { ...t.metadata, collect_pax: pax };
1758
+ this.store.order.persistTempOrder();
1759
+ }
1760
+ this.itemRuleRuntimeConfig = {
1761
+ ...this.itemRuleRuntimeConfig,
1762
+ pax: { total: pax, adult: 0, child: 0 }
1763
+ };
1764
+ this.itemRulePrefillApplied = false;
1765
+ await this.refreshItemRuleQuantityLimits();
1766
+ await this.refreshCartValidationPassed();
1767
+ }
1768
+ getEntryPaxNumber() {
1769
+ return this.store.entryPaxNumber;
1770
+ }
1771
+ // 读取取餐/送餐开关
1772
+ // 依赖 checkResourceAvailable 已缓存的 dineInConfig
1773
+ getFulfillmentModes() {
1774
+ var _a;
1775
+ this.logMethodStart("getFulfillmentModes");
1776
+ const dineInConfig = ((_a = this.otherParams) == null ? void 0 : _a.dineInConfig) || {};
1777
+ const result = {
1778
+ enablePickup: Boolean(dineInConfig["fulfillment.enable_pickup"]),
1779
+ enableTableService: Boolean(dineInConfig["fulfillment.enable_table_service"])
1780
+ };
1781
+ this.logMethodSuccess("getFulfillmentModes", result);
1782
+ return result;
1783
+ }
1784
+ // 判定后台是否开启客户自定义取餐标识
1785
+ // 依赖 checkResourceAvailable 已缓存的 dineInConfig
1786
+ checkManualPickupRef() {
1787
+ var _a;
1788
+ this.logMethodStart("checkManualPickupRef");
1789
+ const dineInConfig = ((_a = this.otherParams) == null ? void 0 : _a.dineInConfig) || {};
1790
+ const refMode = dineInConfig["fulfillment.fulfillment_ref_mode"];
1791
+ const manualInputType = dineInConfig["fulfillment.manual_input_type"];
1792
+ const enabled = refMode === "manual_input";
1793
+ const result = enabled ? { enabled: true, manualInputType } : { enabled: false };
1794
+ this.logMethodSuccess("checkManualPickupRef", {
1795
+ enabled,
1796
+ manualInputType: enabled ? manualInputType : void 0
1797
+ });
1798
+ return result;
1799
+ }
1800
+ };
1801
+ var ScanOrderImpl = _ScanOrderImpl;
1802
+ ScanOrderImpl.PISELL1_LOGIN_SUCCESS = "pisell1.login.success";
1803
+ // ─── UI 状态缓存(按 cacheId 分桶,localStorage) ───
1804
+ //
1805
+ // 用于物料层持久化 UI 层面的轻量状态(如当前步骤、gate 标记、登录回跳意图等)。
1806
+ // 桶键:pisell.scanOrder.uiState:<cacheId>;内部以 JSON object 形式存储多个字段。
1807
+ // 无 cacheId 时所有方法自动降级为 no-op,上层不用判空。
1808
+ //
1809
+ // 之所以用 localStorage 而不是 sessionStorage:
1810
+ // 1. 与 Order 模块 openCache 下的 tempOrder 同栈,购物车在 / UIState 在,行为对齐;
1811
+ // 2. pisell1.login 整页 OAuth 跳转在 H5 壳 / iOS Safari 场景下可能丢 sessionStorage,
1812
+ // 导致登录回跳后 gate 标记失效、pax 弹窗重开、落点错误;localStorage 稳定不受影响。
1813
+ // 3. 失效由上层显式控制:提交成功 clearStepCache / entryContext 不一致 clearUIState /
1814
+ // pendingStep 登录回调 deleteUIState,足够约束生命周期。
1815
+ ScanOrderImpl.UI_STATE_KEY_PREFIX = "pisell.scanOrder.uiState:";
1816
+ // Annotate the CommonJS export names for ESM import in node:
1817
+ 0 && (module.exports = {
1818
+ ScanOrderImpl,
1819
+ ...require("./types")
1820
+ });