@pisell/pisellos 2.1.63 → 2.1.65

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.
@@ -151,6 +151,20 @@ var RulesModule = class extends import_BaseModule.BaseModule {
151
151
  addModeDiscount.push(discount);
152
152
  }
153
153
  });
154
+ const editModeOrderLevelProductIds = /* @__PURE__ */ new Set();
155
+ editModeDiscount.forEach((discount) => {
156
+ var _a, _b;
157
+ if (((_a = discount.discount) == null ? void 0 : _a.discount_calculation_mode) === "order_level") {
158
+ editModeOrderLevelProductIds.add((_b = discount == null ? void 0 : discount.discount) == null ? void 0 : _b.discount_product_id);
159
+ }
160
+ });
161
+ if (editModeOrderLevelProductIds.size > 0) {
162
+ addModeDiscount.forEach((discount) => {
163
+ if (editModeOrderLevelProductIds.has(discount.product_id)) {
164
+ discount.isDisabled = true;
165
+ }
166
+ });
167
+ }
154
168
  const filteredDiscountList = addModeDiscount.filter((discount) => {
155
169
  return !discount.isManualSelect;
156
170
  });
@@ -198,45 +212,85 @@ var RulesModule = class extends import_BaseModule.BaseModule {
198
212
  return flattened;
199
213
  };
200
214
  const sortedDiscountList = [...filteredDiscountList].sort((a, b) => {
201
- var _a, _b;
202
- if (a.tag === "good_pass" && b.tag !== "good_pass")
203
- return -1;
204
- if (b.tag === "good_pass" && a.tag !== "good_pass")
205
- return 1;
206
- if (a.tag === "good_pass" && b.tag === "good_pass") {
207
- return compareByExpireTime(a, b);
208
- } else if (a.tag === "product_discount_card" && b.tag === "product_discount_card") {
209
- const typeA = ((_a = a.metadata) == null ? void 0 : _a.discount_card_type) || "percent";
210
- const typeB = ((_b = b.metadata) == null ? void 0 : _b.discount_card_type) || "percent";
215
+ const isHolderDiscount = (discount) => {
216
+ var _a, _b;
217
+ return ((_b = (_a = discount.metadata) == null ? void 0 : _a.holder) == null ? void 0 : _b.type) === "custom";
218
+ };
219
+ const isGoodPass = (discount) => discount.tag === "good_pass";
220
+ const isOrderLevelDiscount = (discount) => {
221
+ var _a;
222
+ return discount.tag === "product_discount_card" && ((_a = discount.metadata) == null ? void 0 : _a.discount_calculation_mode) === "order_level";
223
+ };
224
+ const isItemLevelDiscount = (discount) => {
225
+ var _a;
226
+ return discount.tag === "product_discount_card" && ((_a = discount.metadata) == null ? void 0 : _a.discount_calculation_mode) !== "order_level";
227
+ };
228
+ const getPriority = (discount) => {
229
+ const isHolder = isHolderDiscount(discount);
230
+ if (isHolder) {
231
+ if (isGoodPass(discount))
232
+ return 1;
233
+ if (isItemLevelDiscount(discount))
234
+ return 2;
235
+ if (isOrderLevelDiscount(discount))
236
+ return 3;
237
+ } else {
238
+ if (isGoodPass(discount))
239
+ return 4;
240
+ if (isItemLevelDiscount(discount))
241
+ return 5;
242
+ if (isOrderLevelDiscount(discount))
243
+ return 6;
244
+ }
245
+ return 7;
246
+ };
247
+ function compareByExpireTime(itemA, itemB) {
248
+ if (itemA.expire_time && itemB.expire_time) {
249
+ const timeA = new Date(itemA.expire_time).getTime();
250
+ const timeB = new Date(itemB.expire_time).getTime();
251
+ return timeA - timeB;
252
+ }
253
+ return itemA.expire_time ? -1 : itemB.expire_time ? 1 : 0;
254
+ }
255
+ function compareDiscountCardValue(itemA, itemB) {
256
+ var _a, _b;
257
+ const typeA = ((_a = itemA.metadata) == null ? void 0 : _a.discount_card_type) || "percent";
258
+ const typeB = ((_b = itemB.metadata) == null ? void 0 : _b.discount_card_type) || "percent";
211
259
  if (typeA === "fixed_amount" && typeB === "percent")
212
260
  return -1;
213
261
  if (typeA === "percent" && typeB === "fixed_amount")
214
262
  return 1;
215
263
  if (typeA === "fixed_amount" && typeB === "fixed_amount") {
216
- if (a.par_value !== b.par_value) {
217
- const valueA = new import_decimal.default(a.par_value || 0);
218
- const valueB = new import_decimal.default(b.par_value || 0);
264
+ if (itemA.par_value !== itemB.par_value) {
265
+ const valueA = new import_decimal.default(itemA.par_value || 0);
266
+ const valueB = new import_decimal.default(itemB.par_value || 0);
219
267
  return valueB.minus(valueA).toNumber();
220
268
  }
221
269
  }
222
270
  if (typeA === "percent" && typeB === "percent") {
223
- if (a.par_value !== b.par_value) {
224
- const valueA = new import_decimal.default(100).minus(a.par_value || 0);
225
- const valueB = new import_decimal.default(100).minus(b.par_value || 0);
271
+ if (itemA.par_value !== itemB.par_value) {
272
+ const valueA = new import_decimal.default(100).minus(itemA.par_value || 0);
273
+ const valueB = new import_decimal.default(100).minus(itemB.par_value || 0);
226
274
  return valueA.minus(valueB).toNumber();
227
275
  }
228
276
  }
277
+ return 0;
278
+ }
279
+ const priorityA = getPriority(a);
280
+ const priorityB = getPriority(b);
281
+ if (priorityA !== priorityB) {
282
+ return priorityA - priorityB;
283
+ }
284
+ if (isGoodPass(a) && isGoodPass(b)) {
229
285
  return compareByExpireTime(a, b);
230
286
  }
231
- return compareByExpireTime(a, b);
232
- function compareByExpireTime(itemA, itemB) {
233
- if (itemA.expire_time && itemB.expire_time) {
234
- const timeA = new Date(itemA.expire_time).getTime();
235
- const timeB = new Date(itemB.expire_time).getTime();
236
- return timeA - timeB;
237
- }
238
- return itemA.expire_time ? -1 : itemB.expire_time ? 1 : 0;
287
+ if (a.tag === "product_discount_card" && b.tag === "product_discount_card") {
288
+ const valueCompare = compareDiscountCardValue(a, b);
289
+ if (valueCompare !== 0)
290
+ return valueCompare;
291
+ return compareByExpireTime(a, b);
239
292
  }
293
+ return compareByExpireTime(a, b);
240
294
  });
241
295
  const flattenedList = flattenProductsWithBundle(productList);
242
296
  const sortedFlattenedList = flattenedList.sort((a, b) => {
@@ -270,6 +324,128 @@ var RulesModule = class extends import_BaseModule.BaseModule {
270
324
  discountApplicability.set(discount.id, []);
271
325
  discountApplicableProducts.set(discount.id, []);
272
326
  });
327
+ const orderLevelDiscountAllocations = /* @__PURE__ */ new Map();
328
+ const orderLevelDiscountApplicableItems = /* @__PURE__ */ new Map();
329
+ const itemApplicableDiscounts = /* @__PURE__ */ new Map();
330
+ const checkItemApplicableForDiscount = (flatItem, discount) => {
331
+ var _a, _b, _c, _d, _e, _f, _g, _h;
332
+ let product;
333
+ if (flatItem.type === "main") {
334
+ product = flatItem.product;
335
+ } else {
336
+ product = {
337
+ _id: flatItem._id,
338
+ id: flatItem.id,
339
+ price: flatItem.price,
340
+ quantity: flatItem.quantity,
341
+ num: flatItem.num,
342
+ booking_id: flatItem.booking_id,
343
+ discount_list: flatItem.discount_list || [],
344
+ startDate: (_a = flatItem.parentProduct) == null ? void 0 : _a.startDate
345
+ };
346
+ }
347
+ const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.length) && ((_c = product == null ? void 0 : product.discount_list) == null ? void 0 : _c.every((d) => d.id && ["good_pass", "discount_card", "product_discount_card"].includes(d.tag || d.type)))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_e = (_d = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _d.discount_list) == null ? void 0 : _e.length) && ((_g = (_f = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _f.discount_list) == null ? void 0 : _g.every((d) => d.id)));
348
+ if (!isAvailableProduct) {
349
+ return false;
350
+ }
351
+ if ((0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
352
+ return false;
353
+ }
354
+ if (Number(product.price) <= 0 || !product.price) {
355
+ return false;
356
+ }
357
+ const limitedData = discount.limited_relation_product_data;
358
+ const timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
359
+ if (!timeLimit) {
360
+ return false;
361
+ }
362
+ let isLimitedProduct = false;
363
+ if (limitedData.type === "product_all") {
364
+ if (limitedData.filter === 1 && ((_h = limitedData.exclude_product_ids) == null ? void 0 : _h.includes(product.id))) {
365
+ isLimitedProduct = false;
366
+ } else {
367
+ isLimitedProduct = true;
368
+ }
369
+ } else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
370
+ isLimitedProduct = true;
371
+ }
372
+ const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
373
+ return isLimitedProduct && isBundleAvailable;
374
+ };
375
+ const selectedOrderLevelDiscounts = sortedDiscountList.filter((discount) => {
376
+ return (0, import_utils.isOrderLevelFixedAmountDiscount)(discount) && discount.isSelected !== false;
377
+ });
378
+ selectedOrderLevelDiscounts.forEach((discount) => {
379
+ const applicableItemIds = /* @__PURE__ */ new Set();
380
+ sortedFlattenedList.forEach((flatItem) => {
381
+ if (checkItemApplicableForDiscount(flatItem, discount)) {
382
+ applicableItemIds.add(flatItem._id);
383
+ if (!itemApplicableDiscounts.has(flatItem._id)) {
384
+ itemApplicableDiscounts.set(flatItem._id, /* @__PURE__ */ new Set());
385
+ }
386
+ itemApplicableDiscounts.get(flatItem._id).add(discount.id);
387
+ }
388
+ });
389
+ orderLevelDiscountApplicableItems.set(discount.id, applicableItemIds);
390
+ });
391
+ const occupiedItems = /* @__PURE__ */ new Map();
392
+ selectedOrderLevelDiscounts.forEach((discount) => {
393
+ const limitedData = discount.limited_relation_product_data;
394
+ const isExclusiveDiscount = limitedData.type !== "product_all";
395
+ if (isExclusiveDiscount) {
396
+ const applicableItems = orderLevelDiscountApplicableItems.get(discount.id);
397
+ if (applicableItems) {
398
+ applicableItems.forEach((itemId) => {
399
+ if (!occupiedItems.has(itemId)) {
400
+ occupiedItems.set(itemId, discount.id);
401
+ }
402
+ });
403
+ }
404
+ }
405
+ });
406
+ console.log("occupiedItems", occupiedItems, "orderLevelDiscountApplicableItems", orderLevelDiscountApplicableItems);
407
+ sortedDiscountList.forEach((discount) => {
408
+ if (!(0, import_utils.isOrderLevelFixedAmountDiscount)(discount)) {
409
+ return;
410
+ }
411
+ const applicableProducts = [];
412
+ sortedFlattenedList.forEach((flatItem) => {
413
+ var _a, _b;
414
+ const occupyingDiscountId = occupiedItems.get(flatItem._id);
415
+ if (occupyingDiscountId !== void 0 && occupyingDiscountId !== discount.id) {
416
+ return;
417
+ }
418
+ if (!checkItemApplicableForDiscount(flatItem, discount)) {
419
+ return;
420
+ }
421
+ let product;
422
+ if (flatItem.type === "main") {
423
+ product = flatItem.product;
424
+ } else {
425
+ product = {
426
+ _id: flatItem._id,
427
+ id: flatItem.id,
428
+ price: flatItem.price,
429
+ quantity: flatItem.quantity,
430
+ num: flatItem.num
431
+ };
432
+ }
433
+ const quantity = flatItem.type === "main" ? product.quantity || 1 : (product.num || 1) * (((_a = flatItem.parentProduct) == null ? void 0 : _a.quantity) || 1);
434
+ const productData = {
435
+ productId: flatItem._id,
436
+ amount: Number(product.price || 0),
437
+ quantity
438
+ };
439
+ if (flatItem.type === "bundle") {
440
+ productData.parentQuantity = ((_b = flatItem.parentProduct) == null ? void 0 : _b.quantity) || 1;
441
+ }
442
+ applicableProducts.push(productData);
443
+ });
444
+ if (applicableProducts.length > 0) {
445
+ const allocation = (0, import_utils.calculateOrderLevelDiscountAllocation)(discount, applicableProducts);
446
+ orderLevelDiscountAllocations.set(discount.id, allocation);
447
+ }
448
+ });
273
449
  const processedProductsMap = /* @__PURE__ */ new Map();
274
450
  const appliedDiscountProducts = /* @__PURE__ */ new Map();
275
451
  sortedFlattenedList.forEach((flatItem) => {
@@ -294,7 +470,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
294
470
  originProduct = flatItem.originProduct;
295
471
  }
296
472
  addModeDiscount.forEach((discount) => {
297
- var _a2, _b, _c, _d, _e, _f;
473
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
298
474
  const limitedData = discount == null ? void 0 : discount.limited_relation_product_data;
299
475
  const _tempVar = (flatItem == null ? void 0 : flatItem.type) === "bundle" ? flatItem == null ? void 0 : flatItem.parentProduct : flatItem == null ? void 0 : flatItem.product;
300
476
  const isHolderMatch = this.checkHolderMatch(
@@ -308,10 +484,16 @@ var RulesModule = class extends import_BaseModule.BaseModule {
308
484
  let timeLimit = true;
309
485
  timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
310
486
  const isLimitedProduct = (limitedData.type === "product_all" || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
311
- const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_a2 = product == null ? void 0 : product.discount_list) == null ? void 0 : _a2.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));
487
+ const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_a2 = product == null ? void 0 : product.discount_list) == null ? void 0 : _a2.length) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.every(
488
+ (discount2) => discount2.id && [
489
+ "good_pass",
490
+ "discount_card",
491
+ "product_discount_card"
492
+ ].includes(discount2.tag || discount2.type)
493
+ ))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_d = (_c = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _c.discount_list) == null ? void 0 : _d.length) && ((_f = (_e = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _e.discount_list) == null ? void 0 : _f.every((discount2) => discount2.id)));
312
494
  const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
313
495
  if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable) {
314
- (_e = discountApplicability.get(discount.id)) == null ? void 0 : _e.push(product.id);
496
+ (_g = discountApplicability.get(discount.id)) == null ? void 0 : _g.push(product.id);
315
497
  const applicableProducts = discountApplicableProducts.get(discount.id) || [];
316
498
  const discountType = discount.tag || discount.type;
317
499
  const isGoodPass = discountType === "good_pass";
@@ -321,8 +503,9 @@ var RulesModule = class extends import_BaseModule.BaseModule {
321
503
  type: discountType,
322
504
  tag: discountType,
323
505
  discount: {
324
- discount_card_type: (_f = discount == null ? void 0 : discount.metadata) == null ? void 0 : _f.discount_card_type,
506
+ discount_card_type: (_h = discount == null ? void 0 : discount.metadata) == null ? void 0 : _h.discount_card_type,
325
507
  fixed_amount: product.price,
508
+ discount_calculation_mode: (_i = discount == null ? void 0 : discount.metadata) == null ? void 0 : _i.discount_calculation_mode,
326
509
  resource_id: discount.id,
327
510
  title: discount.format_title,
328
511
  original_amount: product.price || product.origin_total,
@@ -340,7 +523,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
340
523
  });
341
524
  const processedFlatItemsMap = /* @__PURE__ */ new Map();
342
525
  sortedFlattenedList.forEach((flatItem, index) => {
343
- 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, _y;
526
+ 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, _y, _z, _A, _B;
344
527
  let product, originProduct;
345
528
  if (flatItem.type === "main") {
346
529
  product = flatItem.product;
@@ -560,16 +743,29 @@ var RulesModule = class extends import_BaseModule.BaseModule {
560
743
  if (Number(((_v = originProduct == null ? void 0 : originProduct._productInit) == null ? void 0 : _v.original_price) || 0) > 0 && product.origin_total && product.total && product.origin_total !== product.total) {
561
744
  productOriginTotal = product.total;
562
745
  }
563
- const targetProductTotal = (0, import_utils.getDiscountAmount)(selectedDiscount2, product.price, product.price);
746
+ const isOrderLevel = (0, import_utils.isOrderLevelFixedAmountDiscount)(selectedDiscount2);
747
+ const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount2.id) : null;
748
+ const productAllocation = orderLevelAllocation == null ? void 0 : orderLevelAllocation.get(flatItem._id);
749
+ let targetProductTotal;
750
+ let amount;
751
+ let productDiscountDifference;
752
+ if (isOrderLevel && productAllocation) {
753
+ amount = productAllocation.discountAmount;
754
+ productDiscountDifference = productAllocation.difference;
755
+ targetProductTotal = Math.max(new import_decimal.default(product.price).minus(amount).toNumber(), 0);
756
+ } else {
757
+ targetProductTotal = (0, import_utils.getDiscountAmount)(selectedDiscount2, product.price, product.price);
758
+ amount = new import_decimal.default(product.price).minus(new import_decimal.default(targetProductTotal)).toNumber();
759
+ }
564
760
  const discountType = selectedDiscount2.tag || selectedDiscount2.type;
565
761
  const isGoodPass = discountType === "good_pass";
566
- const amount = new import_decimal.default(product.price).minus(new import_decimal.default(targetProductTotal)).toNumber();
567
762
  const discountDetail = {
568
763
  amount,
569
764
  type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : discountType,
570
765
  discount: {
571
766
  discount_card_type: (_w = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _w.discount_card_type,
572
767
  fixed_amount: amount,
768
+ discount_calculation_mode: (_x = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _x.discount_calculation_mode,
573
769
  resource_id: selectedDiscount2.id,
574
770
  title: selectedDiscount2.format_title,
575
771
  original_amount: product.price,
@@ -579,7 +775,9 @@ var RulesModule = class extends import_BaseModule.BaseModule {
579
775
  // 前端使用的num数量,为了计算优惠金额
580
776
  _num: isGoodPass ? 1 : product.num,
581
777
  metadata: {
582
- num: 1
778
+ num: 1,
779
+ // 🔥 order_level 分摊差值
780
+ ...productDiscountDifference !== void 0 && { product_discount_difference: productDiscountDifference }
583
781
  }
584
782
  };
585
783
  appliedProducts.push(discountDetail);
@@ -636,6 +834,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
636
834
  type: "good_pass",
637
835
  discount: {
638
836
  fixed_amount: product.origin_total,
837
+ discount_calculation_mode: (_y = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _y.discount_calculation_mode,
639
838
  resource_id: selectedDiscount2.id,
640
839
  title: selectedDiscount2.format_title,
641
840
  original_amount: product.origin_total,
@@ -680,18 +879,33 @@ var RulesModule = class extends import_BaseModule.BaseModule {
680
879
  const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[0];
681
880
  usedDiscounts.set(selectedDiscount2.id, true);
682
881
  const productOriginTotal = product.original_price || product.price || 0;
683
- const targetProductTotal = (0, import_utils.getDiscountAmount)(
684
- selectedDiscount2,
685
- productOriginTotal,
686
- productOriginTotal
687
- );
882
+ const isOrderLevel = (0, import_utils.isOrderLevelFixedAmountDiscount)(selectedDiscount2);
883
+ const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount2.id) : null;
884
+ const productAllocation = orderLevelAllocation == null ? void 0 : orderLevelAllocation.get(flatItem._id);
885
+ let targetProductTotal;
886
+ let fixedAmountPerItem;
887
+ let productDiscountDifference;
888
+ if (isOrderLevel && productAllocation) {
889
+ fixedAmountPerItem = productAllocation.discountAmount;
890
+ productDiscountDifference = productAllocation.difference;
891
+ targetProductTotal = Math.max(new import_decimal.default(productOriginTotal).minus(fixedAmountPerItem).toNumber(), 0);
892
+ } else {
893
+ targetProductTotal = (0, import_utils.getDiscountAmount)(
894
+ selectedDiscount2,
895
+ productOriginTotal,
896
+ productOriginTotal
897
+ );
898
+ fixedAmountPerItem = new import_decimal.default(productOriginTotal).minus(targetProductTotal).toNumber();
899
+ }
900
+ debugger;
688
901
  const uniqueId = flatItem._id;
689
902
  const discountDetail = {
690
- amount: new import_decimal.default(productOriginTotal).minus(targetProductTotal).toNumber() * (product.num || 1),
903
+ amount: fixedAmountPerItem * (product.num || 1),
691
904
  type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : selectedDiscount2.tag,
692
905
  discount: {
693
- discount_card_type: (_x = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _x.discount_card_type,
694
- fixed_amount: new import_decimal.default(productOriginTotal).minus(targetProductTotal).toNumber(),
906
+ discount_card_type: (_z = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _z.discount_card_type,
907
+ fixed_amount: fixedAmountPerItem,
908
+ discount_calculation_mode: (_A = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _A.discount_calculation_mode,
695
909
  resource_id: selectedDiscount2.id,
696
910
  title: selectedDiscount2.format_title,
697
911
  original_amount: product.original_price,
@@ -701,9 +915,11 @@ var RulesModule = class extends import_BaseModule.BaseModule {
701
915
  metadata: {
702
916
  // 🔥 使用唯一的 _id
703
917
  custom_product_bundle_map_id: uniqueId,
704
- num: product.num || 1
918
+ num: product.num || 1,
919
+ // 🔥 order_level 分摊差值
920
+ ...productDiscountDifference !== void 0 && { product_discount_difference: productDiscountDifference }
705
921
  },
706
- _num: (product.num || 1) * (((_y = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _y.num) || 1)
922
+ _num: (product.num || 1) * (((_B = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _B.num) || 1)
707
923
  };
708
924
  const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
709
925
  appliedProducts.push(discountDetail);
@@ -711,7 +927,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
711
927
  processedItems.push({
712
928
  ...flatItem,
713
929
  total: targetProductTotal,
714
- price: new import_decimal.default(productOriginTotal || 0).minus(discountDetail.discount.fixed_amount).toNumber(),
930
+ price: new import_decimal.default(productOriginTotal || 0).minus(fixedAmountPerItem).toNumber(),
715
931
  discount_list: [discountDetail],
716
932
  processed: true
717
933
  });
@@ -801,6 +1017,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
801
1017
  return {
802
1018
  ...discount,
803
1019
  metadata: {
1020
+ ...discount.metadata,
804
1021
  num: item.num,
805
1022
  custom_product_bundle_map_id: (_a = item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id
806
1023
  }
@@ -824,6 +1041,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
824
1041
  return {
825
1042
  ...discount,
826
1043
  metadata: {
1044
+ ...discount.metadata,
827
1045
  num: item.num,
828
1046
  custom_product_bundle_map_id: (_a = item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id
829
1047
  }
@@ -854,6 +1072,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
854
1072
  ...discount,
855
1073
  // num: 1,
856
1074
  metadata: {
1075
+ ...discount.metadata,
857
1076
  custom_product_bundle_map_id: (_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.custom_product_bundle_map_id,
858
1077
  num: 1
859
1078
  }
@@ -914,6 +1133,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
914
1133
  return {
915
1134
  ...discount,
916
1135
  metadata: {
1136
+ ...discount.metadata,
917
1137
  num: mainProductQuantity - 1,
918
1138
  custom_product_bundle_map_id: (_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.custom_product_bundle_map_id
919
1139
  }
@@ -972,6 +1192,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
972
1192
  return {
973
1193
  ...discount,
974
1194
  metadata: {
1195
+ ...discount.metadata,
975
1196
  num: item.num,
976
1197
  custom_product_bundle_map_id: (_a2 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id
977
1198
  }
@@ -2,6 +2,11 @@ import Decimal from 'decimal.js';
2
2
  import { CartItem } from '../Cart/types';
3
3
  import { ISummaryState } from './types';
4
4
  export declare const calculatePriceDetails: (shopInfo: any, items: CartItem[]) => ISummaryState['summary'];
5
+ /**
6
+ * 获取子商品折扣信息
7
+ * @param item
8
+ */
9
+ export declare const getBundleDiscountList: (bundle: any[]) => any[];
5
10
  /**
6
11
  * 计算商品小计(不含其他费用)
7
12
  * @param items - 购物车商品数组
@@ -32,7 +32,8 @@ __export(utils_exports, {
32
32
  calculateDeposit: () => calculateDeposit,
33
33
  calculatePriceDetails: () => calculatePriceDetails,
34
34
  calculateSubtotal: () => calculateSubtotal,
35
- calculateTaxFee: () => calculateTaxFee
35
+ calculateTaxFee: () => calculateTaxFee,
36
+ getBundleDiscountList: () => getBundleDiscountList
36
37
  });
37
38
  module.exports = __toCommonJS(utils_exports);
38
39
  var import_decimal = __toESM(require("decimal.js"));
@@ -50,13 +51,35 @@ var calculatePriceDetails = (shopInfo, items) => {
50
51
  deposit
51
52
  };
52
53
  };
54
+ var getBundleDiscountList = (bundle) => {
55
+ if (!bundle) {
56
+ return [];
57
+ }
58
+ let discountList = [];
59
+ bundle.forEach((d) => {
60
+ if (d.discount_list && Array.isArray(d.discount_list)) {
61
+ discountList.push(...d.discount_list.filter((item) => !item.id));
62
+ }
63
+ });
64
+ return discountList;
65
+ };
66
+ var getProductDiscountProductDiscountDifference = (item) => {
67
+ var _a, _b, _c, _d;
68
+ const mainDiscountList = ((_b = (_a = item._origin) == null ? void 0 : _a.product) == null ? void 0 : _b.discount_list) || [];
69
+ const bundleDiscountList = getBundleDiscountList(((_d = (_c = item._origin) == null ? void 0 : _c.product) == null ? void 0 : _d.product_bundle) || []);
70
+ const discountList = [...mainDiscountList, ...bundleDiscountList];
71
+ return discountList.reduce((pre, cur) => {
72
+ return pre + (cur.metadata.product_discount_difference || 0);
73
+ }, 0);
74
+ };
53
75
  var calculateSubtotal = (items) => {
54
76
  if (!(items == null ? void 0 : items.length)) {
55
77
  return "0.00";
56
78
  }
57
79
  const subtotal = items.reduce((sum, item) => {
58
80
  const cartItemTotalPrice = new import_decimal.default(item.summaryTotal || 0);
59
- return sum.plus(cartItemTotalPrice);
81
+ const productDiscountProductDiscountDifference = getProductDiscountProductDiscountDifference(item);
82
+ return sum.plus(cartItemTotalPrice).sub(productDiscountProductDiscountDifference);
60
83
  }, new import_decimal.default(0));
61
84
  return subtotal.toFixed(2);
62
85
  };
@@ -103,5 +126,6 @@ var calculateDeposit = (items) => {
103
126
  calculateDeposit,
104
127
  calculatePriceDetails,
105
128
  calculateSubtotal,
106
- calculateTaxFee
129
+ calculateTaxFee,
130
+ getBundleDiscountList
107
131
  });
@@ -115,7 +115,7 @@ export declare class BookingTicketImpl extends BaseModule implements Module {
115
115
  * 获取当前的客户搜索条件
116
116
  * @returns 当前搜索条件
117
117
  */
118
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
118
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
119
119
  /**
120
120
  * 获取客户列表状态(包含滚动加载相关状态)
121
121
  * @returns 客户状态
@@ -122,6 +122,12 @@ var BookingTicketImpl = class extends import_BaseModule.BaseModule {
122
122
  throw error;
123
123
  }
124
124
  }
125
+ /**
126
+ * 初始化外设扫码结果监听
127
+ */
128
+ initPeripheralsListener() {
129
+ this.scan.initPeripheralsListener();
130
+ }
125
131
  /**
126
132
  * 获取商品列表(不加载到模块中)
127
133
  * @returns 商品列表
@@ -369,7 +369,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
369
369
  if (item.booking_id) {
370
370
  const product = (_a2 = this.hooks) == null ? void 0 : _a2.getProduct(item);
371
371
  (item.discount_list || []).forEach((discount) => {
372
- var _a3, _b, _c;
372
+ var _a3, _b, _c, _d, _e;
373
373
  if (discount.id && ["good_pass", "discount_card"].includes(discount.type)) {
374
374
  const index = editModeDiscountList.findIndex((n) => {
375
375
  var _a4;
@@ -379,7 +379,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
379
379
  editModeDiscountList[index] = {
380
380
  ...editModeDiscountList[index],
381
381
  amount: new import_decimal.default(discount.amount || 0).plus(new import_decimal.default(editModeDiscountList[index].amount || 0)).toNumber(),
382
- savedAmount: new import_decimal.default(discount.amount || 0).times((product == null ? void 0 : product.quantity) || (product == null ? void 0 : product.num) || 1).plus(new import_decimal.default(editModeDiscountList[index].savedAmount || 0)).toNumber()
382
+ savedAmount: new import_decimal.default(discount.amount || 0).times((product == null ? void 0 : product.quantity) || (product == null ? void 0 : product.num) || 1).plus(((_a3 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a3.product_discount_difference) || 0).plus(new import_decimal.default(editModeDiscountList[index].savedAmount || 0)).toNumber()
383
383
  };
384
384
  } else {
385
385
  if (discount.type && !discount.tag) {
@@ -390,13 +390,13 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
390
390
  name: discount.name || discount.discount.title.auto,
391
391
  isEditMode: true,
392
392
  limited_relation_product_data: {},
393
- savedAmount: discount.amount * ((product == null ? void 0 : product.quantity) || (product == null ? void 0 : product.num) || 1),
393
+ savedAmount: new import_decimal.default(discount.amount || 0).times((product == null ? void 0 : product.quantity) || (product == null ? void 0 : product.num) || 1).plus(((_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.product_discount_difference) || 0).toNumber(),
394
394
  isAvailable: true,
395
- id: ((_a3 = discount.discount) == null ? void 0 : _a3.resource_id) || discount.id,
396
- format_title: ((_b = discount.discount) == null ? void 0 : _b.title) || discount.format_title,
395
+ id: ((_c = discount.discount) == null ? void 0 : _c.resource_id) || discount.id,
396
+ format_title: ((_d = discount.discount) == null ? void 0 : _d.title) || discount.format_title,
397
397
  isDisabled: true,
398
398
  isSelected: true,
399
- product_id: ((_c = discount.discount) == null ? void 0 : _c.product_id) || discount.product_id
399
+ product_id: ((_e = discount.discount) == null ? void 0 : _e.product_id) || discount.product_id
400
400
  });
401
401
  }
402
402
  }
@@ -65,3 +65,27 @@ export declare const getDateIsInSchedule: (dateTime: string, scheduleList: Sched
65
65
  * @returns 过滤后的优惠券列表
66
66
  */
67
67
  export declare const filterDiscountListByBookingTime: (discountList: Discount[], bookingTime: string | null) => Discount[];
68
+ /**
69
+ * 判断是否是订单级别的固定金额折扣卡
70
+ * @param discount 折扣
71
+ * @returns 是否是订单级别的固定金额折扣卡
72
+ */
73
+ export declare const isOrderLevelFixedAmountDiscount: (discount: Discount) => boolean;
74
+ /**
75
+ * 计算订单级别固定金额折扣卡的分摊结果
76
+ * @param discount 折扣卡
77
+ * @param applicableProducts 适用商品列表 { productId, amount, quantity, parentQuantity }
78
+ * @returns 分摊结果 Map<productId, { discountAmount, difference }>
79
+ * 注意:
80
+ * - discountAmount 是单价折扣金额(不是总折扣金额)
81
+ * - difference(总差值)优先直接加到数量为1的单商品折扣上,如果没有则存储在metadata中
82
+ */
83
+ export declare const calculateOrderLevelDiscountAllocation: (discount: Discount, applicableProducts: Array<{
84
+ productId: string | number;
85
+ amount: number;
86
+ quantity: number;
87
+ parentQuantity?: number;
88
+ }>) => Map<string | number, {
89
+ discountAmount: number;
90
+ difference: number;
91
+ }>;