@pisell/pisellos 0.10.8 → 0.10.9

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 (98) hide show
  1. package/dist/core/index.js +0 -1
  2. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
  3. package/dist/model/strategy/adapter/dataVariant/evaluator.js +287 -101
  4. package/dist/model/strategy/adapter/dataVariant/type.d.ts +25 -0
  5. package/dist/model/strategy/adapter/promotion/index.js +0 -9
  6. package/dist/model/strategy/adapter/walletPass/evaluator.js +0 -2
  7. package/dist/model/strategy/adapter/walletPass/type.d.ts +5 -0
  8. package/dist/model/strategy/adapter/walletPass/utils.js +57 -26
  9. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +7 -3
  10. package/dist/modules/BookingContext/utils/productExtend.js +5 -9
  11. package/dist/modules/BookingContext/utils/timeSlices.js +24 -3
  12. package/dist/modules/Customer/index.d.ts +4 -0
  13. package/dist/modules/Customer/index.js +91 -59
  14. package/dist/modules/Customer/types.d.ts +2 -0
  15. package/dist/modules/Discount/index.d.ts +2 -0
  16. package/dist/modules/Discount/index.js +38 -5
  17. package/dist/modules/Discount/types.d.ts +11 -0
  18. package/dist/modules/Order/index.d.ts +20 -1
  19. package/dist/modules/Order/index.js +976 -730
  20. package/dist/modules/Order/types.d.ts +6 -1
  21. package/dist/modules/Order/utils/virtualSettlement.d.ts +56 -0
  22. package/dist/modules/Order/utils/virtualSettlement.js +271 -0
  23. package/dist/modules/Order/utils.js +89 -48
  24. package/dist/modules/Payment/types.d.ts +2 -0
  25. package/dist/modules/Payment/utils.js +4 -1
  26. package/dist/modules/Payment/walletpass.d.ts +11 -0
  27. package/dist/modules/Payment/walletpass.js +235 -60
  28. package/dist/modules/Product/types.d.ts +23 -0
  29. package/dist/modules/ProductList/index.d.ts +15 -2
  30. package/dist/modules/ProductList/index.js +92 -13
  31. package/dist/modules/SalesSummary/index.d.ts +1 -0
  32. package/dist/modules/SalesSummary/index.js +4 -3
  33. package/dist/modules/SalesSummary/types.d.ts +1 -0
  34. package/dist/modules/SalesSummary/utils.d.ts +1 -0
  35. package/dist/modules/SalesSummary/utils.js +21 -1
  36. package/dist/server/index.d.ts +9 -0
  37. package/dist/server/index.js +90 -58
  38. package/dist/server/modules/order/index.d.ts +1 -0
  39. package/dist/server/modules/order/index.js +252 -94
  40. package/dist/server/utils/small-ticket.js +2 -1
  41. package/dist/solution/BaseSales/index.d.ts +26 -2
  42. package/dist/solution/BaseSales/index.js +1310 -931
  43. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  44. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +78 -12
  45. package/dist/solution/BookingByStep/index.d.ts +3 -3
  46. package/dist/solution/BookingTicket/index.d.ts +5 -1
  47. package/dist/solution/BookingTicket/index.js +221 -159
  48. package/dist/solution/BookingTicket/utils/addProductDecision.js +2 -1
  49. package/dist/solution/ScanOrder/index.js +25 -64
  50. package/lib/core/index.js +0 -1
  51. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
  52. package/lib/model/strategy/adapter/dataVariant/evaluator.js +170 -7
  53. package/lib/model/strategy/adapter/dataVariant/type.d.ts +25 -0
  54. package/lib/model/strategy/adapter/walletPass/evaluator.js +0 -2
  55. package/lib/model/strategy/adapter/walletPass/type.d.ts +5 -0
  56. package/lib/model/strategy/adapter/walletPass/utils.js +62 -11
  57. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +3 -0
  58. package/lib/modules/BookingContext/utils/productExtend.js +4 -3
  59. package/lib/modules/BookingContext/utils/timeSlices.js +18 -3
  60. package/lib/modules/Customer/index.d.ts +4 -0
  61. package/lib/modules/Customer/index.js +11 -0
  62. package/lib/modules/Customer/types.d.ts +2 -0
  63. package/lib/modules/Discount/index.d.ts +2 -0
  64. package/lib/modules/Discount/index.js +37 -3
  65. package/lib/modules/Discount/types.d.ts +11 -0
  66. package/lib/modules/Order/index.d.ts +20 -1
  67. package/lib/modules/Order/index.js +393 -128
  68. package/lib/modules/Order/types.d.ts +6 -1
  69. package/lib/modules/Order/utils/virtualSettlement.d.ts +56 -0
  70. package/lib/modules/Order/utils/virtualSettlement.js +300 -0
  71. package/lib/modules/Order/utils.js +65 -21
  72. package/lib/modules/Payment/types.d.ts +2 -0
  73. package/lib/modules/Payment/utils.js +5 -1
  74. package/lib/modules/Payment/walletpass.d.ts +11 -0
  75. package/lib/modules/Payment/walletpass.js +198 -17
  76. package/lib/modules/Product/types.d.ts +23 -0
  77. package/lib/modules/ProductList/index.d.ts +15 -2
  78. package/lib/modules/ProductList/index.js +85 -3
  79. package/lib/modules/SalesSummary/index.d.ts +1 -0
  80. package/lib/modules/SalesSummary/index.js +10 -2
  81. package/lib/modules/SalesSummary/types.d.ts +1 -0
  82. package/lib/modules/SalesSummary/utils.d.ts +1 -0
  83. package/lib/modules/SalesSummary/utils.js +25 -1
  84. package/lib/server/index.d.ts +9 -0
  85. package/lib/server/index.js +54 -14
  86. package/lib/server/modules/order/index.d.ts +1 -0
  87. package/lib/server/modules/order/index.js +66 -2
  88. package/lib/server/utils/small-ticket.js +1 -1
  89. package/lib/solution/BaseSales/index.d.ts +26 -2
  90. package/lib/solution/BaseSales/index.js +261 -23
  91. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  92. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +61 -11
  93. package/lib/solution/BookingByStep/index.d.ts +3 -3
  94. package/lib/solution/BookingTicket/index.d.ts +5 -1
  95. package/lib/solution/BookingTicket/index.js +30 -2
  96. package/lib/solution/BookingTicket/utils/addProductDecision.js +2 -1
  97. package/lib/solution/ScanOrder/index.js +17 -54
  98. package/package.json +1 -1
@@ -45,6 +45,7 @@ var import_manualProductDiscount = require("./utils/manualProductDiscount");
45
45
  var import_bundleDiscountHydration = require("./utils/bundleDiscountHydration");
46
46
  var import_orderCollectionIdentity = require("./utils/orderCollectionIdentity");
47
47
  var import_discountProductLineIdentity = require("./utils/discountProductLineIdentity");
48
+ var import_virtualSettlement = require("./utils/virtualSettlement");
48
49
  var import_Discount = require("../Discount");
49
50
  var import_Rules = require("../Rules");
50
51
  var import_types2 = require("../Rules/types");
@@ -354,6 +355,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
354
355
  this.store.tempOrder = null;
355
356
  this.store.summary = (0, import_utils.createEmptySummary)();
356
357
  this.store.availableWalletIds = [];
358
+ this.store.virtualCurrencyList = [];
357
359
  this.store.lastOrderInfo = void 0;
358
360
  this.store.syncState = void 0;
359
361
  this.store.discountList = [];
@@ -366,6 +368,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
366
368
  if (!Array.isArray(this.store.availableWalletIds)) {
367
369
  this.store.availableWalletIds = [];
368
370
  }
371
+ if (!Array.isArray(this.store.virtualCurrencyList)) {
372
+ this.store.virtualCurrencyList = [];
373
+ }
369
374
  this.request = this.core.getPlugin("request");
370
375
  const appPlugin = this.core.getPlugin("app");
371
376
  if (!appPlugin) {
@@ -501,11 +506,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
501
506
  with_wallet_pass_holder: 1,
502
507
  with_available_wallet_flag: 1,
503
508
  with_available_wallet_pass_flag: 1,
509
+ with_virtual_currency: 1,
504
510
  request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
505
511
  ...orderId ? { order_id: orderId } : {}
506
512
  }));
507
513
  const discountList = prepareConfigResult == null ? void 0 : prepareConfigResult.discountList;
508
514
  this.store.availableWalletIds = (prepareConfigResult == null ? void 0 : prepareConfigResult.availableWalletIds) || [];
515
+ this.store.virtualCurrencyList = (prepareConfigResult == null ? void 0 : prepareConfigResult.virtualCurrencyList) || [];
509
516
  if (discountList) {
510
517
  const currentDiscountList = ((_c = this.store.discount) == null ? void 0 : _c.getDiscountList()) || [];
511
518
  const currentEditDiscounts = currentDiscountList.filter((discount) => discount == null ? void 0 : discount.isEditMode);
@@ -542,6 +549,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
542
549
  getAvailableWalletIds() {
543
550
  return Array.isArray(this.store.availableWalletIds) ? [...this.store.availableWalletIds] : [];
544
551
  }
552
+ getVirtualCurrencyList() {
553
+ return (0, import_lodash_es.cloneDeep)(this.store.virtualCurrencyList || []);
554
+ }
545
555
  async syncScannedDiscountsToOriginalDiscountList(discountList) {
546
556
  var _a, _b, _c, _d;
547
557
  const scanDiscounts = (discountList || []).filter((discount) => discount == null ? void 0 : discount.isScan);
@@ -576,6 +586,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
576
586
  }
577
587
  async scanCode(code, customerId) {
578
588
  var _a, _b, _c, _d, _e;
589
+ if (this.isActiveVirtualSettlementOrder(this.store.tempOrder)) {
590
+ return {
591
+ type: "clientCalc",
592
+ isAvailable: false,
593
+ isAccepted: false,
594
+ discountList: [],
595
+ scannedDiscountList: [],
596
+ unavailableReason: import_types2.UnavailableReason.ProductNotApplicable
597
+ };
598
+ }
579
599
  const resultDiscountWithReason = await ((_a = this.store.discount) == null ? void 0 : _a.batchSearch(code, { customerId })) || { discountList: [], unavailableReasonKey: null };
580
600
  const { discountList: resultDiscountList, unavailableReasonKey } = resultDiscountWithReason;
581
601
  const rulesModule = this.store.rules;
@@ -653,13 +673,21 @@ var OrderModule = class extends import_BaseModule.BaseModule {
653
673
  };
654
674
  }
655
675
  applyDiscount(options) {
656
- var _a, _b, _c;
676
+ var _a, _b, _c, _d, _e;
657
677
  const tempOrder = this.store.tempOrder;
658
678
  if (!tempOrder)
659
679
  return;
680
+ if (this.isActiveVirtualSettlementOrder(tempOrder)) {
681
+ tempOrder.products = (0, import_virtualSettlement.normalizeVirtualSettlementProducts)(tempOrder.products);
682
+ tempOrder.discount_list = [];
683
+ tempOrder.shop_discount = "0.00";
684
+ void ((_a = this.store.discount) == null ? void 0 : _a.setDiscountList([]));
685
+ void ((_b = this.store.discount) == null ? void 0 : _b.setOriginalDiscountList([]));
686
+ return;
687
+ }
660
688
  this.syncLinkedBookingHoldersToProducts(tempOrder);
661
689
  delete tempOrder.discount_list;
662
- const discountList = ((_a = this.store.discount) == null ? void 0 : _a.getDiscountList()) || [];
690
+ const discountList = ((_c = this.store.discount) == null ? void 0 : _c.getDiscountList()) || [];
663
691
  const shouldSkipDiscountCalculation = this.shouldSkipDiscountCalculation(tempOrder);
664
692
  if (shouldSkipDiscountCalculation)
665
693
  return;
@@ -671,7 +699,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
671
699
  discountList,
672
700
  holders: [],
673
701
  isFormSubject: (product) => (0, import_utils.resolveIsFormSubject)(tempOrder, product),
674
- orderTotalAmount: Number(((_b = this.store.summary) == null ? void 0 : _b.total_amount) || 0)
702
+ orderTotalAmount: Number(((_d = this.store.summary) == null ? void 0 : _d.total_amount) || 0)
675
703
  }, {
676
704
  reapplyBookingDiscountProductUids: options == null ? void 0 : options.reapplyBookingDiscountProductUids
677
705
  });
@@ -704,7 +732,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
704
732
  result.productList || tempOrder.products,
705
733
  result.discountList
706
734
  );
707
- (_c = this.store.discount) == null ? void 0 : _c.setDiscountList(result.discountList);
735
+ (_e = this.store.discount) == null ? void 0 : _e.setDiscountList(result.discountList);
708
736
  }
709
737
  this.hasActiveCustomerBoundDiscount = (tempOrder.products || []).some(
710
738
  (product) => this.productHasCustomerBoundDiscount(product)
@@ -764,6 +792,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
764
792
  if (!tempOrder) {
765
793
  return;
766
794
  }
795
+ if (this.isActiveVirtualSettlementOrder(tempOrder)) {
796
+ tempOrder.products = (0, import_virtualSettlement.normalizeVirtualSettlementProducts)(tempOrder.products);
797
+ return;
798
+ }
767
799
  const strategyConfigs = (_b = (_a = this.promotionEvaluator).getStrategyConfigs) == null ? void 0 : _b.call(_a);
768
800
  if (Array.isArray(strategyConfigs) && strategyConfigs.length === 0) {
769
801
  return;
@@ -1170,7 +1202,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1170
1202
  paidAmount: netPaidAmount
1171
1203
  });
1172
1204
  const isOrderFullyPaid = orderExpectedAmount.lte(0) ? true : netPaidAmount.gte(orderExpectedAmount);
1173
- const paymentStage = this.isDepositOrder(tempOrder, depositAmount) && !isDepositFullyPaid ? "deposit" : "normal";
1205
+ const paymentStage = this.isDepositOrder(tempOrder, depositAmount) && !isDepositFullyPaid && !this.hasPaidNormalPayment(paymentList) ? "deposit" : "normal";
1174
1206
  return {
1175
1207
  isFullyPaid: isOrderFullyPaid,
1176
1208
  isOrderFullyPaid,
@@ -1191,12 +1223,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1191
1223
  return sum.plus(this.calculatePaymentGapAmount(paymentRecord));
1192
1224
  }, new import_decimal.default(0));
1193
1225
  }
1226
+ hasPaidNormalPayment(payments) {
1227
+ return (payments || []).some((payment) => {
1228
+ const paymentRecord = payment;
1229
+ if (!isPaidPaymentRecord(paymentRecord))
1230
+ return false;
1231
+ return paymentRecord.order_payment_type !== "deposit" && paymentRecord.type !== "deposit";
1232
+ });
1233
+ }
1194
1234
  resolveNextOrderPaymentType(tempOrder) {
1195
1235
  const depositAmount = new import_decimal.default(tempOrder.deposit_amount || "0.00");
1196
1236
  if (!this.isDepositOrder(tempOrder, depositAmount))
1197
1237
  return "normal";
1198
1238
  if (depositAmount.lte(0))
1199
1239
  return "normal";
1240
+ if (this.hasPaidNormalPayment(tempOrder.payments || []))
1241
+ return "normal";
1200
1242
  const depositPaidAmount = this.calculateDepositPaidAmount(tempOrder.payments || []);
1201
1243
  return depositPaidAmount.lt(depositAmount) ? "deposit" : "normal";
1202
1244
  }
@@ -1494,24 +1536,28 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1494
1536
  }
1495
1537
  }
1496
1538
  calculateSummaryAmountGap(params) {
1497
- const { tempOrder, summary, orderPaidAmount } = params;
1539
+ const { tempOrder, summary, orderPaidAmount, payments } = params;
1498
1540
  const refundAmount = this.getSummaryRefundAmount(summary);
1499
1541
  const netOrderPaidAmount = import_decimal.default.max(orderPaidAmount.minus(refundAmount), 0);
1500
1542
  const targetAmount = this.calculatePaymentTargetAmount(
1501
1543
  tempOrder,
1502
1544
  summary,
1503
- netOrderPaidAmount
1545
+ netOrderPaidAmount,
1546
+ payments
1504
1547
  );
1505
1548
  return targetAmount.minus(netOrderPaidAmount).toFixed(2);
1506
1549
  }
1507
1550
  getSummaryRefundAmount(summary) {
1508
1551
  return import_decimal.default.max(new import_decimal.default((summary == null ? void 0 : summary.total_refund_amount) || 0), 0);
1509
1552
  }
1510
- calculatePaymentTargetAmount(tempOrder, summary, paidAmount = new import_decimal.default(0)) {
1553
+ calculatePaymentTargetAmount(tempOrder, summary, paidAmount = new import_decimal.default(0), payments = tempOrder.payments || []) {
1511
1554
  const depositAmount = this.getDepositAmount(tempOrder, summary);
1512
1555
  if (!this.isDepositOrder(tempOrder, depositAmount)) {
1513
1556
  return this.getOrderExpectedAmount(summary);
1514
1557
  }
1558
+ if (this.hasPaidNormalPayment(payments)) {
1559
+ return this.getOrderExpectedAmount(summary);
1560
+ }
1515
1561
  if (this.isDepositCovered({ tempOrder, summary, paidAmount })) {
1516
1562
  return this.getOrderExpectedAmount(summary);
1517
1563
  }
@@ -1691,19 +1737,21 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1691
1737
  return snapshot;
1692
1738
  }
1693
1739
  isSnapshotPayableAmountUnchanged(tempOrder, snapshot, snapshotSummary) {
1694
- const currentPaidPaymentSummary = this.calculatePaidPaymentSummary(tempOrder.payments || []);
1740
+ const currentPayments = tempOrder.payments || [];
1741
+ const currentPaidPaymentSummary = this.calculatePaidPaymentSummary(currentPayments);
1695
1742
  const currentAmountGap = this.calculateSummaryAmountGap({
1696
1743
  tempOrder,
1697
1744
  summary: snapshotSummary,
1698
- orderPaidAmount: currentPaidPaymentSummary.gapPaidAmount
1745
+ orderPaidAmount: currentPaidPaymentSummary.gapPaidAmount,
1746
+ payments: currentPayments
1699
1747
  });
1700
- const snapshotPaidPaymentSummary = this.calculatePaidPaymentSummary(
1701
- Array.isArray(snapshot.payments) ? snapshot.payments : []
1702
- );
1748
+ const snapshotPayments = Array.isArray(snapshot.payments) ? snapshot.payments : [];
1749
+ const snapshotPaidPaymentSummary = this.calculatePaidPaymentSummary(snapshotPayments);
1703
1750
  const snapshotAmountGap = this.calculateSummaryAmountGap({
1704
1751
  tempOrder,
1705
1752
  summary: snapshotSummary,
1706
- orderPaidAmount: snapshotPaidPaymentSummary.gapPaidAmount
1753
+ orderPaidAmount: snapshotPaidPaymentSummary.gapPaidAmount,
1754
+ payments: snapshotPayments
1707
1755
  });
1708
1756
  return currentAmountGap === snapshotAmountGap;
1709
1757
  }
@@ -1745,6 +1793,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1745
1793
  const isPayableAmountUnchanged = this.isSnapshotPayableAmountUnchanged(tempOrder, snapshot, summary);
1746
1794
  if (!isPayableAmountUnchanged)
1747
1795
  return null;
1796
+ const currentPaidPaymentSummary = this.calculatePaidPaymentSummary(tempOrder.payments || []);
1797
+ summary.amount_gap = this.calculateSummaryAmountGap({
1798
+ tempOrder,
1799
+ summary,
1800
+ orderPaidAmount: currentPaidPaymentSummary.gapPaidAmount
1801
+ });
1748
1802
  if (Array.isArray(snapshot.products)) {
1749
1803
  tempOrder.products = (0, import_lodash_es.cloneDeep)(snapshot.products);
1750
1804
  }
@@ -1969,8 +2023,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1969
2023
  }
1970
2024
  sanitizeTempOrderProducts(tempOrder) {
1971
2025
  tempOrder.products = (tempOrder.products || []).map(
1972
- (product) => this.sanitizeOrderProductForTempOrder(product)
2026
+ (product) => this.sanitizeOrderProductForTempOrder(
2027
+ this.normalizeVirtualSettlementProductIfEnabled(product)
2028
+ )
1973
2029
  );
2030
+ this.syncTempOrderSettlementState(tempOrder);
1974
2031
  (0, import_discountProductLineIdentity.ensureUniqueProductLineUids)(tempOrder);
1975
2032
  }
1976
2033
  ensureExtend(tempOrder) {
@@ -2314,6 +2371,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2314
2371
  products: summaryProducts,
2315
2372
  isPriceIncludeTax: tempOrder.is_price_include_tax,
2316
2373
  shopDiscount: tempOrder.shop_discount,
2374
+ virtualSettlementMode: this.shouldUseVirtualSettlementSummary(tempOrder),
2317
2375
  ...((_a = this.otherParams) == null ? void 0 : _a.channel) ? { channel: this.otherParams.channel } : {}
2318
2376
  });
2319
2377
  if (shouldFullRecalculateFromSnapshot) {
@@ -2603,6 +2661,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2603
2661
  const nextCustomerId = tempOrder.customer_id ?? null;
2604
2662
  if (String(previousCustomerId ?? "") !== String(nextCustomerId ?? "")) {
2605
2663
  this.store.availableWalletIds = [];
2664
+ this.store.virtualCurrencyList = [];
2606
2665
  (0, import_utils.clearTempOrderHolderAssignments)(tempOrder);
2607
2666
  this.clearCustomerBoundDiscounts(tempOrder);
2608
2667
  this.applyDiscount();
@@ -2643,6 +2702,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2643
2702
  if (tempOrder._extend)
2644
2703
  delete tempOrder._extend.customerSnapshot;
2645
2704
  this.store.availableWalletIds = [];
2705
+ this.store.virtualCurrencyList = [];
2646
2706
  this.clearCustomerBoundDiscounts(tempOrder);
2647
2707
  this.applyDiscount();
2648
2708
  this.persistTempOrder();
@@ -2950,21 +3010,29 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2950
3010
  devicePrefix
2951
3011
  });
2952
3012
  }
2953
- async shouldMergeProductToOrder(params) {
3013
+ normalizeShouldMergeProductResult(result) {
3014
+ if (typeof result === "boolean")
3015
+ return result;
3016
+ if (result && typeof result === "object" && typeof result.shouldMerge === "boolean") {
3017
+ return result.shouldMerge;
3018
+ }
3019
+ return true;
3020
+ }
3021
+ shouldMergeProductToOrder(params) {
2954
3022
  var _a;
2955
3023
  const onBeforeMergeProductToOrder = (_a = this.orderHooks) == null ? void 0 : _a.onBeforeMergeProductToOrder;
2956
3024
  if (!onBeforeMergeProductToOrder)
2957
3025
  return true;
2958
- const result = await onBeforeMergeProductToOrder({
3026
+ const result = onBeforeMergeProductToOrder({
2959
3027
  ...params,
2960
3028
  defaultShouldMerge: true
2961
3029
  });
2962
- if (typeof result === "boolean")
2963
- return result;
2964
- if (result && typeof result === "object" && typeof result.shouldMerge === "boolean") {
2965
- return result.shouldMerge;
3030
+ if (result && typeof result === "object" && typeof result.then === "function") {
3031
+ return Promise.resolve(result).then(
3032
+ (resolved) => this.normalizeShouldMergeProductResult(resolved)
3033
+ );
2966
3034
  }
2967
- return true;
3035
+ return this.normalizeShouldMergeProductResult(result);
2968
3036
  }
2969
3037
  hasOrderProductLineNote(product) {
2970
3038
  return typeof (product == null ? void 0 : product.note) === "string" && product.note.trim().length > 0;
@@ -2980,6 +3048,101 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2980
3048
  const bookingUid = (product == null ? void 0 : product.booking_uid) ?? ((_a = product == null ? void 0 : product.metadata) == null ? void 0 : _a.booking_uid);
2981
3049
  return bookingUid !== void 0 && bookingUid !== null && String(bookingUid) !== "";
2982
3050
  }
3051
+ isMultiCurrencySettlementEnabled() {
3052
+ var _a;
3053
+ return ((_a = this.otherParams) == null ? void 0 : _a.enableMultiCurrencySettlement) === true;
3054
+ }
3055
+ isActiveVirtualSettlementOrder(tempOrder) {
3056
+ return this.isMultiCurrencySettlementEnabled() && (0, import_virtualSettlement.isVirtualSettlementOrder)(tempOrder);
3057
+ }
3058
+ shouldUseVirtualSettlementSummary(tempOrder) {
3059
+ var _a, _b;
3060
+ return this.isActiveVirtualSettlementOrder(tempOrder) || ((_b = (_a = tempOrder == null ? void 0 : tempOrder.metadata) == null ? void 0 : _a.currency_settlement_config) == null ? void 0 : _b.settlement_type) === "virtual_currency";
3061
+ }
3062
+ normalizeVirtualSettlementProductIfEnabled(product) {
3063
+ return this.isMultiCurrencySettlementEnabled() ? (0, import_virtualSettlement.normalizeVirtualSettlementOrderProduct)(product) : product;
3064
+ }
3065
+ assertAndLockProductSettlement(tempOrder, product) {
3066
+ if (!this.isMultiCurrencySettlementEnabled())
3067
+ return;
3068
+ const currentKey = (0, import_virtualSettlement.getTempOrderSettlementKey)(tempOrder);
3069
+ const incomingKey = (0, import_virtualSettlement.getSettlementKey)(
3070
+ (0, import_virtualSettlement.getSelectedSettlementSnapshot)(product)
3071
+ ) || "legal_currency";
3072
+ if (currentKey && currentKey !== incomingKey) {
3073
+ throw new import_virtualSettlement.OrderSettlementConflictError(currentKey, incomingKey);
3074
+ }
3075
+ const snapshot = (0, import_virtualSettlement.getSelectedSettlementSnapshot)(product);
3076
+ if ((snapshot == null ? void 0 : snapshot.settlement_type) === "virtual_currency" && tempOrder.customer_id && Number(tempOrder.customer_id) !== 1) {
3077
+ const currencyProductId = Number(snapshot.currency_product_id);
3078
+ const asset = (this.store.virtualCurrencyList || []).find(
3079
+ (item) => Number(item == null ? void 0 : item.product_id) === currencyProductId
3080
+ );
3081
+ if (!asset) {
3082
+ throw new import_virtualSettlement.VirtualCurrencyAssetNotFoundError(currencyProductId);
3083
+ }
3084
+ const existedAmount = tempOrder.products.reduce(
3085
+ (sum, item) => sum.plus(
3086
+ new import_decimal.default(item.selling_price || 0).times(item.num || 1)
3087
+ ),
3088
+ new import_decimal.default(0)
3089
+ );
3090
+ const requiredAmount = existedAmount.plus(
3091
+ new import_decimal.default(snapshot.price || 0).times(product.num || 1)
3092
+ );
3093
+ const balance = new import_decimal.default(asset.balance || 0);
3094
+ if (balance.lt(requiredAmount)) {
3095
+ throw new import_virtualSettlement.VirtualCurrencyBalanceError(
3096
+ balance.toFixed(2),
3097
+ requiredAmount.toFixed(2)
3098
+ );
3099
+ }
3100
+ }
3101
+ (0, import_virtualSettlement.applyTempOrderSettlementState)(
3102
+ tempOrder,
3103
+ snapshot || {
3104
+ settlement_type: "legal_currency",
3105
+ price: product.selling_price ?? product.original_price ?? product.payment_price ?? 0,
3106
+ unit_label: tempOrder.currency_code,
3107
+ symbol: tempOrder.currency_symbol,
3108
+ amount_format: tempOrder.currency_format
3109
+ }
3110
+ );
3111
+ }
3112
+ syncTempOrderSettlementState(tempOrder) {
3113
+ if (!this.isMultiCurrencySettlementEnabled())
3114
+ return;
3115
+ tempOrder.metadata = tempOrder.metadata || {};
3116
+ if (!tempOrder.products.length) {
3117
+ (0, import_virtualSettlement.releaseTempOrderSettlementState)(tempOrder);
3118
+ return;
3119
+ }
3120
+ const snapshot = (0, import_virtualSettlement.getTempOrderSettlementSnapshot)(tempOrder);
3121
+ if (snapshot) {
3122
+ (0, import_virtualSettlement.applyTempOrderSettlementState)(tempOrder, snapshot);
3123
+ return;
3124
+ }
3125
+ tempOrder.metadata.cart_settlement_key = "legal_currency";
3126
+ }
3127
+ prepareVirtualSettlementTempOrder(tempOrder) {
3128
+ if (!this.isMultiCurrencySettlementEnabled())
3129
+ return;
3130
+ this.syncTempOrderSettlementState(tempOrder);
3131
+ if (!this.isActiveVirtualSettlementOrder(tempOrder))
3132
+ return;
3133
+ tempOrder.products = (0, import_virtualSettlement.normalizeVirtualSettlementProducts)(tempOrder.products);
3134
+ tempOrder.discount_list = [];
3135
+ tempOrder.shop_discount = "0.00";
3136
+ tempOrder.surcharge_fee = "0.00";
3137
+ tempOrder.surcharges = [];
3138
+ const virtualOrder = tempOrder;
3139
+ virtualOrder.discount_amount = "0.00";
3140
+ virtualOrder.product_tax_fee = "0.00";
3141
+ virtualOrder.tax_fee = "0.00";
3142
+ virtualOrder.shipping_fee = "0.00";
3143
+ virtualOrder.shipping_tax_fee = "0.00";
3144
+ virtualOrder.tip_fee = "0.00";
3145
+ }
2983
3146
  // ─── TempOrder: 商品 CRUD ───
2984
3147
  /**
2985
3148
  * 预约商品加车后的统一收尾:促销、折扣、summary 重算与持久化(批量拆行时只调用一次)。
@@ -2989,13 +3152,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2989
3152
  */
2990
3153
  async finalizeProductOrderMutation(tempOrder, options) {
2991
3154
  this.syncTempOrderHolderFromBookings(tempOrder);
2992
- if (!(options == null ? void 0 : options.skipEditDiscountConfigRefresh)) {
3155
+ this.prepareVirtualSettlementTempOrder(tempOrder);
3156
+ const isVirtualSettlement = this.isActiveVirtualSettlementOrder(tempOrder);
3157
+ if (!(options == null ? void 0 : options.skipEditDiscountConfigRefresh) && !isVirtualSettlement) {
2993
3158
  await this.ensureEditDiscountConfigForProductChange(tempOrder);
2994
3159
  }
2995
- if (!(options == null ? void 0 : options.skipDiscountRecalculation)) {
3160
+ if (!(options == null ? void 0 : options.skipDiscountRecalculation) && !isVirtualSettlement) {
2996
3161
  await this.applyPromotion();
2997
3162
  }
2998
- if (!(options == null ? void 0 : options.skipDiscountRecalculation)) {
3163
+ if (!(options == null ? void 0 : options.skipDiscountRecalculation) && !isVirtualSettlement) {
2999
3164
  this.applyDiscount();
3000
3165
  }
3001
3166
  this.sanitizeTempOrderProducts(tempOrder);
@@ -3007,19 +3172,27 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3007
3172
  * 带 booking 且 num>1 时由 `addProductToOrder` 拆成多次本方法调用(每次 num=1)。
3008
3173
  *
3009
3174
  * @example
3010
- * await this.appendProductLineToTempOrder(tempOrder, { product_id: 1, num: 1 }, booking);
3175
+ * const pending = this.appendProductLineToTempOrder(
3176
+ * tempOrder,
3177
+ * { product_id: 1, num: 1 },
3178
+ * booking,
3179
+ * );
3180
+ * if (pending) await pending;
3011
3181
  */
3012
- async appendProductLineToTempOrder(tempOrder, product, booking, options) {
3013
- var _a, _b, _c, _d, _e, _f, _g;
3182
+ appendProductLineToTempOrder(tempOrder, product, booking, options) {
3183
+ var _a, _b, _c, _d, _e, _f;
3014
3184
  const linked = booking ? this.createLinkedProductAndBooking({ product, booking }) : null;
3015
3185
  const productToAdd = (linked == null ? void 0 : linked.product) || product;
3186
+ this.assertAndLockProductSettlement(tempOrder, productToAdd);
3016
3187
  const incomingFingerprint = (0, import_utils3.buildProductLineFingerprint)(
3017
3188
  (0, import_utils.getProductSkuOptions)(productToAdd),
3018
3189
  productToAdd.product_bundle
3019
3190
  );
3020
- const normalizedIncoming = (0, import_utils.mergeOrderProductDisplayFields)(
3021
- productToAdd,
3022
- (0, import_utils3.normalizeOrderProduct)(productToAdd)
3191
+ const normalizedIncoming = this.normalizeVirtualSettlementProductIfEnabled(
3192
+ (0, import_utils.mergeOrderProductDisplayFields)(
3193
+ productToAdd,
3194
+ (0, import_utils3.normalizeOrderProduct)(productToAdd)
3195
+ )
3023
3196
  );
3024
3197
  const isWeighingProduct = Number(((_a = normalizedIncoming.product_sku) == null ? void 0 : _a.open_sold_weight) || 0) === 1;
3025
3198
  const netWeight = Number((_b = normalizedIncoming.product_sku) == null ? void 0 : _b.net_weight);
@@ -3072,7 +3245,92 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3072
3245
  (0, import_utils.getProductSkuOptions)(matchedProduct),
3073
3246
  matchedProduct.product_bundle
3074
3247
  ) : "";
3075
- const shouldMerge = matchedProduct ? await this.shouldMergeProductToOrder({
3248
+ const commitProductLine = (shouldMerge2) => {
3249
+ var _a2;
3250
+ if (matchedIndex === -1 || !matchedProduct || !shouldMerge2) {
3251
+ this.captureProductRuntime(
3252
+ tempOrder,
3253
+ productToAdd,
3254
+ normalizedIncoming
3255
+ );
3256
+ if (linked) {
3257
+ normalizedIncoming.booking_uid = linked.bookingUid;
3258
+ normalizedIncoming.metadata = {
3259
+ ...normalizedIncoming.metadata || {},
3260
+ booking_uid: linked.bookingUid
3261
+ };
3262
+ }
3263
+ const insertAtIndex = options == null ? void 0 : options.insertAtIndex;
3264
+ if (Number.isInteger(insertAtIndex) && Number(insertAtIndex) >= 0 && Number(insertAtIndex) < tempOrder.products.length) {
3265
+ tempOrder.products = [
3266
+ ...tempOrder.products.slice(0, insertAtIndex),
3267
+ normalizedIncoming,
3268
+ ...tempOrder.products.slice(insertAtIndex)
3269
+ ];
3270
+ } else {
3271
+ tempOrder.products = [...tempOrder.products, normalizedIncoming];
3272
+ }
3273
+ } else {
3274
+ const targetProduct = matchedProduct;
3275
+ const targetUid = (_a2 = targetProduct.metadata) == null ? void 0 : _a2.unique_identification_number;
3276
+ const normalizedProduct = this.normalizeVirtualSettlementProductIfEnabled(
3277
+ (0, import_utils.mergeOrderProductDisplayFields)(
3278
+ targetProduct,
3279
+ (0, import_utils3.normalizeOrderProduct)({
3280
+ ...productToAdd,
3281
+ metadata: {
3282
+ ...productToAdd.metadata || {},
3283
+ unique_identification_number: targetUid
3284
+ }
3285
+ })
3286
+ )
3287
+ );
3288
+ normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
3289
+ normalizedProduct.discount_list
3290
+ );
3291
+ const nextNum = (0, import_utils3.getSafeProductNum)(targetProduct.num + normalizedProduct.num);
3292
+ tempOrder.products[matchedIndex] = {
3293
+ ...targetProduct,
3294
+ ...normalizedProduct,
3295
+ discount_list: normalizedProduct.discount_list,
3296
+ metadata: {
3297
+ ...targetProduct.metadata || {},
3298
+ ...normalizedProduct.metadata || {},
3299
+ unique_identification_number: targetUid
3300
+ },
3301
+ product_sku: {
3302
+ ...targetProduct.product_sku || { option: [] },
3303
+ ...normalizedProduct.product_sku || { option: [] },
3304
+ option: (0, import_utils.getProductSkuOptions)(normalizedProduct)
3305
+ },
3306
+ note: targetProduct.note,
3307
+ order_detail_id: targetProduct.order_detail_id,
3308
+ num: nextNum
3309
+ };
3310
+ this.captureProductRuntime(
3311
+ tempOrder,
3312
+ productToAdd,
3313
+ tempOrder.products[matchedIndex],
3314
+ targetUid
3315
+ );
3316
+ if (matchedIndex !== tempOrder.products.length - 1) {
3317
+ const mergedProduct = tempOrder.products[matchedIndex];
3318
+ tempOrder.products = [
3319
+ ...tempOrder.products.slice(0, matchedIndex),
3320
+ ...tempOrder.products.slice(matchedIndex + 1),
3321
+ mergedProduct
3322
+ ];
3323
+ }
3324
+ }
3325
+ if (linked) {
3326
+ tempOrder.bookings = [...tempOrder.bookings || [], linked.booking];
3327
+ }
3328
+ };
3329
+ if (!matchedProduct) {
3330
+ commitProductLine(false);
3331
+ return;
3332
+ }
3333
+ const shouldMerge = this.shouldMergeProductToOrder({
3076
3334
  incomingProduct: productToAdd,
3077
3335
  normalizedIncoming,
3078
3336
  matchedProduct,
@@ -3081,83 +3339,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3081
3339
  existedFingerprint,
3082
3340
  tempOrder,
3083
3341
  booking
3084
- }) : false;
3085
- if (matchedIndex === -1 || !matchedProduct || !shouldMerge) {
3086
- this.captureProductRuntime(
3087
- tempOrder,
3088
- productToAdd,
3089
- normalizedIncoming
3090
- );
3091
- if (linked) {
3092
- normalizedIncoming.booking_uid = linked.bookingUid;
3093
- normalizedIncoming.metadata = {
3094
- ...normalizedIncoming.metadata || {},
3095
- booking_uid: linked.bookingUid
3096
- };
3097
- }
3098
- const insertAtIndex = options == null ? void 0 : options.insertAtIndex;
3099
- if (Number.isInteger(insertAtIndex) && Number(insertAtIndex) >= 0 && Number(insertAtIndex) < tempOrder.products.length) {
3100
- tempOrder.products = [
3101
- ...tempOrder.products.slice(0, insertAtIndex),
3102
- normalizedIncoming,
3103
- ...tempOrder.products.slice(insertAtIndex)
3104
- ];
3105
- } else {
3106
- tempOrder.products = [...tempOrder.products, normalizedIncoming];
3107
- }
3108
- } else {
3109
- const targetProduct = matchedProduct;
3110
- const targetUid = (_g = targetProduct.metadata) == null ? void 0 : _g.unique_identification_number;
3111
- const normalizedProduct = (0, import_utils.mergeOrderProductDisplayFields)(
3112
- targetProduct,
3113
- (0, import_utils3.normalizeOrderProduct)({
3114
- ...productToAdd,
3115
- metadata: {
3116
- ...productToAdd.metadata || {},
3117
- unique_identification_number: targetUid
3118
- }
3119
- })
3120
- );
3121
- normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
3122
- normalizedProduct.discount_list
3123
- );
3124
- const nextNum = (0, import_utils3.getSafeProductNum)(targetProduct.num + normalizedProduct.num);
3125
- tempOrder.products[matchedIndex] = {
3126
- ...targetProduct,
3127
- ...normalizedProduct,
3128
- discount_list: normalizedProduct.discount_list,
3129
- metadata: {
3130
- ...targetProduct.metadata || {},
3131
- ...normalizedProduct.metadata || {},
3132
- unique_identification_number: targetUid
3133
- },
3134
- product_sku: {
3135
- ...targetProduct.product_sku || { option: [] },
3136
- ...normalizedProduct.product_sku || { option: [] },
3137
- option: (0, import_utils.getProductSkuOptions)(normalizedProduct)
3138
- },
3139
- note: targetProduct.note,
3140
- order_detail_id: targetProduct.order_detail_id,
3141
- num: nextNum
3142
- };
3143
- this.captureProductRuntime(
3144
- tempOrder,
3145
- productToAdd,
3146
- tempOrder.products[matchedIndex],
3147
- targetUid
3148
- );
3149
- if (matchedIndex !== tempOrder.products.length - 1) {
3150
- const mergedProduct = tempOrder.products[matchedIndex];
3151
- tempOrder.products = [
3152
- ...tempOrder.products.slice(0, matchedIndex),
3153
- ...tempOrder.products.slice(matchedIndex + 1),
3154
- mergedProduct
3155
- ];
3156
- }
3157
- }
3158
- if (linked) {
3159
- tempOrder.bookings = [...tempOrder.bookings || [], linked.booking];
3342
+ });
3343
+ if (shouldMerge && typeof shouldMerge === "object" && typeof shouldMerge.then === "function") {
3344
+ return Promise.resolve(shouldMerge).then(commitProductLine);
3160
3345
  }
3346
+ commitProductLine(shouldMerge);
3161
3347
  }
3162
3348
  /**
3163
3349
  * 添加商品行。带 booking 时强制独立行;num>1 时拆成多条 num=1 的 product+booking(对齐 BookingByStep / ticketBooking addService)。
@@ -3185,12 +3371,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3185
3371
  const singleLine = (0, import_lodash_es.cloneDeep)(productRecord);
3186
3372
  singleLine.num = 1;
3187
3373
  delete singleLine.product_quantity;
3188
- await this.appendProductLineToTempOrder(
3374
+ const appendResult2 = this.appendProductLineToTempOrder(
3189
3375
  tempOrder,
3190
3376
  singleLine,
3191
3377
  (0, import_lodash_es.cloneDeep)(booking),
3192
3378
  { insertAtIndex }
3193
3379
  );
3380
+ if (appendResult2)
3381
+ await appendResult2;
3194
3382
  if (insertAtIndex !== void 0)
3195
3383
  insertAtIndex += 1;
3196
3384
  }
@@ -3198,12 +3386,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3198
3386
  return tempOrder.products;
3199
3387
  }
3200
3388
  }
3201
- await this.appendProductLineToTempOrder(
3389
+ const appendResult = this.appendProductLineToTempOrder(
3202
3390
  tempOrder,
3203
3391
  product,
3204
3392
  booking,
3205
3393
  { insertAtIndex }
3206
3394
  );
3395
+ if (appendResult)
3396
+ await appendResult;
3207
3397
  await this.finalizeProductOrderMutation(tempOrder);
3208
3398
  this.logInfo("addProductToOrder success", {
3209
3399
  product_id: product.product_id,
@@ -3238,16 +3428,24 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3238
3428
  const singleLine = (0, import_lodash_es.cloneDeep)(productRecord);
3239
3429
  singleLine.num = 1;
3240
3430
  delete singleLine.product_quantity;
3241
- await this.appendProductLineToTempOrder(
3431
+ const appendResult2 = this.appendProductLineToTempOrder(
3242
3432
  tempOrder,
3243
3433
  singleLine,
3244
3434
  (0, import_lodash_es.cloneDeep)(booking)
3245
3435
  );
3436
+ if (appendResult2)
3437
+ await appendResult2;
3246
3438
  }
3247
3439
  continue;
3248
3440
  }
3249
3441
  }
3250
- await this.appendProductLineToTempOrder(tempOrder, product, booking);
3442
+ const appendResult = this.appendProductLineToTempOrder(
3443
+ tempOrder,
3444
+ product,
3445
+ booking
3446
+ );
3447
+ if (appendResult)
3448
+ await appendResult;
3251
3449
  }
3252
3450
  await this.finalizeProductOrderMutation(tempOrder, options);
3253
3451
  this.logInfo("addProductsToOrder success", {
@@ -3478,9 +3676,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3478
3676
  delete nextProduct.metadata.main_product_original_price;
3479
3677
  delete nextProduct.metadata.price_schema_version;
3480
3678
  }
3481
- let normalizedProduct = (0, import_utils.mergeOrderProductDisplayFields)(
3482
- nextProduct,
3483
- (0, import_utils3.normalizeOrderProduct)(nextProduct)
3679
+ let normalizedProduct = this.normalizeVirtualSettlementProductIfEnabled(
3680
+ (0, import_utils.mergeOrderProductDisplayFields)(
3681
+ nextProduct,
3682
+ (0, import_utils3.normalizeOrderProduct)(nextProduct)
3683
+ )
3484
3684
  );
3485
3685
  normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
3486
3686
  normalizedProduct.discount_list
@@ -3611,20 +3811,49 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3611
3811
  throw new Error("[Order] 目标商品不存在,无法更新数量");
3612
3812
  }
3613
3813
  const targetProduct = tempOrder.products[productIndex];
3614
- const normalizedProduct = (0, import_utils3.normalizeOrderProduct)({
3615
- ...targetProduct,
3616
- num: (0, import_utils3.getSafeProductNum)(num),
3617
- metadata: {
3618
- ...targetProduct.metadata || {},
3619
- unique_identification_number: ((_a = targetProduct.metadata) == null ? void 0 : _a.unique_identification_number) || unique_identification_number
3620
- }
3621
- });
3814
+ const normalizedProduct = this.normalizeVirtualSettlementProductIfEnabled(
3815
+ (0, import_utils3.normalizeOrderProduct)({
3816
+ ...targetProduct,
3817
+ num: (0, import_utils3.getSafeProductNum)(num),
3818
+ metadata: {
3819
+ ...targetProduct.metadata || {},
3820
+ unique_identification_number: ((_a = targetProduct.metadata) == null ? void 0 : _a.unique_identification_number) || unique_identification_number
3821
+ }
3822
+ })
3823
+ );
3622
3824
  normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
3623
3825
  normalizedProduct.discount_list
3624
3826
  );
3827
+ const settlementSnapshot = (0, import_virtualSettlement.getSelectedSettlementSnapshot)(normalizedProduct);
3828
+ if (this.isMultiCurrencySettlementEnabled() && (settlementSnapshot == null ? void 0 : settlementSnapshot.settlement_type) === "virtual_currency" && tempOrder.customer_id && Number(tempOrder.customer_id) !== 1) {
3829
+ const currencyProductId = Number(settlementSnapshot.currency_product_id);
3830
+ const asset = (this.store.virtualCurrencyList || []).find(
3831
+ (item) => Number(item == null ? void 0 : item.product_id) === currencyProductId
3832
+ );
3833
+ if (!asset) {
3834
+ throw new import_virtualSettlement.VirtualCurrencyAssetNotFoundError(currencyProductId);
3835
+ }
3836
+ const requiredAmount = tempOrder.products.reduce((sum, item, index) => {
3837
+ const current = index === productIndex ? normalizedProduct : item;
3838
+ const currentSnapshot = (0, import_virtualSettlement.getSelectedSettlementSnapshot)(current);
3839
+ return sum.plus(
3840
+ new import_decimal.default((currentSnapshot == null ? void 0 : currentSnapshot.price) || current.selling_price || 0).times(current.num || 1)
3841
+ );
3842
+ }, new import_decimal.default(0));
3843
+ const balance = new import_decimal.default(asset.balance || 0);
3844
+ if (balance.lt(requiredAmount)) {
3845
+ throw new import_virtualSettlement.VirtualCurrencyBalanceError(
3846
+ balance.toFixed(2),
3847
+ requiredAmount.toFixed(2)
3848
+ );
3849
+ }
3850
+ }
3625
3851
  tempOrder.products[productIndex] = normalizedProduct;
3626
- await this.applyPromotion();
3627
- this.applyDiscount();
3852
+ this.prepareVirtualSettlementTempOrder(tempOrder);
3853
+ if (!this.isActiveVirtualSettlementOrder(tempOrder)) {
3854
+ await this.applyPromotion();
3855
+ this.applyDiscount();
3856
+ }
3628
3857
  this.sanitizeTempOrderProducts(tempOrder);
3629
3858
  await this.recalculateSummary({ createIfMissing: true });
3630
3859
  this.persistTempOrder();
@@ -3781,6 +4010,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3781
4010
  const tempOrder = this.ensureTempOrder();
3782
4011
  tempOrder.products = [];
3783
4012
  tempOrder.bookings = [];
4013
+ (0, import_virtualSettlement.releaseTempOrderSettlementState)(tempOrder);
3784
4014
  this.syncTempOrderHolderFromBookings(tempOrder);
3785
4015
  if (tempOrder._extend && typeof tempOrder._extend === "object") {
3786
4016
  tempOrder._extend = {
@@ -3796,6 +4026,37 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3796
4026
  this.logInfo("clearOrderCartLines success", {});
3797
4027
  return tempOrder;
3798
4028
  }
4029
+ /**
4030
+ * 切换购物车结算单位时清理所有会影响新币种的订单状态,但保留当前客户。
4031
+ */
4032
+ async clearOrderForSettlementSwitch() {
4033
+ var _a, _b;
4034
+ const tempOrder = this.ensureTempOrder();
4035
+ tempOrder.products = [];
4036
+ tempOrder.bookings = [];
4037
+ tempOrder.discount_list = [];
4038
+ tempOrder.payments = [];
4039
+ tempOrder.refunds = [];
4040
+ tempOrder.shop_discount = "0.00";
4041
+ tempOrder.surcharges = [];
4042
+ (0, import_virtualSettlement.releaseTempOrderSettlementState)(tempOrder);
4043
+ this.syncTempOrderHolderFromBookings(tempOrder);
4044
+ if (tempOrder._extend && typeof tempOrder._extend === "object") {
4045
+ tempOrder._extend = {
4046
+ ...tempOrder._extend,
4047
+ productsByUid: {}
4048
+ };
4049
+ }
4050
+ await ((_a = this.store.discount) == null ? void 0 : _a.setDiscountList([]));
4051
+ await ((_b = this.store.discount) == null ? void 0 : _b.setOriginalDiscountList([]));
4052
+ this.hasActiveCustomerBoundDiscount = false;
4053
+ this.lastUnfulfilledPromotions = [];
4054
+ this.lastGiftActions = null;
4055
+ await this.recalculateSummary({ createIfMissing: true });
4056
+ this.persistTempOrder();
4057
+ this.logInfo("clearOrderForSettlementSwitch success", {});
4058
+ return tempOrder;
4059
+ }
3799
4060
  // ─── TempOrder: 提交 ───
3800
4061
  buildCurrentSubmitPayloadForLocalPrint(params) {
3801
4062
  var _a, _b, _c;
@@ -3886,6 +4147,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3886
4147
  async runSubmitTempOrder(params) {
3887
4148
  var _a, _b, _c, _d, _e;
3888
4149
  const tempOrder = this.ensureTempOrder();
4150
+ this.prepareVirtualSettlementTempOrder(tempOrder);
3889
4151
  const shouldConfirmPendingVoucherPayments = (params == null ? void 0 : params.confirmPendingVoucherPayments) !== false;
3890
4152
  const hasPaymentOverride = (params == null ? void 0 : params.payments) !== void 0;
3891
4153
  const preparedPaymentOverride = hasPaymentOverride ? this.prepareVoucherPaymentsForSubmit(
@@ -4846,8 +5108,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4846
5108
  delete row[`product_${"option"}_item`];
4847
5109
  if (!Array.isArray(row.product_bundle))
4848
5110
  row.product_bundle = [];
4849
- if (!row.metadata || typeof row.metadata !== "object")
4850
- row.metadata = {};
5111
+ row.metadata = row.metadata && typeof row.metadata === "object" ? { ...row.metadata } : {};
5112
+ delete row.bundle_edit;
5113
+ delete row.metadata.bundle_edit;
4851
5114
  if (row.booking_uid && !row.metadata.booking_uid) {
4852
5115
  row.metadata.booking_uid = row.booking_uid;
4853
5116
  }
@@ -4875,7 +5138,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4875
5138
  if (result.metadata)
4876
5139
  delete result.metadata.price_schema_version;
4877
5140
  const restored = (0, import_bundleDiscountHydration.restoreHydratedBundleDiscounts)(result, import_utils.normalizeOrderProductDiscountList);
4878
- return this.sanitizeOrderProductForTempOrder(restored);
5141
+ return this.sanitizeOrderProductForTempOrder(
5142
+ this.normalizeVirtualSettlementProductIfEnabled(restored)
5143
+ );
4879
5144
  }
4880
5145
  getLastOrderInfo() {
4881
5146
  var _a;