@pisell/pisellos 2.1.45 → 2.1.47

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