@pisell/pisellos 2.2.11 → 2.2.13

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 (53) 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 +2 -0
  4. package/dist/modules/Discount/index.js +69 -36
  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/index.js +2 -2
  10. package/dist/modules/Payment/types.d.ts +1 -0
  11. package/dist/modules/Payment/walletpass.js +3 -1
  12. package/dist/modules/ProductList/index.js +8 -9
  13. package/dist/modules/Rules/index.d.ts +7 -0
  14. package/dist/modules/Rules/index.js +1065 -196
  15. package/dist/modules/Rules/types.d.ts +4 -1
  16. package/dist/solution/BookingByStep/index.d.ts +1 -1
  17. package/dist/solution/BookingByStep/index.js +30 -8
  18. package/dist/solution/BookingByStep/utils/products.d.ts +6 -0
  19. package/dist/solution/BookingByStep/utils/products.js +10 -0
  20. package/dist/solution/BookingTicket/index.d.ts +1 -1
  21. package/dist/solution/Checkout/index.js +61 -17
  22. package/dist/solution/ShopDiscount/index.d.ts +2 -0
  23. package/dist/solution/ShopDiscount/index.js +80 -19
  24. package/dist/solution/ShopDiscount/types.d.ts +4 -1
  25. package/dist/solution/ShopDiscount/utils.d.ts +55 -0
  26. package/dist/solution/ShopDiscount/utils.js +432 -3
  27. package/lib/modules/Cart/utils/cartProduct.js +35 -22
  28. package/lib/modules/Customer/index.js +1 -1
  29. package/lib/modules/Discount/index.d.ts +2 -0
  30. package/lib/modules/Discount/index.js +19 -4
  31. package/lib/modules/Discount/types.d.ts +16 -0
  32. package/lib/modules/Order/index.js +2 -0
  33. package/lib/modules/Order/utils.d.ts +1 -0
  34. package/lib/modules/Order/utils.js +11 -0
  35. package/lib/modules/Payment/index.js +1 -1
  36. package/lib/modules/Payment/types.d.ts +1 -0
  37. package/lib/modules/Payment/walletpass.js +10 -1
  38. package/lib/modules/ProductList/index.js +0 -7
  39. package/lib/modules/Rules/index.d.ts +7 -0
  40. package/lib/modules/Rules/index.js +824 -182
  41. package/lib/modules/Rules/types.d.ts +4 -1
  42. package/lib/solution/BookingByStep/index.d.ts +1 -1
  43. package/lib/solution/BookingByStep/index.js +19 -2
  44. package/lib/solution/BookingByStep/utils/products.d.ts +6 -0
  45. package/lib/solution/BookingByStep/utils/products.js +8 -2
  46. package/lib/solution/BookingTicket/index.d.ts +1 -1
  47. package/lib/solution/Checkout/index.js +66 -17
  48. package/lib/solution/ShopDiscount/index.d.ts +2 -0
  49. package/lib/solution/ShopDiscount/index.js +55 -9
  50. package/lib/solution/ShopDiscount/types.d.ts +4 -1
  51. package/lib/solution/ShopDiscount/utils.d.ts +55 -0
  52. package/lib/solution/ShopDiscount/utils.js +266 -3
  53. package/package.json +2 -2
@@ -37,7 +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 flatItem;
40
+ var import_dayjs = __toESM(require("dayjs"));
41
41
  var RulesModule = class extends import_BaseModule.BaseModule {
42
42
  constructor(name, version) {
43
43
  super(name, version);
@@ -108,9 +108,13 @@ var RulesModule = class extends import_BaseModule.BaseModule {
108
108
  let hasApplicableDiscount = false;
109
109
  const newDiscountIds = newDiscountList.map((discount) => discount.id);
110
110
  result.productList.forEach((product) => {
111
- const { discount_list } = this.hooks.getProduct(product);
112
- if (discount_list && discount_list.length > 0) {
113
- 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(
114
118
  (discount) => {
115
119
  var _a;
116
120
  return newDiscountIds.includes((_a = discount == null ? void 0 : discount.discount) == null ? void 0 : _a.resource_id);
@@ -145,6 +149,49 @@ var RulesModule = class extends import_BaseModule.BaseModule {
145
149
  const filteredDiscountList = addModeDiscount.filter((discount) => {
146
150
  return !discount.isManualSelect;
147
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
+ };
148
195
  const sortedDiscountList = [...filteredDiscountList].sort((a, b) => {
149
196
  var _a, _b;
150
197
  if (a.tag === "good_pass" && b.tag !== "good_pass")
@@ -171,7 +218,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
171
218
  if (a.par_value !== b.par_value) {
172
219
  const valueA = new import_decimal.default(100).minus(a.par_value || 0);
173
220
  const valueB = new import_decimal.default(100).minus(b.par_value || 0);
174
- return valueB.minus(valueA).toNumber();
221
+ return valueA.minus(valueB).toNumber();
175
222
  }
176
223
  }
177
224
  return compareByExpireTime(a, b);
@@ -186,19 +233,26 @@ var RulesModule = class extends import_BaseModule.BaseModule {
186
233
  return itemA.expire_time ? -1 : itemB.expire_time ? 1 : 0;
187
234
  }
188
235
  });
189
- const sortedProductList = [...productList].sort((a, b) => {
236
+ const flattenedList = flattenProductsWithBundle(productList);
237
+ const sortedFlattenedList = flattenedList.sort((a, b) => {
190
238
  var _a, _b;
191
- const aProduct = this.hooks.getProduct(a);
192
- const bProduct = this.hooks.getProduct(b);
193
- const priceA = new import_decimal.default(aProduct.price || "0");
194
- const priceB = new import_decimal.default(bProduct.price || "0");
195
- if (priceA.toNumber() === priceB.toNumber()) {
196
- if (aProduct.quantity === bProduct.quantity) {
197
- 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);
198
253
  }
199
- return aProduct.quantity - bProduct.quantity;
200
254
  }
201
- return priceB.toNumber() - priceA.toNumber();
255
+ return priceB.minus(priceA).toNumber();
202
256
  });
203
257
  const usedDiscounts = /* @__PURE__ */ new Map();
204
258
  const discountApplicability = /* @__PURE__ */ new Map();
@@ -209,10 +263,27 @@ var RulesModule = class extends import_BaseModule.BaseModule {
209
263
  });
210
264
  const processedProductsMap = /* @__PURE__ */ new Map();
211
265
  const appliedDiscountProducts = /* @__PURE__ */ new Map();
212
- sortedProductList.forEach((originProduct) => {
213
- 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
+ }
214
285
  addModeDiscount.forEach((discount) => {
215
- var _a, _b, _c, _d, _e, _f;
286
+ var _a, _b, _c, _d, _e, _f, _g, _h;
216
287
  const limitedData = discount == null ? void 0 : discount.limited_relation_product_data;
217
288
  const isHolderMatch = this.checkHolderMatch(
218
289
  discount,
@@ -221,47 +292,80 @@ var RulesModule = class extends import_BaseModule.BaseModule {
221
292
  },
222
293
  holders
223
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;
224
297
  const isLimitedProduct = (limitedData.type === "product_all" || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
225
- const isAvailableProduct = !((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))));
226
- if (isAvailableProduct && isLimitedProduct) {
227
- (_e = discountApplicability.get(discount.id)) == null ? void 0 : _e.push(product.id);
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);
228
302
  const applicableProducts = discountApplicableProducts.get(discount.id) || [];
229
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;
230
306
  const productData = {
231
- amount: product.price,
307
+ amount: product.price * num,
232
308
  type: discountType,
233
309
  tag: discountType,
234
310
  discount: {
235
- discount_card_type: (_f = discount == null ? void 0 : discount.metadata) == null ? void 0 : _f.discount_card_type,
311
+ discount_card_type: (_h = discount == null ? void 0 : discount.metadata) == null ? void 0 : _h.discount_card_type,
236
312
  fixed_amount: product.price,
237
313
  resource_id: discount.id,
238
314
  title: discount.format_title,
239
- original_amount: product.origin_total,
315
+ original_amount: product.price || product.origin_total,
240
316
  pre_value: discount.par_value,
241
317
  product_id: originProduct.id
318
+ },
319
+ metadata: {
320
+ num
242
321
  }
243
322
  };
244
- if (discountType !== "good_pass") {
245
- productData.num = product.num || 1;
246
- }
247
323
  applicableProducts.push(productData);
248
324
  discountApplicableProducts.set(discount.id, applicableProducts);
249
325
  }
250
326
  });
251
327
  });
252
- console.log(sortedProductList, "sortedProductListsortedProductList");
253
- sortedProductList.forEach((originProduct, index) => {
254
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
255
- const product = this.hooks.getProduct(originProduct);
256
- 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)))) {
257
- 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
+ }
258
359
  return;
259
360
  }
260
361
  const applicableDiscounts = sortedDiscountList.filter((discount) => {
261
- var _a2, _b2, _c2;
262
- 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")
263
367
  return false;
264
- 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) => {
265
369
  var _a3;
266
370
  return ((_a3 = n.discount) == null ? void 0 : _a3.resource_id) === discount.id;
267
371
  })) && (discount.tag || discount.type) !== "good_pass")
@@ -270,79 +374,149 @@ var RulesModule = class extends import_BaseModule.BaseModule {
270
374
  if (targetUsedDiscounts && (discount.tag || discount.type) === "good_pass")
271
375
  return false;
272
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
+ }
273
382
  const isHolderMatch = this.checkHolderMatch(
274
383
  discount,
275
384
  {
276
- holder_id: ((flatItem == null ? void 0 : flatItem.type) === "bundle" ? (_b2 = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _b2.holder_id : (_c2 = flatItem == null ? void 0 : flatItem.product) == null ? void 0 : _c2.holder_id) || product.holder_id
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
277
386
  },
278
387
  holders
279
388
  );
280
389
  if (!isHolderMatch)
281
390
  return false;
282
391
  if (limitedData.type === "product_all") {
392
+ if (!this.checkPackageSubItemUsageRules(discount, flatItem)) {
393
+ return false;
394
+ }
283
395
  return true;
284
396
  } else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
397
+ if (!this.checkPackageSubItemUsageRules(discount, flatItem)) {
398
+ return false;
399
+ }
285
400
  return true;
286
401
  }
287
402
  return false;
288
403
  });
289
404
  const selectedDiscountCard = applicableDiscounts.find((n) => n.isScan && n.isSelected && (n.tag || n.type) !== "good_pass");
290
405
  const selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
291
- 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")));
292
- if ((options == null ? void 0 : options.discountId) && ((_f = product.discount_list) == null ? void 0 : _f.some((item) => {
293
- var _a2;
294
- return ((_a2 = item.discount) == null ? void 0 : _a2.resource_id) === options.discountId;
295
- }))) {
296
- 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
+ }
297
420
  }
298
- if ((options == null ? void 0 : options.selectedList) && ((_g = product.discount_list) == null ? void 0 : _g.some((item) => {
299
- var _a2;
300
- return (_a2 = options == null ? void 0 : options.selectedList) == null ? void 0 : _a2.some((n) => {
301
- var _a3;
302
- return n.discountId === ((_a3 = item.discount) == null ? void 0 : _a3.resource_id);
303
- });
304
- }))) {
305
- 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
+ }
306
467
  }
307
468
  if (applicableDiscounts.length === 0 || isManualDiscount || (0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
308
- if (product.isClient) {
309
- processedProductsMap.set(
310
- product._id,
311
- [this.hooks.setProduct(originProduct, {
312
- ...isManualDiscount ? {} : {
313
- origin_total: (0, import_utils2.getProductOriginTotalPrice)({
314
- product: {
315
- original_price: product.original_price
316
- },
317
- bundle: product.bundle,
318
- options: product.options
319
- }),
320
- variant: originProduct._productInit.variant,
321
- original_price: originProduct._productInit.original_price,
322
- total: (0, import_utils2.getProductTotalPrice)({
323
- product: {
324
- price: product.price
325
- },
326
- bundle: product.bundle,
327
- options: product.options
328
- }),
329
- price: product.price
330
- },
331
- discount_list: []
332
- })]
333
- );
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
+ }
334
513
  } else {
335
- processedProductsMap.set(
336
- product._id,
337
- [this.hooks.setProduct(originProduct, {
338
- ...isManualDiscount ? {} : {
339
- _id: product._id.split("___")[0] + "___" + index,
340
- total: product.origin_total || product.total,
341
- price: product.price
342
- },
343
- discount_list: []
344
- })]
345
- );
514
+ processedFlatItemsMap.set(flatItem._id, [{
515
+ ...flatItem,
516
+ discount_list: [],
517
+ price: isManualDiscount ? flatItem.bundleItem.price : flatItem.bundleItem.original_price,
518
+ processed: true
519
+ }]);
346
520
  }
347
521
  return;
348
522
  }
@@ -350,113 +524,512 @@ var RulesModule = class extends import_BaseModule.BaseModule {
350
524
  return;
351
525
  }
352
526
  const isNeedSplit = (selectedDiscount.tag || selectedDiscount.type) === "good_pass";
353
- 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;
354
530
  const arr = [];
355
- if (splitCount < product.quantity && isNeedSplit) {
356
- arr.push(this.hooks.setProduct(originProduct, {
357
- discount_list: [],
358
- quantity: product.quantity - splitCount,
359
- _id: product._id.split("___")[0]
360
- }));
361
- }
362
- for (let i = 0; i < splitCount; i++) {
363
- const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[i];
364
- usedDiscounts.set(selectedDiscount2.id, true);
365
- const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
366
- let productOriginTotal = product.origin_total || product.total || 0;
367
- if (((_h = product.discount_list) == null ? void 0 : _h.length) && product.origin_total) {
368
- productOriginTotal = product.origin_total;
369
- }
370
- 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) {
371
- 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
+ }));
372
538
  }
373
- const targetProductTotal = (0, import_utils.getDiscountAmount)(selectedDiscount2, productOriginTotal, product.price);
374
- const discountType = selectedDiscount2.tag === "product_discount_card" ? "discount_card" : selectedDiscount2.tag;
375
- const discountDetail = {
376
- amount: new import_decimal.default(productOriginTotal).minus(new import_decimal.default(targetProductTotal)).toNumber(),
377
- type: discountType,
378
- discount: {
379
- discount_card_type: (_j = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _j.discount_card_type,
380
- fixed_amount: new import_decimal.default(productOriginTotal).minus(new import_decimal.default(targetProductTotal)).toNumber(),
381
- resource_id: selectedDiscount2.id,
382
- title: selectedDiscount2.format_title,
383
- original_amount: productOriginTotal,
384
- product_id: originProduct.id,
385
- 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
+ }));
386
609
  }
387
- };
388
- if ((selectedDiscount2.tag || selectedDiscount2.type) !== "good_pass") {
389
- discountDetail.num = product.num || 1;
390
610
  }
391
- appliedProducts.push(discountDetail);
392
- appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
393
- if (product.isClient) {
394
- arr.push(this.hooks.setProduct(originProduct, {
395
- discount_list: [discountDetail],
396
- price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
397
- quantity: isNeedSplit ? 1 : product.quantity,
398
- origin_total: (0, import_utils2.getProductOriginTotalPrice)({
399
- product: {
400
- 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
401
630
  },
402
- bundle: product.bundle,
403
- options: product.options
404
- }),
405
- variant: originProduct._productInit.variant,
406
- original_price: new import_decimal.default(product.price || 0).toNumber(),
407
- total: targetProductTotal
408
- }));
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
+ }
409
666
  } else {
410
- arr.push(this.hooks.setProduct(originProduct, {
411
- discount_list: [discountDetail],
412
- _id: product._id.split("___")[0] + "___" + selectedDiscount2.id + "___" + index,
413
- price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
414
- 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,
415
700
  total: targetProductTotal,
416
- origin_total: productOriginTotal
417
- }));
701
+ price: new import_decimal.default(productOriginTotal || 0).minus(discountDetail.discount.fixed_amount).toNumber(),
702
+ discount_list: [discountDetail],
703
+ processed: true
704
+ });
418
705
  }
706
+ processedFlatItemsMap.set(flatItem._id, processedItems);
419
707
  }
420
- console.log(arr, "arrarrarr");
421
- processedProductsMap.set(product._id, arr);
422
708
  });
423
- const processedProductList = [];
424
- productList.forEach((originProduct) => {
425
- const product = this.hooks.getProduct(originProduct);
426
- const getDefaultProduct = () => {
427
- if (product.isClient) {
428
- return this.hooks.setProduct(originProduct, {
429
- discount_list: [],
430
- price: product.price,
431
- origin_total: (0, import_utils2.getProductOriginTotalPrice)({
432
- product: {
433
- original_price: product.original_price
434
- },
435
- bundle: product.bundle,
436
- options: product.options
437
- }),
438
- variant: originProduct._productInit.variant,
439
- original_price: originProduct._productInit.original_price,
440
- total: (0, import_utils2.getProductTotalPrice)({
441
- 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,
442
742
  price: product.price
443
- },
444
- bundle: product.bundle,
445
- options: product.options
446
- })
447
- });
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);
448
752
  } else {
449
- return this.hooks.setProduct(originProduct, {
450
- discount_list: [],
451
- total: product.total,
452
- origin_total: product.origin_total,
453
- price: product.price
454
- });
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
+ }
455
1024
  }
456
- };
457
- const arr = processedProductsMap.get(product._id);
458
- (arr == null ? void 0 : arr.length) ? processedProductList.push(...arr) : processedProductList.push(getDefaultProduct());
459
- });
1025
+ });
1026
+ return result;
1027
+ };
1028
+ const processedProductList = reconstructProductsWithBundle(
1029
+ processedProductsMap,
1030
+ processedFlatItemsMap,
1031
+ productList
1032
+ );
460
1033
  const updatedDiscountList = addModeDiscount.map((discount) => {
461
1034
  const applicableProducts = discountApplicability.get(discount.id) || [];
462
1035
  const applicableProductDetails = discountApplicableProducts.get(discount.id) || [];
@@ -517,6 +1090,75 @@ var RulesModule = class extends import_BaseModule.BaseModule {
517
1090
  discountList: [...editModeDiscount, ...updatedDiscountList]
518
1091
  };
519
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
+ }
520
1162
  async destroy() {
521
1163
  this.core.effects.offByModuleDestroy(this.name);
522
1164
  await this.core.effects.emit(`${this.name}:onDestroy`, {});