@pisell/pisellos 2.2.180 → 2.2.182

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 (175) hide show
  1. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  2. package/dist/modules/BookingContext/index.d.ts +37 -0
  3. package/dist/modules/BookingContext/index.js +436 -0
  4. package/dist/modules/BookingContext/types.d.ts +102 -0
  5. package/dist/modules/BookingContext/types.js +51 -0
  6. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  7. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +276 -0
  8. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  9. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +137 -0
  10. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +75 -0
  11. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.js +215 -0
  12. package/dist/modules/BookingContext/utils/flexible.d.ts +28 -0
  13. package/dist/modules/BookingContext/utils/flexible.js +56 -0
  14. package/dist/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  15. package/dist/modules/BookingContext/utils/formatResourceList.js +38 -0
  16. package/dist/modules/BookingContext/utils/index.d.ts +11 -0
  17. package/dist/modules/BookingContext/utils/index.js +11 -0
  18. package/dist/modules/BookingContext/utils/noResource.d.ts +13 -0
  19. package/dist/modules/BookingContext/utils/noResource.js +77 -0
  20. package/dist/modules/BookingContext/utils/productExtend.d.ts +72 -0
  21. package/dist/modules/BookingContext/utils/productExtend.js +339 -0
  22. package/dist/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  23. package/dist/modules/BookingContext/utils/resourceErrors.js +74 -0
  24. package/dist/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  25. package/dist/modules/BookingContext/utils/resourceSelection.js +24 -0
  26. package/dist/modules/BookingContext/utils/resources.d.ts +80 -0
  27. package/dist/modules/BookingContext/utils/resources.js +486 -0
  28. package/dist/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  29. package/dist/modules/BookingContext/utils/serviceTimes.js +151 -0
  30. package/dist/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  31. package/dist/modules/BookingContext/utils/timeSlices.js +100 -0
  32. package/dist/modules/Customer/index.d.ts +6 -0
  33. package/dist/modules/Customer/index.js +129 -83
  34. package/dist/modules/Customer/types.d.ts +2 -0
  35. package/dist/modules/Discount/index.js +4 -3
  36. package/dist/modules/Discount/types.d.ts +1 -0
  37. package/dist/modules/Order/index.d.ts +101 -10
  38. package/dist/modules/Order/index.js +1444 -490
  39. package/dist/modules/Order/types.d.ts +201 -18
  40. package/dist/modules/Order/types.js +31 -0
  41. package/dist/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  42. package/dist/modules/Order/utils/manualProductDiscount.js +210 -0
  43. package/dist/modules/Order/utils.d.ts +83 -1
  44. package/dist/modules/Order/utils.js +405 -61
  45. package/dist/modules/Product/index.d.ts +1 -1
  46. package/dist/modules/Quotation/index.d.ts +0 -1
  47. package/dist/modules/Quotation/index.js +23 -21
  48. package/dist/modules/Rules/index.d.ts +4 -0
  49. package/dist/modules/Rules/index.js +43 -39
  50. package/dist/modules/Rules/types.d.ts +1 -0
  51. package/dist/modules/SalesSummary/index.js +4 -2
  52. package/dist/modules/SalesSummary/utils.js +21 -7
  53. package/dist/modules/Schedule/index.js +6 -2
  54. package/dist/modules/index.d.ts +1 -0
  55. package/dist/modules/index.js +2 -1
  56. package/dist/server/index.js +87 -29
  57. package/dist/server/modules/order/index.d.ts +23 -0
  58. package/dist/server/modules/order/index.js +123 -46
  59. package/dist/server/modules/order/utils/filterOrders.js +20 -6
  60. package/dist/server/modules/products/index.d.ts +1 -1
  61. package/dist/server/modules/products/index.js +130 -113
  62. package/dist/server/modules/schedule/index.js +13 -6
  63. package/dist/solution/BaseSales/index.d.ts +89 -7
  64. package/dist/solution/BaseSales/index.js +1489 -366
  65. package/dist/solution/BaseSales/types.d.ts +67 -1
  66. package/dist/solution/BaseSales/types.js +3 -1
  67. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +275 -0
  68. package/dist/solution/BaseSales/utils/cartPromotion.js +1258 -0
  69. package/dist/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
  70. package/dist/solution/BaseSales/utils/quotationPrice.js +237 -0
  71. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +68 -16
  72. package/dist/solution/BaseSales/utils.js +46 -8
  73. package/dist/solution/BookingByStep/index.d.ts +1 -1
  74. package/dist/solution/BookingTicket/index.d.ts +152 -2
  75. package/dist/solution/BookingTicket/index.js +848 -184
  76. package/dist/solution/BookingTicket/types.d.ts +2 -0
  77. package/dist/solution/BookingTicket/types.js +3 -0
  78. package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +113 -0
  79. package/dist/solution/BookingTicket/utils/addProductDecision.js +346 -0
  80. package/dist/solution/BookingTicket/utils/cartView.js +4 -2
  81. package/dist/solution/ScanOrder/index.d.ts +9 -3
  82. package/dist/solution/ScanOrder/index.js +231 -128
  83. package/dist/solution/ScanOrder/utils.js +46 -8
  84. package/dist/solution/VenueBooking/index.d.ts +5 -2
  85. package/dist/solution/VenueBooking/index.js +103 -55
  86. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
  87. package/dist/solution/VenueBooking/utils/slotMerge.js +10 -0
  88. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  89. package/lib/modules/BookingContext/index.d.ts +37 -0
  90. package/lib/modules/BookingContext/index.js +297 -0
  91. package/lib/modules/BookingContext/types.d.ts +102 -0
  92. package/lib/modules/BookingContext/types.js +34 -0
  93. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  94. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +271 -0
  95. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  96. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +141 -0
  97. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +75 -0
  98. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +198 -0
  99. package/lib/modules/BookingContext/utils/flexible.d.ts +28 -0
  100. package/lib/modules/BookingContext/utils/flexible.js +80 -0
  101. package/lib/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  102. package/lib/modules/BookingContext/utils/formatResourceList.js +50 -0
  103. package/lib/modules/BookingContext/utils/index.d.ts +11 -0
  104. package/lib/modules/BookingContext/utils/index.js +43 -0
  105. package/lib/modules/BookingContext/utils/noResource.d.ts +13 -0
  106. package/lib/modules/BookingContext/utils/noResource.js +90 -0
  107. package/lib/modules/BookingContext/utils/productExtend.d.ts +72 -0
  108. package/lib/modules/BookingContext/utils/productExtend.js +283 -0
  109. package/lib/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  110. package/lib/modules/BookingContext/utils/resourceErrors.js +80 -0
  111. package/lib/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  112. package/lib/modules/BookingContext/utils/resourceSelection.js +46 -0
  113. package/lib/modules/BookingContext/utils/resources.d.ts +80 -0
  114. package/lib/modules/BookingContext/utils/resources.js +377 -0
  115. package/lib/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  116. package/lib/modules/BookingContext/utils/serviceTimes.js +162 -0
  117. package/lib/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  118. package/lib/modules/BookingContext/utils/timeSlices.js +124 -0
  119. package/lib/modules/Customer/index.d.ts +6 -0
  120. package/lib/modules/Customer/index.js +26 -11
  121. package/lib/modules/Customer/types.d.ts +2 -0
  122. package/lib/modules/Discount/index.js +5 -1
  123. package/lib/modules/Discount/types.d.ts +1 -0
  124. package/lib/modules/Order/index.d.ts +101 -10
  125. package/lib/modules/Order/index.js +751 -114
  126. package/lib/modules/Order/types.d.ts +201 -18
  127. package/lib/modules/Order/types.js +1 -0
  128. package/lib/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  129. package/lib/modules/Order/utils/manualProductDiscount.js +206 -0
  130. package/lib/modules/Order/utils.d.ts +83 -1
  131. package/lib/modules/Order/utils.js +340 -22
  132. package/lib/modules/Product/index.d.ts +1 -1
  133. package/lib/modules/Quotation/index.d.ts +0 -1
  134. package/lib/modules/Quotation/index.js +18 -15
  135. package/lib/modules/Rules/index.d.ts +4 -0
  136. package/lib/modules/Rules/index.js +26 -27
  137. package/lib/modules/Rules/types.d.ts +1 -0
  138. package/lib/modules/SalesSummary/index.js +4 -2
  139. package/lib/modules/SalesSummary/utils.js +21 -7
  140. package/lib/modules/Schedule/index.js +3 -1
  141. package/lib/modules/index.d.ts +1 -0
  142. package/lib/modules/index.js +3 -1
  143. package/lib/server/index.js +41 -4
  144. package/lib/server/modules/order/index.d.ts +23 -0
  145. package/lib/server/modules/order/index.js +46 -14
  146. package/lib/server/modules/order/utils/filterOrders.js +12 -4
  147. package/lib/server/modules/products/index.d.ts +1 -1
  148. package/lib/server/modules/products/index.js +30 -20
  149. package/lib/server/modules/schedule/index.js +2 -1
  150. package/lib/solution/BaseSales/index.d.ts +89 -7
  151. package/lib/solution/BaseSales/index.js +742 -23
  152. package/lib/solution/BaseSales/types.d.ts +67 -1
  153. package/lib/solution/BaseSales/types.js +3 -1
  154. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +275 -0
  155. package/lib/solution/BaseSales/utils/cartPromotion.js +836 -0
  156. package/lib/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
  157. package/lib/solution/BaseSales/utils/quotationPrice.js +277 -0
  158. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +71 -12
  159. package/lib/solution/BaseSales/utils.js +46 -6
  160. package/lib/solution/BookingByStep/index.d.ts +1 -1
  161. package/lib/solution/BookingTicket/index.d.ts +152 -2
  162. package/lib/solution/BookingTicket/index.js +389 -9
  163. package/lib/solution/BookingTicket/types.d.ts +2 -0
  164. package/lib/solution/BookingTicket/types.js +6 -0
  165. package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +113 -0
  166. package/lib/solution/BookingTicket/utils/addProductDecision.js +318 -0
  167. package/lib/solution/BookingTicket/utils/cartView.js +4 -2
  168. package/lib/solution/ScanOrder/index.d.ts +9 -3
  169. package/lib/solution/ScanOrder/index.js +147 -66
  170. package/lib/solution/ScanOrder/utils.js +46 -6
  171. package/lib/solution/VenueBooking/index.d.ts +5 -2
  172. package/lib/solution/VenueBooking/index.js +50 -14
  173. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
  174. package/lib/solution/VenueBooking/utils/slotMerge.js +10 -0
  175. package/package.json +1 -1
@@ -34,13 +34,16 @@ __export(BaseSales_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(BaseSales_exports);
36
36
  var import_BaseModule = require("../../modules/BaseModule");
37
+ var import_types = require("./types");
37
38
  var import_Order = require("../../modules/Order");
38
39
  var import_decimal = __toESM(require("decimal.js"));
39
- var import_types = require("../BookingByStep/types");
40
+ var import_types2 = require("../BookingByStep/types");
40
41
  var import_utils = require("../../modules/Order/utils");
41
42
  var import_dayjs = __toESM(require("dayjs"));
42
43
  __reExport(BaseSales_exports, require("./types"), module.exports);
44
+ var import_Quotation = require("../../modules/Quotation");
43
45
  var import_transformBaseProductToOrderProduct = require("./utils/transformBaseProductToOrderProduct");
46
+ var import_quotationPrice = require("./utils/quotationPrice");
44
47
  var BaseSalesImpl = class extends import_BaseModule.BaseModule {
45
48
  constructor(name, version) {
46
49
  super(name, version);
@@ -48,20 +51,21 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
48
51
  this.defaultVersion = "1.0.0";
49
52
  this.isSolution = true;
50
53
  this.initializeOptions = {};
51
- // LoggerManager 实例
52
54
  this.store = {
53
55
  order: void 0
54
56
  };
55
57
  this.otherParams = {};
56
58
  // 当前缓存中已加载的最新 SalesDetail;只读 getter 走它对外暴露详情数据。
57
59
  this.currentSalesDetail = null;
60
+ this.discountConfigCacheKey = null;
61
+ this.hasManualDiscountSelection = false;
58
62
  }
59
63
  /**
60
64
  * 子类可覆盖此方法以追加/收敛要注册的子模块。
61
- * 默认包含通用销售模块:products / order / salesSummary / schedule / payment。
65
+ * 默认包含通用销售模块:products / order / salesSummary / schedule / payment / quotation
62
66
  */
63
67
  getRegisteredModuleNames() {
64
- return ["products", "order", "salesSummary", "schedule", "payment"];
68
+ return ["products", "order", "salesSummary", "schedule", "payment", "quotation"];
65
69
  }
66
70
  /**
67
71
  * 记录信息日志
@@ -105,13 +109,182 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
105
109
  get payment() {
106
110
  return this.store.payment;
107
111
  }
112
+ getCurrentOrderCustomerId() {
113
+ var _a, _b;
114
+ const tempOrder = (_b = (_a = this.store.order) == null ? void 0 : _a.getTempOrder) == null ? void 0 : _b.call(_a);
115
+ const customerId = tempOrder == null ? void 0 : tempOrder.customer_id;
116
+ if (customerId === null || customerId === void 0)
117
+ return void 0;
118
+ return customerId;
119
+ }
120
+ applyQuotationScheduleResolver(quotation) {
121
+ const scheduleModule = this.store.schedule;
122
+ if (!scheduleModule)
123
+ return;
124
+ quotation.setScheduleResolver((id) => {
125
+ var _a;
126
+ const schedules = ((_a = scheduleModule.getScheduleListByIds) == null ? void 0 : _a.call(scheduleModule, [id])) || [];
127
+ return schedules[0];
128
+ });
129
+ }
130
+ async loadQuotationForPriceQuery(params) {
131
+ var _a;
132
+ if (!params.quotation)
133
+ return;
134
+ this.applyQuotationScheduleResolver(params.quotation);
135
+ await params.quotation.loadQuotations({
136
+ channel: params.channel || ((_a = this.otherParams) == null ? void 0 : _a.channel),
137
+ customer_id: params.customer_id
138
+ });
139
+ }
140
+ getPriceQueryProductId(product) {
141
+ const productId = Number((product == null ? void 0 : product.product_id) ?? (product == null ? void 0 : product.id));
142
+ if (!Number.isFinite(productId))
143
+ return null;
144
+ return productId;
145
+ }
146
+ getPriceQuerySchedule(params) {
147
+ const booking = params.booking || {};
148
+ if (typeof booking.start_date === "string" && booking.start_date.trim()) {
149
+ const scheduleDate = booking.start_date.trim();
150
+ const startTime = typeof booking.start_time === "string" && booking.start_time.trim() ? booking.start_time.trim() : "00:00:00";
151
+ const datetime = (0, import_dayjs.default)(`${scheduleDate} ${startTime}`);
152
+ return {
153
+ schedule_date: scheduleDate,
154
+ schedule_datetime: datetime.isValid() ? datetime.format("YYYY-MM-DD HH:mm:ss") : `${scheduleDate} ${startTime}`
155
+ };
156
+ }
157
+ if (typeof params.datetime === "string" && params.datetime.trim()) {
158
+ const datetime = (0, import_dayjs.default)(params.datetime.trim());
159
+ if (datetime.isValid()) {
160
+ return {
161
+ schedule_date: datetime.format("YYYY-MM-DD"),
162
+ schedule_datetime: datetime.format("YYYY-MM-DD HH:mm:ss")
163
+ };
164
+ }
165
+ }
166
+ const now = (0, import_dayjs.default)();
167
+ return {
168
+ schedule_date: now.format("YYYY-MM-DD"),
169
+ schedule_datetime: now.format("YYYY-MM-DD HH:mm:ss")
170
+ };
171
+ }
172
+ async loadProductForPriceQuery(params, customerId) {
173
+ var _a, _b;
174
+ const product = params.product || {};
175
+ const productId = this.getPriceQueryProductId(product);
176
+ if (productId === null || !this.request)
177
+ return null;
178
+ const schedule = this.getPriceQuerySchedule(params);
179
+ try {
180
+ const response = await this.request.post("/product/query", {
181
+ ids: [productId],
182
+ open_quotation: 1,
183
+ open_bundle: 1,
184
+ status: "published",
185
+ num: 1,
186
+ skip: 1,
187
+ customer_id: customerId,
188
+ schedule_date: schedule.schedule_date,
189
+ schedule_datetime: schedule.schedule_datetime,
190
+ application_code: params.channel || ((_a = this.otherParams) == null ? void 0 : _a.channel)
191
+ }, {
192
+ osServer: true,
193
+ customToast: () => {
194
+ }
195
+ });
196
+ const list = ((_b = response == null ? void 0 : response.data) == null ? void 0 : _b.list) || (response == null ? void 0 : response.list) || [];
197
+ if (!Array.isArray(list))
198
+ return null;
199
+ return list.find((item) => Number((item == null ? void 0 : item.id) ?? (item == null ? void 0 : item.product_id)) === productId) || null;
200
+ } catch (error) {
201
+ this.logWarning("loadProductForPriceQuery: 商品重查失败,使用入参 fallback", {
202
+ productId,
203
+ error: error instanceof Error ? error.message : String(error)
204
+ });
205
+ return null;
206
+ }
207
+ }
208
+ getAuthoritativeBundleItems(product) {
209
+ if (Array.isArray(product == null ? void 0 : product.product_bundle))
210
+ return product.product_bundle;
211
+ const groups = Array.isArray(product == null ? void 0 : product.bundle_group) ? product.bundle_group : Array.isArray(product == null ? void 0 : product.bundleGroup) ? product.bundleGroup : [];
212
+ return groups.flatMap((group) => {
213
+ const items = Array.isArray(group == null ? void 0 : group.bundle_item) ? group.bundle_item : Array.isArray(group == null ? void 0 : group.bundleItem) ? group.bundleItem : [];
214
+ return items.map((item) => ({
215
+ ...item,
216
+ group_id: (item == null ? void 0 : item.group_id) ?? (group == null ? void 0 : group.id),
217
+ bundle_group_id: (item == null ? void 0 : item.bundle_group_id) ?? (item == null ? void 0 : item.group_id) ?? (group == null ? void 0 : group.id)
218
+ }));
219
+ });
220
+ }
221
+ findAuthoritativeBundleItem(bundle, candidates) {
222
+ const bundleId = bundle.bundle_id ?? bundle.id;
223
+ if (bundleId != null) {
224
+ const matchedById = candidates.find((item) => String((item == null ? void 0 : item.bundle_id) ?? (item == null ? void 0 : item.id)) === String(bundleId));
225
+ if (matchedById)
226
+ return matchedById;
227
+ }
228
+ const productId = bundle.bundle_product_id ?? bundle._bundle_product_id;
229
+ const groupId = bundle.bundle_group_id ?? bundle.group_id;
230
+ return candidates.find((item) => {
231
+ const itemProductId = (item == null ? void 0 : item.bundle_product_id) ?? (item == null ? void 0 : item._bundle_product_id);
232
+ const itemGroupId = (item == null ? void 0 : item.bundle_group_id) ?? (item == null ? void 0 : item.group_id);
233
+ if (productId == null || String(itemProductId) !== String(productId))
234
+ return false;
235
+ if (groupId == null)
236
+ return true;
237
+ return String(itemGroupId) === String(groupId);
238
+ }) || null;
239
+ }
240
+ getAuthoritativeBundleUnitPrice(bundle) {
241
+ return bundle.price ?? bundle.bundle_selling_price ?? bundle.custom_price ?? bundle.product_price ?? bundle.base_price;
242
+ }
243
+ mergeProductForPriceQuery(product, authoritativeProduct) {
244
+ if (!authoritativeProduct)
245
+ return product;
246
+ const selectedBundles = Array.isArray(product.product_bundle) ? product.product_bundle : [];
247
+ const authoritativeBundles = this.getAuthoritativeBundleItems(authoritativeProduct);
248
+ const productBundle = selectedBundles.map((bundle) => {
249
+ const authoritativeBundle = this.findAuthoritativeBundleItem(bundle, authoritativeBundles);
250
+ const unitPrice = authoritativeBundle ? this.getAuthoritativeBundleUnitPrice(authoritativeBundle) : void 0;
251
+ if (unitPrice === void 0 || unitPrice === null || unitPrice === "")
252
+ return bundle;
253
+ return {
254
+ ...bundle,
255
+ price: unitPrice,
256
+ bundle_selling_price: unitPrice,
257
+ base_price: (authoritativeBundle == null ? void 0 : authoritativeBundle.base_price) ?? bundle.base_price,
258
+ product_price: (authoritativeBundle == null ? void 0 : authoritativeBundle.product_price) ?? bundle.product_price
259
+ };
260
+ });
261
+ return {
262
+ ...product,
263
+ ...authoritativeProduct,
264
+ id: product.id ?? authoritativeProduct.id,
265
+ product_id: product.product_id ?? authoritativeProduct.product_id ?? authoritativeProduct.id,
266
+ product_variant_id: product.product_variant_id ?? authoritativeProduct.product_variant_id ?? 0,
267
+ num: product.num ?? product.quantity ?? authoritativeProduct.num,
268
+ quantity: product.quantity ?? product.num ?? authoritativeProduct.quantity,
269
+ product_option_item: product.product_option_item ?? authoritativeProduct.product_option_item,
270
+ product_bundle: productBundle,
271
+ metadata: product.metadata ?? authoritativeProduct.metadata
272
+ };
273
+ }
274
+ getSubmitOrderSalesChannel() {
275
+ var _a;
276
+ return (_a = this.otherParams) == null ? void 0 : _a.channel;
277
+ }
108
278
  /**
109
279
  * 工厂入口:根据子模块名实例化对应模块。
110
280
  * 默认使用 BookingByStep 公共 `createModule`。子类若需引入额外类型(如 customer),
111
281
  * 可覆盖此方法并把未识别的 name 委托给 `super.createSubModule(name)`。
112
282
  */
113
283
  createSubModule(moduleName) {
114
- return (0, import_types.createModule)(moduleName, this.name);
284
+ if (moduleName === "quotation") {
285
+ return new import_Quotation.QuotationModule(`${this.name}_quotation`);
286
+ }
287
+ return (0, import_types2.createModule)(moduleName, this.name);
115
288
  }
116
289
  getSubModuleHooks(moduleName) {
117
290
  var _a, _b;
@@ -140,19 +313,64 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
140
313
  return {};
141
314
  }
142
315
  }
316
+ getAppData(key) {
317
+ var _a, _b, _c, _d, _e, _f;
318
+ const getData = (_b = (_a = this.appPlugin).getData) == null ? void 0 : _b.call(_a);
319
+ if (typeof getData === "function")
320
+ return getData(key);
321
+ const app = this.appPlugin.getApp();
322
+ const coreData = (_f = (_d = (_c = app == null ? void 0 : app.models) == null ? void 0 : _c.getStore) == null ? void 0 : (_e = _d.call(_c)).getDataByModel) == null ? void 0 : _f.call(_e, "core", "core");
323
+ return coreData == null ? void 0 : coreData[key];
324
+ }
325
+ syncAppDataToTempOrder(tempOrder) {
326
+ const isPriceIncludeTax = this.getAppData("is_price_include_tax");
327
+ const taxCountryCode = this.getAppData("tax_country_code");
328
+ const currencyCode = this.getAppData("shop_currency_code");
329
+ const currencySymbol = this.getAppData("shop_symbol");
330
+ let isChanged = false;
331
+ if (isPriceIncludeTax !== void 0) {
332
+ const nextIsPriceIncludeTax = Number(isPriceIncludeTax);
333
+ if ((nextIsPriceIncludeTax === 0 || nextIsPriceIncludeTax === 1) && tempOrder.is_price_include_tax !== nextIsPriceIncludeTax) {
334
+ tempOrder.is_price_include_tax = nextIsPriceIncludeTax;
335
+ isChanged = true;
336
+ }
337
+ }
338
+ if (taxCountryCode !== void 0) {
339
+ const nextTaxCountryCode = String(taxCountryCode || "");
340
+ if (tempOrder.tax_country_code !== nextTaxCountryCode) {
341
+ tempOrder.tax_country_code = nextTaxCountryCode;
342
+ isChanged = true;
343
+ }
344
+ }
345
+ if (currencyCode !== void 0) {
346
+ const nextCurrencyCode = String(currencyCode || "");
347
+ if (tempOrder.currency_code !== nextCurrencyCode) {
348
+ tempOrder.currency_code = nextCurrencyCode;
349
+ isChanged = true;
350
+ }
351
+ }
352
+ if (currencySymbol !== void 0) {
353
+ const nextCurrencySymbol = String(currencySymbol || "");
354
+ if (tempOrder.currency_symbol !== nextCurrencySymbol) {
355
+ tempOrder.currency_symbol = nextCurrencySymbol;
356
+ isChanged = true;
357
+ }
358
+ }
359
+ return isChanged;
360
+ }
143
361
  async initialize(core, options = {}) {
144
- var _a;
362
+ var _a, _b;
145
363
  this.core = core;
146
364
  this.initializeOptions = options || {};
147
365
  this.otherParams = options.otherParams || {};
148
366
  this.cacheId = (_a = this.otherParams) == null ? void 0 : _a.cacheId;
149
367
  this.window = core.getPlugin("window");
150
368
  this.request = core.getPlugin("request");
151
- const appPlugin = core.getPlugin("app");
152
- if (!appPlugin) {
369
+ this.appPlugin = core.getPlugin("app");
370
+ if (!this.appPlugin) {
153
371
  throw new Error("Checkout 解决方案需要 app 插件支持");
154
372
  }
155
- const app = appPlugin.getApp();
373
+ const app = this.appPlugin.getApp();
156
374
  this.logger = app.logger;
157
375
  const targetCacheData = this.readSessionCacheData();
158
376
  const moduleNames = this.getRegisteredModuleNames();
@@ -178,6 +396,11 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
178
396
  if (this.store.schedule) {
179
397
  await this.store.schedule.loadAllSchedule();
180
398
  }
399
+ if (this.store.order && typeof ((_b = this.otherParams) == null ? void 0 : _b.enableTempOrderPersist) === "boolean") {
400
+ this.store.order.setEnableTempOrderPersist(
401
+ this.otherParams.enableTempOrderPersist
402
+ );
403
+ }
181
404
  this.core.effects.emit(`${this.name}:onInited`, {});
182
405
  }
183
406
  async destroy() {
@@ -286,6 +509,13 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
286
509
  const result = ((_a = this.store.order) == null ? void 0 : _a.getTempOrder()) || null;
287
510
  return result;
288
511
  }
512
+ async replaceTempOrder(tempOrder) {
513
+ if (!this.store.order)
514
+ throw new Error("order 模块未初始化");
515
+ const nextTempOrder = await this.store.order.replaceTempOrder(tempOrder);
516
+ await this.effectsEmit("onTempOrderReplaced", { tempOrder: nextTempOrder });
517
+ return nextTempOrder;
518
+ }
289
519
  getOrderIdentity() {
290
520
  if (!this.store.order)
291
521
  return null;
@@ -311,16 +541,21 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
311
541
  return "";
312
542
  return this.store.order.getTempOrderNote();
313
543
  }
314
- updateTempOrderNote(note) {
544
+ updateTempOrderNote(note, sync = false) {
315
545
  try {
316
546
  if (!this.store.order)
317
547
  throw new Error("order 模块未初始化");
318
- const result = this.store.order.updateTempOrderNote(note);
548
+ const result = this.store.order.updateTempOrderNote(note, sync);
319
549
  return result;
320
550
  } catch (error) {
321
551
  throw error;
322
552
  }
323
553
  }
554
+ updateRemoteOrderNote(orderId, note) {
555
+ if (!this.store.order)
556
+ throw new Error("order 模块未初始化");
557
+ this.store.order.syncTempOrderNoteToRemote(orderId, note);
558
+ }
324
559
  updateTempOrderShopDiscount(amount) {
325
560
  if (!this.store.order)
326
561
  throw new Error("order 模块未初始化");
@@ -331,6 +566,18 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
331
566
  throw new Error("order 模块未初始化");
332
567
  return this.store.order.updateTempOrderContactsInfo(contactsInfo);
333
568
  }
569
+ /** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化。 */
570
+ setEnableTempOrderPersist(enabled) {
571
+ if (!this.store.order)
572
+ throw new Error("order 模块未初始化");
573
+ this.store.order.setEnableTempOrderPersist(enabled);
574
+ }
575
+ /** 是否允许 saveDraft 写入 IndexedDB 草稿。 */
576
+ isTempOrderPersistEnabled() {
577
+ if (!this.store.order)
578
+ return false;
579
+ return this.store.order.isTempOrderPersistEnabled();
580
+ }
334
581
  ensureTempOrder() {
335
582
  if (!this.store.order)
336
583
  throw new Error("order 模块未初始化");
@@ -342,6 +589,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
342
589
  if (!this.store.order)
343
590
  throw new Error("order 模块未初始化");
344
591
  const tempOrder = await this.store.order.addNewOrder();
592
+ if (this.syncAppDataToTempOrder(tempOrder) && this.isTempOrderPersistEnabled()) {
593
+ this.store.order.persistTempOrder();
594
+ await this.store.order.saveDraft();
595
+ }
345
596
  return tempOrder;
346
597
  } catch (error) {
347
598
  throw error;
@@ -360,6 +611,43 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
360
611
  throw new Error("scanOrder 解决方案需要 order 模块支持");
361
612
  }
362
613
  const tempOrder = this.store.order.restoreOrder();
614
+ this.currentSalesDetail = null;
615
+ this.discountConfigCacheKey = null;
616
+ this.hasManualDiscountSelection = false;
617
+ await this.effectsEmit("onTempOrderReplaced", { tempOrder });
618
+ if (this.syncAppDataToTempOrder(tempOrder) && this.isTempOrderPersistEnabled()) {
619
+ this.store.order.persistTempOrder();
620
+ await this.store.order.saveDraft();
621
+ }
622
+ return tempOrder;
623
+ } catch (error) {
624
+ throw error;
625
+ }
626
+ }
627
+ /**
628
+ * 仅清空 tempOrder 购物车行(products / bookings / discount_list)。
629
+ * 同步清空内存中的 salesDetail 商品/预约视图,避免编辑态仍读到旧 bookings。
630
+ */
631
+ async clearOrderCartLines() {
632
+ try {
633
+ if (!this.store.order)
634
+ throw new Error("order 模块未初始化");
635
+ const tempOrder = await this.store.order.clearOrderCartLines();
636
+ if (this.currentSalesDetail) {
637
+ this.currentSalesDetail = {
638
+ ...this.currentSalesDetail,
639
+ products: [],
640
+ bookings: [],
641
+ rootBooking: null,
642
+ bookingsByProductUid: {},
643
+ discount_list: []
644
+ };
645
+ }
646
+ await this.effectsEmit("onTempOrderReplaced", { tempOrder });
647
+ if (this.syncAppDataToTempOrder(tempOrder) && this.isTempOrderPersistEnabled()) {
648
+ this.store.order.persistTempOrder();
649
+ await this.store.order.saveDraft();
650
+ }
363
651
  return tempOrder;
364
652
  } catch (error) {
365
653
  throw error;
@@ -381,6 +669,246 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
381
669
  throw error;
382
670
  }
383
671
  }
672
+ getHistoricalProductDiscountList(products) {
673
+ const historyDiscountList = [];
674
+ products.forEach((item) => {
675
+ if (!this.isPersistedOrderProduct(item))
676
+ return;
677
+ (item.discount_list || []).forEach((discount) => {
678
+ var _a, _b, _c, _d, _e, _f;
679
+ const discountId = ((_a = discount.discount) == null ? void 0 : _a.resource_id) || discount.id;
680
+ if (!discountId || !["good_pass", "discount_card"].includes(discount.type))
681
+ return;
682
+ const quantity = item.quantity || item.num || item.product_quantity || 1;
683
+ const savedAmount = new import_decimal.default(discount.amount || 0).times(quantity).plus(((_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.product_discount_difference) || 0);
684
+ const index = historyDiscountList.findIndex((n) => n.id === discountId);
685
+ if (index !== -1) {
686
+ historyDiscountList[index] = {
687
+ ...historyDiscountList[index],
688
+ amount: new import_decimal.default(historyDiscountList[index].amount || 0).plus(discount.amount || 0).toNumber(),
689
+ savedAmount: savedAmount.plus(historyDiscountList[index].savedAmount || 0).toNumber()
690
+ };
691
+ return;
692
+ }
693
+ historyDiscountList.push({
694
+ ...discount,
695
+ id: discountId,
696
+ tag: discount.tag || discount.type,
697
+ name: discount.name || ((_d = (_c = discount.discount) == null ? void 0 : _c.title) == null ? void 0 : _d.auto),
698
+ format_title: ((_e = discount.discount) == null ? void 0 : _e.title) || discount.format_title,
699
+ isEditMode: true,
700
+ limited_relation_product_data: {},
701
+ savedAmount: savedAmount.toNumber(),
702
+ isAvailable: true,
703
+ isDisabled: true,
704
+ isSelected: true,
705
+ product_id: ((_f = discount.discount) == null ? void 0 : _f.product_id) || discount.product_id
706
+ });
707
+ });
708
+ });
709
+ return historyDiscountList;
710
+ }
711
+ isPersistedOrderProduct(product) {
712
+ const orderDetailId = product.order_detail_id ?? product.orderDetailId;
713
+ if (orderDetailId !== void 0 && orderDetailId !== null && orderDetailId !== "") {
714
+ return true;
715
+ }
716
+ const bookingId = product.booking_id ?? product.bookingId;
717
+ return bookingId !== void 0 && bookingId !== null && bookingId !== "";
718
+ }
719
+ mergeHistoricalDiscountList(discountList, products) {
720
+ const historyDiscountList = this.getHistoricalProductDiscountList(products);
721
+ const historyIds = new Set(historyDiscountList.map((discount) => discount.id));
722
+ return [
723
+ ...historyDiscountList,
724
+ ...(discountList || []).filter((discount) => !historyIds.has(discount.id))
725
+ ];
726
+ }
727
+ mergeCurrentDiscountSelectionState(discountList, currentDiscountList) {
728
+ if (!currentDiscountList.length)
729
+ return discountList;
730
+ const currentDiscountMap = new Map(
731
+ currentDiscountList.map((discount) => [discount.id, discount])
732
+ );
733
+ return discountList.map((discount) => {
734
+ const currentDiscount = currentDiscountMap.get(discount.id);
735
+ if (!currentDiscount)
736
+ return discount;
737
+ if (currentDiscount.isManualSelect) {
738
+ return {
739
+ ...discount,
740
+ isSelected: false,
741
+ isManualSelect: true
742
+ };
743
+ }
744
+ if (currentDiscount.isSelected) {
745
+ return {
746
+ ...discount,
747
+ isSelected: true,
748
+ isManualSelect: false
749
+ };
750
+ }
751
+ return discount;
752
+ });
753
+ }
754
+ async loadDiscountConfig(params) {
755
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
756
+ if (!this.store.order)
757
+ throw new Error("order 模块未初始化");
758
+ const tempOrder = this.store.order.ensureTempOrder();
759
+ const orderStore = this.store.order.store || {};
760
+ const discountModule = orderStore.discount;
761
+ const rulesModule = orderStore.rules;
762
+ const orderId = tempOrder.order_id || ((_b = (_a = this.getOrderIdentity) == null ? void 0 : _a.call(this)) == null ? void 0 : _b.orderId);
763
+ const customerId = Number(
764
+ (params == null ? void 0 : params.customerId) || tempOrder.customer_id || ((_c = tempOrder.customer) == null ? void 0 : _c.id) || ((_e = (_d = tempOrder._extend) == null ? void 0 : _d.customerSnapshot) == null ? void 0 : _e.id) || ((_g = (_f = tempOrder._extend) == null ? void 0 : _f.customerSnapshot) == null ? void 0 : _g.customer_id) || 0
765
+ );
766
+ const currentDiscountList = ((_h = discountModule == null ? void 0 : discountModule.getDiscountList) == null ? void 0 : _h.call(discountModule)) || [];
767
+ const originalDiscountList = ((_i = discountModule == null ? void 0 : discountModule.getOriginalDiscountList) == null ? void 0 : _i.call(discountModule)) || [];
768
+ const hasManualDiscountSelection = this.hasManualDiscountSelection || currentDiscountList.some((discount) => discount.isManualSelect);
769
+ const discountAction = (params == null ? void 0 : params.action) || (orderId ? "edit" : "create");
770
+ const discountConfigCacheKey = [
771
+ customerId,
772
+ discountAction,
773
+ Number(orderId) || 0
774
+ ].join(":");
775
+ let preparedDiscountList = [];
776
+ if (customerId && customerId !== 1) {
777
+ if (this.discountConfigCacheKey === discountConfigCacheKey) {
778
+ preparedDiscountList = originalDiscountList;
779
+ } else {
780
+ preparedDiscountList = await this.store.order.loadDiscountConfig({
781
+ customerId,
782
+ action: discountAction,
783
+ orderId: Number(orderId) || void 0,
784
+ apply: false
785
+ });
786
+ this.discountConfigCacheKey = discountConfigCacheKey;
787
+ await ((_j = discountModule == null ? void 0 : discountModule.setOriginalDiscountList) == null ? void 0 : _j.call(discountModule, preparedDiscountList));
788
+ }
789
+ }
790
+ if (hasManualDiscountSelection && currentDiscountList.length) {
791
+ return {
792
+ productList: tempOrder.products || [],
793
+ discountList: currentDiscountList
794
+ };
795
+ }
796
+ let nextDiscountList = this.mergeHistoricalDiscountList(
797
+ preparedDiscountList || ((_k = discountModule == null ? void 0 : discountModule.getDiscountList) == null ? void 0 : _k.call(discountModule)) || [],
798
+ tempOrder.products || []
799
+ );
800
+ nextDiscountList = this.mergeCurrentDiscountSelectionState(
801
+ nextDiscountList,
802
+ currentDiscountList
803
+ );
804
+ await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
805
+ if (rulesModule) {
806
+ const holders = ((_l = tempOrder.holder) == null ? void 0 : _l.form_record_id) ? [{ form_record_id: tempOrder.holder.form_record_id }] : [];
807
+ const result = rulesModule.calcDiscount({
808
+ productList: tempOrder.products,
809
+ discountList: nextDiscountList,
810
+ holders,
811
+ isFormSubject: !!((_m = tempOrder.holder) == null ? void 0 : _m.type) && tempOrder.holder.type === "form",
812
+ orderTotalAmount: Number(((_n = orderStore.summary) == null ? void 0 : _n.total_amount) || 0)
813
+ }) || { productList: tempOrder.products, discountList: nextDiscountList };
814
+ if (result.productList) {
815
+ tempOrder.products = result.productList;
816
+ }
817
+ for (const product of tempOrder.products || []) {
818
+ const productUid = (_o = product.metadata) == null ? void 0 : _o.unique_identification_number;
819
+ const runtimeOrigin = productUid ? (_r = (_q = (_p = tempOrder._extend) == null ? void 0 : _p.productsByUid) == null ? void 0 : _q[productUid]) == null ? void 0 : _r.origin : void 0;
820
+ if ((runtimeOrigin == null ? void 0 : runtimeOrigin.isManualDiscount) || ((_s = product.metadata) == null ? void 0 : _s.is_manual_discount))
821
+ continue;
822
+ const totalPerUnitDiscount = (product.discount_list || []).reduce(
823
+ (sum, pd) => sum + Number(pd.amount || 0),
824
+ 0
825
+ );
826
+ const optionSum = (0, import_utils.sumOptionUnitPrice)(product.product_option_item);
827
+ const sourcePrice = ((_t = product.metadata) == null ? void 0 : _t.source_product_price) ?? (((_u = product.metadata) == null ? void 0 : _u.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
828
+ const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
829
+ const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
830
+ if (product.metadata) {
831
+ product.metadata.main_product_selling_price = newMainSellingPrice;
832
+ product.metadata.price_schema_version = 2;
833
+ }
834
+ product.selling_price = (0, import_utils.composeLinePrice)({
835
+ mainPrice: newMainSellingPrice,
836
+ bundle: product.product_bundle
837
+ });
838
+ }
839
+ if (result.discountList) {
840
+ nextDiscountList = this.mergeHistoricalDiscountList(
841
+ result.discountList,
842
+ tempOrder.products || []
843
+ );
844
+ import_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
845
+ await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
846
+ tempOrder.discount_list = nextDiscountList.filter((discount) => discount.isSelected);
847
+ }
848
+ }
849
+ const summary = await this.store.order.recalculateSummary({ createIfMissing: true });
850
+ this.store.order.persistTempOrder();
851
+ await this.effectsEmit("onDiscountApplied", {
852
+ productList: tempOrder.products || [],
853
+ discountList: nextDiscountList,
854
+ selectedDiscountList: tempOrder.discount_list || [],
855
+ tempOrder
856
+ });
857
+ return {
858
+ productList: tempOrder.products || [],
859
+ discountList: nextDiscountList
860
+ };
861
+ }
862
+ async bestDiscount(cb) {
863
+ var _a, _b, _c, _d, _e;
864
+ if (!this.store.order)
865
+ throw new Error("order 模块未初始化");
866
+ const tempOrder = this.store.order.ensureTempOrder();
867
+ const orderStore = this.store.order.store || {};
868
+ const discountModule = orderStore.discount;
869
+ const rulesModule = orderStore.rules;
870
+ const originalDiscountList = ((_a = discountModule == null ? void 0 : discountModule.getOriginalDiscountList) == null ? void 0 : _a.call(discountModule)) || this.getDiscountList();
871
+ const currentDiscountList = ((_b = discountModule == null ? void 0 : discountModule.getDiscountList) == null ? void 0 : _b.call(discountModule)) || [];
872
+ let nextDiscountList = this.mergeHistoricalDiscountList(
873
+ originalDiscountList || [],
874
+ tempOrder.products || []
875
+ );
876
+ let result = {
877
+ productList: tempOrder.products || [],
878
+ discountList: nextDiscountList
879
+ };
880
+ await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
881
+ if (rulesModule) {
882
+ const holders = ((_c = tempOrder.holder) == null ? void 0 : _c.form_record_id) ? [{ form_record_id: tempOrder.holder.form_record_id }] : [];
883
+ result = rulesModule.calcDiscount({
884
+ productList: tempOrder.products,
885
+ discountList: nextDiscountList,
886
+ holders,
887
+ isFormSubject: !!((_d = tempOrder.holder) == null ? void 0 : _d.type) && tempOrder.holder.type === "form",
888
+ orderTotalAmount: Number(((_e = orderStore.summary) == null ? void 0 : _e.total_amount) || 0)
889
+ }) || result;
890
+ if (result.productList) {
891
+ tempOrder.products = result.productList;
892
+ }
893
+ if (result.discountList) {
894
+ nextDiscountList = this.mergeHistoricalDiscountList(
895
+ result.discountList,
896
+ tempOrder.products || []
897
+ );
898
+ import_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
899
+ await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
900
+ tempOrder.discount_list = nextDiscountList.filter((discount) => discount.isSelected);
901
+ result = {
902
+ productList: tempOrder.products,
903
+ discountList: nextDiscountList
904
+ };
905
+ }
906
+ }
907
+ await this.store.order.recalculateSummary({ createIfMissing: true });
908
+ this.store.order.persistTempOrder();
909
+ cb == null ? void 0 : cb(result);
910
+ return result;
911
+ }
384
912
  getDiscountList() {
385
913
  if (!this.store.order)
386
914
  return [];
@@ -418,6 +946,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
418
946
  isManualSelect: !params.isSelected
419
947
  } : d
420
948
  );
949
+ this.hasManualDiscountSelection = true;
421
950
  const tempOrder = this.store.order.ensureTempOrder();
422
951
  const orderStore = this.store.order.store || {};
423
952
  const discountModule = orderStore.discount;
@@ -450,6 +979,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
450
979
  for (const d of nextDiscountList) {
451
980
  if (d.isSelected && !beforeSelectedIds.has(d.id)) {
452
981
  d.isSelected = false;
982
+ d.isManualSelect = true;
453
983
  }
454
984
  }
455
985
  }
@@ -490,6 +1020,40 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
490
1020
  tempOrder.discount_list = (nextDiscountList || []).filter((d) => d.isSelected);
491
1021
  await this.store.order.recalculateSummary({ createIfMissing: true });
492
1022
  this.store.order.persistTempOrder();
1023
+ this.effectsEmit("onDiscountApplied", {
1024
+ productList: tempOrder.products,
1025
+ discountList: nextDiscountList,
1026
+ selectedDiscountList: tempOrder.discount_list,
1027
+ tempOrder
1028
+ });
1029
+ } catch (error) {
1030
+ throw error;
1031
+ }
1032
+ }
1033
+ async applyDiscountCalculationResult(result) {
1034
+ try {
1035
+ if (!this.store.order)
1036
+ throw new Error("order 模块未初始化");
1037
+ if (!result)
1038
+ return;
1039
+ const tempOrder = this.store.order.ensureTempOrder();
1040
+ const orderStore = this.store.order.store || {};
1041
+ const discountModule = orderStore.discount;
1042
+ if (result.productList) {
1043
+ tempOrder.products = result.productList;
1044
+ }
1045
+ if (result.discountList) {
1046
+ import_Order.OrderModule.populateSavedAmounts(
1047
+ tempOrder.products,
1048
+ result.discountList
1049
+ );
1050
+ await (discountModule == null ? void 0 : discountModule.setDiscountList(result.discountList));
1051
+ tempOrder.discount_list = result.discountList.filter(
1052
+ (discount) => discount.isSelected
1053
+ );
1054
+ }
1055
+ await this.store.order.recalculateSummary({ createIfMissing: true });
1056
+ this.store.order.persistTempOrder();
493
1057
  } catch (error) {
494
1058
  throw error;
495
1059
  }
@@ -504,7 +1068,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
504
1068
  * payments 会交给 OrderModule 统一映射为 Sales 协议支付项。
505
1069
  */
506
1070
  async submitSalesOrder(params) {
507
- var _a, _b, _c, _d;
1071
+ var _a, _b, _c;
508
1072
  if (!this.store.order) {
509
1073
  throw new Error("BaseSales 解决方案需要 order 模块支持");
510
1074
  }
@@ -513,19 +1077,57 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
513
1077
  cacheId: this.cacheId,
514
1078
  platform: (_a = this.otherParams) == null ? void 0 : _a.platform,
515
1079
  businessCode: (_b = this.otherParams) == null ? void 0 : _b.businessCode,
516
- channel: (_c = this.otherParams) == null ? void 0 : _c.channel,
517
- type: (_d = this.otherParams) == null ? void 0 : _d.type,
1080
+ channel: this.getSubmitOrderSalesChannel(),
1081
+ type: (_c = this.otherParams) == null ? void 0 : _c.type,
518
1082
  ...(params == null ? void 0 : params.payments) !== void 0 ? { payments: params.payments } : {},
519
1083
  ...(params == null ? void 0 : params.paymentStatus) !== void 0 ? { paymentStatus: params.paymentStatus } : {},
520
1084
  ...(params == null ? void 0 : params.smallTicketDataFlag) !== void 0 ? { smallTicketDataFlag: params.smallTicketDataFlag } : {},
521
1085
  ...(params == null ? void 0 : params.enhancePayload) !== void 0 ? { enhancePayload: params.enhancePayload } : {}
522
1086
  };
1087
+ console.log(submitParams, "submitParams123");
523
1088
  return this.store.order.submitTempOrder(submitParams);
524
1089
  }
525
1090
  async syncPaymentsToOrder(params) {
526
1091
  if (!this.store.order)
527
1092
  throw new Error("order 模块未初始化");
528
- return this.store.order.syncPaymentsToOrder(params);
1093
+ const channel = params.channel ?? this.getSubmitOrderSalesChannel();
1094
+ const syncParams = {
1095
+ ...params,
1096
+ ...channel !== void 0 ? { channel } : {}
1097
+ };
1098
+ const syncState = this.store.order.getOrderSyncState();
1099
+ if (params.submitWhenPaid && syncState === "submitting") {
1100
+ return this.store.order.syncPaymentsToOrder(syncParams);
1101
+ }
1102
+ const payments = params.payments || [];
1103
+ await this.effectsEmit(import_types.BaseSalesHookNames.onPaymentSyncStart, {
1104
+ payments,
1105
+ params: syncParams,
1106
+ amountSnapshot: this.store.order.getOrderAmountSnapshot(),
1107
+ orderSnapshot: this.store.order.getOrderSnapshot()
1108
+ });
1109
+ try {
1110
+ const syncResult = await this.store.order.syncPaymentsToOrder(syncParams);
1111
+ await this.effectsEmit(import_types.BaseSalesHookNames.onPaymentSyncEnd, {
1112
+ ok: true,
1113
+ syncResult,
1114
+ payments: this.store.order.getOrderPayments(),
1115
+ params: syncParams,
1116
+ amountSnapshot: this.store.order.getOrderAmountSnapshot(),
1117
+ orderSnapshot: this.store.order.getOrderSnapshot()
1118
+ });
1119
+ return syncResult;
1120
+ } catch (error) {
1121
+ await this.effectsEmit(import_types.BaseSalesHookNames.onPaymentSyncEnd, {
1122
+ ok: false,
1123
+ error,
1124
+ payments: this.store.order.getOrderPayments(),
1125
+ params: syncParams,
1126
+ amountSnapshot: this.store.order.getOrderAmountSnapshot(),
1127
+ orderSnapshot: this.store.order.getOrderSnapshot()
1128
+ });
1129
+ throw error;
1130
+ }
529
1131
  }
530
1132
  /** 读取当前 BaseSales 订单上下文中的 Sales 协议支付项。 */
531
1133
  getOrderPayments() {
@@ -543,7 +1145,31 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
543
1145
  addOrderPayment(payment) {
544
1146
  if (!this.store.order)
545
1147
  throw new Error("order 模块未初始化");
546
- return this.store.order.addOrderPayment(payment);
1148
+ const paymentRecord = payment;
1149
+ const metadata = paymentRecord.metadata && typeof paymentRecord.metadata === "object" ? { ...paymentRecord.metadata } : {};
1150
+ if (!metadata.unique_identification_number) {
1151
+ metadata.unique_identification_number = (0, import_utils.createUuidV4)();
1152
+ }
1153
+ const payments = this.store.order.addOrderPayment({
1154
+ ...paymentRecord,
1155
+ metadata
1156
+ });
1157
+ const amountSnapshot = this.store.order.getOrderAmountSnapshot();
1158
+ const syncState = this.store.order.getOrderSyncState();
1159
+ if (amountSnapshot && syncState !== "submitting") {
1160
+ const paymentStatus = Number(amountSnapshot.amountGap || 0) <= 0 ? "paid" : "partially_paid";
1161
+ void this.syncPaymentsToOrder({
1162
+ payments,
1163
+ paymentStatus,
1164
+ submitWhenPaid: true,
1165
+ smallTicketDataFlag: 1
1166
+ }).catch((error) => {
1167
+ this.logError("auto sync payments failed", {
1168
+ error: error instanceof Error ? error.message : String(error)
1169
+ });
1170
+ });
1171
+ }
1172
+ return payments;
547
1173
  }
548
1174
  /** 更新当前订单中的指定支付项。 */
549
1175
  updateOrderPayment(paymentIdentity, updates) {
@@ -564,11 +1190,12 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
564
1190
  return this.store.order.updateVoucherOrderPayments(payments);
565
1191
  }
566
1192
  getWalletProductList() {
567
- var _a, _b;
1193
+ var _a, _b, _c;
568
1194
  const tempOrder = (_a = this.store.order) == null ? void 0 : _a.getTempOrder();
569
1195
  if (!((_b = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _b.length))
570
1196
  return [];
571
- return tempOrder.products.map((product) => {
1197
+ const products = (_c = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _c.filter((n) => n.product_id);
1198
+ return products.map((product) => {
572
1199
  const metadata = product.metadata || {};
573
1200
  return {
574
1201
  product_id: product.product_id,
@@ -578,6 +1205,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
578
1205
  is_charge_tax: product.is_charge_tax ?? 0,
579
1206
  tax_fee: product.tax_fee,
580
1207
  selling_price: Number(product.selling_price || 0),
1208
+ discount_list: product.discount_list || [],
581
1209
  holder_id: product.holder_id ?? metadata.holder_id,
582
1210
  original_price: product.original_price,
583
1211
  main_product_original_price: metadata.main_product_original_price ?? product.original_price,
@@ -591,8 +1219,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
591
1219
  const bundleMetadata = bundle.metadata || {};
592
1220
  return {
593
1221
  is_price_include_tax: tempOrder.is_price_include_tax,
594
- bundle_id: bundle.bundle_id,
595
- bundle_product_id: bundle.bundle_product_id,
1222
+ // 套餐子项在 tempOrder 上常为 id(如 1718),prepare/deduction 协议要求 bundle_id
1223
+ bundle_id: bundle.bundle_id ?? bundle.id,
1224
+ bundle_product_id: bundle.bundle_product_id ?? bundle._bundle_product_id,
1225
+ bundle_group_id: bundle.bundle_group_id ?? bundle.group_id,
596
1226
  bundle_variant_id: bundle.bundle_variant_id,
597
1227
  price_type: bundle.price_type,
598
1228
  price_type_ext: bundle.price_type_ext,
@@ -731,6 +1361,24 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
731
1361
  transformBaseProductToOrderProduct(params) {
732
1362
  return (0, import_transformBaseProductToOrderProduct.transformBaseProductToOrderProduct)(params);
733
1363
  }
1364
+ async calculateProductBookingPrice(params) {
1365
+ const quotation = this.store.quotation;
1366
+ const customerId = params.customer_id ?? this.getCurrentOrderCustomerId();
1367
+ const authoritativeProduct = await this.loadProductForPriceQuery(params, customerId);
1368
+ const product = this.mergeProductForPriceQuery(params.product, authoritativeProduct);
1369
+ await this.loadQuotationForPriceQuery({
1370
+ quotation,
1371
+ customer_id: customerId,
1372
+ channel: params.channel
1373
+ });
1374
+ return (0, import_quotationPrice.calculateBaseSalesProductBookingPrice)({
1375
+ ...params,
1376
+ product,
1377
+ fallback_price: authoritativeProduct ? void 0 : params.fallback_price,
1378
+ customer_id: customerId,
1379
+ quotation
1380
+ });
1381
+ }
734
1382
  async addProductToOrder(product, booking) {
735
1383
  try {
736
1384
  if (!this.store.order)
@@ -741,16 +1389,35 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
741
1389
  throw error;
742
1390
  }
743
1391
  }
744
- async updateProductInOrder(params) {
1392
+ async updateOrderProduct(params) {
745
1393
  try {
746
1394
  if (!this.store.order)
747
1395
  throw new Error("order 模块未初始化");
748
- const products = await this.store.order.updateProductInOrder(params);
1396
+ const products = await this.store.order.updateOrderProduct(params);
749
1397
  return products;
750
1398
  } catch (error) {
751
1399
  throw error;
752
1400
  }
753
1401
  }
1402
+ async updateOrderProductQuantity(params) {
1403
+ try {
1404
+ if (!this.store.order)
1405
+ throw new Error("order 模块未初始化");
1406
+ const products = await this.store.order.updateOrderProductQuantity(params);
1407
+ return products;
1408
+ } catch (error) {
1409
+ throw error;
1410
+ }
1411
+ }
1412
+ updateOrderBooking(params) {
1413
+ try {
1414
+ if (!this.store.order)
1415
+ throw new Error("order 模块未初始化");
1416
+ return this.store.order.updateOrderBooking(params);
1417
+ } catch (error) {
1418
+ throw error;
1419
+ }
1420
+ }
754
1421
  /**
755
1422
  * 设置单行商品备注(与整单 `updateTempOrderNote` 区分)。
756
1423
  * 多行同 SKU 时必须传入与删除/更新一致的 unique_identification_number。
@@ -770,7 +1437,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
770
1437
  }
771
1438
  if (identity.product_bundle !== void 0)
772
1439
  params.product_bundle = identity.product_bundle;
773
- const products = await this.updateProductInOrder(params);
1440
+ const products = await this.updateOrderProduct(params);
774
1441
  return products;
775
1442
  } catch (error) {
776
1443
  throw error;
@@ -786,6 +1453,58 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
786
1453
  throw error;
787
1454
  }
788
1455
  }
1456
+ // ─── 促销/赠品 透传(迁移自 booking usePromotion) ────────────────
1457
+ /**
1458
+ * 注入促销评估器到底层 OrderModule。
1459
+ *
1460
+ * @example
1461
+ * solution.setPromotionEvaluator(appHelper.utils.promotionEvaluator);
1462
+ */
1463
+ setPromotionEvaluator(evaluator) {
1464
+ if (!this.store.order)
1465
+ throw new Error("order 模块未初始化");
1466
+ this.store.order.setPromotionEvaluator(evaluator);
1467
+ }
1468
+ /**
1469
+ * 注入赠品选择 resolver。UI 层(SalesSdk)通过 bridge 提供。
1470
+ *
1471
+ * @example
1472
+ * solution.setGiftSelectResolver(async (ctx) => bridge.request(ctx));
1473
+ */
1474
+ setGiftSelectResolver(resolver) {
1475
+ if (!this.store.order)
1476
+ throw new Error("order 模块未初始化");
1477
+ this.store.order.setGiftSelectResolver(resolver);
1478
+ }
1479
+ /**
1480
+ * 为商品目录追加促销标签,供 SalesSdkProductProvider 等商品列表入口复用。
1481
+ *
1482
+ * @example
1483
+ * const products = solution.appendPromotionTags(catalogProducts);
1484
+ */
1485
+ appendPromotionTags(products) {
1486
+ if (!this.store.order)
1487
+ throw new Error("order 模块未初始化");
1488
+ return this.store.order.appendPromotionTags(products);
1489
+ }
1490
+ /**
1491
+ * 主动触发一次促销应用(一般写路径会自动触发,少数场景如客户切换后可手动调)。
1492
+ */
1493
+ async applyPromotion() {
1494
+ if (!this.store.order)
1495
+ throw new Error("order 模块未初始化");
1496
+ await this.store.order.applyPromotion();
1497
+ }
1498
+ /** 最近一次促销计算输出的未满足提示。 */
1499
+ getUnfulfilledPromotions() {
1500
+ var _a;
1501
+ return ((_a = this.store.order) == null ? void 0 : _a.getUnfulfilledPromotions()) || [];
1502
+ }
1503
+ /** 最近一次促销计算输出的赠品操作 diff。 */
1504
+ getLastGiftActions() {
1505
+ var _a;
1506
+ return ((_a = this.store.order) == null ? void 0 : _a.getLastGiftActions()) || null;
1507
+ }
789
1508
  // 获取商品列表
790
1509
  // TODO 需要跟 webpos 内的对齐一下
791
1510
  async getProductList() {