@pisell/pisellos 3.0.71 → 3.0.73

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