@pisell/pisellos 2.1.171 → 2.1.172

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 (230) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +1 -3
  3. package/dist/model/strategy/adapter/index.d.ts +0 -4
  4. package/dist/model/strategy/adapter/index.js +1 -5
  5. package/dist/model/strategy/adapter/promotion/evaluator.js +99 -26
  6. package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  7. package/dist/model/strategy/adapter/walletPass/evaluator.js +61 -8
  8. package/dist/model/strategy/adapter/walletPass/locales.js +12 -3
  9. package/dist/model/strategy/engine.d.ts +18 -5
  10. package/dist/model/strategy/engine.js +145 -45
  11. package/dist/model/strategy/type.d.ts +17 -0
  12. package/dist/model/strategy/type.js +4 -0
  13. package/dist/modules/Cart/types.d.ts +2 -0
  14. package/dist/modules/Cart/utils/cartProduct.js +56 -25
  15. package/dist/modules/Cart/utils/changePrice.js +9 -16
  16. package/dist/modules/Discount/index.d.ts +4 -13
  17. package/dist/modules/Discount/index.js +12 -124
  18. package/dist/modules/Discount/types.d.ts +18 -13
  19. package/dist/modules/Order/index.d.ts +1 -67
  20. package/dist/modules/Order/index.js +30 -918
  21. package/dist/modules/Order/types.d.ts +12 -176
  22. package/dist/modules/Order/types.js +0 -2
  23. package/dist/modules/Order/utils.d.ts +0 -118
  24. package/dist/modules/Order/utils.js +2 -586
  25. package/dist/modules/Payment/index.d.ts +2 -1
  26. package/dist/modules/Payment/index.js +10 -7
  27. package/dist/modules/Payment/utils.js +3 -0
  28. package/dist/modules/Payment/walletpass.d.ts +23 -0
  29. package/dist/modules/Payment/walletpass.js +191 -95
  30. package/dist/modules/Product/utils.js +2 -2
  31. package/dist/modules/ProductList/index.d.ts +2 -4
  32. package/dist/modules/ProductList/index.js +12 -24
  33. package/dist/modules/Rules/index.d.ts +9 -5
  34. package/dist/modules/Rules/index.js +669 -173
  35. package/dist/modules/Rules/types.d.ts +2 -0
  36. package/dist/modules/Schedule/getDateIsInSchedule.js +18 -16
  37. package/dist/modules/Schedule/utils.d.ts +1 -1
  38. package/dist/modules/Summary/types.d.ts +2 -0
  39. package/dist/modules/Summary/utils.d.ts +9 -3
  40. package/dist/modules/Summary/utils.js +57 -67
  41. package/dist/modules/index.d.ts +0 -4
  42. package/dist/modules/index.js +1 -5
  43. package/dist/plugins/window.d.ts +2 -0
  44. package/dist/solution/BookingByStep/index.d.ts +3 -2
  45. package/dist/solution/BookingByStep/index.js +43 -46
  46. package/dist/solution/BookingByStep/types.d.ts +1 -3
  47. package/dist/solution/BookingByStep/types.js +1 -5
  48. package/dist/solution/BookingByStep/utils/timeslots.d.ts +1 -3
  49. package/dist/solution/BookingByStep/utils/timeslots.js +12 -19
  50. package/dist/solution/Checkout/index.js +2 -0
  51. package/dist/solution/ShopDiscount/index.d.ts +2 -3
  52. package/dist/solution/ShopDiscount/index.js +60 -62
  53. package/dist/solution/ShopDiscount/types.d.ts +1 -1
  54. package/dist/solution/ShopDiscount/types.js +2 -1
  55. package/dist/solution/ShopDiscount/utils.js +26 -12
  56. package/dist/solution/index.d.ts +0 -2
  57. package/dist/solution/index.js +1 -3
  58. package/lib/index.d.ts +1 -1
  59. package/lib/index.js +3 -4
  60. package/lib/model/strategy/adapter/index.d.ts +0 -4
  61. package/lib/model/strategy/adapter/index.js +2 -13
  62. package/lib/model/strategy/adapter/promotion/evaluator.js +57 -8
  63. package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  64. package/lib/model/strategy/adapter/walletPass/evaluator.js +34 -3
  65. package/lib/model/strategy/adapter/walletPass/locales.js +12 -3
  66. package/lib/model/strategy/engine.d.ts +18 -5
  67. package/lib/model/strategy/engine.js +85 -21
  68. package/lib/model/strategy/type.d.ts +17 -0
  69. package/lib/modules/Cart/types.d.ts +2 -0
  70. package/lib/modules/Cart/utils/cartProduct.js +39 -12
  71. package/lib/modules/Cart/utils/changePrice.js +9 -13
  72. package/lib/modules/Discount/index.d.ts +4 -13
  73. package/lib/modules/Discount/index.js +5 -76
  74. package/lib/modules/Discount/types.d.ts +18 -13
  75. package/lib/modules/Order/index.d.ts +1 -67
  76. package/lib/modules/Order/index.js +1 -525
  77. package/lib/modules/Order/types.d.ts +12 -176
  78. package/lib/modules/Order/utils.d.ts +0 -118
  79. package/lib/modules/Order/utils.js +2 -483
  80. package/lib/modules/Payment/index.d.ts +2 -1
  81. package/lib/modules/Payment/index.js +1 -0
  82. package/lib/modules/Payment/utils.js +3 -0
  83. package/lib/modules/Payment/walletpass.d.ts +23 -0
  84. package/lib/modules/Payment/walletpass.js +94 -17
  85. package/lib/modules/Product/utils.js +2 -2
  86. package/lib/modules/ProductList/index.d.ts +2 -4
  87. package/lib/modules/ProductList/index.js +39 -46
  88. package/lib/modules/Rules/index.d.ts +9 -5
  89. package/lib/modules/Rules/index.js +776 -292
  90. package/lib/modules/Rules/types.d.ts +2 -0
  91. package/lib/modules/Schedule/getDateIsInSchedule.js +11 -13
  92. package/lib/modules/Schedule/utils.d.ts +1 -1
  93. package/lib/modules/Summary/types.d.ts +2 -0
  94. package/lib/modules/Summary/utils.d.ts +9 -3
  95. package/lib/modules/Summary/utils.js +34 -45
  96. package/lib/modules/index.d.ts +0 -4
  97. package/lib/modules/index.js +1 -9
  98. package/lib/plugins/window.d.ts +2 -0
  99. package/lib/solution/BookingByStep/index.d.ts +3 -2
  100. package/lib/solution/BookingByStep/index.js +4 -6
  101. package/lib/solution/BookingByStep/types.d.ts +1 -3
  102. package/lib/solution/BookingByStep/types.js +0 -10
  103. package/lib/solution/BookingByStep/utils/timeslots.d.ts +1 -3
  104. package/lib/solution/BookingByStep/utils/timeslots.js +11 -19
  105. package/lib/solution/Checkout/index.js +2 -0
  106. package/lib/solution/ShopDiscount/index.d.ts +2 -3
  107. package/lib/solution/ShopDiscount/index.js +27 -22
  108. package/lib/solution/ShopDiscount/types.d.ts +1 -1
  109. package/lib/solution/ShopDiscount/utils.js +10 -6
  110. package/lib/solution/index.d.ts +0 -2
  111. package/lib/solution/index.js +1 -5
  112. package/package.json +2 -2
  113. package/dist/apis/picoding.d.ts +0 -0
  114. package/dist/apis/picoding.js +0 -1
  115. package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +0 -50
  116. package/dist/model/strategy/adapter/dataVariant/adapter.js +0 -167
  117. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -89
  118. package/dist/model/strategy/adapter/dataVariant/evaluator.js +0 -780
  119. package/dist/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
  120. package/dist/model/strategy/adapter/dataVariant/examples.js +0 -277
  121. package/dist/model/strategy/adapter/dataVariant/index.d.ts +0 -4
  122. package/dist/model/strategy/adapter/dataVariant/index.js +0 -4
  123. package/dist/model/strategy/adapter/dataVariant/type.d.ts +0 -148
  124. package/dist/model/strategy/adapter/dataVariant/type.js +0 -54
  125. package/dist/modules/OpenData/index.d.ts +0 -24
  126. package/dist/modules/OpenData/index.js +0 -173
  127. package/dist/modules/OpenData/types.d.ts +0 -73
  128. package/dist/modules/OpenData/types.js +0 -1
  129. package/dist/modules/OpenData/utils.d.ts +0 -2
  130. package/dist/modules/OpenData/utils.js +0 -75
  131. package/dist/modules/Quotation/index.d.ts +0 -48
  132. package/dist/modules/Quotation/index.js +0 -248
  133. package/dist/modules/Quotation/types.d.ts +0 -42
  134. package/dist/modules/Quotation/types.js +0 -1
  135. package/dist/modules/SalesSummary/index.d.ts +0 -63
  136. package/dist/modules/SalesSummary/index.js +0 -174
  137. package/dist/modules/SalesSummary/types.d.ts +0 -60
  138. package/dist/modules/SalesSummary/types.js +0 -1
  139. package/dist/modules/SalesSummary/utils.d.ts +0 -30
  140. package/dist/modules/SalesSummary/utils.js +0 -480
  141. package/dist/modules/ScanOrderLogger/index.d.ts +0 -23
  142. package/dist/modules/ScanOrderLogger/index.js +0 -174
  143. package/dist/modules/ScanOrderLogger/providers/feishu.d.ts +0 -2
  144. package/dist/modules/ScanOrderLogger/providers/feishu.js +0 -221
  145. package/dist/modules/ScanOrderLogger/providers/grafana.d.ts +0 -2
  146. package/dist/modules/ScanOrderLogger/providers/grafana.js +0 -50
  147. package/dist/modules/ScanOrderLogger/types.d.ts +0 -53
  148. package/dist/modules/ScanOrderLogger/types.js +0 -1
  149. package/dist/solution/ScanOrder/index.d.ts +0 -158
  150. package/dist/solution/ScanOrder/index.js +0 -3474
  151. package/dist/solution/ScanOrder/types.d.ts +0 -306
  152. package/dist/solution/ScanOrder/types.js +0 -35
  153. package/dist/solution/ScanOrder/utils.d.ts +0 -172
  154. package/dist/solution/ScanOrder/utils.js +0 -796
  155. package/dist/solution/VenueBooking/index.d.ts +0 -262
  156. package/dist/solution/VenueBooking/index.js +0 -3991
  157. package/dist/solution/VenueBooking/sales-section-4-annotated.json +0 -343
  158. package/dist/solution/VenueBooking/types.d.ts +0 -156
  159. package/dist/solution/VenueBooking/types.js +0 -22
  160. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +0 -11
  161. package/dist/solution/VenueBooking/utils/dateSummary.js +0 -91
  162. package/dist/solution/VenueBooking/utils/resource.d.ts +0 -14
  163. package/dist/solution/VenueBooking/utils/resource.js +0 -131
  164. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +0 -32
  165. package/dist/solution/VenueBooking/utils/slotMerge.js +0 -233
  166. package/dist/solution/VenueBooking/utils/smartPricing.d.ts +0 -70
  167. package/dist/solution/VenueBooking/utils/smartPricing.js +0 -233
  168. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +0 -34
  169. package/dist/solution/VenueBooking/utils/timeSlot.js +0 -458
  170. package/dist/solution/VenueBooking/utils.d.ts +0 -1
  171. package/dist/solution/VenueBooking/utils.js +0 -1
  172. package/lib/apis/picoding.d.ts +0 -0
  173. package/lib/apis/picoding.js +0 -0
  174. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +0 -50
  175. package/lib/model/strategy/adapter/dataVariant/adapter.js +0 -149
  176. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -89
  177. package/lib/model/strategy/adapter/dataVariant/evaluator.js +0 -583
  178. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
  179. package/lib/model/strategy/adapter/dataVariant/examples.js +0 -293
  180. package/lib/model/strategy/adapter/dataVariant/index.d.ts +0 -4
  181. package/lib/model/strategy/adapter/dataVariant/index.js +0 -38
  182. package/lib/model/strategy/adapter/dataVariant/type.d.ts +0 -148
  183. package/lib/model/strategy/adapter/dataVariant/type.js +0 -31
  184. package/lib/modules/OpenData/index.d.ts +0 -24
  185. package/lib/modules/OpenData/index.js +0 -119
  186. package/lib/modules/OpenData/types.d.ts +0 -73
  187. package/lib/modules/OpenData/types.js +0 -17
  188. package/lib/modules/OpenData/utils.d.ts +0 -2
  189. package/lib/modules/OpenData/utils.js +0 -111
  190. package/lib/modules/Quotation/index.d.ts +0 -48
  191. package/lib/modules/Quotation/index.js +0 -152
  192. package/lib/modules/Quotation/types.d.ts +0 -42
  193. package/lib/modules/Quotation/types.js +0 -17
  194. package/lib/modules/SalesSummary/index.d.ts +0 -63
  195. package/lib/modules/SalesSummary/index.js +0 -105
  196. package/lib/modules/SalesSummary/types.d.ts +0 -60
  197. package/lib/modules/SalesSummary/types.js +0 -17
  198. package/lib/modules/SalesSummary/utils.d.ts +0 -30
  199. package/lib/modules/SalesSummary/utils.js +0 -420
  200. package/lib/modules/ScanOrderLogger/index.d.ts +0 -23
  201. package/lib/modules/ScanOrderLogger/index.js +0 -147
  202. package/lib/modules/ScanOrderLogger/providers/feishu.d.ts +0 -2
  203. package/lib/modules/ScanOrderLogger/providers/feishu.js +0 -157
  204. package/lib/modules/ScanOrderLogger/providers/grafana.d.ts +0 -2
  205. package/lib/modules/ScanOrderLogger/providers/grafana.js +0 -52
  206. package/lib/modules/ScanOrderLogger/types.d.ts +0 -53
  207. package/lib/modules/ScanOrderLogger/types.js +0 -17
  208. package/lib/solution/ScanOrder/index.d.ts +0 -158
  209. package/lib/solution/ScanOrder/index.js +0 -2135
  210. package/lib/solution/ScanOrder/types.d.ts +0 -306
  211. package/lib/solution/ScanOrder/types.js +0 -36
  212. package/lib/solution/ScanOrder/utils.d.ts +0 -172
  213. package/lib/solution/ScanOrder/utils.js +0 -658
  214. package/lib/solution/VenueBooking/index.d.ts +0 -262
  215. package/lib/solution/VenueBooking/index.js +0 -2394
  216. package/lib/solution/VenueBooking/sales-section-4-annotated.json +0 -343
  217. package/lib/solution/VenueBooking/types.d.ts +0 -156
  218. package/lib/solution/VenueBooking/types.js +0 -45
  219. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +0 -11
  220. package/lib/solution/VenueBooking/utils/dateSummary.js +0 -105
  221. package/lib/solution/VenueBooking/utils/resource.d.ts +0 -14
  222. package/lib/solution/VenueBooking/utils/resource.js +0 -92
  223. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +0 -32
  224. package/lib/solution/VenueBooking/utils/slotMerge.js +0 -236
  225. package/lib/solution/VenueBooking/utils/smartPricing.d.ts +0 -70
  226. package/lib/solution/VenueBooking/utils/smartPricing.js +0 -180
  227. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +0 -34
  228. package/lib/solution/VenueBooking/utils/timeSlot.js +0 -343
  229. package/lib/solution/VenueBooking/utils.d.ts +0 -1
  230. package/lib/solution/VenueBooking/utils.js +0 -69
@@ -1,2394 +0,0 @@
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/VenueBooking/index.ts
31
- var VenueBooking_exports = {};
32
- __export(VenueBooking_exports, {
33
- VenueBookingImpl: () => VenueBookingImpl
34
- });
35
- module.exports = __toCommonJS(VenueBooking_exports);
36
- var import_BaseModule = require("../../modules/BaseModule");
37
- var import_types = require("./types");
38
- var import_utils = require("./utils");
39
- var import_types2 = require("../BookingByStep/types");
40
- var import_ProductList = require("../../modules/ProductList");
41
- var import_Date = require("../../modules/Date");
42
- var import_Schedule = require("../../modules/Schedule");
43
- var import_utils2 = require("../../modules/Schedule/utils");
44
- var import_Quotation = require("../../modules/Quotation");
45
- var import_OpenData = require("../../modules/OpenData");
46
- var import_types3 = require("../../modules/Account/types");
47
- var import_dayjs = __toESM(require("dayjs"));
48
- var import_itemRule = require("../../model/strategy/adapter/itemRule");
49
- var import_resource = require("./utils/resource");
50
- var import_timeSlot = require("./utils/timeSlot");
51
- var import_dateSummary = require("./utils/dateSummary");
52
- var import_slotMerge = require("./utils/slotMerge");
53
- var import_smartPricing = require("./utils/smartPricing");
54
- var import_utils3 = require("../../modules/Order/utils");
55
- var import_Order = require("../../modules/Order");
56
- var import_types4 = require("../RegisterAndLogin/types");
57
- var import_decimal = __toESM(require("decimal.js"));
58
- __reExport(VenueBooking_exports, require("./types"), module.exports);
59
- var OPEN_DATA_SECTION_CODES = [
60
- "basic",
61
- "fulfillment",
62
- "reservation",
63
- "sale",
64
- "menu",
65
- "availability",
66
- "workflow",
67
- "checkout"
68
- ];
69
- function cloneCustomDepositData(customDepositData) {
70
- if (!customDepositData || typeof customDepositData !== "object")
71
- return void 0;
72
- return {
73
- ...customDepositData,
74
- self_deposit_policy_ids: Array.isArray(customDepositData.self_deposit_policy_ids) ? [...customDepositData.self_deposit_policy_ids] : [],
75
- deposit_policy_ids: Array.isArray(customDepositData.deposit_policy_ids) ? [...customDepositData.deposit_policy_ids] : [],
76
- deposit_policy_data: Array.isArray(customDepositData.deposit_policy_data) ? [...customDepositData.deposit_policy_data] : []
77
- };
78
- }
79
- var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
80
- constructor(name, version) {
81
- super(name, version);
82
- this.defaultName = "venueBooking";
83
- this.defaultVersion = "1.0.0";
84
- this.isSolution = true;
85
- this.initializeOptions = {};
86
- this.store = {
87
- entryContext: null,
88
- status: "idle",
89
- flow: {},
90
- error: null,
91
- products: void 0,
92
- rawResourceData: [],
93
- slotConfig: { ...import_types.DEFAULT_SLOT_CONFIG },
94
- itemRuleQuantityLimits: [],
95
- cartValidation: {
96
- passed: null,
97
- failures: []
98
- }
99
- };
100
- this.otherParams = {};
101
- this.baseSlotConfig = { ...import_types.DEFAULT_SLOT_CONFIG };
102
- this.itemRuleEvaluator = new import_itemRule.ItemRuleEvaluator();
103
- this.itemRuleConfigs = [];
104
- this.itemRuleConfigsPromise = null;
105
- this.itemRulePrefillApplied = false;
106
- this.itemRuleRuntimeConfig = {};
107
- this.resourceProductMap = /* @__PURE__ */ new Map();
108
- this.loginEffectDisposers = [];
109
- this.customerLoginRefreshInFlight = null;
110
- this.customerLoginRefreshIdInFlight = null;
111
- this.loadAllProductsInFlight = null;
112
- this.productsLoaded = false;
113
- this.loadOpenDataConfigInFlight = null;
114
- /** 按日期缓存 slot 智能定价 Map,避免同周重复 resolveProducts */
115
- this.slotPriceMapCache = /* @__PURE__ */ new Map();
116
- /** loadProducts 后缓存的全量商品(venue + addon),供分段算价复用 */
117
- this.smartPricingProductCatalog = [];
118
- }
119
- getLoggerContext() {
120
- return {
121
- cacheId: this.cacheId,
122
- solutionName: this.name,
123
- moduleName: "venueBooking"
124
- };
125
- }
126
- safeStringify(value) {
127
- try {
128
- return JSON.stringify(value);
129
- } catch {
130
- return void 0;
131
- }
132
- }
133
- pickErrorMessage(error) {
134
- var _a, _b, _c, _d;
135
- const candidates = [
136
- error.message,
137
- (_a = error.data) == null ? void 0 : _a.message,
138
- (_c = (_b = error.response) == null ? void 0 : _b.data) == null ? void 0 : _c.message,
139
- (_d = error.error) == null ? void 0 : _d.message
140
- ];
141
- for (const candidate of candidates) {
142
- if (typeof candidate === "string" && candidate.trim())
143
- return candidate;
144
- }
145
- return void 0;
146
- }
147
- serializeError(error) {
148
- if (error instanceof Error) {
149
- return {
150
- name: error.name,
151
- message: error.message,
152
- stack: error.stack
153
- };
154
- }
155
- if (error && typeof error === "object") {
156
- const raw = error;
157
- const message = this.pickErrorMessage(raw) || this.safeStringify(raw) || String(error);
158
- return {
159
- ...typeof raw.name === "string" ? { name: raw.name } : {},
160
- message,
161
- ..."code" in raw ? { code: raw.code } : {},
162
- ..."status" in raw ? { status: raw.status } : {},
163
- ...this.safeStringify(raw) ? { raw: this.safeStringify(raw) } : {}
164
- };
165
- }
166
- return {
167
- message: String(error)
168
- };
169
- }
170
- async addVenueBookingLog(params) {
171
- const payload = {
172
- cacheId: this.cacheId,
173
- ...params.payload || {}
174
- };
175
- const extra = {
176
- ...params.extra || {}
177
- };
178
- const logger = this.store.scanOrderLogger;
179
- if (!logger) {
180
- if ((params.level || "info") === "error") {
181
- console.error("[VenueBooking][log-fallback]", params.title, { payload, extra });
182
- } else {
183
- console.log("[VenueBooking][log-fallback]", params.title, { payload, extra });
184
- }
185
- return;
186
- }
187
- await logger.addLog({
188
- ...params,
189
- payload,
190
- extra
191
- });
192
- }
193
- /**
194
- * 临时线上排查日志:
195
- * - 仅对指定页面 cacheId 开启,避免影响其他页面
196
- * - 不 await,且吞掉日志上报异常,保证日志系统不会阻断登录/商品加载主流程
197
- */
198
- logPricingDiagnostics(title, payload = {}) {
199
- if (!this.isPricingDiagnosticsEnabled())
200
- return;
201
- void this.addVenueBookingLog({
202
- level: "info",
203
- title,
204
- payload
205
- }).catch((error) => {
206
- console.warn("[VenueBooking] pricing diagnostic log failed", error);
207
- });
208
- }
209
- isPricingDiagnosticsEnabled() {
210
- return String(this.cacheId || "") === _VenueBookingImpl.PRICING_DEBUG_CACHE_ID;
211
- }
212
- getAvailableWalletIdsForDiagnostics() {
213
- var _a, _b;
214
- try {
215
- return (_b = (_a = this.store.order) == null ? void 0 : _a.getAvailableWalletIds) == null ? void 0 : _b.call(_a);
216
- } catch (error) {
217
- return {
218
- readFailed: true,
219
- error: this.serializeError(error)
220
- };
221
- }
222
- }
223
- getOrderPricingSnapshotForDiagnostics() {
224
- var _a, _b;
225
- try {
226
- const products = (_b = (_a = this.store.order) == null ? void 0 : _a.getTempOrder()) == null ? void 0 : _b.products;
227
- if (!Array.isArray(products))
228
- return [];
229
- return products.map((product) => {
230
- var _a2, _b2, _c, _d, _e, _f;
231
- return {
232
- productId: product == null ? void 0 : product.product_id,
233
- resourceId: (_a2 = product == null ? void 0 : product.metadata) == null ? void 0 : _a2.resource_id,
234
- isVenueBooking: !!((_b2 = product == null ? void 0 : product.metadata) == null ? void 0 : _b2.venue_booking),
235
- sellingPrice: product == null ? void 0 : product.selling_price,
236
- originalPrice: product == null ? void 0 : product.original_price,
237
- sourceProductPrice: (_c = product == null ? void 0 : product.metadata) == null ? void 0 : _c.source_product_price,
238
- mainProductOriginalPrice: (_d = product == null ? void 0 : product.metadata) == null ? void 0 : _d.main_product_original_price,
239
- mainProductSellingPrice: (_e = product == null ? void 0 : product.metadata) == null ? void 0 : _e.main_product_selling_price,
240
- priceBreakdown: (_f = product == null ? void 0 : product.metadata) == null ? void 0 : _f.price_breakdown,
241
- discountList: product == null ? void 0 : product.discount_list
242
- };
243
- });
244
- } catch (error) {
245
- return [{ readFailed: true, error: this.serializeError(error) }];
246
- }
247
- }
248
- getCatalogPricingSnapshotForDiagnostics() {
249
- const orderProductIds = new Set(
250
- this.getOrderPricingSnapshotForDiagnostics().map((product) => Number(product.productId)).filter((productId) => Number.isFinite(productId))
251
- );
252
- return this.getAllProductsForSmartPricing().filter((product) => orderProductIds.has(Number(product == null ? void 0 : product.id))).map((product) => ({
253
- productId: product == null ? void 0 : product.id,
254
- price: product == null ? void 0 : product.price,
255
- sellingPrice: product == null ? void 0 : product.selling_price,
256
- dataVariants: Array.isArray(product == null ? void 0 : product.data_variants) ? product.data_variants.map((variant) => ({
257
- ruleId: variant == null ? void 0 : variant.data_variant_rule_id,
258
- data: variant == null ? void 0 : variant.data
259
- })) : []
260
- }));
261
- }
262
- logMethodStart(method, payload = {}) {
263
- void this.addVenueBookingLog({
264
- level: "info",
265
- title: `[VenueBooking] ${method} start`,
266
- payload: {
267
- method,
268
- ...payload
269
- }
270
- });
271
- }
272
- logMethodSuccess(method, payload = {}) {
273
- void this.addVenueBookingLog({
274
- level: "info",
275
- title: `[VenueBooking] ${method} success`,
276
- payload: {
277
- method,
278
- ...payload
279
- }
280
- });
281
- }
282
- logMethodError(method, error, payload = {}) {
283
- void this.addVenueBookingLog({
284
- level: "error",
285
- title: `[VenueBooking] ${method} failed`,
286
- payload: {
287
- method,
288
- ...payload,
289
- error: this.serializeError(error)
290
- }
291
- });
292
- }
293
- async addLog(params) {
294
- await this.addVenueBookingLog({
295
- ...params,
296
- payload: {
297
- source: "ui-bridge",
298
- ...params.payload || {}
299
- }
300
- });
301
- }
302
- normalizeCustomerId(value) {
303
- const customerId = Number(value);
304
- if (!Number.isFinite(customerId) || customerId <= 0)
305
- return null;
306
- return customerId;
307
- }
308
- resolveCustomerIdFromLoginPayload(payload) {
309
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
310
- const candidates = [
311
- payload == null ? void 0 : payload.customerId,
312
- payload == null ? void 0 : payload.customer_id,
313
- payload == null ? void 0 : payload.id,
314
- (_a = payload == null ? void 0 : payload.user) == null ? void 0 : _a.customerId,
315
- (_b = payload == null ? void 0 : payload.user) == null ? void 0 : _b.customer_id,
316
- (_c = payload == null ? void 0 : payload.user) == null ? void 0 : _c.id,
317
- (_e = (_d = payload == null ? void 0 : payload.user) == null ? void 0 : _d._origin) == null ? void 0 : _e.customer_id,
318
- (_f = payload == null ? void 0 : payload.account) == null ? void 0 : _f.customerId,
319
- (_g = payload == null ? void 0 : payload.account) == null ? void 0 : _g.customer_id,
320
- (_h = payload == null ? void 0 : payload.account) == null ? void 0 : _h.id,
321
- (_i = payload == null ? void 0 : payload._origin) == null ? void 0 : _i.customer_id
322
- ];
323
- for (const candidate of candidates) {
324
- const customerId = this.normalizeCustomerId(candidate);
325
- if (customerId)
326
- return customerId;
327
- }
328
- return null;
329
- }
330
- clearLoginEffectListeners() {
331
- for (const dispose of this.loginEffectDisposers) {
332
- dispose();
333
- }
334
- this.loginEffectDisposers = [];
335
- }
336
- registerLoginEffect(event, callback) {
337
- var _a;
338
- const effects = (_a = this.core) == null ? void 0 : _a.effects;
339
- if (!(effects == null ? void 0 : effects.on))
340
- return;
341
- effects.on(event, callback);
342
- this.loginEffectDisposers.push(() => {
343
- if (typeof effects.off === "function") {
344
- effects.off(event, callback);
345
- }
346
- });
347
- }
348
- registerCustomerLoginListeners() {
349
- this.clearLoginEffectListeners();
350
- const createHandleLogin = () => async (payload) => {
351
- const customerId = this.resolveCustomerIdFromLoginPayload(payload);
352
- if (!customerId)
353
- return;
354
- await this.refreshOrderMarketingAfterLogin({ customerId });
355
- };
356
- this.registerLoginEffect(_VenueBookingImpl.PISELL1_LOGIN_SUCCESS, createHandleLogin());
357
- this.registerLoginEffect(import_types3.AccountHooks.OnLogin, createHandleLogin());
358
- this.registerLoginEffect(import_types4.RegisterAndLoginHooks.onLoginSuccess, createHandleLogin());
359
- }
360
- async refreshOrderMarketingAfterLogin(params) {
361
- if (!this.store.order)
362
- throw new Error("order 模块未初始化");
363
- const pricingDiagnosticsEnabled = this.isPricingDiagnosticsEnabled();
364
- if (pricingDiagnosticsEnabled) {
365
- this.logPricingDiagnostics("[VenueBooking] refreshOrderMarketingAfterLogin entered", {
366
- customerId: params.customerId,
367
- hasCustomerLoginRefreshInFlight: !!this.customerLoginRefreshInFlight,
368
- customerLoginRefreshIdInFlight: this.customerLoginRefreshIdInFlight,
369
- hasLoadAllProductsInFlight: !!this.loadAllProductsInFlight,
370
- productsLoaded: this.productsLoaded,
371
- smartPricingProductCatalogCount: this.smartPricingProductCatalog.length,
372
- note: "This login refresh reloads products with the confirmed customer context before recalculation"
373
- });
374
- }
375
- if (this.customerLoginRefreshInFlight) {
376
- if (this.customerLoginRefreshIdInFlight === params.customerId) {
377
- await this.customerLoginRefreshInFlight;
378
- return;
379
- }
380
- await this.customerLoginRefreshInFlight;
381
- }
382
- this.customerLoginRefreshIdInFlight = params.customerId;
383
- const refreshTask = (async () => {
384
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
385
- this.smartPricingCustomerId = params.customerId;
386
- if (pricingDiagnosticsEnabled) {
387
- this.logPricingDiagnostics("[VenueBooking] login pricing customer context set", {
388
- customerId: params.customerId,
389
- userPluginCustomerId: this.resolveCustomerIdForSmartPricing(),
390
- availableWalletIdsBeforeDiscountConfig: this.getAvailableWalletIdsForDiagnostics(),
391
- orderProductsBeforeDiscountConfig: this.getOrderPricingSnapshotForDiagnostics()
392
- });
393
- }
394
- await this.store.order.loadDiscountConfig({
395
- customerId: params.customerId
396
- });
397
- if (pricingDiagnosticsEnabled) {
398
- const productsLoadBeforeLogin = this.loadAllProductsInFlight;
399
- if (productsLoadBeforeLogin) {
400
- this.logPricingDiagnostics("[VenueBooking] login waiting for previous product load", {
401
- customerId: params.customerId
402
- });
403
- try {
404
- await productsLoadBeforeLogin;
405
- } catch (error) {
406
- this.logPricingDiagnostics("[VenueBooking] previous product load failed before login reload", {
407
- customerId: params.customerId,
408
- error: this.serializeError(error)
409
- });
410
- }
411
- }
412
- this.logPricingDiagnostics("[VenueBooking] login product reload starting", {
413
- customerId: params.customerId,
414
- productsLoadedBeforeReload: this.productsLoaded,
415
- catalogCountBeforeReload: this.smartPricingProductCatalog.length,
416
- availableWalletIds: this.getAvailableWalletIdsForDiagnostics()
417
- });
418
- const loginProducts = await this.loadAllProducts();
419
- this.logPricingDiagnostics("[VenueBooking] login product reload completed", {
420
- customerId: params.customerId,
421
- venueProductCount: loginProducts.venueProducts.length,
422
- addonProductCount: loginProducts.addonProducts.length,
423
- catalogCountAfterReload: this.smartPricingProductCatalog.length,
424
- resourceProductMapSize: this.resourceProductMap.size
425
- });
426
- }
427
- if (pricingDiagnosticsEnabled) {
428
- const smartPricingContext = this.buildSmartPricingContext();
429
- const strategyConfigs = ((_b = (_a = smartPricingContext.evaluator) == null ? void 0 : _a.getStrategyConfigs) == null ? void 0 : _b.call(_a)) || [];
430
- this.logPricingDiagnostics("[VenueBooking] login discount config loaded", {
431
- customerId: params.customerId,
432
- availableWalletIdsAfterDiscountConfig: this.getAvailableWalletIdsForDiagnostics(),
433
- discountList: this.store.order.getDiscountList(),
434
- smartPricingContext: {
435
- customerId: smartPricingContext.customerId,
436
- availableWalletIds: smartPricingContext.availableWalletIds,
437
- channel: smartPricingContext.channel,
438
- businessCode: smartPricingContext.businessCode,
439
- orderType: smartPricingContext.orderType,
440
- scheduleCount: ((_c = smartPricingContext.scheduleList) == null ? void 0 : _c.length) || 0,
441
- menuCount: ((_d = smartPricingContext.menuList) == null ? void 0 : _d.length) || 0,
442
- hasEvaluator: !!smartPricingContext.evaluator
443
- },
444
- strategyConfigs: strategyConfigs.map((config) => {
445
- var _a2, _b2, _c2, _d2, _e2, _f2;
446
- return {
447
- ruleId: (_a2 = config == null ? void 0 : config.metadata) == null ? void 0 : _a2.id,
448
- name: (_b2 = config == null ? void 0 : config.metadata) == null ? void 0 : _b2.name,
449
- status: (_d2 = (_c2 = config == null ? void 0 : config.metadata) == null ? void 0 : _c2.custom) == null ? void 0 : _d2.status,
450
- priority: (_f2 = (_e2 = config == null ? void 0 : config.metadata) == null ? void 0 : _e2.custom) == null ? void 0 : _f2.priority,
451
- conditions: config == null ? void 0 : config.conditions
452
- };
453
- }),
454
- productsLoaded: this.productsLoaded,
455
- smartPricingProductCatalogCount: (_e = this.smartPricingProductCatalog) == null ? void 0 : _e.length,
456
- resourceProductMapSize: this.resourceProductMap.size,
457
- matchingCatalogProducts: this.getCatalogPricingSnapshotForDiagnostics()
458
- });
459
- }
460
- this.clearSlotPriceMapCache();
461
- if (pricingDiagnosticsEnabled) {
462
- this.logPricingDiagnostics("[VenueBooking] login smart pricing recalculation starting", {
463
- slotPriceMapCacheSizeAfterClear: this.slotPriceMapCache.size,
464
- orderProductsBeforeRecalculation: this.getOrderPricingSnapshotForDiagnostics()
465
- });
466
- }
467
- this.recalculateOrderPricesFromSmartPricing();
468
- if (pricingDiagnosticsEnabled) {
469
- this.logPricingDiagnostics("[VenueBooking] login smart pricing recalculation completed", {
470
- orderProductsAfterRecalculation: this.getOrderPricingSnapshotForDiagnostics()
471
- });
472
- }
473
- this.store.order.applyDiscount();
474
- this.normalizeDiscountedOrderPrices(
475
- this.store.order.getDiscountList()
476
- );
477
- if (pricingDiagnosticsEnabled) {
478
- this.logPricingDiagnostics("[VenueBooking] login discounts reapplied", {
479
- discountList: this.store.order.getDiscountList(),
480
- orderProductsAfterDiscount: this.getOrderPricingSnapshotForDiagnostics()
481
- });
482
- }
483
- await this.store.order.recalculateSummary({ createIfMissing: true });
484
- this.store.order.persistTempOrder();
485
- if (pricingDiagnosticsEnabled) {
486
- this.logPricingDiagnostics("[VenueBooking] login pricing summary persisted", {
487
- summary: (_f = this.store.order.getTempOrder()) == null ? void 0 : _f.summary,
488
- orderProducts: this.getOrderPricingSnapshotForDiagnostics()
489
- });
490
- }
491
- await this.refreshItemRuleQuantityLimits();
492
- await this.refreshCartValidationPassed();
493
- await ((_i = (_h = (_g = this.core) == null ? void 0 : _g.effects) == null ? void 0 : _h.emit) == null ? void 0 : _i.call(_h, import_types.VenueBookingHooks.onSmartPricingUpdated, {
494
- customerId: params.customerId
495
- }));
496
- if (pricingDiagnosticsEnabled) {
497
- this.logPricingDiagnostics("[VenueBooking] login smart pricing update emitted", {
498
- customerId: params.customerId,
499
- cartValidation: this.store.cartValidation
500
- });
501
- }
502
- })();
503
- this.customerLoginRefreshInFlight = refreshTask;
504
- try {
505
- await refreshTask;
506
- } catch (error) {
507
- if (pricingDiagnosticsEnabled) {
508
- this.logPricingDiagnostics("[VenueBooking] login smart pricing refresh failed", {
509
- customerId: params.customerId,
510
- error: this.serializeError(error),
511
- productsLoaded: this.productsLoaded,
512
- smartPricingProductCatalogCount: this.smartPricingProductCatalog.length,
513
- resourceProductMapSize: this.resourceProductMap.size,
514
- orderProducts: this.getOrderPricingSnapshotForDiagnostics()
515
- });
516
- }
517
- throw error;
518
- } finally {
519
- if (this.customerLoginRefreshInFlight === refreshTask) {
520
- this.customerLoginRefreshInFlight = null;
521
- this.customerLoginRefreshIdInFlight = null;
522
- }
523
- }
524
- }
525
- async initialize(core, options = {}) {
526
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
527
- this.logMethodStart("initialize");
528
- this.core = core;
529
- this.initializeOptions = options || {};
530
- this.store = { ...this.store, ...options.store };
531
- this.smartPricingCustomerId = void 0;
532
- this.store.entryContext = ((_a = options.otherParams) == null ? void 0 : _a.entryContext) || this.store.entryContext;
533
- this.store.status = "initializing";
534
- this.store.error = null;
535
- this.store.rawResourceData = [];
536
- this.baseSlotConfig = {
537
- ...import_types.DEFAULT_SLOT_CONFIG,
538
- ...((_b = options.otherParams) == null ? void 0 : _b.slotConfig) || {}
539
- };
540
- this.store.slotConfig = { ...this.baseSlotConfig };
541
- this.otherParams = options.otherParams || {};
542
- this.cacheId = (_c = this.otherParams) == null ? void 0 : _c.cacheId;
543
- this.itemRuleRuntimeConfig = ((_d = this.otherParams) == null ? void 0 : _d.venueBookingItemRule) || ((_e = this.otherParams) == null ? void 0 : _e.itemRule) || {};
544
- this.itemRuleConfigs = [];
545
- this.itemRuleConfigsPromise = null;
546
- this.itemRulePrefillApplied = false;
547
- this.store.itemRuleQuantityLimits = [];
548
- this.store.cartValidation = {
549
- passed: null,
550
- failures: []
551
- };
552
- this.window = core.getPlugin("window");
553
- this.request = core.getPlugin("request");
554
- if (!this.window) {
555
- this.logMethodError("initialize", "window plugin missing");
556
- throw new Error("venueBooking解决方案需要 window 插件支持");
557
- }
558
- if (!this.request) {
559
- this.logMethodError("initialize", "request plugin missing");
560
- throw new Error("venueBooking解决方案需要 request 插件支持");
561
- }
562
- const baseModules = [
563
- "scanOrderLogger",
564
- "products",
565
- "order",
566
- "salesSummary"
567
- ];
568
- baseModules.forEach((step) => {
569
- var _a2, _b2, _c2, _d2, _e2, _f2;
570
- const targetModule = (0, import_types2.createModule)(step, this.name);
571
- if (targetModule) {
572
- this.store[step] = targetModule;
573
- const initialState = step === "salesSummary" ? {
574
- summary: ((_b2 = (_a2 = this.store.order) == null ? void 0 : _a2.getTempOrder()) == null ? void 0 : _b2.summary) || (0, import_utils.createEmptySummary)()
575
- } : {};
576
- const loggerProvider = ((_c2 = this.otherParams) == null ? void 0 : _c2.loggerProvider) || "feishu";
577
- const loggerConfig = ((_d2 = this.otherParams) == null ? void 0 : _d2.loggerConfig) || {
578
- feishu: {
579
- webhook: "https://open.feishu.cn/open-apis/bot/v2/hook/8f069b14-9d39-4728-8f78-b56f393bfde8",
580
- errorHook: "https://open.feishu.cn/open-apis/bot/v2/hook/bdefae5e-f233-4705-8688-946887d9543d"
581
- }
582
- };
583
- this.core.registerModule(targetModule, {
584
- initialState,
585
- otherParams: {
586
- ...this.otherParams,
587
- fatherModule: this.name,
588
- openCache: ((_e2 = this.otherParams) == null ? void 0 : _e2.cacheId) ? true : false,
589
- cacheId: (_f2 = this.otherParams) == null ? void 0 : _f2.cacheId,
590
- salesSummaryModuleName: `${this.name}_salesSummary`,
591
- provider: loggerProvider,
592
- providerConfig: loggerConfig,
593
- context: this.getLoggerContext()
594
- }
595
- });
596
- } else {
597
- this.logMethodError("initialize", `module ${step} missing`);
598
- throw new Error(`模块 ${step} 不存在`);
599
- }
600
- });
601
- const venueProductsModule = new import_ProductList.ProductList(`${this.name}_venueProducts`);
602
- this.store.venueProducts = venueProductsModule;
603
- this.core.registerModule(venueProductsModule, {
604
- otherParams: {
605
- ...this.otherParams,
606
- fatherModule: this.name
607
- }
608
- });
609
- const addonProductsModule = new import_ProductList.ProductList(`${this.name}_addonProducts`);
610
- this.store.addonProducts = addonProductsModule;
611
- this.core.registerModule(addonProductsModule, {
612
- otherParams: {
613
- ...this.otherParams,
614
- fatherModule: this.name
615
- }
616
- });
617
- const dateModule = new import_Date.DateModule(`${this.name}_date`);
618
- this.store.date = dateModule;
619
- this.core.registerModule(dateModule, {
620
- otherParams: {
621
- ...this.otherParams,
622
- fatherModule: this.name,
623
- cacheId: this.cacheId
624
- }
625
- });
626
- const scheduleModule = new import_Schedule.ScheduleModule(`${this.name}_schedule`);
627
- this.store.schedule = scheduleModule;
628
- this.core.registerModule(scheduleModule, {
629
- otherParams: {
630
- ...this.otherParams,
631
- fatherModule: this.name
632
- }
633
- });
634
- const quotationModule = new import_Quotation.QuotationModule(`${this.name}_quotation`);
635
- this.store.quotation = quotationModule;
636
- this.core.registerModule(quotationModule, {
637
- otherParams: {
638
- ...this.otherParams,
639
- fatherModule: this.name
640
- }
641
- });
642
- const openDataModule = new import_OpenData.OpenDataModule(`${this.name}_openData`);
643
- this.store.openData = openDataModule;
644
- this.core.registerModule(openDataModule, {
645
- otherParams: {
646
- ...this.otherParams,
647
- fatherModule: this.name,
648
- openCache: !!((_f = this.otherParams) == null ? void 0 : _f.cacheId),
649
- cacheId: (_g = this.otherParams) == null ? void 0 : _g.cacheId
650
- }
651
- });
652
- if (this.store.scanOrderLogger) {
653
- this.store.scanOrderLogger.setContext(this.getLoggerContext());
654
- }
655
- this.registerCustomerLoginListeners();
656
- console.log("[VenueBooking] 初始化开始");
657
- try {
658
- await ((_h = this.store.order) == null ? void 0 : _h.recalculateSummary({ createIfMissing: false }));
659
- (_i = this.store.order) == null ? void 0 : _i.persistTempOrder();
660
- await this.loadRuntimeConfigs();
661
- if (this.store.schedule) {
662
- await this.store.schedule.loadAllSchedule();
663
- }
664
- await this.refreshItemRuleQuantityLimits();
665
- this.store.status = "ready";
666
- console.log("[VenueBooking] 初始化完成");
667
- await this.core.effects.emit(import_types.VenueBookingHooks.onInited, {
668
- status: this.store.status
669
- });
670
- this.logMethodSuccess("initialize", {
671
- status: this.store.status
672
- });
673
- } catch (error) {
674
- this.store.status = "error";
675
- this.store.error = error instanceof Error ? error.message : "初始化失败";
676
- console.error("[VenueBooking] 初始化失败", error);
677
- this.logMethodError("initialize", error, {
678
- status: this.store.status
679
- });
680
- throw error;
681
- }
682
- }
683
- async destroy() {
684
- this.logMethodStart("destroy");
685
- this.clearLoginEffectListeners();
686
- await this.core.effects.emit(import_types.VenueBookingHooks.onDestroy, {});
687
- console.log("[VenueBooking] 已销毁");
688
- this.logMethodSuccess("destroy");
689
- }
690
- async retryInit() {
691
- this.logMethodStart("retryInit");
692
- console.log("[VenueBooking] retryInit 调用");
693
- await this.core.effects.emit(import_types.VenueBookingHooks.onRetryInit, {});
694
- try {
695
- await this.initialize(this.core, this.initializeOptions);
696
- this.logMethodSuccess("retryInit");
697
- } catch (error) {
698
- this.logMethodError("retryInit", error);
699
- throw error;
700
- }
701
- }
702
- async refresh() {
703
- this.logMethodStart("refresh");
704
- console.log("[VenueBooking] refresh 调用");
705
- try {
706
- this.store.status = "initializing";
707
- await this.loadRuntimeConfigs();
708
- await this.refreshItemRuleQuantityLimits();
709
- this.store.status = "ready";
710
- await this.core.effects.emit(import_types.VenueBookingHooks.onRefresh, {
711
- status: this.store.status
712
- });
713
- this.logMethodSuccess("refresh", {
714
- status: this.store.status
715
- });
716
- } catch (error) {
717
- this.logMethodError("refresh", error);
718
- throw error;
719
- }
720
- }
721
- // ─── 状态查询 ───
722
- getStatus() {
723
- return this.store.status;
724
- }
725
- getEntryContext() {
726
- return this.store.entryContext;
727
- }
728
- getItemRuleQuantityLimits() {
729
- return this.store.itemRuleQuantityLimits || [];
730
- }
731
- getCartValidationPassed() {
732
- var _a;
733
- return ((_a = this.store.cartValidation) == null ? void 0 : _a.passed) ?? null;
734
- }
735
- getCartValidation() {
736
- return this.store.cartValidation || { passed: null, failures: [] };
737
- }
738
- /** 清除 slot 价格分段缓存(商品重载 / 登录后 customerId 变化时调用) */
739
- clearSlotPriceMapCache() {
740
- this.slotPriceMapCache.clear();
741
- }
742
- /** 读取当前登录 customerId */
743
- resolveCustomerIdForSmartPricing() {
744
- var _a, _b, _c;
745
- if (this.smartPricingCustomerId)
746
- return this.smartPricingCustomerId;
747
- try {
748
- const userPlugin = (_a = this.core) == null ? void 0 : _a.getPlugin("user");
749
- const customerId = Number((_c = (_b = userPlugin == null ? void 0 : userPlugin.get) == null ? void 0 : _b.call(userPlugin)) == null ? void 0 : _c.id);
750
- return Number.isFinite(customerId) && customerId > 0 ? customerId : void 0;
751
- } catch {
752
- return void 0;
753
- }
754
- }
755
- resolveAvailableWalletIdsForSmartPricing() {
756
- var _a, _b, _c, _d, _e, _f, _g, _h;
757
- const orderWalletIds = (_b = (_a = this.store.order) == null ? void 0 : _a.getAvailableWalletIds) == null ? void 0 : _b.call(_a);
758
- const fallbackWalletIds = ((_c = this.otherParams) == null ? void 0 : _c.available_wallet_ids) || ((_d = this.otherParams) == null ? void 0 : _d.availableWalletIds) || ((_f = (_e = this.otherParams) == null ? void 0 : _e.strategy_context) == null ? void 0 : _f.available_wallet_ids) || ((_h = (_g = this.otherParams) == null ? void 0 : _g.strategy_context) == null ? void 0 : _h.availableWalletIds);
759
- const source = Array.isArray(orderWalletIds) && orderWalletIds.length ? orderWalletIds : fallbackWalletIds;
760
- if (!Array.isArray(source))
761
- return [];
762
- const ids = source.map((item) => Number(item)).filter((item) => Number.isFinite(item) && item > 0);
763
- return Array.from(new Set(ids));
764
- }
765
- /** 读取 schedule 全量列表,供智能定价 schedule_match 使用 */
766
- getScheduleListForSmartPricing() {
767
- var _a;
768
- const scheduleModule = this.store.schedule;
769
- const list = (_a = scheduleModule == null ? void 0 : scheduleModule.store) == null ? void 0 : _a.scheduleList;
770
- return Array.isArray(list) ? list : [];
771
- }
772
- /** 构建智能定价上下文,对齐 OS Server buildProductFormatterContext */
773
- buildSmartPricingContext(customerId) {
774
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
775
- const evaluator = (_b = (_a = this.core) == null ? void 0 : _a.context) == null ? void 0 : _b.dataVariantEvaluator;
776
- return {
777
- evaluator,
778
- scheduleList: this.getScheduleListForSmartPricing(),
779
- menuList: ((_c = this.otherParams) == null ? void 0 : _c.menuList) || ((_e = (_d = this.otherParams) == null ? void 0 : _d.openData) == null ? void 0 : _e.menuList) || [],
780
- customerId: customerId ?? this.resolveCustomerIdForSmartPricing(),
781
- availableWalletIds: this.resolveAvailableWalletIdsForSmartPricing(),
782
- channel: (_f = this.otherParams) == null ? void 0 : _f.channel,
783
- businessCode: (_g = this.otherParams) == null ? void 0 : _g.businessCode,
784
- orderType: ((_h = this.otherParams) == null ? void 0 : _h.orderType) || ((_i = this.otherParams) == null ? void 0 : _i.type),
785
- strategy_context: (_j = this.otherParams) == null ? void 0 : _j.strategy_context
786
- };
787
- }
788
- /** venue + addon 全量商品,供智能定价评估 */
789
- getAllProductsForSmartPricing() {
790
- if (this.smartPricingProductCatalog.length) {
791
- return this.smartPricingProductCatalog;
792
- }
793
- const venueList = this.getVenueProducts();
794
- const addonList = this.getAddonProductsList();
795
- return [...venueList, ...addonList];
796
- }
797
- getSlotPriceMapCacheKey(date, context) {
798
- return [
799
- date,
800
- context.customerId ?? "",
801
- (context.availableWalletIds || []).join(","),
802
- context.channel ?? "",
803
- context.businessCode ?? ""
804
- ].join("|");
805
- }
806
- /**
807
- * 按 schedule 分段构建 slot 价格 Map,带实例级缓存。
808
- */
809
- buildSlotPriceMapForDate(date, config, productIds) {
810
- const context = this.buildSmartPricingContext();
811
- const cacheKey = this.getSlotPriceMapCacheKey(date, context);
812
- const cached = this.slotPriceMapCache.get(cacheKey);
813
- if (cached)
814
- return cached;
815
- const timeLabels = (0, import_timeSlot.generateTimeLabels)(config);
816
- const slotPriceMap = (0, import_smartPricing.buildSlotPriceMapByScheduleSegments)({
817
- products: this.getAllProductsForSmartPricing(),
818
- productIds,
819
- date,
820
- timeLabels,
821
- config,
822
- context
823
- });
824
- this.slotPriceMapCache.set(cacheKey, slotPriceMap);
825
- return slotPriceMap;
826
- }
827
- // ─── 场地商品 & 附加商品 ───
828
- async loadAllProducts() {
829
- if (this.loadAllProductsInFlight)
830
- return this.loadAllProductsInFlight;
831
- this.loadAllProductsInFlight = this._doLoadAllProducts().finally(() => {
832
- this.loadAllProductsInFlight = null;
833
- });
834
- return this.loadAllProductsInFlight;
835
- }
836
- async _doLoadAllProducts() {
837
- var _a, _b, _c;
838
- this.logMethodStart("loadAllProducts");
839
- try {
840
- if (!this.store.venueProducts)
841
- throw new Error("venueProducts 模块未初始化");
842
- if (!this.store.addonProducts)
843
- throw new Error("addonProducts 模块未初始化");
844
- await this.loadOpenDataConfig();
845
- const associatedMenus = ((_b = (_a = this.otherParams) == null ? void 0 : _a.openData) == null ? void 0 : _b["menu.associated_menus"]) || [];
846
- if (!associatedMenus.length) {
847
- this.logMethodError("loadAllProducts", new Error("未获取到餐牌配置(menu.associated_menus),请检查 OpenData 配置"));
848
- throw new Error("未获取到餐牌配置(menu.associated_menus),请检查 OpenData 配置");
849
- }
850
- const menuListIds = associatedMenus.map((n) => Number(n.value));
851
- const allProducts = await this.store.venueProducts.loadProducts({
852
- menu_list_ids: menuListIds,
853
- cacheId: this.cacheId,
854
- schedule_date: (0, import_dayjs.default)().format("YYYY-MM-DD"),
855
- schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"),
856
- with_extra: ["dataVariants"]
857
- });
858
- const rawList = Array.isArray(allProducts) ? allProducts : [];
859
- let list = rawList;
860
- this.smartPricingProductCatalog = rawList.slice();
861
- list = (0, import_smartPricing.formatProductsWithDataVariant)(
862
- list,
863
- this.buildSmartPricingContext(),
864
- (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
865
- );
866
- this.clearSlotPriceMapCache();
867
- const venueList = list.filter((p) => p.duration != null);
868
- const addonList = list.filter((p) => p.duration == null);
869
- const venueStore = (_c = this.store.venueProducts) == null ? void 0 : _c.store;
870
- if (venueStore) {
871
- venueStore.list = venueList.slice().sort((a, b) => Number(b.sort) - Number(a.sort));
872
- }
873
- this.store.addonProducts.addProduct(addonList);
874
- this.resourceProductMap = (0, import_resource.buildResourceProductMap)(venueList);
875
- this.productsLoaded = true;
876
- this.logMethodSuccess("loadAllProducts", {
877
- total: list.length,
878
- venueCount: venueList.length,
879
- addonCount: addonList.length,
880
- resourceCount: this.resourceProductMap.size
881
- });
882
- return { venueProducts: venueList, addonProducts: addonList };
883
- } catch (error) {
884
- this.logMethodError("loadAllProducts", error);
885
- throw error;
886
- }
887
- }
888
- async loadVenueProducts() {
889
- const result = await this.loadAllProducts();
890
- return result.venueProducts;
891
- }
892
- async loadAddonProducts() {
893
- const result = await this.loadAllProducts();
894
- return result.addonProducts;
895
- }
896
- getVenueProducts() {
897
- var _a, _b;
898
- return ((_b = (_a = this.store.venueProducts) == null ? void 0 : _a.store) == null ? void 0 : _b.list) || [];
899
- }
900
- getAddonProductsList() {
901
- var _a, _b;
902
- return ((_b = (_a = this.store.addonProducts) == null ? void 0 : _a.store) == null ? void 0 : _b.list) || [];
903
- }
904
- // ─── 报价单 ───
905
- async loadQuotations(params) {
906
- this.logMethodStart("loadQuotations");
907
- try {
908
- if (!this.store.quotation)
909
- throw new Error("quotation 模块未初始化");
910
- await this.store.quotation.loadQuotations(params);
911
- this.logMethodSuccess("loadQuotations", {
912
- count: this.store.quotation.getQuotationList().length
913
- });
914
- } catch (error) {
915
- this.logMethodError("loadQuotations", error);
916
- throw error;
917
- }
918
- }
919
- // ─── 资源可用性 ───
920
- async fetchResourceAvailability(params) {
921
- this.logMethodStart("fetchResourceAvailability", params);
922
- try {
923
- const venueProducts = this.getVenueProducts();
924
- if (!venueProducts.length) {
925
- this.store.rawResourceData = [];
926
- this.logMethodSuccess("fetchResourceAvailability", { resourceCount: 0 });
927
- return;
928
- }
929
- const resourceIds = (0, import_resource.extractResourceIds)(venueProducts);
930
- if (!resourceIds.length) {
931
- this.store.rawResourceData = [];
932
- this.logMethodSuccess("fetchResourceAvailability", { resourceIds: [] });
933
- return;
934
- }
935
- const config = this.store.slotConfig;
936
- const crossDay = (0, import_timeSlot.isBusinessHoursCrossDay)(config);
937
- const effectiveEndDate = crossDay ? (0, import_dayjs.default)(params.endDate).add(1, "day").format("YYYY-MM-DD") : params.endDate;
938
- if (!this.store.date)
939
- throw new Error("date 模块未初始化");
940
- const res = await this.store.date.fetchResourceDates({
941
- query: {
942
- start_date: params.startDate,
943
- end_date: effectiveEndDate,
944
- resource_ids: resourceIds
945
- },
946
- useCache: false
947
- });
948
- const rawData = [];
949
- if ((res == null ? void 0 : res.data) && Array.isArray(res.data)) {
950
- for (const item of res.data) {
951
- rawData.push({
952
- resourceId: item.id,
953
- formId: item.form_id,
954
- times: Array.isArray(item.times) ? item.times : [],
955
- ...item
956
- });
957
- }
958
- }
959
- this.store.rawResourceData = rawData;
960
- for (const item of rawData) {
961
- const mappings = this.resourceProductMap.get(item.resourceId);
962
- if (!mappings)
963
- continue;
964
- for (const mapping of mappings) {
965
- if (item.main_field)
966
- mapping.resourceName = item.main_field;
967
- if (item.resource_form_id)
968
- mapping.formId = item.resource_form_id;
969
- }
970
- }
971
- this.logMethodSuccess("fetchResourceAvailability", {
972
- resourceCount: rawData.length,
973
- totalTimes: rawData.reduce((sum, r) => sum + r.times.length, 0)
974
- });
975
- } catch (error) {
976
- this.store.rawResourceData = [];
977
- this.logMethodError("fetchResourceAvailability", error);
978
- throw error;
979
- }
980
- }
981
- // ─── 日期概览 & 时间槽矩阵(纯计算,不发请求) ───
982
- getOperatingHoursScheduleIds() {
983
- var _a, _b;
984
- const openData = this.otherParams.openData || ((_b = (_a = this.store.openData) == null ? void 0 : _a.getOpenData) == null ? void 0 : _b.call(_a)) || null;
985
- const rawIds = openData == null ? void 0 : openData["availability.operating_hours"];
986
- if (!Array.isArray(rawIds))
987
- return [];
988
- return [...new Set(
989
- rawIds.map((id) => Number(id)).filter((id) => Number.isFinite(id) && id > 0).map((id) => Math.floor(id))
990
- )];
991
- }
992
- resolveSlotConfigForDate(date) {
993
- var _a;
994
- const nextSlotConfig = { ...this.baseSlotConfig };
995
- if (!date || !this.store.schedule)
996
- return nextSlotConfig;
997
- const operatingHoursScheduleIds = this.getOperatingHoursScheduleIds();
998
- if (!operatingHoursScheduleIds.length)
999
- return nextSlotConfig;
1000
- const scheduleList = this.store.schedule.getScheduleListByIds(
1001
- operatingHoursScheduleIds
1002
- );
1003
- if (!scheduleList.length)
1004
- return nextSlotConfig;
1005
- const timeRangeMap = (0, import_utils2.calcMinTimeMaxTimeBySchedules)(
1006
- scheduleList,
1007
- void 0,
1008
- date
1009
- );
1010
- let earliestStart = null;
1011
- let latestEnd = null;
1012
- for (const schedule of scheduleList) {
1013
- const dateRangeList = ((_a = timeRangeMap == null ? void 0 : timeRangeMap[schedule.id]) == null ? void 0 : _a.dateRangeFormat) || [];
1014
- for (const range of dateRangeList) {
1015
- const start = (0, import_dayjs.default)(range == null ? void 0 : range.start);
1016
- const end = (0, import_dayjs.default)(range == null ? void 0 : range.end);
1017
- if (!start.isValid() || !end.isValid())
1018
- continue;
1019
- if (!earliestStart || start.isBefore(earliestStart)) {
1020
- earliestStart = start;
1021
- }
1022
- if (!latestEnd || end.isAfter(latestEnd)) {
1023
- latestEnd = end;
1024
- }
1025
- }
1026
- }
1027
- if (!earliestStart || !latestEnd)
1028
- return nextSlotConfig;
1029
- return {
1030
- ...nextSlotConfig,
1031
- businessStartTime: earliestStart.format("HH:mm"),
1032
- businessEndTime: latestEnd.format("HH:mm")
1033
- };
1034
- }
1035
- syncOperatingHoursToSlotConfig(date) {
1036
- const resolvedSlotConfig = this.resolveSlotConfigForDate(date);
1037
- this.store.slotConfig = resolvedSlotConfig;
1038
- return resolvedSlotConfig;
1039
- }
1040
- getDateRangeSummary(params) {
1041
- return (0, import_dateSummary.buildDateRangeSummary)({
1042
- startDate: params.startDate,
1043
- endDate: params.endDate,
1044
- config: this.baseSlotConfig,
1045
- rawResources: this.store.rawResourceData,
1046
- resourceProductMap: this.resourceProductMap,
1047
- resolveConfig: (date) => this.resolveSlotConfigForDate(date),
1048
- buildSlotPriceMap: (date, config, productIds) => this.buildSlotPriceMapForDate(date, config, productIds)
1049
- });
1050
- }
1051
- getTimeSlotGrid(date) {
1052
- const resolvedSlotConfig = this.syncOperatingHoursToSlotConfig(date);
1053
- const productIds = [
1054
- ...new Set(
1055
- [...this.resourceProductMap.values()].flat().map((m) => m.productId)
1056
- )
1057
- ];
1058
- const slotPriceMap = productIds.length ? this.buildSlotPriceMapForDate(date, resolvedSlotConfig, productIds) : void 0;
1059
- return (0, import_timeSlot.buildTimeSlotGrid)({
1060
- date,
1061
- config: resolvedSlotConfig,
1062
- rawResources: this.store.rawResourceData,
1063
- resourceProductMap: this.resourceProductMap,
1064
- slotPriceMap
1065
- });
1066
- }
1067
- // ─── 时间槽订单操作 ───
1068
- /**
1069
- * 切换单个时段的选中状态(选中/取消)。
1070
- * 内部自动处理连续时段的合并与拆分,订单是唯一真相源。
1071
- *
1072
- * slot.productId 指定当前操作针对的是该 resourceId 下的哪一个商品。
1073
- * 同一资源下不同 productId 之间互相隔离,不会相互合并。
1074
- */
1075
- async toggleSlot(slot) {
1076
- this.logMethodStart("toggleSlot", {
1077
- resourceId: slot.resourceId,
1078
- productId: slot.productId,
1079
- startTime: slot.startTime
1080
- });
1081
- try {
1082
- const mappings = this.resourceProductMap.get(slot.resourceId);
1083
- if (!mappings || !mappings.length) {
1084
- throw new Error(`未找到资源 ${slot.resourceId} 的商品映射`);
1085
- }
1086
- const mapping = mappings.find((m) => m.productId === slot.productId);
1087
- if (!mapping) {
1088
- throw new Error(`资源 ${slot.resourceId} 未关联商品 ${slot.productId}`);
1089
- }
1090
- if (!this.store.order)
1091
- throw new Error("order 模块未初始化");
1092
- const currentSlots = this.getSelectedSlotsForResourceProduct(
1093
- slot.resourceId,
1094
- slot.productId
1095
- );
1096
- const existIndex = currentSlots.findIndex((s) => s.startTime === slot.startTime);
1097
- let nextSlots;
1098
- if (existIndex !== -1) {
1099
- nextSlots = currentSlots.filter((_, i) => i !== existIndex);
1100
- } else {
1101
- nextSlots = [...currentSlots, slot];
1102
- }
1103
- await this.reconcileOrderForResourceProduct(
1104
- slot.resourceId,
1105
- slot.productId,
1106
- nextSlots
1107
- );
1108
- const products = this.store.order.getOrderProducts();
1109
- await this.refreshItemRuleQuantityLimits();
1110
- await this.refreshCartValidationPassed();
1111
- this.logMethodSuccess("toggleSlot", {
1112
- action: existIndex !== -1 ? "remove" : "add",
1113
- resourceId: slot.resourceId,
1114
- productId: slot.productId,
1115
- slotCount: nextSlots.length
1116
- });
1117
- return products;
1118
- } catch (error) {
1119
- this.logMethodError("toggleSlot", error);
1120
- throw error;
1121
- }
1122
- }
1123
- /**
1124
- * 获取某资源当前选中的所有独立时段(从订单中解析)。
1125
- * 不传 productId 时返回该资源下所有商品的选中时段;传了则精确匹配。
1126
- */
1127
- getSelectedSlotsForResource(resourceId, productId) {
1128
- var _a;
1129
- const tempOrder = (_a = this.store.order) == null ? void 0 : _a.getTempOrder();
1130
- if (!tempOrder)
1131
- return [];
1132
- const venueProducts = tempOrder.products.filter((p) => {
1133
- var _a2, _b;
1134
- if (!((_a2 = p.metadata) == null ? void 0 : _a2.venue_booking))
1135
- return false;
1136
- if (String((_b = p.metadata) == null ? void 0 : _b.resource_id) !== String(resourceId))
1137
- return false;
1138
- if (productId != null && Number(p.product_id) !== Number(productId))
1139
- return false;
1140
- return true;
1141
- });
1142
- const slotDuration = this.store.slotConfig.slotDurationMinutes;
1143
- const slots = [];
1144
- for (const product of venueProducts) {
1145
- slots.push(
1146
- ...(0, import_slotMerge.expandMergedSlotToIndividual)(product, slotDuration).map((s) => ({
1147
- ...s,
1148
- productId: Number(product.product_id)
1149
- }))
1150
- );
1151
- }
1152
- return slots.sort((a, b) => a.startTime.localeCompare(b.startTime));
1153
- }
1154
- /** getSelectedSlotsForResource 的 (resourceId, productId) 精确版,内部使用。 */
1155
- getSelectedSlotsForResourceProduct(resourceId, productId) {
1156
- return this.getSelectedSlotsForResource(resourceId, productId);
1157
- }
1158
- /**
1159
- * 判断某个时段是否已选中。
1160
- * 不传 productId 时:只要该资源下任一商品在 startTime 被选中即返回 true;传了则精确匹配。
1161
- */
1162
- isSlotSelected(resourceId, startTime, productId) {
1163
- return this.getSelectedSlotsForResource(resourceId, productId).some((s) => s.startTime === startTime);
1164
- }
1165
- /**
1166
- * 判断指定 (resourceId, productId, startTime) 格子是否应因其它已选项而被禁用。
1167
- * 规则:
1168
- * 1) 同一 resourceId 下若已选了另一个 productId 的同 startTime → 禁用
1169
- * 2) 当前 resource 是组合资源:若其任一 child resource 在 startTime 被选中 → 禁用
1170
- * 3) 当前 resource 是某些组合资源的 child:若该组合资源在 startTime 被选中 → 禁用
1171
- * 4) 两个组合资源的 child 集合有交集,且对方在该 startTime 被选中 → 禁用
1172
- */
1173
- isSlotDisabledBySelection(params) {
1174
- const { resourceId, productId, startTime } = params;
1175
- const allSelected = this.getAllSelectedSlots();
1176
- const getSelectedAt = (resId) => {
1177
- const list = allSelected.get(resId) || [];
1178
- return list.filter((s) => s.startTime === startTime);
1179
- };
1180
- const sameResourceSelections = getSelectedAt(resourceId);
1181
- if (sameResourceSelections.some((s) => Number(s.productId) !== Number(productId))) {
1182
- return true;
1183
- }
1184
- const getCombinedChildIds = (resId) => {
1185
- const raw = this.store.rawResourceData.find(
1186
- (r) => String(r.resourceId) === String(resId)
1187
- );
1188
- const combined = raw == null ? void 0 : raw.combined_resource;
1189
- if (combined && combined.status === 1 && Array.isArray(combined.resource_ids)) {
1190
- return combined.resource_ids;
1191
- }
1192
- return [];
1193
- };
1194
- const currentChildIds = getCombinedChildIds(resourceId);
1195
- const currentIsCombined = currentChildIds.length > 0;
1196
- if (currentIsCombined) {
1197
- for (const childId of currentChildIds) {
1198
- if (getSelectedAt(childId).length > 0)
1199
- return true;
1200
- }
1201
- }
1202
- for (const [selectedResId, slots] of allSelected) {
1203
- if (!slots.some((s) => s.startTime === startTime))
1204
- continue;
1205
- if (String(selectedResId) === String(resourceId))
1206
- continue;
1207
- const selectedChildIds = getCombinedChildIds(selectedResId);
1208
- if (selectedChildIds.length === 0)
1209
- continue;
1210
- if (selectedChildIds.some((id) => String(id) === String(resourceId))) {
1211
- return true;
1212
- }
1213
- if (currentIsCombined) {
1214
- const intersect = selectedChildIds.some(
1215
- (id) => currentChildIds.some((cid) => String(cid) === String(id))
1216
- );
1217
- if (intersect)
1218
- return true;
1219
- }
1220
- }
1221
- return false;
1222
- }
1223
- /**
1224
- * 获取所有已选时段(按资源分组)。每个 slot 上带 productId,便于 UI 做 per-product 判定。
1225
- */
1226
- getAllSelectedSlots() {
1227
- var _a, _b;
1228
- const result = /* @__PURE__ */ new Map();
1229
- const tempOrder = (_a = this.store.order) == null ? void 0 : _a.getTempOrder();
1230
- if (!tempOrder)
1231
- return result;
1232
- const venueProducts = tempOrder.products.filter((p) => {
1233
- var _a2;
1234
- return (_a2 = p.metadata) == null ? void 0 : _a2.venue_booking;
1235
- });
1236
- const slotDuration = this.store.slotConfig.slotDurationMinutes;
1237
- for (const product of venueProducts) {
1238
- const resourceId = (_b = product.metadata) == null ? void 0 : _b.resource_id;
1239
- if (resourceId == null)
1240
- continue;
1241
- const productId = Number(product.product_id);
1242
- const existing = result.get(resourceId) || [];
1243
- existing.push(
1244
- ...(0, import_slotMerge.expandMergedSlotToIndividual)(product, slotDuration).map((s) => ({
1245
- ...s,
1246
- productId
1247
- }))
1248
- );
1249
- result.set(resourceId, existing);
1250
- }
1251
- for (const [key, slots] of result) {
1252
- result.set(key, slots.sort((a, b) => a.startTime.localeCompare(b.startTime)));
1253
- }
1254
- return result;
1255
- }
1256
- /**
1257
- * 对指定 (resourceId, productId) 的订单商品进行 reconcile:
1258
- * 清除旧商品 → 合并连续时段 → 重新写入。
1259
- * 同一场地下不同商品互不干扰,各自单独 reconcile。
1260
- */
1261
- async reconcileOrderForResourceProduct(resourceId, productId, slots) {
1262
- const mappings = this.resourceProductMap.get(resourceId);
1263
- if (!mappings || !mappings.length || !this.store.order)
1264
- return;
1265
- const mapping = mappings.find((m) => m.productId === productId);
1266
- if (!mapping)
1267
- return;
1268
- const tempOrder = this.store.order.ensureTempOrder();
1269
- const matchesCurrent = (meta, pid) => !!(meta == null ? void 0 : meta.venue_booking) && String(meta == null ? void 0 : meta.resource_id) === String(resourceId) && Number(pid) === Number(productId);
1270
- tempOrder.products = tempOrder.products.filter(
1271
- (p) => !matchesCurrent(p.metadata, p.product_id)
1272
- );
1273
- tempOrder.bookings = (tempOrder.bookings || []).filter(
1274
- (b) => {
1275
- var _a, _b, _c, _d;
1276
- if (!((_a = b.metadata) == null ? void 0 : _a.venue_booking))
1277
- return true;
1278
- if (String((_b = b.metadata) == null ? void 0 : _b.resource_id) !== String(resourceId))
1279
- return true;
1280
- const bookingProductId = ((_c = b.metadata) == null ? void 0 : _c.product_id) ?? ((_d = b == null ? void 0 : b.product) == null ? void 0 : _d.product_id);
1281
- if (bookingProductId == null)
1282
- return false;
1283
- return Number(bookingProductId) !== Number(productId);
1284
- }
1285
- );
1286
- if (!slots.length) {
1287
- this.store.order.applyDiscount();
1288
- await this.store.order.recalculateSummary({ createIfMissing: true });
1289
- this.store.order.persistTempOrder();
1290
- return;
1291
- }
1292
- const merged = (0, import_slotMerge.mergeConsecutiveSlots)(slots);
1293
- const rawResource = this.store.rawResourceData.find(
1294
- (r) => String(r.resourceId) === String(resourceId)
1295
- );
1296
- const childRawResources = this.getCombinedChildRawResources(rawResource);
1297
- const venueProduct = this.getVenueProducts().find((p) => p.id === mapping.productId);
1298
- tempOrder.bookings = tempOrder.bookings || [];
1299
- for (let i = 0; i < merged.length; i++) {
1300
- const group = merged[i];
1301
- const identityKey = (0, import_slotMerge.buildVenueIdentityKey)(resourceId, i);
1302
- const bookingUuid = (0, import_utils3.createUuidV4)();
1303
- const startMoment = (0, import_dayjs.default)(group.startTime, "YYYY-MM-DD HH:mm");
1304
- const endMoment = (0, import_dayjs.default)(group.endTime, "YYYY-MM-DD HH:mm");
1305
- const duration = endMoment.diff(startMoment, "minute");
1306
- const customDepositData = cloneCustomDepositData(venueProduct == null ? void 0 : venueProduct.custom_deposit_data);
1307
- const resourceEntry = {
1308
- relation_type: "form",
1309
- like_status: "common",
1310
- id: resourceId,
1311
- main_field: mapping.resourceName,
1312
- form_id: (rawResource == null ? void 0 : rawResource.form_id) ?? mapping.formId,
1313
- relation_id: resourceId,
1314
- capacity: 1,
1315
- metadata: (0, import_slotMerge.buildVenueResourceMetadata)({ mapping, rawResource })
1316
- };
1317
- if (childRawResources && childRawResources.length) {
1318
- resourceEntry.children = childRawResources.map((child) => ({
1319
- relation_type: "form",
1320
- like_status: "common",
1321
- id: child.resourceId,
1322
- main_field: child.main_field || "",
1323
- form_id: child.form_id ?? child.formId,
1324
- relation_id: child.resourceId,
1325
- capacity: child.capacity ?? 1,
1326
- metadata: {}
1327
- }));
1328
- }
1329
- tempOrder.products.push(
1330
- (0, import_utils.normalizeOrderProduct)({
1331
- product_id: mapping.productId,
1332
- product_variant_id: 0,
1333
- identity_key: identityKey,
1334
- num: 1,
1335
- selling_price: group.totalPrice,
1336
- original_price: group.totalPrice,
1337
- is_charge_tax: (venueProduct == null ? void 0 : venueProduct.is_charge_tax) ?? 0,
1338
- metadata: {
1339
- venue_booking: true,
1340
- resource_id: resourceId,
1341
- resource_form_id: mapping.formId,
1342
- resource_name: mapping.resourceName,
1343
- start_time: group.startTime,
1344
- end_time: group.endTime,
1345
- slot_count: group.slotCount,
1346
- booking_uid: bookingUuid,
1347
- price_breakdown: (0, import_slotMerge.buildPriceBreakdown)({
1348
- group,
1349
- productId: mapping.productId
1350
- })
1351
- },
1352
- _origin: {
1353
- name: mapping.productTitle,
1354
- cover: (venueProduct == null ? void 0 : venueProduct.cover) || "",
1355
- custom_deposit_data: customDepositData,
1356
- id: 0,
1357
- number: 1,
1358
- registration_type: "all",
1359
- relation_products: [],
1360
- is_all: false,
1361
- product: {
1362
- product_id: mapping.productId,
1363
- product_variant_id: 0,
1364
- num: 1,
1365
- product_bundle: [],
1366
- product_option_item: [],
1367
- discount_list: [],
1368
- custom_deposit_data: customDepositData,
1369
- metadata: {}
1370
- },
1371
- sub_type: "minutes",
1372
- duration,
1373
- like_status: "common",
1374
- resources: [resourceEntry],
1375
- schedule_id: 0,
1376
- select_date: startMoment.format("YYYY-MM-DD"),
1377
- start_date: startMoment.format("YYYY-MM-DD"),
1378
- start_time: startMoment.format("HH:mm"),
1379
- end_date: endMoment.format("YYYY-MM-DD"),
1380
- end_time: endMoment.format("HH:mm"),
1381
- metadata: {
1382
- venue_booking: true,
1383
- slot_count: group.slotCount
1384
- },
1385
- holder: null
1386
- }
1387
- })
1388
- );
1389
- const booking = (0, import_slotMerge.buildVenueBookingEntry)({
1390
- group,
1391
- resourceId,
1392
- mapping,
1393
- rawResource,
1394
- bookingUuid,
1395
- productUid: identityKey,
1396
- childResources: childRawResources
1397
- });
1398
- tempOrder.bookings.push(booking);
1399
- }
1400
- this.store.order.applyDiscount();
1401
- await this.store.order.recalculateSummary({ createIfMissing: true });
1402
- this.store.order.persistTempOrder();
1403
- }
1404
- /** 给定一个父 rawResource,返回其 combined_resource.resource_ids 对应的子 rawResource 列表。 */
1405
- getCombinedChildRawResources(rawResource) {
1406
- if (!rawResource)
1407
- return void 0;
1408
- const combined = rawResource.combined_resource;
1409
- if (!combined || combined.status !== 1 || !Array.isArray(combined.resource_ids) || !combined.resource_ids.length) {
1410
- return void 0;
1411
- }
1412
- const children = [];
1413
- for (const id of combined.resource_ids) {
1414
- const child = this.store.rawResourceData.find(
1415
- (r) => String(r.resourceId) === String(id)
1416
- );
1417
- if (child)
1418
- children.push(child);
1419
- }
1420
- return children.length ? children : void 0;
1421
- }
1422
- // ─── 配置 ───
1423
- setSlotConfig(config) {
1424
- this.baseSlotConfig = {
1425
- ...this.baseSlotConfig,
1426
- ...config
1427
- };
1428
- this.store.slotConfig = {
1429
- ...this.baseSlotConfig
1430
- };
1431
- }
1432
- getSlotConfig() {
1433
- return { ...this.store.slotConfig };
1434
- }
1435
- // ─── 日程 ───
1436
- async loadSchedules() {
1437
- this.logMethodStart("loadSchedules");
1438
- try {
1439
- if (!this.store.schedule)
1440
- throw new Error("schedule 模块未初始化");
1441
- await this.store.schedule.loadAllSchedule();
1442
- this.logMethodSuccess("loadSchedules");
1443
- } catch (error) {
1444
- this.logMethodError("loadSchedules", error);
1445
- throw error;
1446
- }
1447
- }
1448
- getScheduleListByIds(ids) {
1449
- if (!this.store.schedule)
1450
- return [];
1451
- return this.store.schedule.getScheduleListByIds(ids);
1452
- }
1453
- // ─── 临时订单操作(保留原有能力) ───
1454
- getTempOrder() {
1455
- var _a;
1456
- const result = ((_a = this.store.order) == null ? void 0 : _a.getTempOrder()) || null;
1457
- return result;
1458
- }
1459
- updateTempOrderNote(note) {
1460
- if (!this.store.order)
1461
- throw new Error("order 模块未初始化");
1462
- return this.store.order.updateTempOrderNote(note);
1463
- }
1464
- updateTempOrderContactsInfo(contactsInfo) {
1465
- if (!this.store.order)
1466
- throw new Error("order 模块未初始化");
1467
- return this.store.order.updateTempOrderContactsInfo(contactsInfo);
1468
- }
1469
- ensureTempOrder() {
1470
- if (!this.store.order)
1471
- throw new Error("order 模块未初始化");
1472
- return this.store.order.ensureTempOrder();
1473
- }
1474
- async onCustomerLogin(params) {
1475
- this.logMethodStart("onCustomerLogin", { customerId: params.customerId });
1476
- try {
1477
- await this.refreshOrderMarketingAfterLogin({
1478
- customerId: params.customerId
1479
- });
1480
- this.logMethodSuccess("onCustomerLogin", { customerId: params.customerId });
1481
- } catch (error) {
1482
- this.logMethodError("onCustomerLogin", error);
1483
- throw error;
1484
- }
1485
- }
1486
- /**
1487
- * 接收 pisell2 VenueBooking 登录链路诊断日志。
1488
- * 实际是否上报仍由 OS 内部 cacheId 白名单统一控制。
1489
- */
1490
- logPricingDiagnosticsFromClient(params) {
1491
- this.logPricingDiagnostics(
1492
- `[VenueBooking][pisell2] ${String((params == null ? void 0 : params.title) || "diagnostic")}`,
1493
- (params == null ? void 0 : params.payload) || {}
1494
- );
1495
- }
1496
- recalculateOrderPricesFromSmartPricing() {
1497
- var _a, _b;
1498
- if (!this.store.order) {
1499
- this.logPricingDiagnostics("[VenueBooking] order smart pricing recalculation skipped", {
1500
- reason: "order module is missing"
1501
- });
1502
- return;
1503
- }
1504
- const tempOrder = this.store.order.getTempOrder();
1505
- if (!((_a = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _a.length)) {
1506
- this.logPricingDiagnostics("[VenueBooking] order smart pricing recalculation skipped", {
1507
- reason: "temp order has no products"
1508
- });
1509
- return;
1510
- }
1511
- const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1512
- const catalog = this.getAllProductsForSmartPricing();
1513
- const context = this.buildSmartPricingContext();
1514
- const productDiagnostics = this.isPricingDiagnosticsEnabled() ? [] : null;
1515
- for (const product of tempOrder.products) {
1516
- if ((_b = product.metadata) == null ? void 0 : _b.venue_booking) {
1517
- const mappings = this.resourceProductMap.get(product.metadata.resource_id);
1518
- if (!mappings || !mappings.length) {
1519
- productDiagnostics == null ? void 0 : productDiagnostics.push({
1520
- productId: product.product_id,
1521
- resourceId: product.metadata.resource_id,
1522
- originalSellingPrice: product.selling_price,
1523
- result: "skipped",
1524
- reason: "resourceProductMap has no mapping for resource"
1525
- });
1526
- continue;
1527
- }
1528
- const mapping = mappings.find((m) => Number(m.productId) === Number(product.product_id)) || mappings[0];
1529
- if (!mapping) {
1530
- productDiagnostics == null ? void 0 : productDiagnostics.push({
1531
- productId: product.product_id,
1532
- resourceId: product.metadata.resource_id,
1533
- originalSellingPrice: product.selling_price,
1534
- result: "skipped",
1535
- reason: "no product mapping selected",
1536
- mappings
1537
- });
1538
- continue;
1539
- }
1540
- const slots = (0, import_slotMerge.expandMergedSlotToIndividual)(
1541
- product,
1542
- this.store.slotConfig.slotDurationMinutes
1543
- );
1544
- const uniqueDates = [
1545
- ...new Set(slots.map((slot) => (0, import_dayjs.default)(slot.startTime).format("YYYY-MM-DD")))
1546
- ];
1547
- const slotPriceMaps = /* @__PURE__ */ new Map();
1548
- for (const slotDate of uniqueDates) {
1549
- slotPriceMaps.set(
1550
- slotDate,
1551
- this.buildSlotPriceMapForDate(slotDate, this.store.slotConfig, [mapping.productId])
1552
- );
1553
- }
1554
- const updatedSlots = slots.map((slot) => {
1555
- const slotDate = (0, import_dayjs.default)(slot.startTime).format("YYYY-MM-DD");
1556
- const slotPriceMap = slotPriceMaps.get(slotDate);
1557
- return {
1558
- ...slot,
1559
- productId: mapping.productId,
1560
- price: slotPriceMap ? (0, import_smartPricing.getSlotPriceFromMap)({
1561
- slotPriceMap,
1562
- productId: mapping.productId,
1563
- slotStartTime: slot.startTime,
1564
- fallbackPrice: mapping.price
1565
- }) : mapping.price
1566
- };
1567
- });
1568
- const merged = (0, import_slotMerge.mergeConsecutiveSlots)(updatedSlots);
1569
- if (merged.length === 1) {
1570
- const previousSellingPrice = product == null ? void 0 : product.selling_price;
1571
- this.resetProductPriceForSmartPricing({
1572
- product,
1573
- price: merged[0].totalPrice,
1574
- priceBreakdown: (0, import_slotMerge.buildPriceBreakdown)({
1575
- group: merged[0],
1576
- productId: mapping.productId
1577
- })
1578
- });
1579
- productDiagnostics == null ? void 0 : productDiagnostics.push({
1580
- productId: product.product_id,
1581
- resourceId: product.metadata.resource_id,
1582
- result: "price reset",
1583
- previousSellingPrice,
1584
- finalSellingPrice: product.selling_price,
1585
- mapping,
1586
- slots: updatedSlots,
1587
- merged,
1588
- slotPriceMaps: Array.from(slotPriceMaps.entries()).map(([date, priceMap]) => ({
1589
- date,
1590
- entries: Array.from(priceMap.entries())
1591
- }))
1592
- });
1593
- } else {
1594
- productDiagnostics == null ? void 0 : productDiagnostics.push({
1595
- productId: product.product_id,
1596
- resourceId: product.metadata.resource_id,
1597
- originalSellingPrice: product.selling_price,
1598
- result: "skipped",
1599
- reason: "expanded slots did not merge into exactly one group",
1600
- mapping,
1601
- slots: updatedSlots,
1602
- merged
1603
- });
1604
- }
1605
- } else if (product.product_id != null) {
1606
- const catalogProduct = productDiagnostics ? catalog == null ? void 0 : catalog.find(
1607
- (item) => Number(item == null ? void 0 : item.id) === Number(product == null ? void 0 : product.product_id)
1608
- ) : void 0;
1609
- const previousSellingPrice = product == null ? void 0 : product.selling_price;
1610
- const smartPrice = (0, import_smartPricing.getPriceForProductAtDatetime)({
1611
- products: catalog,
1612
- context,
1613
- productId: Number(product.product_id),
1614
- datetime: now,
1615
- fallbackPrice: product.selling_price
1616
- });
1617
- this.resetProductPriceForSmartPricing({
1618
- product,
1619
- price: smartPrice
1620
- });
1621
- productDiagnostics == null ? void 0 : productDiagnostics.push({
1622
- productId: product.product_id,
1623
- result: "price reset",
1624
- previousSellingPrice,
1625
- resolvedSmartPrice: smartPrice,
1626
- finalSellingPrice: product.selling_price,
1627
- catalogProduct: catalogProduct ? {
1628
- price: catalogProduct.price,
1629
- sellingPrice: catalogProduct.selling_price,
1630
- dataVariants: catalogProduct.data_variants
1631
- } : null
1632
- });
1633
- } else {
1634
- productDiagnostics == null ? void 0 : productDiagnostics.push({
1635
- productId: product.product_id,
1636
- originalSellingPrice: product.selling_price,
1637
- result: "skipped",
1638
- reason: "product_id is missing"
1639
- });
1640
- }
1641
- }
1642
- if (productDiagnostics) {
1643
- this.logPricingDiagnostics("[VenueBooking] order smart pricing recalculation detail", {
1644
- now,
1645
- context: {
1646
- customerId: context.customerId,
1647
- availableWalletIds: context.availableWalletIds,
1648
- channel: context.channel,
1649
- businessCode: context.businessCode,
1650
- orderType: context.orderType,
1651
- hasEvaluator: !!context.evaluator
1652
- },
1653
- catalogCount: catalog.length,
1654
- resourceProductMapSize: this.resourceProductMap.size,
1655
- productDiagnostics
1656
- });
1657
- }
1658
- }
1659
- /**
1660
- * DataVariant 重算价格后,同步刷新订单展示、Rules 与 Summary 共用的价格口径。
1661
- * Rules 会在本轮结束后根据当前客户的 discountList 重新写入实际折扣。
1662
- */
1663
- resetProductPriceForSmartPricing(params) {
1664
- const { product, price, priceBreakdown } = params;
1665
- const metadata = product.metadata || {};
1666
- product.selling_price = price;
1667
- product.original_price = price;
1668
- product.discount_list = [];
1669
- product.metadata = {
1670
- ...metadata,
1671
- ...priceBreakdown ? { price_breakdown: priceBreakdown } : {},
1672
- source_product_price: price,
1673
- main_product_original_price: price,
1674
- main_product_selling_price: price,
1675
- price_schema_version: 2
1676
- };
1677
- }
1678
- async scanCode(code, customerId) {
1679
- this.logMethodStart("scanCode", { code });
1680
- try {
1681
- if (!this.store.order)
1682
- throw new Error("order 模块未初始化");
1683
- const result = await this.store.order.scanCode(code, customerId);
1684
- if (result.isAvailable) {
1685
- await this.store.order.recalculateSummary({ createIfMissing: true });
1686
- this.store.order.persistTempOrder();
1687
- }
1688
- this.logMethodSuccess("scanCode", { isAvailable: result.isAvailable });
1689
- return result;
1690
- } catch (error) {
1691
- this.logMethodError("scanCode", error);
1692
- throw error;
1693
- }
1694
- }
1695
- /** 获取当前折扣列表(包装 order.getDiscountList) */
1696
- getDiscountList() {
1697
- if (!this.store.order)
1698
- return [];
1699
- return this.store.order.getDiscountList();
1700
- }
1701
- /** 勾选/取消勾选某张折扣券,重新计算折扣并持久化 */
1702
- async setDiscountSelected(params) {
1703
- var _a, _b, _c, _d, _e;
1704
- this.logMethodStart("setDiscountSelected", params);
1705
- try {
1706
- if (!this.store.order)
1707
- throw new Error("order 模块未初始化");
1708
- const list = this.store.order.getDiscountList();
1709
- const beforeTarget = list.find((d) => d.id === params.discountId) || null;
1710
- const updated = list.map(
1711
- (d) => d.id === params.discountId ? {
1712
- ...d,
1713
- isSelected: params.isSelected,
1714
- isManualSelect: !params.isSelected
1715
- } : d
1716
- );
1717
- const updatedTarget = updated.find((d) => d.id === params.discountId) || null;
1718
- const tempOrder = this.store.order.ensureTempOrder();
1719
- const orderStore = this.store.order.store || {};
1720
- const discountModule = orderStore.discount;
1721
- const rulesModule = orderStore.rules;
1722
- const holders = ((_a = tempOrder.holder) == null ? void 0 : _a.form_record_id) ? [{ form_record_id: tempOrder.holder.form_record_id }] : [];
1723
- let nextDiscountList = updated;
1724
- await (discountModule == null ? void 0 : discountModule.setDiscountList(updated));
1725
- if (rulesModule) {
1726
- const result = rulesModule.calcDiscount(
1727
- {
1728
- productList: tempOrder.products,
1729
- discountList: updated,
1730
- holders,
1731
- isFormSubject: !!((_b = tempOrder.holder) == null ? void 0 : _b.type) && tempOrder.holder.type === "form"
1732
- },
1733
- {
1734
- discountId: params.discountId,
1735
- isSelected: params.isSelected
1736
- }
1737
- ) || { productList: tempOrder.products, discountList: updated };
1738
- if (result == null ? void 0 : result.productList) {
1739
- tempOrder.products = result.productList;
1740
- }
1741
- if (result == null ? void 0 : result.discountList) {
1742
- nextDiscountList = result.discountList;
1743
- if (!params.isSelected) {
1744
- const beforeSelectedIds = new Set(
1745
- updated.filter((d) => d.isSelected).map((d) => d.id)
1746
- );
1747
- for (const d of nextDiscountList) {
1748
- if (d.isSelected && !beforeSelectedIds.has(d.id)) {
1749
- d.isSelected = false;
1750
- }
1751
- }
1752
- }
1753
- }
1754
- }
1755
- this.normalizeDiscountedOrderPrices(nextDiscountList);
1756
- import_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
1757
- await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
1758
- tempOrder.discount_list = (nextDiscountList || []).filter((d) => d.isSelected);
1759
- const afterApplyTarget = this.store.order.getDiscountList().find((d) => d.id === params.discountId) || null;
1760
- await this.store.order.recalculateSummary({ createIfMissing: true });
1761
- this.store.order.persistTempOrder();
1762
- const finalSummary = ((_c = this.store.order.getTempOrder()) == null ? void 0 : _c.summary) || null;
1763
- const finalProduct = ((_e = (_d = this.store.order.getTempOrder()) == null ? void 0 : _d.products) == null ? void 0 : _e[0]) || null;
1764
- this.logMethodSuccess("setDiscountSelected", params);
1765
- const finalTarget = this.store.order.getDiscountList().find((d) => d.id === params.discountId) || null;
1766
- return this.store.order.getDiscountList();
1767
- } catch (error) {
1768
- this.logMethodError("setDiscountSelected", error);
1769
- throw error;
1770
- }
1771
- }
1772
- /**
1773
- * 统一 VenueBooking 折扣后的订单行价。
1774
- *
1775
- * Rules 的 `discount_list.amount` 是已经按适用规则计算出的每件优惠额;它是这里唯一
1776
- * 的折扣金额来源。使用智能定价写入的 source_product_price 减去该金额,再同步
1777
- * selling_price 与 Summary 使用的 main_product_selling_price,避免 UI 的购物车行价、
1778
- * 小计和提交订单各自读取到不同的价格字段。
1779
- */
1780
- normalizeDiscountedOrderPrices(discountList) {
1781
- var _a;
1782
- const order = this.store.order;
1783
- if (!order)
1784
- return;
1785
- const tempOrder = order.ensureTempOrder();
1786
- const selectedResourceIds = new Set(
1787
- (discountList || []).filter((discount) => discount.isSelected).map((discount) => discount.id)
1788
- );
1789
- for (const product of tempOrder.products) {
1790
- if ((_a = product._origin) == null ? void 0 : _a.isManualDiscount)
1791
- continue;
1792
- product.discount_list = (product.discount_list || []).filter((detail) => {
1793
- var _a2;
1794
- const resourceId = ((_a2 = detail.discount) == null ? void 0 : _a2.resource_id) ?? detail.id;
1795
- return resourceId != null && selectedResourceIds.has(resourceId);
1796
- });
1797
- const totalPerUnitDiscount = (product.discount_list || []).reduce(
1798
- (total, detail) => total.plus(detail.amount || 0),
1799
- new import_decimal.default(0)
1800
- );
1801
- const metadata = product.metadata || (product.metadata = {});
1802
- const optionSum = (0, import_utils3.sumOptionUnitPrice)(product.product_option_item);
1803
- const sourcePrice = metadata.source_product_price ?? (metadata.main_product_original_price != null ? new import_decimal.default(Number(metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
1804
- const nextSourceSellingPrice = import_decimal.default.max(
1805
- 0,
1806
- new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount)
1807
- ).toDecimalPlaces(2).toString();
1808
- const nextMainSellingPrice = new import_decimal.default(Number(nextSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
1809
- metadata.main_product_selling_price = nextMainSellingPrice;
1810
- metadata.price_schema_version = 2;
1811
- product.selling_price = (0, import_utils3.composeLinePrice)({
1812
- mainPrice: nextMainSellingPrice,
1813
- bundle: product.product_bundle
1814
- });
1815
- }
1816
- }
1817
- async addNewOrder() {
1818
- this.logMethodStart("addNewOrder");
1819
- try {
1820
- if (!this.store.order)
1821
- throw new Error("order 模块未初始化");
1822
- const tempOrder = await this.store.order.addNewOrder();
1823
- this.logMethodSuccess("addNewOrder", {
1824
- productCount: tempOrder.products.length
1825
- });
1826
- return tempOrder;
1827
- } catch (error) {
1828
- this.logMethodError("addNewOrder", error);
1829
- throw error;
1830
- }
1831
- }
1832
- getOrderProducts() {
1833
- if (!this.store.order)
1834
- throw new Error("order 模块未初始化");
1835
- return this.store.order.getOrderProducts();
1836
- }
1837
- async getSummary() {
1838
- this.logMethodStart("getSummary");
1839
- try {
1840
- if (!this.store.order)
1841
- throw new Error("order 模块未初始化");
1842
- const summary = await this.store.order.getScanOrderSummary();
1843
- this.logMethodSuccess("getSummary", {
1844
- totalAmount: summary.total_amount
1845
- });
1846
- return summary;
1847
- } catch (error) {
1848
- this.logMethodError("getSummary", error);
1849
- throw error;
1850
- }
1851
- }
1852
- async submitOrder() {
1853
- var _a, _b, _c, _d, _e;
1854
- this.logMethodStart("submitOrder");
1855
- try {
1856
- await this.validateBeforeSubmitByItemRule();
1857
- if (!this.store.order) {
1858
- throw new Error("venueBooking解决方案需要 order 模块支持");
1859
- }
1860
- const result = await this.store.order.submitTempOrder({
1861
- cacheId: this.cacheId,
1862
- platform: (_a = this.otherParams) == null ? void 0 : _a.platform,
1863
- businessCode: (_b = this.otherParams) == null ? void 0 : _b.businessCode,
1864
- channel: (_c = this.otherParams) == null ? void 0 : _c.channel,
1865
- type: (_d = this.otherParams) == null ? void 0 : _d.type
1866
- });
1867
- const tempOrder = this.store.order.getTempOrder();
1868
- this.logMethodSuccess("submitOrder", {
1869
- productCount: ((_e = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _e.length) || 0
1870
- });
1871
- return result;
1872
- } catch (error) {
1873
- this.logMethodError("submitOrder", error);
1874
- throw error;
1875
- }
1876
- }
1877
- /**
1878
- * 0 元订单免费领取(非定金场景)
1879
- * 与 appointment getFreeProduct 同接口:POST /pay/order/free-pay/:id
1880
- */
1881
- async submitFreeOrder(id) {
1882
- this.logMethodStart("submitFreeOrder", { id });
1883
- try {
1884
- if (!id) {
1885
- throw new Error("订单 ID 不能为空");
1886
- }
1887
- const res = await this.request.post(`/pay/order/free-pay/${id}`);
1888
- this.logMethodSuccess("submitFreeOrder", { id, status: res == null ? void 0 : res.status });
1889
- return res;
1890
- } catch (error) {
1891
- this.logMethodError("submitFreeOrder", error);
1892
- throw error;
1893
- }
1894
- }
1895
- async addProductToOrder(product) {
1896
- var _a, _b;
1897
- this.logMethodStart("addProductToOrder", {
1898
- product_id: product.product_id,
1899
- product_variant_id: product.product_variant_id
1900
- });
1901
- try {
1902
- if (!this.store.order)
1903
- throw new Error("order 模块未初始化");
1904
- if (!((_a = product.metadata) == null ? void 0 : _a.venue_booking) && product.product_id != null) {
1905
- const smartPrice = (0, import_smartPricing.getPriceForProductAtDatetime)({
1906
- products: this.getAllProductsForSmartPricing(),
1907
- context: this.buildSmartPricingContext(),
1908
- productId: Number(product.product_id),
1909
- datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"),
1910
- fallbackPrice: product.selling_price
1911
- });
1912
- product.selling_price = smartPrice;
1913
- product.original_price = smartPrice;
1914
- } else if (product.selling_price != null && !((_b = product.metadata) == null ? void 0 : _b.venue_booking)) {
1915
- product.original_price = product.selling_price;
1916
- }
1917
- const products = await this.store.order.addProductToOrder(product);
1918
- await this.refreshItemRuleQuantityLimits();
1919
- await this.refreshCartValidationPassed();
1920
- this.logMethodSuccess("addProductToOrder", {
1921
- productCount: products.length
1922
- });
1923
- return products;
1924
- } catch (error) {
1925
- this.logMethodError("addProductToOrder", error);
1926
- throw error;
1927
- }
1928
- }
1929
- async updateProductInOrder(params) {
1930
- this.logMethodStart("updateProductInOrder", {
1931
- product_id: params.product_id,
1932
- product_variant_id: params.product_variant_id
1933
- });
1934
- try {
1935
- if (!this.store.order)
1936
- throw new Error("order 模块未初始化");
1937
- const products = await this.store.order.updateProductInOrder(params);
1938
- await this.refreshItemRuleQuantityLimits();
1939
- await this.refreshCartValidationPassed();
1940
- this.logMethodSuccess("updateProductInOrder", {
1941
- productCount: products.length
1942
- });
1943
- return products;
1944
- } catch (error) {
1945
- this.logMethodError("updateProductInOrder", error);
1946
- throw error;
1947
- }
1948
- }
1949
- async removeProductFromOrder(identity) {
1950
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1951
- this.logMethodStart("removeProductFromOrder", {
1952
- product_id: identity.product_id,
1953
- product_variant_id: identity.product_variant_id
1954
- });
1955
- try {
1956
- if (!this.store.order)
1957
- throw new Error("order 模块未初始化");
1958
- const tempOrder = ((_b = (_a = this.store.order).getTempOrder) == null ? void 0 : _b.call(_a)) || ((_d = (_c = this.store.order).ensureTempOrder) == null ? void 0 : _d.call(_c));
1959
- const products = await this.store.order.removeProductFromOrder(identity);
1960
- if ((_e = tempOrder == null ? void 0 : tempOrder.bookings) == null ? void 0 : _e.length) {
1961
- const venueProductUids = /* @__PURE__ */ new Set();
1962
- const venueBookingUids = /* @__PURE__ */ new Set();
1963
- for (const product of tempOrder.products || []) {
1964
- if (!((_f = product == null ? void 0 : product.metadata) == null ? void 0 : _f.venue_booking))
1965
- continue;
1966
- if (product.identity_key)
1967
- venueProductUids.add(String(product.identity_key));
1968
- if ((_g = product.metadata) == null ? void 0 : _g.booking_uid) {
1969
- venueBookingUids.add(String(product.metadata.booking_uid));
1970
- }
1971
- }
1972
- const beforeBookingCount = ((_h = tempOrder.bookings) == null ? void 0 : _h.length) || 0;
1973
- tempOrder.bookings = (tempOrder.bookings || []).filter((booking) => {
1974
- var _a2, _b2;
1975
- if (!((_a2 = booking == null ? void 0 : booking.metadata) == null ? void 0 : _a2.venue_booking))
1976
- return true;
1977
- if (booking.product_uid) {
1978
- return venueProductUids.has(String(booking.product_uid));
1979
- }
1980
- const bookingUid = (_b2 = booking.metadata) == null ? void 0 : _b2.unique_identification_number;
1981
- if (bookingUid)
1982
- return venueBookingUids.has(String(bookingUid));
1983
- return true;
1984
- });
1985
- if ((((_i = tempOrder.bookings) == null ? void 0 : _i.length) || 0) !== beforeBookingCount) {
1986
- (_k = (_j = this.store.order).persistTempOrder) == null ? void 0 : _k.call(_j);
1987
- }
1988
- }
1989
- await this.refreshItemRuleQuantityLimits();
1990
- await this.refreshCartValidationPassed();
1991
- this.logMethodSuccess("removeProductFromOrder", {
1992
- productCount: products.length
1993
- });
1994
- return products;
1995
- } catch (error) {
1996
- this.logMethodError("removeProductFromOrder", error);
1997
- throw error;
1998
- }
1999
- }
2000
- async getProductList() {
2001
- if (this.productsLoaded) {
2002
- return (0, import_utils.attachItemRuleLimitsToTopLevelProducts)(
2003
- this.getAddonProductsList(),
2004
- this.store.itemRuleQuantityLimits || []
2005
- );
2006
- }
2007
- const result = await this.loadAllProducts();
2008
- return (0, import_utils.attachItemRuleLimitsToTopLevelProducts)(
2009
- result.addonProducts,
2010
- this.store.itemRuleQuantityLimits || []
2011
- );
2012
- }
2013
- // ─── ItemRule 引擎 ───
2014
- async loadOpenDataConfig() {
2015
- if (!this.store.openData)
2016
- throw new Error("openData 模块未初始化");
2017
- const lastFetchedAt = this.store.openData.getLastFetchedAt();
2018
- const cachedData = this.store.openData.getOpenData();
2019
- if (cachedData && lastFetchedAt && Date.now() - lastFetchedAt < _VenueBookingImpl.OPEN_DATA_CACHE_TTL) {
2020
- this.otherParams.openData = cachedData;
2021
- return cachedData;
2022
- }
2023
- if (this.loadOpenDataConfigInFlight)
2024
- return await this.loadOpenDataConfigInFlight;
2025
- this.loadOpenDataConfigInFlight = this.store.openData.fetchOpenData({
2026
- scope: "board",
2027
- target: "venue_booking+online_store",
2028
- section_code: [...OPEN_DATA_SECTION_CODES]
2029
- });
2030
- try {
2031
- const openDataConfig = await this.loadOpenDataConfigInFlight;
2032
- this.otherParams.openData = openDataConfig;
2033
- return openDataConfig;
2034
- } finally {
2035
- this.loadOpenDataConfigInFlight = null;
2036
- }
2037
- }
2038
- async loadRuntimeConfigs() {
2039
- await this.loadOpenDataConfig();
2040
- const itemRuleConfigs = await this.ensureItemRuleConfigsLoaded();
2041
- this.logMethodSuccess("loadRuntimeConfigs", {
2042
- itemRuleCount: itemRuleConfigs.length
2043
- });
2044
- return { itemRuleConfigs };
2045
- }
2046
- async fetchItemRuleConfigsByModelIds(strategyModelIds) {
2047
- this.logMethodStart("fetchItemRuleConfigsByModelIds", { strategyModelIds });
2048
- if (!strategyModelIds.length)
2049
- return [];
2050
- try {
2051
- const result = await this.request.get("/promotion", {
2052
- skip: 1,
2053
- num: 99,
2054
- status: "active",
2055
- ids: strategyModelIds
2056
- });
2057
- let configs = [];
2058
- if (result.code === 200) {
2059
- configs = result.data.list.map((item) => item.metadata);
2060
- }
2061
- this.logMethodSuccess("fetchItemRuleConfigsByModelIds", {
2062
- strategyModelIds,
2063
- strategyCount: configs.length
2064
- });
2065
- return configs;
2066
- } catch (error) {
2067
- this.logMethodError("fetchItemRuleConfigsByModelIds", error, { strategyModelIds });
2068
- return [];
2069
- }
2070
- }
2071
- async buildPrefillProductSourceMap() {
2072
- const sourceMap = /* @__PURE__ */ new Map();
2073
- try {
2074
- const productList = await this.getProductList();
2075
- if (!Array.isArray(productList))
2076
- return sourceMap;
2077
- const visited = /* @__PURE__ */ new Set();
2078
- const collectFromValue = (value) => {
2079
- if (!value || typeof value !== "object")
2080
- return;
2081
- if (visited.has(value))
2082
- return;
2083
- visited.add(value);
2084
- if (Array.isArray(value)) {
2085
- for (const item of value)
2086
- collectFromValue(item);
2087
- return;
2088
- }
2089
- const node = value;
2090
- const rawProductId = node.product_id ?? node.id;
2091
- const productId = Number(rawProductId);
2092
- if (Number.isFinite(productId) && productId > 0) {
2093
- const productVariantId = Number(node.product_variant_id ?? node.variant_id ?? 0);
2094
- const normalizedVariantId = Number.isNaN(productVariantId) ? 0 : productVariantId;
2095
- const key = (0, import_utils.buildProductKey)(productId, normalizedVariantId);
2096
- if (!sourceMap.has(key))
2097
- sourceMap.set(key, node);
2098
- }
2099
- for (const childValue of Object.values(node)) {
2100
- if (childValue && typeof childValue === "object")
2101
- collectFromValue(childValue);
2102
- }
2103
- };
2104
- collectFromValue(productList);
2105
- } catch (error) {
2106
- this.logMethodError("buildPrefillProductSourceMap", error);
2107
- }
2108
- return sourceMap;
2109
- }
2110
- getItemRuleRuntimeConfig() {
2111
- return this.itemRuleRuntimeConfig || {};
2112
- }
2113
- async ensureItemRuleConfigsLoaded() {
2114
- if (this.itemRuleConfigs.length > 0)
2115
- return this.itemRuleConfigs;
2116
- if (this.itemRuleConfigsPromise)
2117
- return this.itemRuleConfigsPromise;
2118
- this.itemRuleConfigsPromise = (async () => {
2119
- const runtimeConfig = this.getItemRuleRuntimeConfig();
2120
- const staticConfigs = (0, import_utils.normalizeItemRuleStrategies)(runtimeConfig.strategyConfigs);
2121
- if (staticConfigs.length > 0) {
2122
- this.itemRuleConfigs = staticConfigs;
2123
- this.itemRuleEvaluator.setStrategyConfigs(staticConfigs);
2124
- return this.itemRuleConfigs;
2125
- }
2126
- this.itemRuleConfigs = [];
2127
- this.itemRuleEvaluator.setStrategyConfigs([]);
2128
- return this.itemRuleConfigs;
2129
- })();
2130
- return await this.itemRuleConfigsPromise;
2131
- }
2132
- async refreshItemRuleQuantityLimits() {
2133
- try {
2134
- const strategyConfigs = await this.ensureItemRuleConfigsLoaded();
2135
- if (!strategyConfigs.length) {
2136
- this.store.itemRuleQuantityLimits = [];
2137
- return [];
2138
- }
2139
- const businessData = (0, import_utils.buildItemRuleBusinessData)({
2140
- tempOrder: this.ensureTempOrder(),
2141
- runtimeConfig: this.getItemRuleRuntimeConfig(),
2142
- itemRuleConfigs: this.itemRuleConfigs
2143
- });
2144
- const limits = this.itemRuleEvaluator.getQuantityLimits(businessData);
2145
- this.store.itemRuleQuantityLimits = limits;
2146
- this.logMethodSuccess("refreshItemRuleQuantityLimits", { limitCount: limits.length });
2147
- return limits;
2148
- } catch (error) {
2149
- this.store.itemRuleQuantityLimits = [];
2150
- this.logMethodError("refreshItemRuleQuantityLimits", error);
2151
- return [];
2152
- }
2153
- }
2154
- async applyPrefillByItemRule() {
2155
- var _a;
2156
- if (this.itemRulePrefillApplied)
2157
- return;
2158
- if (!this.store.order)
2159
- return;
2160
- const strategyConfigs = await this.ensureItemRuleConfigsLoaded();
2161
- if (!strategyConfigs.length)
2162
- return;
2163
- const businessData = (0, import_utils.buildItemRuleBusinessData)({
2164
- tempOrder: this.ensureTempOrder(),
2165
- runtimeConfig: this.getItemRuleRuntimeConfig(),
2166
- itemRuleConfigs: this.itemRuleConfigs
2167
- });
2168
- const prefillItems = this.itemRuleEvaluator.getPrefillItems(businessData);
2169
- if (!prefillItems.length) {
2170
- this.itemRulePrefillApplied = true;
2171
- return;
2172
- }
2173
- const productSourceMap = await this.buildPrefillProductSourceMap();
2174
- const tempOrder = this.ensureTempOrder();
2175
- let hasChanges = false;
2176
- for (const prefillItem of prefillItems) {
2177
- const productId = Number(prefillItem.product_id);
2178
- const productVariantId = Number(prefillItem.product_variant_id ?? 0);
2179
- const targetQuantity = (0, import_utils.toNonNegativeInt)(prefillItem.quantity);
2180
- if (!Number.isFinite(productId) || targetQuantity <= 0)
2181
- continue;
2182
- if (Number.isNaN(productVariantId))
2183
- continue;
2184
- const sourceItem = productSourceMap.get((0, import_utils.buildProductKey)(productId, productVariantId)) || productSourceMap.get((0, import_utils.buildProductKey)(productId, 0)) || null;
2185
- const productIndex = (0, import_utils.getProductIdentityIndex)(tempOrder.products, {
2186
- product_id: productId,
2187
- product_variant_id: productVariantId
2188
- });
2189
- if (productIndex === -1) {
2190
- const sellingPrice = (0, import_utils.toPriceString)((sourceItem == null ? void 0 : sourceItem.price) ?? (sourceItem == null ? void 0 : sourceItem.selling_price), "0.00");
2191
- tempOrder.products.push(
2192
- (0, import_utils.normalizeOrderProduct)({
2193
- product_id: productId,
2194
- product_variant_id: productVariantId,
2195
- num: targetQuantity,
2196
- selling_price: sellingPrice,
2197
- original_price: sellingPrice,
2198
- metadata: { item_rule_prefill: true, item_rule_id: prefillItem.ruleId },
2199
- _origin: { ...sourceItem || {}, item_rule_prefill: true, item_rule_id: prefillItem.ruleId }
2200
- })
2201
- );
2202
- hasChanges = true;
2203
- continue;
2204
- }
2205
- const targetProduct = tempOrder.products[productIndex];
2206
- const existedQuantity = (0, import_utils.toNonNegativeInt)(targetProduct.num);
2207
- const delta = targetQuantity - existedQuantity;
2208
- const nextProduct = {
2209
- ...targetProduct,
2210
- ...delta > 0 ? { num: (0, import_utils.getSafeProductNum)(existedQuantity + delta) } : {},
2211
- metadata: { ...targetProduct.metadata || {}, item_rule_prefill: true, item_rule_id: prefillItem.ruleId },
2212
- _origin: sourceItem ? { ...targetProduct._origin || {}, ...sourceItem } : targetProduct._origin
2213
- };
2214
- if (delta > 0 || Boolean(sourceItem && (!targetProduct._origin || ((_a = targetProduct._origin) == null ? void 0 : _a.price) !== (sourceItem == null ? void 0 : sourceItem.price)))) {
2215
- tempOrder.products[productIndex] = nextProduct;
2216
- hasChanges = true;
2217
- }
2218
- }
2219
- if (hasChanges) {
2220
- this.store.order.applyDiscount();
2221
- await this.store.order.recalculateSummary({ createIfMissing: true });
2222
- this.store.order.persistTempOrder();
2223
- }
2224
- await this.refreshItemRuleQuantityLimits();
2225
- this.itemRulePrefillApplied = true;
2226
- this.logMethodSuccess("applyPrefillByItemRule", {
2227
- prefillCount: prefillItems.length,
2228
- hasChanges
2229
- });
2230
- }
2231
- async applyItemRulePrefill() {
2232
- this.logMethodStart("applyItemRulePrefill");
2233
- await this.applyPrefillByItemRule();
2234
- await this.refreshItemRuleQuantityLimits();
2235
- await this.refreshCartValidationPassed();
2236
- }
2237
- async evaluateCartValidationByItemRule() {
2238
- const strategyConfigs = await this.ensureItemRuleConfigsLoaded();
2239
- if (!strategyConfigs.length)
2240
- return { passed: true, failures: [] };
2241
- const businessData = (0, import_utils.buildItemRuleBusinessData)({
2242
- tempOrder: this.ensureTempOrder(),
2243
- runtimeConfig: this.getItemRuleRuntimeConfig(),
2244
- itemRuleConfigs: this.itemRuleConfigs
2245
- });
2246
- return this.itemRuleEvaluator.validateCart(businessData);
2247
- }
2248
- async validateBeforeSubmitByItemRule() {
2249
- const validationResult = await this.evaluateCartValidationByItemRule();
2250
- if (validationResult.passed)
2251
- return;
2252
- const firstFailure = validationResult.failures[0];
2253
- const errorMessage = (firstFailure == null ? void 0 : firstFailure.validationMessage) || "当前购物车未满足商品规则,请调整后再提交";
2254
- const error = new Error(String(errorMessage));
2255
- error.failures = validationResult.failures;
2256
- throw error;
2257
- }
2258
- async refreshCartValidationPassed() {
2259
- const previous = this.store.cartValidation || { passed: null, failures: [] };
2260
- let nextState = {
2261
- passed: null,
2262
- failures: []
2263
- };
2264
- try {
2265
- const validationResult = await this.evaluateCartValidationByItemRule();
2266
- nextState = {
2267
- passed: validationResult.passed,
2268
- failures: validationResult.failures || []
2269
- };
2270
- } catch {
2271
- nextState = { passed: false, failures: [] };
2272
- }
2273
- this.store.cartValidation = nextState;
2274
- const changed = previous.passed !== nextState.passed || previous.failures !== nextState.failures;
2275
- if (changed) {
2276
- await this.core.effects.emit(import_types.VenueBookingHooks.onCartValidationChanged, {
2277
- cartValidation: nextState,
2278
- cartValidationPassed: nextState.passed
2279
- });
2280
- }
2281
- return nextState.passed;
2282
- }
2283
- async setItemRuleRuntimeConfig(config = {}) {
2284
- var _a, _b;
2285
- this.logMethodStart("setItemRuleRuntimeConfig");
2286
- this.itemRuleRuntimeConfig = {
2287
- ...this.itemRuleRuntimeConfig,
2288
- ...config,
2289
- pax: { ...((_a = this.itemRuleRuntimeConfig) == null ? void 0 : _a.pax) || {}, ...(config == null ? void 0 : config.pax) || {} },
2290
- custom: { ...((_b = this.itemRuleRuntimeConfig) == null ? void 0 : _b.custom) || {}, ...(config == null ? void 0 : config.custom) || {} }
2291
- };
2292
- if ("strategyConfigs" in config) {
2293
- this.itemRuleConfigs = [];
2294
- this.itemRuleConfigsPromise = null;
2295
- this.itemRuleEvaluator.setStrategyConfigs([]);
2296
- }
2297
- this.itemRulePrefillApplied = false;
2298
- await this.refreshItemRuleQuantityLimits();
2299
- await this.refreshCartValidationPassed();
2300
- this.logMethodSuccess("setItemRuleRuntimeConfig", {
2301
- strategyCount: Array.isArray(this.itemRuleRuntimeConfig.strategyConfigs) ? this.itemRuleRuntimeConfig.strategyConfigs.length : 0
2302
- });
2303
- }
2304
- getOtherParams() {
2305
- return this.otherParams;
2306
- }
2307
- getUIStateBucketKey() {
2308
- if (!this.cacheId)
2309
- return null;
2310
- return `${_VenueBookingImpl.UI_STATE_KEY_PREFIX}${this.cacheId}`;
2311
- }
2312
- readUIStateBucket() {
2313
- var _a;
2314
- const key = this.getUIStateBucketKey();
2315
- if (!key || !((_a = this.window) == null ? void 0 : _a.sessionStorage))
2316
- return {};
2317
- try {
2318
- const raw = this.window.sessionStorage.getItem(key) || "{}";
2319
- const parsed = JSON.parse(raw);
2320
- return parsed && typeof parsed === "object" ? parsed : {};
2321
- } catch {
2322
- return {};
2323
- }
2324
- }
2325
- writeUIStateBucket(bucket) {
2326
- var _a;
2327
- const key = this.getUIStateBucketKey();
2328
- if (!key || !((_a = this.window) == null ? void 0 : _a.sessionStorage))
2329
- return;
2330
- this.window.sessionStorage.setItem(key, JSON.stringify(bucket));
2331
- }
2332
- setUIState(key, value) {
2333
- if (!this.getUIStateBucketKey())
2334
- return;
2335
- const bucket = this.readUIStateBucket();
2336
- bucket[key] = value;
2337
- this.writeUIStateBucket(bucket);
2338
- }
2339
- getUIState(key) {
2340
- if (!this.getUIStateBucketKey())
2341
- return void 0;
2342
- const bucket = this.readUIStateBucket();
2343
- return bucket[key];
2344
- }
2345
- deleteUIState(key) {
2346
- if (!this.getUIStateBucketKey())
2347
- return;
2348
- const bucket = this.readUIStateBucket();
2349
- if (key in bucket) {
2350
- delete bucket[key];
2351
- this.writeUIStateBucket(bucket);
2352
- }
2353
- }
2354
- setBookingHolder(bookingUid, holder) {
2355
- var _a;
2356
- const order = this.getTempOrder();
2357
- const booking = (_a = order == null ? void 0 : order.bookings) == null ? void 0 : _a.find((b) => {
2358
- var _a2;
2359
- return ((_a2 = b.metadata) == null ? void 0 : _a2.unique_identification_number) === bookingUid;
2360
- });
2361
- if (booking) {
2362
- booking.holder = holder;
2363
- }
2364
- }
2365
- // ─── OpenData 可用性 ───
2366
- async checkOpenDataAvailability() {
2367
- if (!this.store.openData)
2368
- throw new Error("openData 模块未初始化");
2369
- await this.loadOpenDataConfig();
2370
- return this.store.openData.checkAvailability(this.store.schedule);
2371
- }
2372
- async setOtherParams(params, { cover = false } = {}) {
2373
- if (cover) {
2374
- this.otherParams = params;
2375
- } else {
2376
- this.otherParams = { ...this.otherParams, ...params };
2377
- }
2378
- }
2379
- };
2380
- var VenueBookingImpl = _VenueBookingImpl;
2381
- VenueBookingImpl.PRICING_DEBUG_CACHE_ID = "031596279011848516";
2382
- VenueBookingImpl.OPEN_DATA_CACHE_TTL = 5 * 60 * 1e3;
2383
- VenueBookingImpl.PISELL1_LOGIN_SUCCESS = "pisell1.login.success";
2384
- // ─── UI 状态缓存(按 cacheId 分桶,sessionStorage) ───
2385
- //
2386
- // 用于物料层持久化 UI 层面的轻量状态(如当前步骤、登录回跳意图等)。
2387
- // 桶键:pisell.venueBooking.uiState:<cacheId>;内部以 JSON object 形式存储多个字段。
2388
- // 无 cacheId 时所有方法自动降级为 no-op,上层不用判空。
2389
- VenueBookingImpl.UI_STATE_KEY_PREFIX = "pisell.venueBooking.uiState:";
2390
- // Annotate the CommonJS export names for ESM import in node:
2391
- 0 && (module.exports = {
2392
- VenueBookingImpl,
2393
- ...require("./types")
2394
- });