@pisell/pisellos 0.10.7 → 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 (124) 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/walletPass/evaluator.js +0 -2
  6. package/dist/model/strategy/adapter/walletPass/type.d.ts +5 -0
  7. package/dist/model/strategy/adapter/walletPass/utils.js +57 -26
  8. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +18 -12
  9. package/dist/modules/BookingContext/utils/productExtend.js +5 -9
  10. package/dist/modules/BookingContext/utils/timeSlices.js +24 -3
  11. package/dist/modules/Customer/index.d.ts +4 -0
  12. package/dist/modules/Customer/index.js +91 -59
  13. package/dist/modules/Customer/types.d.ts +2 -0
  14. package/dist/modules/Discount/index.d.ts +2 -0
  15. package/dist/modules/Discount/index.js +38 -5
  16. package/dist/modules/Discount/types.d.ts +11 -0
  17. package/dist/modules/Order/index.d.ts +32 -6
  18. package/dist/modules/Order/index.js +1165 -819
  19. package/dist/modules/Order/types.d.ts +32 -4
  20. package/dist/modules/Order/types.js +11 -0
  21. package/dist/modules/Order/utils/discountProductLineIdentity.d.ts +45 -0
  22. package/dist/modules/Order/utils/discountProductLineIdentity.js +227 -0
  23. package/dist/modules/Order/utils/virtualSettlement.d.ts +56 -0
  24. package/dist/modules/Order/utils/virtualSettlement.js +271 -0
  25. package/dist/modules/Order/utils.js +89 -48
  26. package/dist/modules/Payment/types.d.ts +2 -0
  27. package/dist/modules/Payment/utils.js +4 -1
  28. package/dist/modules/Payment/walletpass.d.ts +11 -0
  29. package/dist/modules/Payment/walletpass.js +235 -60
  30. package/dist/modules/Product/types.d.ts +23 -0
  31. package/dist/modules/ProductList/index.d.ts +15 -2
  32. package/dist/modules/ProductList/index.js +92 -13
  33. package/dist/modules/Rules/index.js +125 -52
  34. package/dist/modules/SalesSummary/index.d.ts +1 -0
  35. package/dist/modules/SalesSummary/index.js +4 -3
  36. package/dist/modules/SalesSummary/types.d.ts +1 -0
  37. package/dist/modules/SalesSummary/utils.d.ts +1 -0
  38. package/dist/modules/SalesSummary/utils.js +28 -2
  39. package/dist/server/index.d.ts +15 -0
  40. package/dist/server/index.js +894 -781
  41. package/dist/server/modules/order/index.d.ts +2 -0
  42. package/dist/server/modules/order/index.js +261 -96
  43. package/dist/server/modules/order/types.d.ts +1 -1
  44. package/dist/server/utils/small-ticket.js +2 -1
  45. package/dist/solution/BaseSales/index.d.ts +41 -7
  46. package/dist/solution/BaseSales/index.js +1405 -974
  47. package/dist/solution/BaseSales/utils/cartPromotion.js +26 -3
  48. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  49. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +79 -13
  50. package/dist/solution/BaseSales/utils.js +31 -20
  51. package/dist/solution/BookingByStep/index.d.ts +3 -3
  52. package/dist/solution/BookingTicket/index.d.ts +5 -1
  53. package/dist/solution/BookingTicket/index.js +221 -162
  54. package/dist/solution/BookingTicket/types.d.ts +3 -0
  55. package/dist/solution/BookingTicket/utils/addProductDecision.js +2 -1
  56. package/dist/solution/BookingTicket/utils/cartView.js +44 -32
  57. package/dist/solution/Sales/index.d.ts +1 -0
  58. package/dist/solution/Sales/index.js +16 -2
  59. package/dist/solution/ScanOrder/index.js +25 -64
  60. package/dist/solution/ScanOrder/utils.js +31 -20
  61. package/dist/solution/UnifiedBookingSales/index.d.ts +5 -4
  62. package/dist/solution/UnifiedBookingSales/index.js +51 -39
  63. package/lib/core/index.js +0 -1
  64. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
  65. package/lib/model/strategy/adapter/dataVariant/evaluator.js +170 -7
  66. package/lib/model/strategy/adapter/dataVariant/type.d.ts +25 -0
  67. package/lib/model/strategy/adapter/walletPass/evaluator.js +0 -2
  68. package/lib/model/strategy/adapter/walletPass/type.d.ts +5 -0
  69. package/lib/model/strategy/adapter/walletPass/utils.js +62 -11
  70. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +6 -1
  71. package/lib/modules/BookingContext/utils/productExtend.js +4 -3
  72. package/lib/modules/BookingContext/utils/timeSlices.js +18 -3
  73. package/lib/modules/Customer/index.d.ts +4 -0
  74. package/lib/modules/Customer/index.js +11 -0
  75. package/lib/modules/Customer/types.d.ts +2 -0
  76. package/lib/modules/Discount/index.d.ts +2 -0
  77. package/lib/modules/Discount/index.js +37 -3
  78. package/lib/modules/Discount/types.d.ts +11 -0
  79. package/lib/modules/Order/index.d.ts +32 -6
  80. package/lib/modules/Order/index.js +518 -148
  81. package/lib/modules/Order/types.d.ts +32 -4
  82. package/lib/modules/Order/utils/discountProductLineIdentity.d.ts +45 -0
  83. package/lib/modules/Order/utils/discountProductLineIdentity.js +170 -0
  84. package/lib/modules/Order/utils/virtualSettlement.d.ts +56 -0
  85. package/lib/modules/Order/utils/virtualSettlement.js +300 -0
  86. package/lib/modules/Order/utils.js +65 -21
  87. package/lib/modules/Payment/types.d.ts +2 -0
  88. package/lib/modules/Payment/utils.js +5 -1
  89. package/lib/modules/Payment/walletpass.d.ts +11 -0
  90. package/lib/modules/Payment/walletpass.js +198 -17
  91. package/lib/modules/Product/types.d.ts +23 -0
  92. package/lib/modules/ProductList/index.d.ts +15 -2
  93. package/lib/modules/ProductList/index.js +85 -3
  94. package/lib/modules/Rules/index.js +100 -20
  95. package/lib/modules/SalesSummary/index.d.ts +1 -0
  96. package/lib/modules/SalesSummary/index.js +10 -2
  97. package/lib/modules/SalesSummary/types.d.ts +1 -0
  98. package/lib/modules/SalesSummary/utils.d.ts +1 -0
  99. package/lib/modules/SalesSummary/utils.js +30 -2
  100. package/lib/server/index.d.ts +15 -0
  101. package/lib/server/index.js +105 -14
  102. package/lib/server/modules/order/index.d.ts +2 -0
  103. package/lib/server/modules/order/index.js +75 -5
  104. package/lib/server/modules/order/types.d.ts +1 -1
  105. package/lib/server/utils/small-ticket.js +1 -1
  106. package/lib/solution/BaseSales/index.d.ts +41 -7
  107. package/lib/solution/BaseSales/index.js +325 -39
  108. package/lib/solution/BaseSales/utils/cartPromotion.js +26 -2
  109. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  110. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +62 -12
  111. package/lib/solution/BaseSales/utils.js +29 -18
  112. package/lib/solution/BookingByStep/index.d.ts +3 -3
  113. package/lib/solution/BookingTicket/index.d.ts +5 -1
  114. package/lib/solution/BookingTicket/index.js +31 -6
  115. package/lib/solution/BookingTicket/types.d.ts +3 -0
  116. package/lib/solution/BookingTicket/utils/addProductDecision.js +2 -1
  117. package/lib/solution/BookingTicket/utils/cartView.js +43 -30
  118. package/lib/solution/Sales/index.d.ts +1 -0
  119. package/lib/solution/Sales/index.js +15 -3
  120. package/lib/solution/ScanOrder/index.js +17 -54
  121. package/lib/solution/ScanOrder/utils.js +29 -18
  122. package/lib/solution/UnifiedBookingSales/index.d.ts +5 -4
  123. package/lib/solution/UnifiedBookingSales/index.js +35 -26
  124. package/package.json +1 -1
@@ -705,7 +705,7 @@ function normalizeSubmitPlatform(platform) {
705
705
  return "H5";
706
706
  return value;
707
707
  }
708
- function formatSubmitOptionItems(options) {
708
+ function formatSubmitOptionItems(options, formatOptions = {}) {
709
709
  if (!Array.isArray(options))
710
710
  return [];
711
711
  return options.map((d) => {
@@ -716,8 +716,11 @@ function formatSubmitOptionItems(options) {
716
716
  option_group_id: d == null ? void 0 : d.option_group_id
717
717
  };
718
718
  const addPrice = (d == null ? void 0 : d.add_price) ?? (d == null ? void 0 : d.price);
719
- if (addPrice !== void 0)
719
+ if (formatOptions.virtualSettlementMode) {
720
+ option.add_price = 0;
721
+ } else if (addPrice !== void 0) {
720
722
  option.add_price = String(addPrice);
723
+ }
721
724
  delete option.price;
722
725
  return option;
723
726
  });
@@ -734,7 +737,7 @@ function toMoneyString(value) {
734
737
  return "0.00";
735
738
  return String(value);
736
739
  }
737
- function formatSubmitBundleItems(bundle) {
740
+ function formatSubmitBundleItems(bundle, formatOptions = {}) {
738
741
  if (!Array.isArray(bundle))
739
742
  return [];
740
743
  return bundle.map((b) => {
@@ -744,9 +747,9 @@ function formatSubmitBundleItems(bundle) {
744
747
  custom_product_bundle_map_id: _customProductBundleMapId,
745
748
  ...submitMetadata
746
749
  } = existedMetadata;
747
- const sellingPrice = getBundleSellingMagnitude(rawBundle).toFixed(2);
748
- const paymentPrice = rawBundle.bundle_payment_price !== void 0 && rawBundle.bundle_payment_price !== null && rawBundle.bundle_payment_price !== "" ? toMoneyString(rawBundle.bundle_payment_price) : sellingPrice;
749
- const priceValue = rawBundle.price ?? rawBundle.custom_price ?? rawBundle.bundle_selling_price;
750
+ const sellingPrice = formatOptions.virtualSettlementMode ? "0.00" : getBundleSellingMagnitude(rawBundle).toFixed(2);
751
+ const paymentPrice = formatOptions.virtualSettlementMode ? "0.00" : rawBundle.bundle_payment_price !== void 0 && rawBundle.bundle_payment_price !== null && rawBundle.bundle_payment_price !== "" ? toMoneyString(rawBundle.bundle_payment_price) : sellingPrice;
752
+ const priceValue = formatOptions.virtualSettlementMode ? 0 : rawBundle.price ?? rawBundle.custom_price ?? rawBundle.bundle_selling_price;
750
753
  const relationSurchargeIds = Array.isArray(rawBundle.relation_surcharge_ids) ? rawBundle.relation_surcharge_ids : Array.isArray(existedMetadata.relation_surcharge_ids) ? existedMetadata.relation_surcharge_ids : [];
751
754
  const surchargeFee = toMoneyString(
752
755
  rawBundle.surcharge_fee ?? existedMetadata.surcharge_fee
@@ -759,7 +762,7 @@ function formatSubmitBundleItems(bundle) {
759
762
  const bundleMapId = resolveSubmitBundleMapId(rawBundle);
760
763
  const hasSubmitBundleDiscounts = Array.isArray(rawBundle.discount_list) && rawBundle.discount_list.length > 0;
761
764
  return {
762
- is_charge_tax: rawBundle.is_charge_tax ?? 0,
765
+ is_charge_tax: formatOptions.virtualSettlementMode ? 0 : rawBundle.is_charge_tax ?? 0,
763
766
  bundle_variant_id: rawBundle.bundle_variant_id ?? 0,
764
767
  num,
765
768
  quantity: toBundleNumber(rawBundle.quantity ?? rawBundle.num, num),
@@ -770,7 +773,7 @@ function formatSubmitBundleItems(bundle) {
770
773
  price_type_ext: rawBundle.price_type_ext ?? rawBundle.custom_price_type_ext ?? "",
771
774
  bundle_selling_price: sellingPrice,
772
775
  bundle_payment_price: paymentPrice,
773
- option: formatSubmitOptionItems(rawBundle.option),
776
+ option: formatSubmitOptionItems(rawBundle.option, formatOptions),
774
777
  bundle_group_id: (rawBundle == null ? void 0 : rawBundle.bundle_group_id) ?? (rawBundle == null ? void 0 : rawBundle.group_id),
775
778
  bundle_id: (rawBundle == null ? void 0 : rawBundle.bundle_id) ?? (rawBundle == null ? void 0 : rawBundle.id),
776
779
  bundle_product_id: (rawBundle == null ? void 0 : rawBundle.bundle_product_id) ?? (rawBundle == null ? void 0 : rawBundle._bundle_product_id),
@@ -778,15 +781,15 @@ function formatSubmitBundleItems(bundle) {
778
781
  metadata: {
779
782
  ...submitMetadata,
780
783
  ...hasSubmitBundleDiscounts && bundleMapId !== void 0 ? { custom_product_bundle_map_id: bundleMapId } : {},
781
- surcharge_fee: surchargeFee,
782
- relation_surcharge_ids: relationSurchargeIds,
783
- product_discount_difference: productDiscountDifference
784
+ surcharge_fee: formatOptions.virtualSettlementMode ? "0.00" : surchargeFee,
785
+ relation_surcharge_ids: formatOptions.virtualSettlementMode ? [] : relationSurchargeIds,
786
+ product_discount_difference: formatOptions.virtualSettlementMode ? "" : productDiscountDifference
784
787
  }
785
788
  };
786
789
  });
787
790
  }
788
- function normalizeSubmitProduct(product) {
789
- var _a;
791
+ function normalizeSubmitProduct(product, formatOptions = {}) {
792
+ var _a, _b;
790
793
  const { unique_identification_number: _runtimeUid, ...submitProduct } = product;
791
794
  const {
792
795
  num,
@@ -801,6 +804,8 @@ function normalizeSubmitProduct(product) {
801
804
  delete productRest[`product_${"option"}_item`];
802
805
  const rawMetadata = submitProduct.metadata || {};
803
806
  const bookingUid = rawMetadata.booking_uid;
807
+ const hasProductBundle = Array.isArray(submitProduct.product_bundle) && submitProduct.product_bundle.length > 0;
808
+ const bundleEdit = submitProduct.bundle_edit ?? rawMetadata.bundle_edit ?? (hasProductBundle ? 0 : void 0);
804
809
  const cleanMetadata = {};
805
810
  if (rawMetadata.unique_identification_number) {
806
811
  cleanMetadata.unique_identification_number = rawMetadata.unique_identification_number;
@@ -818,8 +823,10 @@ function normalizeSubmitProduct(product) {
818
823
  "tax_fee_rounding_remainder",
819
824
  "relation_surcharge_ids",
820
825
  "discountable_flag",
826
+ "price_schema_version",
821
827
  "parent_unique_identification_number",
822
- "product_add_schedule_time"
828
+ "product_add_schedule_time",
829
+ "data_variant_ids"
823
830
  ];
824
831
  for (const key of priceMetaKeys) {
825
832
  if (rawMetadata[key] !== void 0) {
@@ -836,21 +843,54 @@ function normalizeSubmitProduct(product) {
836
843
  if (rawMetadata.holder_config !== void 0) {
837
844
  cleanMetadata.holder_config = rawMetadata.holder_config;
838
845
  }
846
+ const virtualPrice = toMoneyString(
847
+ ((_a = rawMetadata.selected_settlement_snapshot) == null ? void 0 : _a.price) ?? submitProduct.selling_price
848
+ );
849
+ if (formatOptions.virtualSettlementMode) {
850
+ Object.assign(cleanMetadata, {
851
+ source_product_price: virtualPrice,
852
+ main_product_original_price: virtualPrice,
853
+ main_product_selling_price: virtualPrice,
854
+ main_product_attached_bundle_selling_price: virtualPrice,
855
+ main_product_attached_bundle_payment_price: virtualPrice,
856
+ main_product_attached_bundle_surcharge_fee: "0.00",
857
+ main_product_attached_bundle_tax_fee: "0.00",
858
+ surcharge_rounding_remainder: "0.00",
859
+ tax_fee_rounding_remainder: "0.00",
860
+ relation_surcharge_ids: [],
861
+ average_discount_amount_rate: "1",
862
+ product_discount_difference: "",
863
+ discountable_flag: 0,
864
+ price_schema_version: 2
865
+ });
866
+ }
839
867
  const productSku = {
840
868
  ...submitProduct.product_sku && typeof submitProduct.product_sku === "object" ? submitProduct.product_sku : {},
841
- option: formatSubmitOptionItems((_a = submitProduct.product_sku) == null ? void 0 : _a.option)
869
+ option: formatSubmitOptionItems(
870
+ (_b = submitProduct.product_sku) == null ? void 0 : _b.option,
871
+ formatOptions
872
+ )
842
873
  };
843
874
  return {
844
875
  ...productRest,
876
+ ...formatOptions.virtualSettlementMode ? {
877
+ selling_price: virtualPrice,
878
+ original_price: virtualPrice,
879
+ is_charge_tax: 0
880
+ } : {},
845
881
  ...bookingUid ? { booking_uid: bookingUid } : {},
882
+ ...bundleEdit !== void 0 ? { bundle_edit: bundleEdit } : {},
846
883
  product_quantity: toBundleNumber(num ?? submitProduct.product_quantity, 1),
847
884
  product_sku: productSku,
848
- discount_list: collectSubmitProductDiscountList(submitProduct),
849
- product_bundle: formatSubmitBundleItems(submitProduct.product_bundle),
885
+ discount_list: formatOptions.virtualSettlementMode ? [] : collectSubmitProductDiscountList(submitProduct),
886
+ product_bundle: formatSubmitBundleItems(
887
+ submitProduct.product_bundle,
888
+ formatOptions
889
+ ),
850
890
  metadata: cleanMetadata,
851
891
  // 出站兼容:后端消费 payment_price 字段(行 composite 已减整单折扣均摊)。
852
892
  // 由整单折扣均摊层产出;缺省(无折扣)时与 selling_price 同义。
853
- payment_price: submitProduct.payment_price ?? submitProduct.selling_price
893
+ payment_price: formatOptions.virtualSettlementMode ? virtualPrice : submitProduct.payment_price ?? submitProduct.selling_price
854
894
  };
855
895
  }
856
896
  var SUBMIT_BOOKING_METADATA_WHITELIST = [
@@ -953,7 +993,7 @@ function createDefaultTempOrder(params) {
953
993
  };
954
994
  }
955
995
  function buildSubmitPayload(params) {
956
- var _a;
996
+ var _a, _b, _c;
957
997
  const {
958
998
  tempOrder,
959
999
  cacheId,
@@ -967,6 +1007,7 @@ function buildSubmitPayload(params) {
967
1007
  } = params;
968
1008
  const scheduleDate = tempOrder.schedule_date || tempOrder.created_at || formatDateTime(now);
969
1009
  const bookingUuid = (0, import_orderCollectionIdentity.createUuidV4)();
1010
+ const virtualSettlementMode = ((_b = (_a = tempOrder.metadata) == null ? void 0 : _a.currency_settlement_config) == null ? void 0 : _b.settlement_type) === "virtual_currency";
970
1011
  const {
971
1012
  _extend,
972
1013
  relation_id: _relationId,
@@ -990,7 +1031,7 @@ function buildSubmitPayload(params) {
990
1031
  } = tempOrder;
991
1032
  let submitType = type ?? tempOrder.type;
992
1033
  if (!submitType) {
993
- if ((_a = tempOrder == null ? void 0 : tempOrder.bookings) == null ? void 0 : _a.length) {
1034
+ if ((_c = tempOrder == null ? void 0 : tempOrder.bookings) == null ? void 0 : _c.length) {
994
1035
  submitType = "appointment_booking";
995
1036
  } else {
996
1037
  submitType = "virtual";
@@ -1038,12 +1079,15 @@ function buildSubmitPayload(params) {
1038
1079
  const {
1039
1080
  collect_pax: _collectPax,
1040
1081
  table_occupancy_duration: _tableOccupancyDuration,
1082
+ cart_settlement_key: _cartSettlementKey,
1083
+ cart_settlement_snapshot: _cartSettlementSnapshot,
1084
+ legal_currency_snapshot: _legalCurrencySnapshot,
1041
1085
  ...rest
1042
1086
  } = tempOrder.metadata || {};
1043
1087
  return { ...rest };
1044
1088
  })(),
1045
1089
  products: (tempOrder.products || []).map(
1046
- (product) => normalizeSubmitProduct(product)
1090
+ (product) => normalizeSubmitProduct(product, { virtualSettlementMode })
1047
1091
  )
1048
1092
  };
1049
1093
  if (!enhance)
@@ -486,6 +486,8 @@ export interface WalletPassPayment {
486
486
  importWalletAssetsSnapshot: (snapshot: WalletAssetsSnapshot) => WalletAssetsState;
487
487
  /** 设置单张钱包资产的选择状态并重新计算其实际抵扣额。 */
488
488
  selectWalletAsset: (assetId: WalletAssetId, options: SelectWalletAssetOptions) => WalletAssetsState;
489
+ /** 更新已选钱包资产的手动使用金额,并保持原有选择顺序重新计算。 */
490
+ updateWalletAssetAmount: (assetId: WalletAssetId, amount: number) => WalletAssetsState;
489
491
  /** 精确搜索钱包资产;仅当前券可用时自动选择。 */
490
492
  scanWalletAssetAsync: (code: string) => Promise<ScanWalletAssetResult>;
491
493
  /** 清空未确认的钱包资产选择。 */
@@ -34,7 +34,11 @@ var formatWalletPassList2PreparePayments = (list) => {
34
34
  const formatted = (list || []).map((item) => {
35
35
  return {
36
36
  voucher_id: item.id || 0,
37
- amount: Number(item.edit_current_amount || getAvailableMaxAmount(item)) || 0,
37
+ // 前端策略重算后的 actualDeduction 才是最终可同步金额;
38
+ // edit_current_amount 只是用户请求值,仍可能被策略和订单剩余金额裁剪。
39
+ amount: Number(
40
+ item.actualDeduction ?? item.edit_current_amount ?? getAvailableMaxAmount(item)
41
+ ) || 0,
38
42
  tag: item.tag || "",
39
43
  wallet_pass_usage_unit: item.wallet_pass_usage_unit || {},
40
44
  wallet_pass_use_value: item.wallet_pass_use_value || void 0
@@ -24,6 +24,11 @@ export declare class WalletPassPaymentImpl implements WalletPassPayment {
24
24
  private emitEvent;
25
25
  private publishWalletAssetsState;
26
26
  private recalculateWalletAssets;
27
+ /**
28
+ * 搜索接口只返回后端 Wallet Pass 数据,不包含前端策略 config。
29
+ * 在资产进入共享选择状态前补齐策略结果,避免增量重算回退到接口状态。
30
+ */
31
+ private formatSearchedWalletPaymentAssets;
27
32
  /** 获取当前缓存中所有支付类 Wallet 资产的扫码 code。 */
28
33
  private getSearchedWalletAssetCodes;
29
34
  /**
@@ -106,7 +111,13 @@ export declare class WalletPassPaymentImpl implements WalletPassPayment {
106
111
  getWalletAssetsState(): WalletAssetsState;
107
112
  exportWalletAssetsSnapshot(): WalletAssetsSnapshot;
108
113
  importWalletAssetsSnapshot(snapshot: WalletAssetsSnapshot): WalletAssetsState;
114
+ private updateWalletAssetEditAmountInCaches;
109
115
  selectWalletAsset(assetId: WalletAssetId, options: SelectWalletAssetOptions): WalletAssetsState;
116
+ /**
117
+ * 更新已选资产的手动金额。只允许在当前实际抵扣额内向下调整,
118
+ * 金额为 0 时沿用 legacy 行为取消选择。
119
+ */
120
+ updateWalletAssetAmount(assetId: WalletAssetId, amount: number): WalletAssetsState;
110
121
  scanWalletAssetAsync(code: string): Promise<ScanWalletAssetResult>;
111
122
  clearWalletAssetSelection(): WalletAssetsState;
112
123
  setCommittedWalletAssets(committedIds: WalletAssetId[], committedAssets?: any[]): WalletAssetsState;
@@ -52,6 +52,25 @@ function normalizeWalletAssetCode(code) {
52
52
  function getWalletAssetCodeKeys(asset) {
53
53
  return [asset == null ? void 0 : asset.code, asset == null ? void 0 : asset.encoded].map(normalizeWalletAssetCode).filter(Boolean);
54
54
  }
55
+ function withWalletAssetRecalculationBaseAmount(asset) {
56
+ const existingBaseAmount = Number(
57
+ asset == null ? void 0 : asset._wallet_asset_recalculation_base_amount
58
+ );
59
+ if (Number.isFinite(existingBaseAmount) && existingBaseAmount >= 0) {
60
+ return asset;
61
+ }
62
+ if (!["product_voucher", "gift_card"].includes(asset == null ? void 0 : asset.tag)) {
63
+ return asset;
64
+ }
65
+ const balanceParValue = Number(asset == null ? void 0 : asset.balance_par_value);
66
+ if (!Number.isFinite(balanceParValue) || balanceParValue < 0) {
67
+ return asset;
68
+ }
69
+ return {
70
+ ...asset,
71
+ _wallet_asset_recalculation_base_amount: balanceParValue
72
+ };
73
+ }
55
74
  function isWalletAssetAvailable(asset) {
56
75
  if (!asset)
57
76
  return false;
@@ -90,6 +109,16 @@ function mergeWalletAssets(...groups) {
90
109
  });
91
110
  return merged;
92
111
  }
112
+ function orderWalletAssetsByIds(assets, orderedIds) {
113
+ const assetByKey = new Map(
114
+ assets.map((asset) => [getWalletAssetKey(asset), asset])
115
+ );
116
+ const orderedKeys = new Set(orderedIds.map((id) => String(id)));
117
+ return [
118
+ ...orderedIds.map((id) => assetByKey.get(String(id))).filter((asset) => asset !== void 0),
119
+ ...assets.filter((asset) => !orderedKeys.has(getWalletAssetKey(asset)))
120
+ ];
121
+ }
93
122
  function createInitialWalletAssetsState() {
94
123
  return {
95
124
  status: "idle",
@@ -222,6 +251,42 @@ var WalletPassPaymentImpl = class {
222
251
  error: null
223
252
  });
224
253
  }
254
+ /**
255
+ * 搜索接口只返回后端 Wallet Pass 数据,不包含前端策略 config。
256
+ * 在资产进入共享选择状态前补齐策略结果,避免增量重算回退到接口状态。
257
+ */
258
+ formatSearchedWalletPaymentAssets(assets) {
259
+ var _a, _b, _c, _d;
260
+ if (!assets.length)
261
+ return assets;
262
+ const assetsWithRecalculationBase = assets.map(
263
+ withWalletAssetRecalculationBaseAmount
264
+ );
265
+ const evaluator = (_b = (_a = this.paymentModule.window) == null ? void 0 : _a.getWalletPassEvaluator) == null ? void 0 : _b.call(_a);
266
+ if (!(evaluator == null ? void 0 : evaluator.searchVoucherFormat))
267
+ return assetsWithRecalculationBase;
268
+ const hasCalculationProducts = this.walletAssetsCalculationContext.products.length > 0;
269
+ const products = hasCalculationProducts ? this.walletAssetsCalculationContext.products : ((_c = this.walletParams) == null ? void 0 : _c.products) || [];
270
+ const orderTotalAmount = Number(
271
+ hasCalculationProducts ? this.walletAssetsCalculationContext.orderTotalAmount : ((_d = this.walletParams) == null ? void 0 : _d.order_wait_pay_amount) || 0
272
+ );
273
+ try {
274
+ const formattedAssets = evaluator.searchVoucherFormat({
275
+ orderTotalAmount,
276
+ products,
277
+ vouchers: assetsWithRecalculationBase
278
+ });
279
+ return formattedAssets;
280
+ } catch (error) {
281
+ this.paymentModule.logWarning(
282
+ "[WalletPass] 搜索资产策略格式化失败,保留接口结果",
283
+ {
284
+ error: error instanceof Error ? error.message : String(error)
285
+ }
286
+ );
287
+ return assetsWithRecalculationBase;
288
+ }
289
+ }
225
290
  /** 获取当前缓存中所有支付类 Wallet 资产的扫码 code。 */
226
291
  getSearchedWalletAssetCodes() {
227
292
  const cachedAssets = this.searchResults.filter(isWalletPaymentAsset);
@@ -245,11 +310,23 @@ var WalletPassPaymentImpl = class {
245
310
  );
246
311
  if (searchedCodeKeys.size === 0)
247
312
  return cachedAssets;
313
+ const cachedAssetByCode = /* @__PURE__ */ new Map();
314
+ cachedAssets.forEach((item) => {
315
+ getWalletAssetCodeKeys(item).forEach((code) => {
316
+ cachedAssetByCode.set(code, item);
317
+ });
318
+ });
248
319
  const refreshedAssets = refreshedCandidates.filter(
249
320
  (item) => isWalletPaymentAsset(item) && searchedCodeKeys.has(
250
321
  String((item == null ? void 0 : item.code) || "").trim().toUpperCase()
251
322
  )
252
- );
323
+ ).map((item) => {
324
+ const cachedAsset = getWalletAssetCodeKeys(item).map((code) => cachedAssetByCode.get(code)).find(Boolean);
325
+ return withWalletAssetRecalculationBaseAmount({
326
+ ...cachedAsset,
327
+ ...item
328
+ });
329
+ });
253
330
  if (refreshedAssets.length > 0) {
254
331
  const replacedCodes = new Set(
255
332
  refreshedAssets.map(
@@ -321,6 +398,10 @@ var WalletPassPaymentImpl = class {
321
398
  payment_order_id
322
399
  };
323
400
  this.walletParams = walletParams;
401
+ this.walletAssetsCalculationContext = {
402
+ orderTotalAmount: Number(walletParams.order_wait_pay_amount || 0),
403
+ products: Array.isArray(walletParams.products) ? walletParams.products : []
404
+ };
324
405
  this.paymentModule.logInfo("[WalletPass] 钱包默认参数已生成并存储", {
325
406
  customer_id: walletParams.customer_id,
326
407
  holder_id: walletParams.holder_id,
@@ -472,7 +553,6 @@ var WalletPassPaymentImpl = class {
472
553
  vouchers: allList
473
554
  });
474
555
  const { recommended, transformList, noApplicableVoucher, recommendedAmount } = res;
475
- console.log(res, "resres12");
476
556
  this.walletRecommendList = recommended;
477
557
  this.walletInitData = {
478
558
  transformList,
@@ -535,8 +615,12 @@ var WalletPassPaymentImpl = class {
535
615
  const customerWalletPassList = Array.isArray(
536
616
  responseData == null ? void 0 : responseData.customer_wallet_pass_list
537
617
  ) ? responseData.customer_wallet_pass_list : [];
538
- const allList = mergeWalletAssets(
618
+ const orderedRecalculateList = orderWalletAssetsByIds(
539
619
  recalculateList,
620
+ selectedIds
621
+ );
622
+ const allList = mergeWalletAssets(
623
+ orderedRecalculateList,
540
624
  customerWalletPassList
541
625
  );
542
626
  const walletPassEvaluator = (_b = (_a = this.paymentModule.window) == null ? void 0 : _a.getWalletPassEvaluator) == null ? void 0 : _b.call(_a);
@@ -552,7 +636,7 @@ var WalletPassPaymentImpl = class {
552
636
  )
553
637
  };
554
638
  const returnedSelectedKeys = new Set(
555
- recalculateList.filter(isWalletAssetAvailable).map((item) => getWalletAssetKey(item))
639
+ allList.map((item) => getWalletAssetKey(item))
556
640
  );
557
641
  const authoritativeSelectedIds = selectedIds.filter(
558
642
  (id) => returnedSelectedKeys.has(String(id))
@@ -830,6 +914,17 @@ var WalletPassPaymentImpl = class {
830
914
  const assetId = getWalletAssetId(asset);
831
915
  return assetId !== void 0 && assetId !== null && selectionSources[String(assetId)] === "scan";
832
916
  }) : [];
917
+ const manualEditAmountByKey = /* @__PURE__ */ new Map();
918
+ if (preserveSelection) {
919
+ this.walletAssetsState.selectedItems.forEach((asset) => {
920
+ if (typeof (asset == null ? void 0 : asset.edit_current_amount) !== "number")
921
+ return;
922
+ manualEditAmountByKey.set(
923
+ getWalletAssetKey(asset),
924
+ asset.edit_current_amount
925
+ );
926
+ });
927
+ }
833
928
  if (!((_a = businessData.products) == null ? void 0 : _a.length)) {
834
929
  this.queuePendingAutoSelectForAssets(scanSelectedAssets);
835
930
  this.generateWalletParams(businessData);
@@ -928,12 +1023,16 @@ var WalletPassPaymentImpl = class {
928
1023
  searchedWalletAssets,
929
1024
  result.transformList || [],
930
1025
  result.noApplicableVoucher || []
931
- ).map((asset) => ({
932
- ...asset,
933
- _wallet_asset_recommended: recommendedKeys.has(
934
- getWalletAssetKey(asset)
935
- )
936
- }));
1026
+ ).map((asset) => {
1027
+ const assetKey = getWalletAssetKey(asset);
1028
+ return {
1029
+ ...asset,
1030
+ ...manualEditAmountByKey.has(assetKey) ? {
1031
+ edit_current_amount: manualEditAmountByKey.get(assetKey)
1032
+ } : {},
1033
+ _wallet_asset_recommended: recommendedKeys.has(assetKey)
1034
+ };
1035
+ });
937
1036
  const latestSelectedIds = preserveSelection ? authoritativeSelectedIds : [];
938
1037
  const latestSelectionSources = preserveSelection ? { ...this.walletAssetsState.selectionSources } : {};
939
1038
  const pendingAutoSelectAssets = this.walletAssetsBehavior.autoSelectAfterSearch ? items.filter(
@@ -1047,6 +1146,13 @@ var WalletPassPaymentImpl = class {
1047
1146
  selectionSources: snapshot.state.selectionSources || {}
1048
1147
  });
1049
1148
  }
1149
+ updateWalletAssetEditAmountInCaches(assetKey, amount) {
1150
+ const updateAsset = (asset) => getWalletAssetKey(asset) === assetKey ? { ...asset, edit_current_amount: amount } : asset;
1151
+ this.searchResults = this.searchResults.map(
1152
+ updateAsset
1153
+ );
1154
+ return this.walletAssetsState.items.map(updateAsset);
1155
+ }
1050
1156
  selectWalletAsset(assetId, options) {
1051
1157
  const assetKey = String(assetId);
1052
1158
  const asset = this.walletAssetsState.items.find(
@@ -1062,6 +1168,7 @@ var WalletPassPaymentImpl = class {
1062
1168
  );
1063
1169
  const selectionSources = { ...this.walletAssetsState.selectionSources };
1064
1170
  delete selectionSources[assetKey];
1171
+ let nextItems = this.walletAssetsState.items;
1065
1172
  if (options.selected) {
1066
1173
  if (!asset || !isWalletAssetAvailable(asset)) {
1067
1174
  return this.getWalletAssetsState();
@@ -1070,9 +1177,13 @@ var WalletPassPaymentImpl = class {
1070
1177
  selectionSources[assetKey] = options.source || "manual";
1071
1178
  } else if (asset) {
1072
1179
  this.clearPendingAutoSelectForAsset(asset);
1180
+ nextItems = this.updateWalletAssetEditAmountInCaches(
1181
+ assetKey,
1182
+ void 0
1183
+ );
1073
1184
  }
1074
1185
  const nextState = this.recalculateWalletAssets(
1075
- this.walletAssetsState.items,
1186
+ nextItems,
1076
1187
  selectedIds,
1077
1188
  selectionSources
1078
1189
  );
@@ -1081,6 +1192,54 @@ var WalletPassPaymentImpl = class {
1081
1192
  }
1082
1193
  return nextState;
1083
1194
  }
1195
+ /**
1196
+ * 更新已选资产的手动金额。只允许在当前实际抵扣额内向下调整,
1197
+ * 金额为 0 时沿用 legacy 行为取消选择。
1198
+ */
1199
+ updateWalletAssetAmount(assetId, amount) {
1200
+ const assetKey = String(assetId);
1201
+ const committedKeys = new Set(
1202
+ this.walletAssetsState.committedIds.map((id) => String(id))
1203
+ );
1204
+ const selectedKeys = new Set(
1205
+ this.walletAssetsState.selectedIds.map((id) => String(id))
1206
+ );
1207
+ const asset = this.walletAssetsState.items.find(
1208
+ (item) => getWalletAssetKey(item) === assetKey
1209
+ );
1210
+ const requestedAmount = Number(amount);
1211
+ if (!asset || committedKeys.has(assetKey) || !selectedKeys.has(assetKey) || !Number.isFinite(requestedAmount) || requestedAmount < 0) {
1212
+ return this.getWalletAssetsState();
1213
+ }
1214
+ const selectedIds = [...this.walletAssetsState.selectedIds];
1215
+ const selectionSources = { ...this.walletAssetsState.selectionSources };
1216
+ if (requestedAmount === 0) {
1217
+ const nextItems2 = this.updateWalletAssetEditAmountInCaches(
1218
+ assetKey,
1219
+ void 0
1220
+ );
1221
+ delete selectionSources[assetKey];
1222
+ this.clearPendingAutoSelectForAsset(asset);
1223
+ return this.recalculateWalletAssets(
1224
+ nextItems2,
1225
+ selectedIds.filter((id) => String(id) !== assetKey),
1226
+ selectionSources
1227
+ );
1228
+ }
1229
+ const currentDeductionAmount = getWalletAssetDeductionAmount(asset);
1230
+ const editAmount = Math.min(requestedAmount, currentDeductionAmount);
1231
+ if (editAmount <= 0)
1232
+ return this.getWalletAssetsState();
1233
+ const nextItems = this.updateWalletAssetEditAmountInCaches(
1234
+ assetKey,
1235
+ editAmount
1236
+ );
1237
+ return this.recalculateWalletAssets(
1238
+ nextItems,
1239
+ selectedIds,
1240
+ selectionSources
1241
+ );
1242
+ }
1084
1243
  async scanWalletAssetAsync(code) {
1085
1244
  const normalizedCode = String(code || "").trim();
1086
1245
  if (!normalizedCode) {
@@ -1109,7 +1268,15 @@ var WalletPassPaymentImpl = class {
1109
1268
  this.walletAssetsState.selectedItems
1110
1269
  )
1111
1270
  });
1112
- const paymentAssets = result.data.filter(isWalletPaymentAsset);
1271
+ const paymentAssets = this.formatSearchedWalletPaymentAssets(
1272
+ result.data.filter(isWalletPaymentAsset)
1273
+ );
1274
+ if (paymentAssets.length > 0) {
1275
+ this.searchResults = mergeWalletAssets(
1276
+ this.searchResults,
1277
+ paymentAssets
1278
+ );
1279
+ }
1113
1280
  const asset = paymentAssets.find(
1114
1281
  (item) => String((item == null ? void 0 : item.code) || "") === normalizedCode
1115
1282
  ) || paymentAssets[0];
@@ -1128,30 +1295,44 @@ var WalletPassPaymentImpl = class {
1128
1295
  this.walletAssetsState.selectionSources
1129
1296
  );
1130
1297
  const assetId = getWalletAssetId(asset);
1131
- const selected = this.walletAssetsBehavior.autoSelectAfterSearch && assetId !== void 0 && isWalletAssetAvailable(asset) ? this.selectWalletAsset(assetId, {
1298
+ const recalculatedAsset = assetId === void 0 ? void 0 : recalculatedState.items.find(
1299
+ (item) => getWalletAssetKey(item) === String(assetId)
1300
+ );
1301
+ const selected = this.walletAssetsBehavior.autoSelectAfterSearch && assetId !== void 0 && isWalletAssetAvailable(recalculatedAsset) ? this.selectWalletAsset(assetId, {
1132
1302
  selected: true,
1133
1303
  source: "scan"
1134
1304
  }) : recalculatedState;
1135
1305
  const isSelected = assetId !== void 0 && selected.selectedIds.some((id) => String(id) === String(assetId));
1306
+ const selectedStateAsset = assetId === void 0 ? void 0 : selected.items.find(
1307
+ (item) => getWalletAssetKey(item) === String(assetId)
1308
+ );
1309
+ const resolvedAsset = selectedStateAsset || recalculatedAsset || asset;
1136
1310
  if (isSelected) {
1137
- this.clearPendingAutoSelectForAsset(asset);
1311
+ this.clearPendingAutoSelectForAsset(resolvedAsset);
1138
1312
  } else if (this.walletAssetsBehavior.autoSelectAfterSearch) {
1139
1313
  this.pendingAutoSelectSearchCodes.add(
1140
1314
  normalizeWalletAssetCode(normalizedCode)
1141
1315
  );
1142
- this.queuePendingAutoSelectForAssets([asset]);
1316
+ this.queuePendingAutoSelectForAssets([resolvedAsset]);
1143
1317
  }
1144
1318
  return {
1145
1319
  type: result.type,
1146
- asset,
1320
+ asset: resolvedAsset,
1147
1321
  selected: isSelected,
1148
1322
  state: selected
1149
1323
  };
1150
1324
  }
1151
1325
  clearWalletAssetSelection() {
1152
1326
  this.pendingAutoSelectSearchCodes.clear();
1327
+ const selectedKeys = new Set(
1328
+ this.walletAssetsState.selectedIds.map((id) => String(id))
1329
+ );
1330
+ const clearSelectedEditAmount = (asset) => selectedKeys.has(getWalletAssetKey(asset)) ? { ...asset, edit_current_amount: void 0 } : asset;
1331
+ this.searchResults = this.searchResults.map(
1332
+ clearSelectedEditAmount
1333
+ );
1153
1334
  return this.recalculateWalletAssets(
1154
- this.walletAssetsState.items,
1335
+ this.walletAssetsState.items.map(clearSelectedEditAmount),
1155
1336
  [],
1156
1337
  {}
1157
1338
  );
@@ -23,12 +23,25 @@ export interface ProductDataVariant {
23
23
  module_data_id: number;
24
24
  /** 关联 data_variant_rule.id */
25
25
  data_variant_rule_id: number;
26
+ /** 多货币结算等业务类型 */
27
+ business_type?: 'multi_currency_settlement' | string;
28
+ /** 数据状态;多货币结算仅处理 enable 记录 */
29
+ status?: 'enable' | 'disable' | string;
26
30
  /** 命中策略后覆盖到商品上的字段 */
27
31
  data: Record<string, any>;
28
32
  created_at: string | null;
29
33
  updated_at: string | null;
30
34
  deleted_at: string | null;
31
35
  }
36
+ export interface ProductSettlementOption extends Record<string, any> {
37
+ settlement_type: 'legal_currency' | 'virtual_currency' | string;
38
+ currency_product_id?: number;
39
+ price: string;
40
+ data_variant_id?: number;
41
+ data_variant_rule_id: number | string;
42
+ available: boolean;
43
+ disabled_reason?: string;
44
+ }
32
45
  /**
33
46
  * 商品基本信息接口
34
47
  */
@@ -61,6 +74,8 @@ export interface ProductData {
61
74
  sum_stock: number;
62
75
  /** 商品价格 */
63
76
  price: string;
77
+ /** 当前上下文解析出的可选结算货币 */
78
+ available_settlement_options?: ProductSettlementOption[];
64
79
  /** 商品原价 */
65
80
  original_price: string;
66
81
  /** 商品成本价 */
@@ -237,6 +252,14 @@ export interface ProductData {
237
252
  option_group_count: number;
238
253
  /** 智能定价变体列表,/product/query with dataVariants 返回 */
239
254
  data_variants?: ProductDataVariant[];
255
+ /**
256
+ * 商品接口规则计算结果;data_variant_ids 按优先级从高到低排列。
257
+ * 空数组表示规则已经计算完成但没有命中 Data Variant。
258
+ */
259
+ metadata?: {
260
+ data_variant_ids?: Array<number | string>;
261
+ [key: string]: any;
262
+ };
240
263
  /** 服务时长 */
241
264
  service_times?: any;
242
265
  }