@pisell/pisellos 2.2.276 → 2.2.277

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.
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 1 | 2 | 3 | 6 | 4 | 5;
314
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;
package/lib/core/index.js CHANGED
@@ -50,7 +50,6 @@ var PisellOSCore = class {
50
50
  this.serverOptions = options.server;
51
51
  }
52
52
  this.initialize(options);
53
- console.log("constructor1234");
54
53
  }
55
54
  initialize(options) {
56
55
  if (options == null ? void 0 : options.plugins) {
@@ -1,51 +0,0 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
-
29
- // src/model/strategy/adapter/promotion/index.ts
30
- var promotion_exports = {};
31
- __export(promotion_exports, {
32
- BUY_X_GET_Y_FREE_STRATEGY: () => import_examples.BUY_X_GET_Y_FREE_STRATEGY,
33
- ITEM_REWARD_STRATEGY: () => import_examples.ITEM_REWARD_STRATEGY,
34
- PromotionAdapter: () => import_adapter.PromotionAdapter,
35
- PromotionEvaluator: () => import_evaluator.PromotionEvaluator,
36
- X_ITEMS_FOR_Y_PRICE_STRATEGY: () => import_examples.X_ITEMS_FOR_Y_PRICE_STRATEGY,
37
- default: () => import_adapter2.default
38
- });
39
- module.exports = __toCommonJS(promotion_exports);
40
- var import_evaluator = require("./evaluator");
41
- var import_adapter = require("./adapter");
42
- var import_adapter2 = __toESM(require("./adapter"));
43
- var import_examples = require("./examples");
44
- // Annotate the CommonJS export names for ESM import in node:
45
- 0 && (module.exports = {
46
- BUY_X_GET_Y_FREE_STRATEGY,
47
- ITEM_REWARD_STRATEGY,
48
- PromotionAdapter,
49
- PromotionEvaluator,
50
- X_ITEMS_FOR_Y_PRICE_STRATEGY
51
- });
@@ -214,7 +214,6 @@ var WalletPassEvaluator = class {
214
214
  }
215
215
  const rawText = this.getText(reasonCode);
216
216
  const currency = failedField && AMOUNT_FIELDS.has(failedField) ? ((_g = (_f = this.otherParams) == null ? void 0 : _f.getData) == null ? void 0 : _g.call(_f, "shop_symbol")) || "" : "";
217
- console.log(currency, "currency12345");
218
217
  const reason = thresholdValue !== void 0 ? formatReason(rawText, thresholdValue, currency) : rawText;
219
218
  results.push({
220
219
  voucher,
@@ -416,7 +415,6 @@ var WalletPassEvaluator = class {
416
415
  * 计算适用商品的总金额和数量
417
416
  */
418
417
  calculateApplicableProducts(products, applicableProductIds, deductTaxAndFee) {
419
- console.log(products, "products1234");
420
418
  let total = 0;
421
419
  let count = 0;
422
420
  if (applicableProductIds !== null && applicableProductIds.length === 0) {
@@ -26,6 +26,11 @@ export interface Voucher {
26
26
  recommended_usage_amount: number;
27
27
  /** 后端计算推荐使用金额(仅商品) 不包含税费附加费 */
28
28
  recommended_pure_product_usage_amount: number;
29
+ /**
30
+ * 扫码资产自身可供前端重新计算的金额基准。
31
+ * 后端 recommended_usage_amount 会包含当前已选券上下文,取消勾选后不能继续把它当作资产永久上限。
32
+ */
33
+ _wallet_asset_recalculation_base_amount?: number;
29
34
  /** 实际抵扣金额 */
30
35
  actualDeduction: number;
31
36
  /** 抵扣详情 */
@@ -43,6 +43,21 @@ __export(utils_exports, {
43
43
  });
44
44
  module.exports = __toCommonJS(utils_exports);
45
45
  var import_decimal = __toESM(require("decimal.js"));
46
+ var DEFAULT_WALLET_PASS_CALCULATION_CONFIG = {
47
+ maxDeductionAmount: 99999,
48
+ maxUsagePerOrder: 0,
49
+ allowCrossProduct: true,
50
+ applicableProductLimit: 0,
51
+ deductTaxAndFee: true,
52
+ maxPassesPerItem: 0,
53
+ deductOptionPrice: false
54
+ };
55
+ function getWalletPassCalculationConfig(voucher) {
56
+ return {
57
+ ...DEFAULT_WALLET_PASS_CALCULATION_CONFIG,
58
+ ...(voucher == null ? void 0 : voucher.config) || {}
59
+ };
60
+ }
46
61
  var getProductQuantity = (product) => {
47
62
  return product.quantity || product.product_quantity || 1;
48
63
  };
@@ -105,9 +120,15 @@ function applyMaxPassUsageIncrements(usageMap, walletPassProductId, maxPassesPer
105
120
  });
106
121
  }
107
122
  var getRecommendedAmount = (voucher) => {
108
- console.log("voucher312", voucher);
109
123
  const { config, recommended_usage_amount, recommended_pure_product_usage_amount } = voucher;
110
124
  const deductTaxAndFee = (config == null ? void 0 : config.deductTaxAndFee) ?? true;
125
+ const rawRecalculationBaseAmount = voucher._wallet_asset_recalculation_base_amount;
126
+ if (rawRecalculationBaseAmount !== void 0 && rawRecalculationBaseAmount !== null) {
127
+ const recalculationBaseAmount = Number(rawRecalculationBaseAmount);
128
+ if (Number.isFinite(recalculationBaseAmount) && recalculationBaseAmount >= 0) {
129
+ return recalculationBaseAmount;
130
+ }
131
+ }
111
132
  return deductTaxAndFee ? recommended_usage_amount : recommended_pure_product_usage_amount ?? recommended_usage_amount;
112
133
  };
113
134
  var getApplicableProductIds = (voucher) => {
@@ -145,7 +166,6 @@ var getApplicableProducts = (voucher, productsData) => {
145
166
  return productsData.filter((p) => applicableProductIds.includes(p.product_id));
146
167
  };
147
168
  function processVouchers(applicableVouchers, orderTotalAmount, products) {
148
- console.log(products, "products123");
149
169
  const productsCopy = expandProductsWithBundleItems(products, true);
150
170
  let remainingOrderAmount = new import_decimal.default(orderTotalAmount);
151
171
  const getItemPassUsage = (usageMap, walletPassProductId, lineKey) => {
@@ -218,7 +238,7 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
218
238
  return import_decimal.default.min(baseAmount, finalApplicableAmount, remainingOrderAmount);
219
239
  };
220
240
  const isVoucherAvailable = (voucher, productsData, usedVoucherCounts2, itemPassUsage) => {
221
- const { config, id, product_id } = voucher;
241
+ const { config, product_id } = voucher;
222
242
  const recommendedAmount = getRecommendedAmount(voucher);
223
243
  if (recommendedAmount <= 0) {
224
244
  return { isAvailable: false, reasonCode: "not_meet_the_required_conditions" };
@@ -453,6 +473,7 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
453
473
  const productsForCalc = expandProductsWithBundleItems(products, true);
454
474
  let remainingOrderAmount = new import_decimal.default(orderTotalAmount);
455
475
  const selectedWithDetails = [];
476
+ const usedVoucherCounts = /* @__PURE__ */ new Map();
456
477
  const itemPassUsageMap = /* @__PURE__ */ new Map();
457
478
  const getItemPassUsageRecalc = (walletPassProductId, lineKey) => {
458
479
  var _a;
@@ -469,8 +490,29 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
469
490
  });
470
491
  };
471
492
  selectedVouchers.forEach((selectedVoucher) => {
472
- const { config, id } = selectedVoucher;
473
- const { maxDeductionAmount, allowCrossProduct, applicableProductLimit, deductTaxAndFee = true, maxPassesPerItem = 0 } = config;
493
+ const { product_id } = selectedVoucher;
494
+ const config = getWalletPassCalculationConfig(selectedVoucher);
495
+ const {
496
+ maxDeductionAmount,
497
+ maxUsagePerOrder,
498
+ allowCrossProduct,
499
+ applicableProductLimit,
500
+ deductTaxAndFee,
501
+ maxPassesPerItem
502
+ } = config;
503
+ const usedCount = usedVoucherCounts.get(product_id) || 0;
504
+ if (maxUsagePerOrder > 0 && usedCount >= maxUsagePerOrder) {
505
+ selectedWithDetails.push({
506
+ ...selectedVoucher,
507
+ config,
508
+ actualDeduction: 0,
509
+ deductionDetails: [],
510
+ _available_max_amount: 0,
511
+ _unified_available_status: 0,
512
+ reasonCode: "usage_limit_reached"
513
+ });
514
+ return;
515
+ }
474
516
  const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
475
517
  const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
476
518
  let applicableProducts = getApplicableProducts(
@@ -481,6 +523,7 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
481
523
  if (applicableProducts.length === 0) {
482
524
  selectedWithDetails.push({
483
525
  ...selectedVoucher,
526
+ config,
484
527
  actualDeduction: 0,
485
528
  deductionDetails: [],
486
529
  _available_max_amount: 0,
@@ -558,6 +601,7 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
558
601
  applyMaxPassUsageIncrements(itemPassUsageMap, selectedVoucher.product_id, maxPassesPerItem, deductionDetails);
559
602
  selectedWithDetails.push({
560
603
  ...selectedVoucher,
604
+ config,
561
605
  actualDeduction: totalDeducted.toNumber(),
562
606
  // 转换为数字
563
607
  deductionDetails,
@@ -565,12 +609,11 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
565
609
  // 转换为数字
566
610
  _unified_available_status: totalDeducted.greaterThan(0) ? 1 : 0
567
611
  });
612
+ if (totalDeducted.greaterThan(0)) {
613
+ usedVoucherCounts.set(product_id, usedCount + 1);
614
+ }
568
615
  });
569
616
  const selectedIds = new Set(selectedVouchers.map((v) => v.id));
570
- const usedVoucherCounts = /* @__PURE__ */ new Map();
571
- selectedVouchers.forEach((v) => {
572
- usedVoucherCounts.set(v.product_id, (usedVoucherCounts.get(v.product_id) || 0) + 1);
573
- });
574
617
  const allWithUpdatedStatus = allVouchers.map((voucher) => {
575
618
  if (selectedIds.has(voucher.id)) {
576
619
  const selectedDetail = selectedWithDetails.find(
@@ -578,8 +621,15 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
578
621
  );
579
622
  return selectedDetail || voucher;
580
623
  }
581
- const { config, id, product_id } = voucher;
582
- const { maxDeductionAmount, allowCrossProduct, applicableProductLimit, deductTaxAndFee = true, maxPassesPerItem = 0 } = config;
624
+ const { product_id } = voucher;
625
+ const config = getWalletPassCalculationConfig(voucher);
626
+ const {
627
+ maxDeductionAmount,
628
+ allowCrossProduct,
629
+ applicableProductLimit,
630
+ deductTaxAndFee,
631
+ maxPassesPerItem
632
+ } = config;
583
633
  const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
584
634
  const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
585
635
  const recommendedAmount = getRecommendedAmount(voucher);
@@ -663,6 +713,7 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
663
713
  }
664
714
  return {
665
715
  ...voucher,
716
+ config,
666
717
  _available_max_amount: calculatedMaxAmount.toNumber(),
667
718
  // 转换为数字
668
719
  _unified_available_status: isAvailable ? 1 : 0,
@@ -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;
@@ -222,6 +241,42 @@ var WalletPassPaymentImpl = class {
222
241
  error: null
223
242
  });
224
243
  }
244
+ /**
245
+ * 搜索接口只返回后端 Wallet Pass 数据,不包含前端策略 config。
246
+ * 在资产进入共享选择状态前补齐策略结果,避免增量重算回退到接口状态。
247
+ */
248
+ formatSearchedWalletPaymentAssets(assets) {
249
+ var _a, _b, _c, _d;
250
+ if (!assets.length)
251
+ return assets;
252
+ const assetsWithRecalculationBase = assets.map(
253
+ withWalletAssetRecalculationBaseAmount
254
+ );
255
+ const evaluator = (_b = (_a = this.paymentModule.window) == null ? void 0 : _a.getWalletPassEvaluator) == null ? void 0 : _b.call(_a);
256
+ if (!(evaluator == null ? void 0 : evaluator.searchVoucherFormat))
257
+ return assetsWithRecalculationBase;
258
+ const hasCalculationProducts = this.walletAssetsCalculationContext.products.length > 0;
259
+ const products = hasCalculationProducts ? this.walletAssetsCalculationContext.products : ((_c = this.walletParams) == null ? void 0 : _c.products) || [];
260
+ const orderTotalAmount = Number(
261
+ hasCalculationProducts ? this.walletAssetsCalculationContext.orderTotalAmount : ((_d = this.walletParams) == null ? void 0 : _d.order_wait_pay_amount) || 0
262
+ );
263
+ try {
264
+ const formattedAssets = evaluator.searchVoucherFormat({
265
+ orderTotalAmount,
266
+ products,
267
+ vouchers: assetsWithRecalculationBase
268
+ });
269
+ return formattedAssets;
270
+ } catch (error) {
271
+ this.paymentModule.logWarning(
272
+ "[WalletPass] 搜索资产策略格式化失败,保留接口结果",
273
+ {
274
+ error: error instanceof Error ? error.message : String(error)
275
+ }
276
+ );
277
+ return assetsWithRecalculationBase;
278
+ }
279
+ }
225
280
  /** 获取当前缓存中所有支付类 Wallet 资产的扫码 code。 */
226
281
  getSearchedWalletAssetCodes() {
227
282
  const cachedAssets = this.searchResults.filter(isWalletPaymentAsset);
@@ -245,11 +300,23 @@ var WalletPassPaymentImpl = class {
245
300
  );
246
301
  if (searchedCodeKeys.size === 0)
247
302
  return cachedAssets;
303
+ const cachedAssetByCode = /* @__PURE__ */ new Map();
304
+ cachedAssets.forEach((item) => {
305
+ getWalletAssetCodeKeys(item).forEach((code) => {
306
+ cachedAssetByCode.set(code, item);
307
+ });
308
+ });
248
309
  const refreshedAssets = refreshedCandidates.filter(
249
310
  (item) => isWalletPaymentAsset(item) && searchedCodeKeys.has(
250
311
  String((item == null ? void 0 : item.code) || "").trim().toUpperCase()
251
312
  )
252
- );
313
+ ).map((item) => {
314
+ const cachedAsset = getWalletAssetCodeKeys(item).map((code) => cachedAssetByCode.get(code)).find(Boolean);
315
+ return withWalletAssetRecalculationBaseAmount({
316
+ ...cachedAsset,
317
+ ...item
318
+ });
319
+ });
253
320
  if (refreshedAssets.length > 0) {
254
321
  const replacedCodes = new Set(
255
322
  refreshedAssets.map(
@@ -321,6 +388,10 @@ var WalletPassPaymentImpl = class {
321
388
  payment_order_id
322
389
  };
323
390
  this.walletParams = walletParams;
391
+ this.walletAssetsCalculationContext = {
392
+ orderTotalAmount: Number(walletParams.order_wait_pay_amount || 0),
393
+ products: Array.isArray(walletParams.products) ? walletParams.products : []
394
+ };
324
395
  this.paymentModule.logInfo("[WalletPass] 钱包默认参数已生成并存储", {
325
396
  customer_id: walletParams.customer_id,
326
397
  holder_id: walletParams.holder_id,
@@ -472,7 +543,6 @@ var WalletPassPaymentImpl = class {
472
543
  vouchers: allList
473
544
  });
474
545
  const { recommended, transformList, noApplicableVoucher, recommendedAmount } = res;
475
- console.log(res, "resres12");
476
546
  this.walletRecommendList = recommended;
477
547
  this.walletInitData = {
478
548
  transformList,
@@ -552,7 +622,7 @@ var WalletPassPaymentImpl = class {
552
622
  )
553
623
  };
554
624
  const returnedSelectedKeys = new Set(
555
- recalculateList.filter(isWalletAssetAvailable).map((item) => getWalletAssetKey(item))
625
+ allList.map((item) => getWalletAssetKey(item))
556
626
  );
557
627
  const authoritativeSelectedIds = selectedIds.filter(
558
628
  (id) => returnedSelectedKeys.has(String(id))
@@ -818,6 +888,17 @@ var WalletPassPaymentImpl = class {
818
888
  const assetId = getWalletAssetId(asset);
819
889
  return assetId !== void 0 && assetId !== null && selectionSources[String(assetId)] === "scan";
820
890
  }) : [];
891
+ const manualEditAmountByKey = /* @__PURE__ */ new Map();
892
+ if (preserveSelection) {
893
+ this.walletAssetsState.selectedItems.forEach((asset) => {
894
+ if (typeof (asset == null ? void 0 : asset.edit_current_amount) !== "number")
895
+ return;
896
+ manualEditAmountByKey.set(
897
+ getWalletAssetKey(asset),
898
+ asset.edit_current_amount
899
+ );
900
+ });
901
+ }
821
902
  if (!((_a = businessData.products) == null ? void 0 : _a.length)) {
822
903
  this.queuePendingAutoSelectForAssets(scanSelectedAssets);
823
904
  this.generateWalletParams(businessData);
@@ -916,12 +997,16 @@ var WalletPassPaymentImpl = class {
916
997
  searchedWalletAssets,
917
998
  result.transformList || [],
918
999
  result.noApplicableVoucher || []
919
- ).map((asset) => ({
920
- ...asset,
921
- _wallet_asset_recommended: recommendedKeys.has(
922
- getWalletAssetKey(asset)
923
- )
924
- }));
1000
+ ).map((asset) => {
1001
+ const assetKey = getWalletAssetKey(asset);
1002
+ return {
1003
+ ...asset,
1004
+ ...manualEditAmountByKey.has(assetKey) ? {
1005
+ edit_current_amount: manualEditAmountByKey.get(assetKey)
1006
+ } : {},
1007
+ _wallet_asset_recommended: recommendedKeys.has(assetKey)
1008
+ };
1009
+ });
925
1010
  const latestSelectedIds = preserveSelection ? authoritativeSelectedIds : [];
926
1011
  const latestSelectionSources = preserveSelection ? { ...this.walletAssetsState.selectionSources } : {};
927
1012
  const pendingAutoSelectAssets = this.walletAssetsBehavior.autoSelectAfterSearch ? items.filter(
@@ -1035,6 +1120,13 @@ var WalletPassPaymentImpl = class {
1035
1120
  selectionSources: snapshot.state.selectionSources || {}
1036
1121
  });
1037
1122
  }
1123
+ updateWalletAssetEditAmountInCaches(assetKey, amount) {
1124
+ const updateAsset = (asset) => getWalletAssetKey(asset) === assetKey ? { ...asset, edit_current_amount: amount } : asset;
1125
+ this.searchResults = this.searchResults.map(
1126
+ updateAsset
1127
+ );
1128
+ return this.walletAssetsState.items.map(updateAsset);
1129
+ }
1038
1130
  selectWalletAsset(assetId, options) {
1039
1131
  const assetKey = String(assetId);
1040
1132
  const asset = this.walletAssetsState.items.find(
@@ -1050,6 +1142,7 @@ var WalletPassPaymentImpl = class {
1050
1142
  );
1051
1143
  const selectionSources = { ...this.walletAssetsState.selectionSources };
1052
1144
  delete selectionSources[assetKey];
1145
+ let nextItems = this.walletAssetsState.items;
1053
1146
  if (options.selected) {
1054
1147
  if (!asset || !isWalletAssetAvailable(asset)) {
1055
1148
  return this.getWalletAssetsState();
@@ -1058,9 +1151,13 @@ var WalletPassPaymentImpl = class {
1058
1151
  selectionSources[assetKey] = options.source || "manual";
1059
1152
  } else if (asset) {
1060
1153
  this.clearPendingAutoSelectForAsset(asset);
1154
+ nextItems = this.updateWalletAssetEditAmountInCaches(
1155
+ assetKey,
1156
+ void 0
1157
+ );
1061
1158
  }
1062
1159
  const nextState = this.recalculateWalletAssets(
1063
- this.walletAssetsState.items,
1160
+ nextItems,
1064
1161
  selectedIds,
1065
1162
  selectionSources
1066
1163
  );
@@ -1069,6 +1166,54 @@ var WalletPassPaymentImpl = class {
1069
1166
  }
1070
1167
  return nextState;
1071
1168
  }
1169
+ /**
1170
+ * 更新已选资产的手动金额。只允许在当前实际抵扣额内向下调整,
1171
+ * 金额为 0 时沿用 legacy 行为取消选择。
1172
+ */
1173
+ updateWalletAssetAmount(assetId, amount) {
1174
+ const assetKey = String(assetId);
1175
+ const committedKeys = new Set(
1176
+ this.walletAssetsState.committedIds.map((id) => String(id))
1177
+ );
1178
+ const selectedKeys = new Set(
1179
+ this.walletAssetsState.selectedIds.map((id) => String(id))
1180
+ );
1181
+ const asset = this.walletAssetsState.items.find(
1182
+ (item) => getWalletAssetKey(item) === assetKey
1183
+ );
1184
+ const requestedAmount = Number(amount);
1185
+ if (!asset || committedKeys.has(assetKey) || !selectedKeys.has(assetKey) || !Number.isFinite(requestedAmount) || requestedAmount < 0) {
1186
+ return this.getWalletAssetsState();
1187
+ }
1188
+ const selectedIds = [...this.walletAssetsState.selectedIds];
1189
+ const selectionSources = { ...this.walletAssetsState.selectionSources };
1190
+ if (requestedAmount === 0) {
1191
+ const nextItems2 = this.updateWalletAssetEditAmountInCaches(
1192
+ assetKey,
1193
+ void 0
1194
+ );
1195
+ delete selectionSources[assetKey];
1196
+ this.clearPendingAutoSelectForAsset(asset);
1197
+ return this.recalculateWalletAssets(
1198
+ nextItems2,
1199
+ selectedIds.filter((id) => String(id) !== assetKey),
1200
+ selectionSources
1201
+ );
1202
+ }
1203
+ const currentDeductionAmount = getWalletAssetDeductionAmount(asset);
1204
+ const editAmount = Math.min(requestedAmount, currentDeductionAmount);
1205
+ if (editAmount <= 0)
1206
+ return this.getWalletAssetsState();
1207
+ const nextItems = this.updateWalletAssetEditAmountInCaches(
1208
+ assetKey,
1209
+ editAmount
1210
+ );
1211
+ return this.recalculateWalletAssets(
1212
+ nextItems,
1213
+ selectedIds,
1214
+ selectionSources
1215
+ );
1216
+ }
1072
1217
  async scanWalletAssetAsync(code) {
1073
1218
  const normalizedCode = String(code || "").trim();
1074
1219
  if (!normalizedCode) {
@@ -1097,7 +1242,15 @@ var WalletPassPaymentImpl = class {
1097
1242
  this.walletAssetsState.selectedItems
1098
1243
  )
1099
1244
  });
1100
- const paymentAssets = result.data.filter(isWalletPaymentAsset);
1245
+ const paymentAssets = this.formatSearchedWalletPaymentAssets(
1246
+ result.data.filter(isWalletPaymentAsset)
1247
+ );
1248
+ if (paymentAssets.length > 0) {
1249
+ this.searchResults = mergeWalletAssets(
1250
+ this.searchResults,
1251
+ paymentAssets
1252
+ );
1253
+ }
1101
1254
  const asset = paymentAssets.find(
1102
1255
  (item) => String((item == null ? void 0 : item.code) || "") === normalizedCode
1103
1256
  ) || paymentAssets[0];
@@ -1116,30 +1269,44 @@ var WalletPassPaymentImpl = class {
1116
1269
  this.walletAssetsState.selectionSources
1117
1270
  );
1118
1271
  const assetId = getWalletAssetId(asset);
1119
- const selected = this.walletAssetsBehavior.autoSelectAfterSearch && assetId !== void 0 && isWalletAssetAvailable(asset) ? this.selectWalletAsset(assetId, {
1272
+ const recalculatedAsset = assetId === void 0 ? void 0 : recalculatedState.items.find(
1273
+ (item) => getWalletAssetKey(item) === String(assetId)
1274
+ );
1275
+ const selected = this.walletAssetsBehavior.autoSelectAfterSearch && assetId !== void 0 && isWalletAssetAvailable(recalculatedAsset) ? this.selectWalletAsset(assetId, {
1120
1276
  selected: true,
1121
1277
  source: "scan"
1122
1278
  }) : recalculatedState;
1123
1279
  const isSelected = assetId !== void 0 && selected.selectedIds.some((id) => String(id) === String(assetId));
1280
+ const selectedStateAsset = assetId === void 0 ? void 0 : selected.items.find(
1281
+ (item) => getWalletAssetKey(item) === String(assetId)
1282
+ );
1283
+ const resolvedAsset = selectedStateAsset || recalculatedAsset || asset;
1124
1284
  if (isSelected) {
1125
- this.clearPendingAutoSelectForAsset(asset);
1285
+ this.clearPendingAutoSelectForAsset(resolvedAsset);
1126
1286
  } else if (this.walletAssetsBehavior.autoSelectAfterSearch) {
1127
1287
  this.pendingAutoSelectSearchCodes.add(
1128
1288
  normalizeWalletAssetCode(normalizedCode)
1129
1289
  );
1130
- this.queuePendingAutoSelectForAssets([asset]);
1290
+ this.queuePendingAutoSelectForAssets([resolvedAsset]);
1131
1291
  }
1132
1292
  return {
1133
1293
  type: result.type,
1134
- asset,
1294
+ asset: resolvedAsset,
1135
1295
  selected: isSelected,
1136
1296
  state: selected
1137
1297
  };
1138
1298
  }
1139
1299
  clearWalletAssetSelection() {
1140
1300
  this.pendingAutoSelectSearchCodes.clear();
1301
+ const selectedKeys = new Set(
1302
+ this.walletAssetsState.selectedIds.map((id) => String(id))
1303
+ );
1304
+ const clearSelectedEditAmount = (asset) => selectedKeys.has(getWalletAssetKey(asset)) ? { ...asset, edit_current_amount: void 0 } : asset;
1305
+ this.searchResults = this.searchResults.map(
1306
+ clearSelectedEditAmount
1307
+ );
1141
1308
  return this.recalculateWalletAssets(
1142
- this.walletAssetsState.items,
1309
+ this.walletAssetsState.items.map(clearSelectedEditAmount),
1143
1310
  [],
1144
1311
  {}
1145
1312
  );
@@ -355,6 +355,11 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
355
355
  selected: boolean;
356
356
  source?: WalletAssetSelectionSource;
357
357
  }): Promise<WalletAssetsState>;
358
+ /** 更新已选钱包资产的手动使用金额,并同步 pending payment。 */
359
+ updateWalletAssetAmount(params: {
360
+ assetId: WalletAssetId;
361
+ amount: number;
362
+ }): Promise<WalletAssetsState>;
358
363
  /** 扫码精确查券;仅可用资产会被自动选中。 */
359
364
  scanWalletAsset(code: string): Promise<ScanWalletAssetResult>;
360
365
  /** 清空全部未确认钱包选择,已支付钱包项由 Order 模块继续保留。 */
@@ -2638,11 +2638,27 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
2638
2638
  await this.syncSelectedWalletAssets(state);
2639
2639
  return this.publishWalletAssetsState(state);
2640
2640
  }
2641
+ /** 更新已选钱包资产的手动使用金额,并同步 pending payment。 */
2642
+ async updateWalletAssetAmount(params) {
2643
+ if (!this.store.payment)
2644
+ throw new Error("payment 模块未初始化");
2645
+ const state = this.store.payment.wallet.updateWalletAssetAmount(
2646
+ params.assetId,
2647
+ params.amount
2648
+ );
2649
+ await this.syncSelectedWalletAssets(state);
2650
+ return this.publishWalletAssetsState(state);
2651
+ }
2641
2652
  /** 扫码精确查券;仅可用资产会被自动选中。 */
2642
2653
  async scanWalletAsset(code) {
2643
2654
  if (!this.store.payment)
2644
2655
  throw new Error("payment 模块未初始化");
2645
- const result = await this.store.payment.wallet.scanWalletAssetAsync(code);
2656
+ const wallet = this.store.payment.wallet;
2657
+ const businessData = this.buildWalletInitBusinessData();
2658
+ if (businessData) {
2659
+ wallet.generateWalletParams(businessData);
2660
+ }
2661
+ const result = await wallet.scanWalletAssetAsync(code);
2646
2662
  if (result.type === "normalCode") {
2647
2663
  await this.syncSelectedWalletAssets(result.state);
2648
2664
  await this.publishWalletAssetsState(result.state);
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 1 | 2 | 3 | 6 | 4 | 5;
314
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;