@pisell/pisellos 2.2.8 → 2.2.10

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 (61) hide show
  1. package/dist/modules/Cart/utils/cartProduct.js +41 -26
  2. package/dist/modules/Customer/index.js +1 -1
  3. package/dist/modules/Discount/index.d.ts +3 -0
  4. package/dist/modules/Discount/index.js +70 -37
  5. package/dist/modules/Discount/types.d.ts +16 -0
  6. package/dist/modules/Order/index.js +4 -1
  7. package/dist/modules/Order/utils.d.ts +1 -0
  8. package/dist/modules/Order/utils.js +9 -0
  9. package/dist/modules/Payment/cash.js +1 -1
  10. package/dist/modules/Payment/eftpos.js +1 -1
  11. package/dist/modules/Payment/index.js +101 -31
  12. package/dist/modules/Payment/types.d.ts +22 -2
  13. package/dist/modules/Payment/walletpass.js +8 -3
  14. package/dist/modules/Product/index.d.ts +1 -1
  15. package/dist/modules/ProductList/index.js +8 -9
  16. package/dist/modules/Rules/index.d.ts +16 -2
  17. package/dist/modules/Rules/index.js +1102 -200
  18. package/dist/modules/Rules/types.d.ts +8 -1
  19. package/dist/solution/BookingByStep/index.js +30 -8
  20. package/dist/solution/BookingByStep/utils/products.d.ts +6 -0
  21. package/dist/solution/BookingByStep/utils/products.js +10 -0
  22. package/dist/solution/BookingTicket/index.d.ts +1 -1
  23. package/dist/solution/Checkout/index.d.ts +2 -0
  24. package/dist/solution/Checkout/index.js +277 -88
  25. package/dist/solution/Checkout/types.d.ts +2 -0
  26. package/dist/solution/ShopDiscount/index.d.ts +5 -0
  27. package/dist/solution/ShopDiscount/index.js +96 -24
  28. package/dist/solution/ShopDiscount/types.d.ts +9 -1
  29. package/dist/solution/ShopDiscount/utils.d.ts +55 -0
  30. package/dist/solution/ShopDiscount/utils.js +432 -3
  31. package/lib/modules/Cart/utils/cartProduct.js +35 -22
  32. package/lib/modules/Customer/index.js +1 -1
  33. package/lib/modules/Discount/index.d.ts +3 -0
  34. package/lib/modules/Discount/index.js +20 -5
  35. package/lib/modules/Discount/types.d.ts +16 -0
  36. package/lib/modules/Order/index.js +2 -0
  37. package/lib/modules/Order/utils.d.ts +1 -0
  38. package/lib/modules/Order/utils.js +11 -0
  39. package/lib/modules/Payment/cash.js +1 -1
  40. package/lib/modules/Payment/eftpos.js +1 -1
  41. package/lib/modules/Payment/index.js +71 -11
  42. package/lib/modules/Payment/types.d.ts +22 -2
  43. package/lib/modules/Payment/walletpass.js +15 -4
  44. package/lib/modules/Product/index.d.ts +1 -1
  45. package/lib/modules/ProductList/index.js +0 -7
  46. package/lib/modules/Rules/index.d.ts +16 -2
  47. package/lib/modules/Rules/index.js +857 -184
  48. package/lib/modules/Rules/types.d.ts +8 -1
  49. package/lib/solution/BookingByStep/index.js +19 -2
  50. package/lib/solution/BookingByStep/utils/products.d.ts +6 -0
  51. package/lib/solution/BookingByStep/utils/products.js +8 -2
  52. package/lib/solution/BookingTicket/index.d.ts +1 -1
  53. package/lib/solution/Checkout/index.d.ts +2 -0
  54. package/lib/solution/Checkout/index.js +185 -25
  55. package/lib/solution/Checkout/types.d.ts +2 -0
  56. package/lib/solution/ShopDiscount/index.d.ts +5 -0
  57. package/lib/solution/ShopDiscount/index.js +67 -13
  58. package/lib/solution/ShopDiscount/types.d.ts +9 -1
  59. package/lib/solution/ShopDiscount/utils.d.ts +55 -0
  60. package/lib/solution/ShopDiscount/utils.js +266 -3
  61. package/package.json +2 -2
@@ -37,6 +37,7 @@ var import_utils = require("../../solution/ShopDiscount/utils");
37
37
  var import_utils2 = require("../Cart/utils");
38
38
  var import_decimal = __toESM(require("decimal.js"));
39
39
  var import_lodash_es = require("lodash-es");
40
+ var import_dayjs = __toESM(require("dayjs"));
40
41
  var RulesModule = class extends import_BaseModule.BaseModule {
41
42
  constructor(name, version) {
42
43
  super(name, version);
@@ -56,11 +57,23 @@ var RulesModule = class extends import_BaseModule.BaseModule {
56
57
  getRulesList() {
57
58
  return this.store.rulesList;
58
59
  }
60
+ // 检查 holder 是否匹配
61
+ checkHolderMatch(discount, product, holders) {
62
+ var _a;
63
+ if (((_a = discount.holder) == null ? void 0 : _a.holder_type) !== "form")
64
+ return true;
65
+ const orderHolderId = Array.isArray(holders) && holders.length > 0 ? holders[0].form_record_id : void 0;
66
+ const productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
67
+ if (!orderHolderId && !productHolderId)
68
+ return true;
69
+ return (productHolderId || orderHolderId) === discount.holder.holder_id;
70
+ }
59
71
  // 判断discountList 是否可以对当前productList生效
60
72
  isDiscountListAvailable({
61
73
  oldDiscountList,
62
74
  newDiscountList,
63
- productList
75
+ productList,
76
+ holders
64
77
  }) {
65
78
  if (!newDiscountList || newDiscountList.length === 0) {
66
79
  return {
@@ -87,16 +100,21 @@ var RulesModule = class extends import_BaseModule.BaseModule {
87
100
  ]), "product_id");
88
101
  const result = this.calcDiscount({
89
102
  discountList: mergedDiscountList,
90
- productList: [...productList]
103
+ productList: [...productList],
104
+ holders
91
105
  }, {
92
106
  scan: true
93
107
  });
94
108
  let hasApplicableDiscount = false;
95
109
  const newDiscountIds = newDiscountList.map((discount) => discount.id);
96
110
  result.productList.forEach((product) => {
97
- const { discount_list } = this.hooks.getProduct(product);
98
- if (discount_list && discount_list.length > 0) {
99
- const usedNewDiscount = discount_list.some(
111
+ const { discount_list, bundle } = this.hooks.getProduct(product);
112
+ const allDiscountList = [...discount_list || []];
113
+ (bundle || []).forEach((item) => {
114
+ allDiscountList.push(...(item == null ? void 0 : item.discount_list) || []);
115
+ });
116
+ if (allDiscountList && allDiscountList.length > 0) {
117
+ const usedNewDiscount = allDiscountList.some(
100
118
  (discount) => {
101
119
  var _a;
102
120
  return newDiscountIds.includes((_a = discount == null ? void 0 : discount.discount) == null ? void 0 : _a.resource_id);
@@ -115,7 +133,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
115
133
  }
116
134
  calcDiscount({
117
135
  discountList,
118
- productList
136
+ productList,
137
+ holders
119
138
  }, options) {
120
139
  const isEditModeAddNewProduct = productList.find((n) => n.booking_id) && productList.find((n) => !n.booking_id);
121
140
  const editModeDiscount = [];
@@ -130,6 +149,49 @@ var RulesModule = class extends import_BaseModule.BaseModule {
130
149
  const filteredDiscountList = addModeDiscount.filter((discount) => {
131
150
  return !discount.isManualSelect;
132
151
  });
152
+ const flattenProductsWithBundle = (productList2) => {
153
+ const flattened = [];
154
+ productList2.forEach((originProduct) => {
155
+ const product = this.hooks.getProduct(originProduct);
156
+ flattened.push({
157
+ type: "main",
158
+ originProduct,
159
+ product,
160
+ price: Number(product.price || 0),
161
+ id: product.id,
162
+ _id: product._id,
163
+ parentId: product._id,
164
+ quantity: product.quantity,
165
+ num: product.num
166
+ });
167
+ if (product.bundle && Array.isArray(product.bundle) && product.bundle.length > 0) {
168
+ product.bundle.forEach((bundleItem, bundleIndex) => {
169
+ flattened.push({
170
+ type: "bundle",
171
+ originProduct,
172
+ parentProduct: product,
173
+ bundleItem,
174
+ bundleIndex,
175
+ // 虚拟商品属性
176
+ price: Number(bundleItem.price || 0),
177
+ id: bundleItem._bundle_product_id,
178
+ // 🔥 使用 _bundle_product_id
179
+ _id: `${product._id}_bundle_${bundleIndex}`,
180
+ parentId: product._id,
181
+ num: bundleItem.num || 1,
182
+ quantity: bundleItem.num || 1,
183
+ total: new import_decimal.default(bundleItem.price || 0).mul(bundleItem.num || 1).toNumber(),
184
+ origin_total: new import_decimal.default(bundleItem.price || 0).mul(bundleItem.num || 1).toNumber(),
185
+ original_price: bundleItem.original_price,
186
+ // 继承主商品属性
187
+ booking_id: product.booking_id,
188
+ discount_list: bundleItem.discount_list || []
189
+ });
190
+ });
191
+ }
192
+ });
193
+ return flattened;
194
+ };
133
195
  const sortedDiscountList = [...filteredDiscountList].sort((a, b) => {
134
196
  var _a, _b;
135
197
  if (a.tag === "good_pass" && b.tag !== "good_pass")
@@ -156,7 +218,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
156
218
  if (a.par_value !== b.par_value) {
157
219
  const valueA = new import_decimal.default(100).minus(a.par_value || 0);
158
220
  const valueB = new import_decimal.default(100).minus(b.par_value || 0);
159
- return valueB.minus(valueA).toNumber();
221
+ return valueA.minus(valueB).toNumber();
160
222
  }
161
223
  }
162
224
  return compareByExpireTime(a, b);
@@ -171,19 +233,26 @@ var RulesModule = class extends import_BaseModule.BaseModule {
171
233
  return itemA.expire_time ? -1 : itemB.expire_time ? 1 : 0;
172
234
  }
173
235
  });
174
- const sortedProductList = [...productList].sort((a, b) => {
236
+ const flattenedList = flattenProductsWithBundle(productList);
237
+ const sortedFlattenedList = flattenedList.sort((a, b) => {
175
238
  var _a, _b;
176
- const aProduct = this.hooks.getProduct(a);
177
- const bProduct = this.hooks.getProduct(b);
178
- const priceA = new import_decimal.default(aProduct.price || "0");
179
- const priceB = new import_decimal.default(bProduct.price || "0");
180
- if (priceA.toNumber() === priceB.toNumber()) {
181
- if (aProduct.quantity === bProduct.quantity) {
182
- return ((_a = bProduct.discount_list) == null ? void 0 : _a.length) - ((_b = aProduct.discount_list) == null ? void 0 : _b.length);
239
+ const priceA = new import_decimal.default(a.price || "0");
240
+ const priceB = new import_decimal.default(b.price || "0");
241
+ if (priceA.equals(priceB)) {
242
+ if (a.type !== b.type) {
243
+ return a.type === "main" ? -1 : 1;
244
+ }
245
+ if (a.type === "main" && b.type === "main") {
246
+ if (a.product.quantity === b.product.quantity) {
247
+ return (((_a = b.product.discount_list) == null ? void 0 : _a.length) || 0) - (((_b = a.product.discount_list) == null ? void 0 : _b.length) || 0);
248
+ }
249
+ return a.product.quantity - b.product.quantity;
250
+ }
251
+ if (a.type === "bundle" && b.type === "bundle") {
252
+ return (a.num || 1) - (b.num || 1);
183
253
  }
184
- return aProduct.quantity - bProduct.quantity;
185
254
  }
186
- return priceB.toNumber() - priceA.toNumber();
255
+ return priceB.minus(priceA).toNumber();
187
256
  });
188
257
  const usedDiscounts = /* @__PURE__ */ new Map();
189
258
  const discountApplicability = /* @__PURE__ */ new Map();
@@ -194,52 +263,109 @@ var RulesModule = class extends import_BaseModule.BaseModule {
194
263
  });
195
264
  const processedProductsMap = /* @__PURE__ */ new Map();
196
265
  const appliedDiscountProducts = /* @__PURE__ */ new Map();
197
- sortedProductList.forEach((originProduct) => {
198
- const product = this.hooks.getProduct(originProduct);
266
+ sortedFlattenedList.forEach((flatItem) => {
267
+ let product, originProduct;
268
+ if (flatItem.type === "main") {
269
+ product = flatItem.product;
270
+ originProduct = flatItem.originProduct;
271
+ } else {
272
+ product = {
273
+ _id: flatItem._id,
274
+ id: flatItem.id,
275
+ price: flatItem.price,
276
+ quantity: flatItem.quantity,
277
+ num: flatItem.num,
278
+ total: flatItem.total,
279
+ origin_total: flatItem.origin_total,
280
+ booking_id: flatItem.booking_id,
281
+ discount_list: flatItem.discount_list || []
282
+ };
283
+ originProduct = flatItem.originProduct;
284
+ }
199
285
  addModeDiscount.forEach((discount) => {
200
- var _a, _b, _c, _d;
286
+ var _a, _b, _c, _d, _e, _f, _g, _h;
201
287
  const limitedData = discount == null ? void 0 : discount.limited_relation_product_data;
202
- const isLimitedProduct = limitedData.type === "product_all" || limitedData.product_ids && limitedData.product_ids.includes(product.id);
203
- const isAvailableProduct = !((product == null ? void 0 : product.booking_id) && ((_a = product == null ? void 0 : product.discount_list) == null ? void 0 : _a.length) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.every((discount2) => discount2.id && ["good_pass", "discount_card", "product_discount_card"].includes(discount2.tag || discount2.type))));
204
- if (isAvailableProduct && isLimitedProduct) {
205
- (_c = discountApplicability.get(discount.id)) == null ? void 0 : _c.push(product.id);
288
+ const isHolderMatch = this.checkHolderMatch(
289
+ discount,
290
+ {
291
+ holder_id: ((flatItem == null ? void 0 : flatItem.type) === "bundle" ? (_a = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _a.holder_id : (_b = flatItem == null ? void 0 : flatItem.product) == null ? void 0 : _b.holder_id) || product.holder_id
292
+ },
293
+ holders
294
+ );
295
+ let timeLimit = true;
296
+ timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
297
+ const isLimitedProduct = (limitedData.type === "product_all" || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
298
+ const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_c = product == null ? void 0 : product.discount_list) == null ? void 0 : _c.length) && ((_d = product == null ? void 0 : product.discount_list) == null ? void 0 : _d.every((discount2) => discount2.id && ["good_pass", "discount_card", "product_discount_card"].includes(discount2.tag || discount2.type)))) : !((flatItem == null ? void 0 : flatItem.booking_id) && ((_f = (_e = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _e.metadata) == null ? void 0 : _f.custom_product_bundle_map_id));
299
+ const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
300
+ if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable) {
301
+ (_g = discountApplicability.get(discount.id)) == null ? void 0 : _g.push(product.id);
206
302
  const applicableProducts = discountApplicableProducts.get(discount.id) || [];
207
303
  const discountType = discount.tag || discount.type;
304
+ const isGoodPass = discountType === "good_pass";
305
+ const num = isGoodPass || (flatItem == null ? void 0 : flatItem.type) === "main" ? 1 : product.num;
208
306
  const productData = {
209
- amount: product.price,
307
+ amount: product.price * num,
210
308
  type: discountType,
211
309
  tag: discountType,
212
310
  discount: {
213
- discount_card_type: (_d = discount == null ? void 0 : discount.metadata) == null ? void 0 : _d.discount_card_type,
311
+ discount_card_type: (_h = discount == null ? void 0 : discount.metadata) == null ? void 0 : _h.discount_card_type,
214
312
  fixed_amount: product.price,
215
313
  resource_id: discount.id,
216
314
  title: discount.format_title,
217
- original_amount: product.origin_total,
315
+ original_amount: product.price || product.origin_total,
218
316
  pre_value: discount.par_value,
219
317
  product_id: originProduct.id
318
+ },
319
+ metadata: {
320
+ num
220
321
  }
221
322
  };
222
- if (discountType !== "good_pass") {
223
- productData.num = product.num || 1;
224
- }
225
323
  applicableProducts.push(productData);
226
324
  discountApplicableProducts.set(discount.id, applicableProducts);
227
325
  }
228
326
  });
229
327
  });
230
- console.log(sortedProductList, "sortedProductListsortedProductList");
231
- sortedProductList.forEach((originProduct, index) => {
232
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
233
- const product = this.hooks.getProduct(originProduct);
234
- if ((product == null ? void 0 : product.booking_id) && ((_a = product.discount_list) == null ? void 0 : _a.length) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.every((discount) => discount.id && ["good_pass", "discount_card", "product_discount_card"].includes(discount.tag || discount.type)))) {
235
- processedProductsMap.set(product._id, [originProduct]);
328
+ const processedFlatItemsMap = /* @__PURE__ */ new Map();
329
+ sortedFlattenedList.forEach((flatItem, index) => {
330
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
331
+ let product, originProduct;
332
+ if (flatItem.type === "main") {
333
+ product = flatItem.product;
334
+ originProduct = flatItem.originProduct;
335
+ } else {
336
+ product = {
337
+ _id: flatItem._id,
338
+ id: flatItem.id,
339
+ price: flatItem.price,
340
+ quantity: flatItem.quantity,
341
+ num: flatItem.num,
342
+ total: flatItem.total,
343
+ original_price: (_a = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _a.original_price,
344
+ origin_total: (_b = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _b.original_price,
345
+ booking_id: flatItem.booking_id,
346
+ discount_list: ((_c = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _c.discount_list) || []
347
+ };
348
+ originProduct = flatItem.originProduct;
349
+ }
350
+ if ((product == null ? void 0 : product.booking_id) && ((_d = product.discount_list) == null ? void 0 : _d.length) && ((_e = product == null ? void 0 : product.discount_list) == null ? void 0 : _e.every((discount) => discount.id && ["good_pass", "discount_card", "product_discount_card"].includes(discount.tag || discount.type)))) {
351
+ if (flatItem.type === "main") {
352
+ processedProductsMap.set(product._id, [originProduct]);
353
+ } else {
354
+ processedFlatItemsMap.set(flatItem._id, [{
355
+ ...flatItem,
356
+ processed: true
357
+ }]);
358
+ }
236
359
  return;
237
360
  }
238
361
  const applicableDiscounts = sortedDiscountList.filter((discount) => {
239
- var _a2;
240
- if ((Number(product.price) <= 0 || !product.price) && (discount.tag || discount.type) === "good_pass")
362
+ var _a2, _b2, _c2, _d2;
363
+ if ((Number(product.price) <= 0 || !product.price) && !((_a2 = product.discount_list) == null ? void 0 : _a2.find((n) => {
364
+ var _a3;
365
+ return ((_a3 = n.discount) == null ? void 0 : _a3.resource_id) === discount.id;
366
+ })) && (discount.tag || discount.type) === "good_pass")
241
367
  return false;
242
- if ((Number(product.total) <= 0 || !product.total) && !((_a2 = product.discount_list) == null ? void 0 : _a2.find((n) => {
368
+ if ((Number(product.price) <= 0 || !product.price) && !((_b2 = product.discount_list) == null ? void 0 : _b2.find((n) => {
243
369
  var _a3;
244
370
  return ((_a3 = n.discount) == null ? void 0 : _a3.resource_id) === discount.id;
245
371
  })) && (discount.tag || discount.type) !== "good_pass")
@@ -248,70 +374,149 @@ var RulesModule = class extends import_BaseModule.BaseModule {
248
374
  if (targetUsedDiscounts && (discount.tag || discount.type) === "good_pass")
249
375
  return false;
250
376
  const limitedData = discount.limited_relation_product_data;
377
+ let timeLimit = true;
378
+ timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], (product.startDate || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
379
+ if (!timeLimit) {
380
+ return false;
381
+ }
382
+ const isHolderMatch = this.checkHolderMatch(
383
+ discount,
384
+ {
385
+ holder_id: ((flatItem == null ? void 0 : flatItem.type) === "bundle" ? (_c2 = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _c2.holder_id : (_d2 = flatItem == null ? void 0 : flatItem.product) == null ? void 0 : _d2.holder_id) || product.holder_id
386
+ },
387
+ holders
388
+ );
389
+ if (!isHolderMatch)
390
+ return false;
251
391
  if (limitedData.type === "product_all") {
392
+ if (!this.checkPackageSubItemUsageRules(discount, flatItem)) {
393
+ return false;
394
+ }
252
395
  return true;
253
396
  } else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
397
+ if (!this.checkPackageSubItemUsageRules(discount, flatItem)) {
398
+ return false;
399
+ }
254
400
  return true;
255
401
  }
256
402
  return false;
257
403
  });
258
404
  const selectedDiscountCard = applicableDiscounts.find((n) => n.isScan && n.isSelected && (n.tag || n.type) !== "good_pass");
259
405
  const selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
260
- let isManualDiscount = typeof product.isManualDiscount === "boolean" ? product.isManualDiscount : product.total != product.origin_total && (!((_c = product.discount_list) == null ? void 0 : _c.length) || ((_e = (_d = product == null ? void 0 : product.discount_list) == null ? void 0 : _d.every) == null ? void 0 : _e.call(_d, (item) => item.type === "product")));
261
- if ((options == null ? void 0 : options.discountId) && ((_f = product.discount_list) == null ? void 0 : _f.some((item) => {
262
- var _a2;
263
- return ((_a2 = item.discount) == null ? void 0 : _a2.resource_id) === options.discountId;
264
- }))) {
265
- isManualDiscount = false;
406
+ let isManualDiscount = false;
407
+ if (flatItem.type === "main") {
408
+ isManualDiscount = typeof product.isManualDiscount === "boolean" ? product.isManualDiscount : product.total != product.origin_total && (product.bundle || []).every((item) => {
409
+ var _a2;
410
+ return !((_a2 = item.discount_list || []) == null ? void 0 : _a2.length);
411
+ }) && (!((_f = product.discount_list) == null ? void 0 : _f.length) || ((_h = (_g = product == null ? void 0 : product.discount_list) == null ? void 0 : _g.every) == null ? void 0 : _h.call(_g, (item) => item.type === "product")));
412
+ } else {
413
+ const parentProduct = flatItem.parentProduct;
414
+ if (parentProduct) {
415
+ isManualDiscount = typeof parentProduct.isManualDiscount === "boolean" ? parentProduct.isManualDiscount : parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every((item) => {
416
+ var _a2;
417
+ return !((_a2 = item.discount_list || []) == null ? void 0 : _a2.length);
418
+ }) && (!((_i = parentProduct.discount_list) == null ? void 0 : _i.length) || ((_k = (_j = parentProduct == null ? void 0 : parentProduct.discount_list) == null ? void 0 : _j.every) == null ? void 0 : _k.call(_j, (item) => item.type === "product")));
419
+ }
266
420
  }
267
- if ((options == null ? void 0 : options.selectedList) && ((_g = product.discount_list) == null ? void 0 : _g.some((item) => {
268
- var _a2;
269
- return (_a2 = options == null ? void 0 : options.selectedList) == null ? void 0 : _a2.some((n) => {
270
- var _a3;
271
- return n.discountId === ((_a3 = item.discount) == null ? void 0 : _a3.resource_id);
272
- });
273
- }))) {
274
- isManualDiscount = false;
421
+ if (options == null ? void 0 : options.discountId) {
422
+ if (flatItem.type === "main" && ((_l = product.discount_list) == null ? void 0 : _l.some((item) => {
423
+ var _a2;
424
+ return ((_a2 = item.discount) == null ? void 0 : _a2.resource_id) === options.discountId;
425
+ }))) {
426
+ isManualDiscount = false;
427
+ }
428
+ if (flatItem.type === "bundle") {
429
+ if (((_m = product.discount_list) == null ? void 0 : _m.some((item) => {
430
+ var _a2;
431
+ return ((_a2 = item.discount) == null ? void 0 : _a2.resource_id) === options.discountId;
432
+ })) || ((_o = (_n = flatItem.parentProduct) == null ? void 0 : _n.discount_list) == null ? void 0 : _o.some((item) => {
433
+ var _a2;
434
+ return ((_a2 = item.discount) == null ? void 0 : _a2.resource_id) === options.discountId;
435
+ }))) {
436
+ isManualDiscount = false;
437
+ }
438
+ }
439
+ }
440
+ if (options == null ? void 0 : options.selectedList) {
441
+ if (flatItem.type === "main" && ((_p = product.discount_list) == null ? void 0 : _p.some((item) => {
442
+ var _a2;
443
+ return (_a2 = options == null ? void 0 : options.selectedList) == null ? void 0 : _a2.some((n) => {
444
+ var _a3;
445
+ return n.discountId === ((_a3 = item.discount) == null ? void 0 : _a3.resource_id);
446
+ });
447
+ }))) {
448
+ isManualDiscount = false;
449
+ }
450
+ if (flatItem.type === "bundle") {
451
+ if (((_q = product.discount_list) == null ? void 0 : _q.some((item) => {
452
+ var _a2;
453
+ return (_a2 = options == null ? void 0 : options.selectedList) == null ? void 0 : _a2.some((n) => {
454
+ var _a3;
455
+ return n.discountId === ((_a3 = item.discount) == null ? void 0 : _a3.resource_id);
456
+ });
457
+ })) || ((_s = (_r = flatItem.parentProduct) == null ? void 0 : _r.discount_list) == null ? void 0 : _s.some((item) => {
458
+ var _a2;
459
+ return (_a2 = options == null ? void 0 : options.selectedList) == null ? void 0 : _a2.some((n) => {
460
+ var _a3;
461
+ return n.discountId === ((_a3 = item.discount) == null ? void 0 : _a3.resource_id);
462
+ });
463
+ }))) {
464
+ isManualDiscount = false;
465
+ }
466
+ }
275
467
  }
276
468
  if (applicableDiscounts.length === 0 || isManualDiscount || (0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
277
- if (product.isClient) {
278
- processedProductsMap.set(
279
- product._id,
280
- [this.hooks.setProduct(originProduct, {
281
- ...isManualDiscount ? {} : {
282
- origin_total: (0, import_utils2.getProductOriginTotalPrice)({
283
- product: {
284
- original_price: product.original_price
285
- },
286
- bundle: product.bundle,
287
- options: product.options
288
- }),
289
- variant: originProduct._productInit.variant,
290
- original_price: originProduct._productInit.original_price,
291
- total: (0, import_utils2.getProductTotalPrice)({
292
- product: {
293
- price: product.price
294
- },
295
- bundle: product.bundle,
296
- options: product.options
297
- }),
298
- price: product.price
299
- },
300
- discount_list: []
301
- })]
302
- );
469
+ if (flatItem.type === "main") {
470
+ if (product.isClient) {
471
+ processedProductsMap.set(
472
+ product._id,
473
+ [this.hooks.setProduct(originProduct, {
474
+ ...isManualDiscount ? {} : {
475
+ origin_total: (0, import_utils2.getProductOriginTotalPrice)({
476
+ product: {
477
+ original_price: product.original_price
478
+ },
479
+ bundle: product.bundle,
480
+ options: product.options
481
+ }),
482
+ variant: originProduct._productInit.variant,
483
+ original_price: originProduct._productInit.original_price,
484
+ total: (0, import_utils2.getProductTotalPrice)({
485
+ product: {
486
+ price: product.price
487
+ },
488
+ bundle: product.bundle,
489
+ options: product.options
490
+ }),
491
+ price: product.price
492
+ },
493
+ discount_list: []
494
+ })]
495
+ );
496
+ } else {
497
+ processedProductsMap.set(
498
+ product._id,
499
+ [this.hooks.setProduct(originProduct, {
500
+ ...isManualDiscount ? {
501
+ price: product.price,
502
+ main_product_selling_price: product.price
503
+ } : {
504
+ _id: product._id.split("___")[0] + "___" + index,
505
+ total: product.origin_total || product.total,
506
+ price: product.price,
507
+ main_product_selling_price: product.price
508
+ },
509
+ discount_list: []
510
+ })]
511
+ );
512
+ }
303
513
  } else {
304
- processedProductsMap.set(
305
- product._id,
306
- [this.hooks.setProduct(originProduct, {
307
- ...isManualDiscount ? {} : {
308
- _id: product._id.split("___")[0] + "___" + index,
309
- total: product.origin_total || product.total,
310
- price: product.price
311
- },
312
- discount_list: []
313
- })]
314
- );
514
+ processedFlatItemsMap.set(flatItem._id, [{
515
+ ...flatItem,
516
+ discount_list: [],
517
+ price: isManualDiscount ? flatItem.bundleItem.price : flatItem.bundleItem.original_price,
518
+ processed: true
519
+ }]);
315
520
  }
316
521
  return;
317
522
  }
@@ -319,113 +524,512 @@ var RulesModule = class extends import_BaseModule.BaseModule {
319
524
  return;
320
525
  }
321
526
  const isNeedSplit = (selectedDiscount.tag || selectedDiscount.type) === "good_pass";
322
- const splitCount = isNeedSplit ? Math.min(product.quantity || product.num || 1, applicableDiscounts.filter((item) => (item.tag || item.type) === "good_pass").length) : 1;
527
+ const totalQuantity = product.quantity || product.num || 1;
528
+ const availableGoodPassCount = applicableDiscounts.filter((item) => (item.tag || item.type) === "good_pass").length;
529
+ const splitCount = isNeedSplit ? Math.min(totalQuantity, availableGoodPassCount) : 1;
323
530
  const arr = [];
324
- if (splitCount < product.quantity && isNeedSplit) {
325
- arr.push(this.hooks.setProduct(originProduct, {
326
- discount_list: [],
327
- quantity: product.quantity - splitCount,
328
- _id: product._id.split("___")[0]
329
- }));
330
- }
331
- for (let i = 0; i < splitCount; i++) {
332
- const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[i];
333
- usedDiscounts.set(selectedDiscount2.id, true);
334
- const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
335
- let productOriginTotal = product.origin_total || product.total || 0;
336
- if (((_h = product.discount_list) == null ? void 0 : _h.length) && product.origin_total) {
337
- productOriginTotal = product.origin_total;
338
- }
339
- if (Number(((_i = originProduct == null ? void 0 : originProduct._productInit) == null ? void 0 : _i.original_price) || 0) > 0 && product.origin_total && product.total && product.origin_total !== product.total) {
340
- productOriginTotal = product.total;
531
+ if (flatItem.type === "main") {
532
+ if (splitCount < totalQuantity && isNeedSplit) {
533
+ arr.push(this.hooks.setProduct(originProduct, {
534
+ discount_list: [],
535
+ quantity: totalQuantity - splitCount,
536
+ _id: product._id.split("___")[0]
537
+ }));
341
538
  }
342
- const targetProductTotal = (0, import_utils.getDiscountAmount)(selectedDiscount2, productOriginTotal, product.price);
343
- const discountType = selectedDiscount2.tag === "product_discount_card" ? "discount_card" : selectedDiscount2.tag;
344
- const discountDetail = {
345
- amount: new import_decimal.default(productOriginTotal).minus(new import_decimal.default(targetProductTotal)).toNumber(),
346
- type: discountType,
347
- discount: {
348
- discount_card_type: (_j = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _j.discount_card_type,
349
- fixed_amount: new import_decimal.default(productOriginTotal).minus(new import_decimal.default(targetProductTotal)).toNumber(),
350
- resource_id: selectedDiscount2.id,
351
- title: selectedDiscount2.format_title,
352
- original_amount: productOriginTotal,
353
- product_id: originProduct.id,
354
- percent: selectedDiscount2.par_value
539
+ for (let i = 0; i < splitCount; i++) {
540
+ const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[i];
541
+ usedDiscounts.set(selectedDiscount2.id, true);
542
+ const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
543
+ let productOriginTotal = product.origin_total || product.total || 0;
544
+ if (((_t = product.discount_list) == null ? void 0 : _t.length) && product.origin_total) {
545
+ productOriginTotal = product.origin_total;
546
+ }
547
+ if (Number(((_u = originProduct == null ? void 0 : originProduct._productInit) == null ? void 0 : _u.original_price) || 0) > 0 && product.origin_total && product.total && product.origin_total !== product.total) {
548
+ productOriginTotal = product.total;
549
+ }
550
+ const targetProductTotal = (0, import_utils.getDiscountAmount)(selectedDiscount2, product.price, product.price);
551
+ const discountType = selectedDiscount2.tag || selectedDiscount2.type;
552
+ const isGoodPass = discountType === "good_pass";
553
+ const amount = new import_decimal.default(product.price).minus(new import_decimal.default(targetProductTotal)).toNumber();
554
+ const discountDetail = {
555
+ amount,
556
+ type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : discountType,
557
+ discount: {
558
+ discount_card_type: (_v = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _v.discount_card_type,
559
+ fixed_amount: amount,
560
+ resource_id: selectedDiscount2.id,
561
+ title: selectedDiscount2.format_title,
562
+ original_amount: product.price,
563
+ product_id: originProduct.id,
564
+ percent: selectedDiscount2.par_value
565
+ },
566
+ // 前端使用的num数量,为了计算优惠金额
567
+ _num: isGoodPass ? 1 : product.num,
568
+ metadata: {
569
+ num: 1
570
+ }
571
+ };
572
+ appliedProducts.push(discountDetail);
573
+ appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
574
+ let total = targetProductTotal;
575
+ if (product.options) {
576
+ total = product.options.reduce((accumulator, currentValue) => {
577
+ const currentPrice = new import_decimal.default(currentValue.price || 0);
578
+ const currentNum = new import_decimal.default(currentValue.num || 0);
579
+ return accumulator.add(currentPrice.mul(currentNum));
580
+ }, new import_decimal.default(total)).toNumber();
581
+ }
582
+ if (product.isClient) {
583
+ debugger;
584
+ arr.push(this.hooks.setProduct(originProduct, {
585
+ discount_list: [discountDetail],
586
+ price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
587
+ quantity: isNeedSplit ? 1 : product.quantity,
588
+ origin_total: (0, import_utils2.getProductOriginTotalPrice)({
589
+ product: {
590
+ original_price: product.original_price
591
+ },
592
+ bundle: product.bundle,
593
+ options: product.options
594
+ }),
595
+ variant: originProduct._productInit.variant,
596
+ original_price: new import_decimal.default(product.price || 0).toNumber(),
597
+ total
598
+ }));
599
+ } else {
600
+ arr.push(this.hooks.setProduct(originProduct, {
601
+ discount_list: [discountDetail],
602
+ _id: product._id.split("___")[0] + "___" + selectedDiscount2.id + index,
603
+ price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
604
+ quantity: isNeedSplit ? 1 : product.quantity,
605
+ total,
606
+ origin_total: productOriginTotal,
607
+ main_product_selling_price: targetProductTotal
608
+ }));
355
609
  }
356
- };
357
- if ((selectedDiscount2.tag || selectedDiscount2.type) !== "good_pass") {
358
- discountDetail.num = product.num || 1;
359
610
  }
360
- appliedProducts.push(discountDetail);
361
- appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
362
- if (product.isClient) {
363
- arr.push(this.hooks.setProduct(originProduct, {
364
- discount_list: [discountDetail],
365
- price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
366
- quantity: isNeedSplit ? 1 : product.quantity,
367
- origin_total: (0, import_utils2.getProductOriginTotalPrice)({
368
- product: {
369
- original_price: product.original_price
611
+ processedProductsMap.set(product._id, arr);
612
+ } else {
613
+ const processedItems = [];
614
+ if (isNeedSplit) {
615
+ const discountNum = splitCount;
616
+ const normalNum = totalQuantity - discountNum;
617
+ for (let i = 0; i < discountNum; i++) {
618
+ const selectedDiscount2 = applicableDiscounts[i];
619
+ usedDiscounts.set(selectedDiscount2.id, true);
620
+ const uniqueId = `${flatItem._id}_split_${i}`;
621
+ const discountDetail = {
622
+ amount: product.origin_total,
623
+ type: "good_pass",
624
+ discount: {
625
+ fixed_amount: product.origin_total,
626
+ resource_id: selectedDiscount2.id,
627
+ title: selectedDiscount2.format_title,
628
+ original_amount: product.origin_total,
629
+ product_id: product.id
370
630
  },
371
- bundle: product.bundle,
372
- options: product.options
373
- }),
374
- variant: originProduct._productInit.variant,
375
- original_price: new import_decimal.default(product.price || 0).toNumber(),
376
- total: targetProductTotal
377
- }));
631
+ metadata: {
632
+ // 🔥 使用拆分后的唯一 _id
633
+ custom_product_bundle_map_id: uniqueId,
634
+ num: 1
635
+ },
636
+ _num: 1
637
+ };
638
+ const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
639
+ appliedProducts.push(discountDetail);
640
+ appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
641
+ processedItems.push({
642
+ ...flatItem,
643
+ // 🔥 使用唯一的 _id
644
+ _id: uniqueId,
645
+ num: 1,
646
+ quantity: 1,
647
+ price: 0,
648
+ // 商品券价格为0
649
+ total: 0,
650
+ discount_list: [discountDetail],
651
+ processed: true,
652
+ _discountId: selectedDiscount2.id
653
+ });
654
+ }
655
+ if (normalNum > 0) {
656
+ processedItems.push({
657
+ ...flatItem,
658
+ // 🔥 为剩余商品生成唯一的 _id
659
+ _id: `${flatItem._id}_split_rest`,
660
+ num: normalNum,
661
+ quantity: normalNum,
662
+ discount_list: [],
663
+ processed: true
664
+ });
665
+ }
378
666
  } else {
379
- arr.push(this.hooks.setProduct(originProduct, {
380
- discount_list: [discountDetail],
381
- _id: product._id.split("___")[0] + "___" + selectedDiscount2.id + "___" + index,
382
- price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
383
- quantity: isNeedSplit ? 1 : product.quantity,
667
+ const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[0];
668
+ usedDiscounts.set(selectedDiscount2.id, true);
669
+ const productOriginTotal = product.original_price || product.price || 0;
670
+ const targetProductTotal = (0, import_utils.getDiscountAmount)(
671
+ selectedDiscount2,
672
+ productOriginTotal,
673
+ productOriginTotal
674
+ );
675
+ const uniqueId = flatItem._id;
676
+ const discountDetail = {
677
+ amount: new import_decimal.default(productOriginTotal).minus(targetProductTotal).toNumber() * (product.num || 1),
678
+ type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : selectedDiscount2.tag,
679
+ discount: {
680
+ discount_card_type: (_w = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _w.discount_card_type,
681
+ fixed_amount: new import_decimal.default(productOriginTotal).minus(targetProductTotal).toNumber(),
682
+ resource_id: selectedDiscount2.id,
683
+ title: selectedDiscount2.format_title,
684
+ original_amount: product.original_price,
685
+ product_id: product.id,
686
+ percent: selectedDiscount2.par_value
687
+ },
688
+ metadata: {
689
+ // 🔥 使用唯一的 _id
690
+ custom_product_bundle_map_id: uniqueId,
691
+ num: product.num || 1
692
+ },
693
+ _num: (product.num || 1) * (((_x = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _x.num) || 1)
694
+ };
695
+ const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
696
+ appliedProducts.push(discountDetail);
697
+ appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
698
+ processedItems.push({
699
+ ...flatItem,
384
700
  total: targetProductTotal,
385
- origin_total: productOriginTotal
386
- }));
701
+ price: new import_decimal.default(productOriginTotal || 0).minus(discountDetail.discount.fixed_amount).toNumber(),
702
+ discount_list: [discountDetail],
703
+ processed: true
704
+ });
387
705
  }
706
+ processedFlatItemsMap.set(flatItem._id, processedItems);
388
707
  }
389
- console.log(arr, "arrarrarr");
390
- processedProductsMap.set(product._id, arr);
391
708
  });
392
- const processedProductList = [];
393
- productList.forEach((originProduct) => {
394
- const product = this.hooks.getProduct(originProduct);
395
- const getDefaultProduct = () => {
396
- if (product.isClient) {
397
- return this.hooks.setProduct(originProduct, {
398
- discount_list: [],
399
- price: product.price,
400
- origin_total: (0, import_utils2.getProductOriginTotalPrice)({
401
- product: {
402
- original_price: product.original_price
403
- },
404
- bundle: product.bundle,
405
- options: product.options
406
- }),
407
- variant: originProduct._productInit.variant,
408
- original_price: originProduct._productInit.original_price,
409
- total: (0, import_utils2.getProductTotalPrice)({
410
- product: {
709
+ const reconstructProductsWithBundle = (processedProductsMap2, processedFlatItemsMap2, originalProductList) => {
710
+ const result = [];
711
+ originalProductList.forEach((originProduct) => {
712
+ const product = this.hooks.getProduct(originProduct);
713
+ const mainProductArr = processedProductsMap2.get(product._id);
714
+ if (!mainProductArr || mainProductArr.length === 0) {
715
+ const getDefaultProduct = () => {
716
+ if (product.isClient) {
717
+ return this.hooks.setProduct(originProduct, {
718
+ discount_list: [],
719
+ price: product.price,
720
+ origin_total: (0, import_utils2.getProductOriginTotalPrice)({
721
+ product: {
722
+ original_price: product.original_price
723
+ },
724
+ bundle: product.bundle,
725
+ options: product.options
726
+ }),
727
+ variant: originProduct._productInit.variant,
728
+ original_price: originProduct._productInit.original_price,
729
+ total: (0, import_utils2.getProductTotalPrice)({
730
+ product: {
731
+ price: product.price
732
+ },
733
+ bundle: product.bundle,
734
+ options: product.options
735
+ })
736
+ });
737
+ } else {
738
+ return this.hooks.setProduct(originProduct, {
739
+ discount_list: [],
740
+ total: product.total,
741
+ origin_total: product.origin_total,
411
742
  price: product.price
412
- },
413
- bundle: product.bundle,
414
- options: product.options
415
- })
416
- });
743
+ });
744
+ }
745
+ };
746
+ result.push(getDefaultProduct());
747
+ return;
748
+ }
749
+ const hasBundle = product.bundle && Array.isArray(product.bundle) && product.bundle.length > 0;
750
+ if (!hasBundle) {
751
+ result.push(...mainProductArr);
417
752
  } else {
418
- return this.hooks.setProduct(originProduct, {
419
- discount_list: [],
420
- total: product.total,
421
- origin_total: product.origin_total,
422
- price: product.price
423
- });
753
+ const bundleProcessingInfo = /* @__PURE__ */ new Map();
754
+ let hasGoodPassApplied = false;
755
+ if (product.bundle && Array.isArray(product.bundle)) {
756
+ product.bundle.forEach((bundleItem, bundleIndex) => {
757
+ const bundleItemId = `${product._id}_bundle_${bundleIndex}`;
758
+ const processedBundleItems = processedFlatItemsMap2.get(bundleItemId);
759
+ if (!processedBundleItems || processedBundleItems.length === 0) {
760
+ bundleProcessingInfo.set(bundleIndex, [bundleItem]);
761
+ } else {
762
+ bundleProcessingInfo.set(bundleIndex, processedBundleItems);
763
+ const hasGoodPass = processedBundleItems.some(
764
+ (item) => {
765
+ var _a;
766
+ return (_a = item.discount_list) == null ? void 0 : _a.some(
767
+ (discount) => discount.type === "good_pass" || discount.tag === "good_pass"
768
+ );
769
+ }
770
+ );
771
+ if (hasGoodPass) {
772
+ hasGoodPassApplied = true;
773
+ }
774
+ }
775
+ });
776
+ }
777
+ const mainProductQuantity = mainProductArr[0] ? this.hooks.getProduct(mainProductArr[0]).quantity : 1;
778
+ if (hasGoodPassApplied && mainProductArr.length === 1 && mainProductQuantity > 1) {
779
+ const mainProduct = mainProductArr[0];
780
+ const mainProductData = this.hooks.getProduct(mainProduct);
781
+ const newBundleWithDiscount = [];
782
+ (product.bundle || []).forEach((bundleItem, bundleIndex) => {
783
+ const processedItems = bundleProcessingInfo.get(bundleIndex) || [bundleItem];
784
+ if (processedItems.length > 1) {
785
+ processedItems.forEach((item) => {
786
+ const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
787
+ var _a;
788
+ return {
789
+ ...discount,
790
+ metadata: {
791
+ num: item.num,
792
+ custom_product_bundle_map_id: (_a = item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id
793
+ }
794
+ // num: item.num, // 使用拆分后的 num
795
+ };
796
+ });
797
+ newBundleWithDiscount.push({
798
+ ...bundleItem,
799
+ _id: item._id,
800
+ product_id: bundleItem.product_id,
801
+ price: item.price,
802
+ num: item.num,
803
+ discount_list: updatedDiscountList2
804
+ });
805
+ });
806
+ } else {
807
+ const item = processedItems[0];
808
+ if (item.processed) {
809
+ const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
810
+ var _a;
811
+ return {
812
+ ...discount,
813
+ metadata: {
814
+ num: item.num,
815
+ custom_product_bundle_map_id: (_a = item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id
816
+ }
817
+ // num: item.num, // 使用当前的 num
818
+ };
819
+ });
820
+ newBundleWithDiscount.push({
821
+ ...bundleItem,
822
+ _id: item._id,
823
+ product_id: bundleItem.product_id,
824
+ price: item.price,
825
+ num: item.num,
826
+ discount_list: updatedDiscountList2
827
+ });
828
+ } else {
829
+ newBundleWithDiscount.push(item);
830
+ }
831
+ }
832
+ });
833
+ let newTotalWithDiscount = Number(mainProductData.price || 0);
834
+ let newOriginTotalWithDiscount = Number(mainProductData.original_price || mainProductData.price || 0);
835
+ const updatedMainDiscountList = mainProductData.discount_list.map((discount) => {
836
+ var _a, _b;
837
+ if ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.custom_product_bundle_map_id) {
838
+ return discount;
839
+ }
840
+ return {
841
+ ...discount,
842
+ // num: 1,
843
+ metadata: {
844
+ custom_product_bundle_map_id: (_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.custom_product_bundle_map_id,
845
+ num: 1
846
+ }
847
+ };
848
+ });
849
+ const mainDiscountList = updatedMainDiscountList.filter((item) => {
850
+ var _a;
851
+ return !((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id);
852
+ });
853
+ if (mainDiscountList && mainDiscountList.length > 0) {
854
+ const allDiscountAmount = (0, import_utils.getDiscountListAmountTotal)(mainDiscountList);
855
+ newTotalWithDiscount = new import_decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotalWithDiscount;
856
+ newOriginTotalWithDiscount = mainProductData.origin_total ?? newOriginTotalWithDiscount;
857
+ }
858
+ if (newBundleWithDiscount.length > 0) {
859
+ newBundleWithDiscount.forEach((item) => {
860
+ newTotalWithDiscount += Number(item.price) * Number(item.num);
861
+ });
862
+ newBundleWithDiscount.forEach((item) => {
863
+ var _a, _b, _c;
864
+ const originalPrice = ((_c = (_b = (_a = item.discount_list) == null ? void 0 : _a[0]) == null ? void 0 : _b.discount) == null ? void 0 : _c.original_amount) || item.price;
865
+ newOriginTotalWithDiscount += Number(originalPrice) * Number(item.num);
866
+ });
867
+ }
868
+ if (product == null ? void 0 : product.options) {
869
+ newTotalWithDiscount = product.options.reduce((accumulator, currentValue) => {
870
+ const currentPrice = new import_decimal.default(currentValue.price || 0);
871
+ const currentNum = new import_decimal.default(currentValue.num || 0);
872
+ return accumulator.add(currentPrice.mul(currentNum));
873
+ }, new import_decimal.default(newTotalWithDiscount)).toNumber();
874
+ }
875
+ result.push(
876
+ this.hooks.setProduct(mainProduct, {
877
+ ...mainProductData,
878
+ _id: `${mainProductData._id.split("___")[0]}___split_discount`,
879
+ quantity: 1,
880
+ discount_list: updatedMainDiscountList,
881
+ bundle: newBundleWithDiscount,
882
+ total: newTotalWithDiscount,
883
+ origin_total: newOriginTotalWithDiscount
884
+ })
885
+ );
886
+ if (mainProductQuantity > 1) {
887
+ const newBundleOriginal = [];
888
+ (product.bundle || []).forEach((bundleItem, bundleIndex) => {
889
+ newBundleOriginal.push({
890
+ ...bundleItem,
891
+ discount_list: []
892
+ });
893
+ });
894
+ let newTotalOriginal = Number(mainProductData.price || 0);
895
+ let newOriginTotalOriginal = Number(mainProductData.original_price || mainProductData.price || 0);
896
+ const updatedMainDiscountListOriginal = mainProductData.discount_list.map((discount) => {
897
+ var _a, _b;
898
+ if ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.custom_product_bundle_map_id) {
899
+ return discount;
900
+ }
901
+ return {
902
+ ...discount,
903
+ metadata: {
904
+ num: mainProductQuantity - 1,
905
+ custom_product_bundle_map_id: (_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.custom_product_bundle_map_id
906
+ }
907
+ // num: mainProductQuantity - 1,
908
+ };
909
+ });
910
+ const mainDiscountListOriginal = updatedMainDiscountListOriginal.filter((item) => {
911
+ var _a;
912
+ return !((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id);
913
+ });
914
+ if (mainDiscountListOriginal && mainDiscountListOriginal.length > 0) {
915
+ const allDiscountAmount = (0, import_utils.getDiscountListAmount)(mainDiscountListOriginal);
916
+ newTotalOriginal = new import_decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotalOriginal;
917
+ newOriginTotalOriginal = mainProductData.origin_total ?? newOriginTotalOriginal;
918
+ }
919
+ if (newBundleOriginal.length > 0) {
920
+ newBundleOriginal.forEach((item) => {
921
+ newTotalOriginal += Number(item.price) * Number(item.num);
922
+ newOriginTotalOriginal += Number(item.price) * Number(item.num);
923
+ });
924
+ }
925
+ if (product == null ? void 0 : product.options) {
926
+ newTotalOriginal = product.options.reduce((accumulator, currentValue) => {
927
+ const currentPrice = new import_decimal.default(currentValue.price || 0);
928
+ const currentNum = new import_decimal.default(currentValue.num || 0);
929
+ return accumulator.add(currentPrice.mul(currentNum));
930
+ }, new import_decimal.default(newTotalOriginal)).toNumber();
931
+ }
932
+ result.push(
933
+ this.hooks.setProduct(mainProduct, {
934
+ ...mainProductData,
935
+ _id: `${mainProductData._id.split("___")[0]}___split_normal`,
936
+ quantity: mainProductQuantity - 1,
937
+ discount_list: updatedMainDiscountListOriginal,
938
+ bundle: newBundleOriginal,
939
+ total: newTotalOriginal,
940
+ origin_total: newOriginTotalOriginal
941
+ })
942
+ );
943
+ }
944
+ } else {
945
+ mainProductArr.forEach((mainProduct) => {
946
+ var _a, _b, _c;
947
+ const mainProductData = this.hooks.getProduct(mainProduct);
948
+ const newBundle = [];
949
+ if (product.bundle && Array.isArray(product.bundle)) {
950
+ product.bundle.forEach((bundleItem, bundleIndex) => {
951
+ const bundleItemId = `${product._id}_bundle_${bundleIndex}`;
952
+ const processedBundleItems = processedFlatItemsMap2.get(bundleItemId);
953
+ if (!processedBundleItems || processedBundleItems.length === 0) {
954
+ newBundle.push(bundleItem);
955
+ } else {
956
+ processedBundleItems.forEach((item) => {
957
+ const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
958
+ var _a2;
959
+ return {
960
+ ...discount,
961
+ metadata: {
962
+ num: item.num,
963
+ custom_product_bundle_map_id: (_a2 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id
964
+ }
965
+ // num: item.num, // 使用拆分后的 num
966
+ };
967
+ });
968
+ newBundle.push({
969
+ ...bundleItem,
970
+ _id: item._id,
971
+ product_id: bundleItem.product_id,
972
+ price: item.price,
973
+ num: item.num,
974
+ discount_list: updatedDiscountList2
975
+ });
976
+ });
977
+ }
978
+ });
979
+ }
980
+ let newTotal = Number(mainProductData.price || 0);
981
+ let newOriginTotal = Number(mainProductData.original_price || mainProductData.price || 0);
982
+ const isManualDiscount = typeof mainProductData.isManualDiscount === "boolean" ? mainProductData.isManualDiscount : mainProductData.total != mainProductData.origin_total && (!((_a = mainProductData.discount_list) == null ? void 0 : _a.length) || ((_c = (_b = mainProductData == null ? void 0 : mainProductData.discount_list) == null ? void 0 : _b.every) == null ? void 0 : _c.call(_b, (item) => item.type === "product")));
983
+ if (isManualDiscount) {
984
+ newTotal = mainProductData.total ?? newTotal;
985
+ newOriginTotal = mainProductData.origin_total ?? newOriginTotal;
986
+ } else {
987
+ const mainDiscountList = mainProductData.discount_list.filter((item) => {
988
+ var _a2;
989
+ return !((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id);
990
+ });
991
+ if (mainDiscountList && mainDiscountList.length > 0) {
992
+ const allDiscountAmount = (0, import_utils.getDiscountListAmount)(mainDiscountList);
993
+ newTotal = new import_decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotal;
994
+ newOriginTotal = mainProductData.origin_total ?? newOriginTotal;
995
+ }
996
+ if (newBundle.length > 0) {
997
+ newBundle.forEach((item) => {
998
+ newTotal += Number(item.price) * Number(item.num);
999
+ });
1000
+ newBundle.forEach((item) => {
1001
+ var _a2, _b2, _c2;
1002
+ const originalPrice = ((_c2 = (_b2 = (_a2 = item.discount_list) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.discount) == null ? void 0 : _c2.original_amount) || item.price;
1003
+ newOriginTotal += Number(originalPrice) * Number(item.num);
1004
+ });
1005
+ }
1006
+ }
1007
+ if (product == null ? void 0 : product.options) {
1008
+ newTotal = product.options.reduce((accumulator, currentValue) => {
1009
+ const currentPrice = new import_decimal.default(currentValue.price || 0);
1010
+ const currentNum = new import_decimal.default(currentValue.num || 0);
1011
+ return accumulator.add(currentPrice.mul(currentNum));
1012
+ }, new import_decimal.default(newTotal)).toNumber();
1013
+ }
1014
+ result.push(
1015
+ this.hooks.setProduct(mainProduct, {
1016
+ ...mainProductData,
1017
+ bundle: newBundle,
1018
+ total: newTotal,
1019
+ origin_total: newOriginTotal
1020
+ })
1021
+ );
1022
+ });
1023
+ }
424
1024
  }
425
- };
426
- const arr = processedProductsMap.get(product._id);
427
- (arr == null ? void 0 : arr.length) ? processedProductList.push(...arr) : processedProductList.push(getDefaultProduct());
428
- });
1025
+ });
1026
+ return result;
1027
+ };
1028
+ const processedProductList = reconstructProductsWithBundle(
1029
+ processedProductsMap,
1030
+ processedFlatItemsMap,
1031
+ productList
1032
+ );
429
1033
  const updatedDiscountList = addModeDiscount.map((discount) => {
430
1034
  const applicableProducts = discountApplicability.get(discount.id) || [];
431
1035
  const applicableProductDetails = discountApplicableProducts.get(discount.id) || [];
@@ -486,6 +1090,75 @@ var RulesModule = class extends import_BaseModule.BaseModule {
486
1090
  discountList: [...editModeDiscount, ...updatedDiscountList]
487
1091
  };
488
1092
  }
1093
+ /**
1094
+ * 检查优惠是否符合 PackageSubItemUsageRules 配置
1095
+ * @param discount 优惠券
1096
+ * @param flatItem 扁平化后的商品项(可能是主商品或bundle子商品)
1097
+ * @returns 是否可用
1098
+ */
1099
+ checkPackageSubItemUsageRules(discount, flatItem) {
1100
+ var _a, _b, _c, _d;
1101
+ const limitedData = discount.limited_relation_product_data;
1102
+ const usageRules = limitedData == null ? void 0 : limitedData.package_sub_item_usage_rules;
1103
+ const rules = ["original_price", ...(usageRules == null ? void 0 : usageRules.rules) || []];
1104
+ if (!usageRules) {
1105
+ return true;
1106
+ }
1107
+ const ruleType = usageRules.type;
1108
+ const isMainProduct = flatItem.type === "main";
1109
+ const isBundleItem = flatItem.type === "bundle";
1110
+ if (isMainProduct) {
1111
+ return true;
1112
+ }
1113
+ if (ruleType === "universal_discount") {
1114
+ if (isMainProduct) {
1115
+ return true;
1116
+ }
1117
+ if (isBundleItem) {
1118
+ const priceType = (_a = flatItem.bundleItem) == null ? void 0 : _a.price_type;
1119
+ const priceTypeExt = (_b = flatItem.bundleItem) == null ? void 0 : _b.price_type_ext;
1120
+ const isOriginalPrice = priceType === "markup" && priceTypeExt === "product_price";
1121
+ const isMarkupPrice = priceType === "markup" && (priceTypeExt === "" || !priceTypeExt);
1122
+ if (rules.length > 0) {
1123
+ if (isOriginalPrice && rules.includes("original_price")) {
1124
+ return true;
1125
+ }
1126
+ if (isMarkupPrice && rules.includes("markup_price")) {
1127
+ return true;
1128
+ }
1129
+ return false;
1130
+ }
1131
+ return isOriginalPrice;
1132
+ }
1133
+ return true;
1134
+ }
1135
+ if (ruleType === "package_exclusive") {
1136
+ if (isMainProduct) {
1137
+ return false;
1138
+ }
1139
+ if (isBundleItem) {
1140
+ const priceType = (_c = flatItem.bundleItem) == null ? void 0 : _c.price_type;
1141
+ const priceTypeExt = (_d = flatItem.bundleItem) == null ? void 0 : _d.price_type_ext;
1142
+ const isOriginalPrice = priceType === "markup" && priceTypeExt === "product_price";
1143
+ const isMarkupPrice = priceType === "markup" && (priceTypeExt === "" || !priceTypeExt);
1144
+ if (rules.length > 0) {
1145
+ if (isOriginalPrice && rules.includes("original_price")) {
1146
+ return true;
1147
+ }
1148
+ if (isMarkupPrice && rules.includes("markup_price")) {
1149
+ return true;
1150
+ }
1151
+ return false;
1152
+ }
1153
+ return isOriginalPrice;
1154
+ }
1155
+ return false;
1156
+ }
1157
+ if (ruleType === "single_item_promo") {
1158
+ return isMainProduct;
1159
+ }
1160
+ return true;
1161
+ }
489
1162
  async destroy() {
490
1163
  this.core.effects.offByModuleDestroy(this.name);
491
1164
  await this.core.effects.emit(`${this.name}:onDestroy`, {});