@pisell/pisellos 3.0.90 → 3.0.92

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