@pisell/pisellos 1.0.62 → 1.0.64

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.
@@ -12,6 +12,7 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
12
12
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
13
13
  import Decimal from 'decimal.js';
14
14
  import { isNormalProduct } from "../../Product/utils";
15
+ import { getDiscountAmount } from "../../../solution/ShopDiscount/utils";
15
16
 
16
17
  /**
17
18
  * @title 处理组合商品
@@ -192,8 +193,14 @@ export var getProductTotalPrice = function getProductTotalPrice(params) {
192
193
  // 不是商品券则代表折扣卡,计算打折后的价格
193
194
  // 一个商品折扣卡只能存在于一张
194
195
  if (currentValue.type !== 'good_pass') {
195
- var discountPrice = new Decimal(100).minus(currentValue.discount.percent || 0).div(100).mul(new Decimal(price || 0)).toFixed(2);
196
- price = Number(discountPrice);
196
+ var _currentValue$discoun;
197
+ price = getDiscountAmount({
198
+ tag: currentValue.type,
199
+ par_value: currentValue.discount.percent,
200
+ metadata: {
201
+ discount_card_type: currentValue === null || currentValue === void 0 || (_currentValue$discoun = currentValue.discount) === null || _currentValue$discoun === void 0 ? void 0 : _currentValue$discoun.discount_card_type
202
+ }
203
+ }, price, price);
197
204
  }
198
205
  });
199
206
  }
@@ -70,6 +70,9 @@ export interface Discount {
70
70
  limited_relation_product_data: Limitedrelationproductdata;
71
71
  balance: string;
72
72
  format_title: Formattitle;
73
+ metadata?: {
74
+ discount_card_type?: 'fixed_amount' | 'percent';
75
+ };
73
76
  product: Product;
74
77
  type: "product" | 'good_pass';
75
78
  resource_id?: number;
@@ -25,7 +25,7 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
25
25
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
26
26
  import { BaseModule } from "../BaseModule";
27
27
  import { RulesHooks } from "./types";
28
- import { uniqueById } from "../../solution/ShopDiscount/utils";
28
+ import { uniqueById, getDiscountAmount } from "../../solution/ShopDiscount/utils";
29
29
  import { getProductOriginTotalPrice, getProductTotalPrice } from "../Cart/utils";
30
30
  import Decimal from 'decimal.js';
31
31
  import { isBoolean } from 'lodash-es';
@@ -189,8 +189,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
189
189
  });
190
190
 
191
191
  // 优惠力度排序,传进来的数据里可能有商品券,也可能有优惠券
192
- // 商品券(n.tag=good_pass)视为最优惠(免费),折扣券(n.tag=product_discount_card)按照n.par_value排序
193
- // 如果最后拍出来商品券有多个,或者说没有商品券,但是有多个相同折扣的折扣券(比如 6 折券有 3张),则按照过期时间(n.expire_time)排序
192
+ // 1. 商品券(n.tag=good_pass)视为最优惠(免费)
193
+ // 2. 折扣券(n.tag=product_discount_card)按照新的优先级排序:
194
+ // - 固定金额优先于百分比(固定金额 > 百分比)
195
+ // - 固定金额内部:金额越大越优先
196
+ // - 百分比内部:折扣越大越优先(par_value越小越优先)
197
+ // 3. 相同类型和金额的情况下,按照过期时间(n.expire_time)排序
194
198
  var sortedDiscountList = _toConsumableArray(filteredDiscountList).sort(function (a, b) {
195
199
  // 1. 商品券优先级最高
196
200
  if (a.tag === 'good_pass' && b.tag !== 'good_pass') return -1;
@@ -201,13 +205,34 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
201
205
  // 都是商品券,按照过期时间排序
202
206
  return compareByExpireTime(a, b);
203
207
  } else if (a.tag === 'product_discount_card' && b.tag === 'product_discount_card') {
204
- // 都是折扣券,按照par_value排序(折扣越大越优先,即par_value越小越优先)
205
- if (a.par_value !== b.par_value) {
206
- var valueA = new Decimal(100).minus(a.par_value || 0);
207
- var valueB = new Decimal(100).minus(b.par_value || 0);
208
- return valueA.minus(valueB).toNumber();
208
+ var _a$metadata, _b$metadata;
209
+ // 都是折扣券,按照新的优先级排序:固定金额优先于百分比
210
+ var typeA = ((_a$metadata = a.metadata) === null || _a$metadata === void 0 ? void 0 : _a$metadata.discount_card_type) || 'percent'; // 默认为百分比
211
+ var typeB = ((_b$metadata = b.metadata) === null || _b$metadata === void 0 ? void 0 : _b$metadata.discount_card_type) || 'percent'; // 默认为百分比
212
+
213
+ // 1. 固定金额优先于百分比
214
+ if (typeA === 'fixed_amount' && typeB === 'percent') return -1;
215
+ if (typeA === 'percent' && typeB === 'fixed_amount') return 1;
216
+
217
+ // 2. 都是固定金额时,金额越大越优先
218
+ if (typeA === 'fixed_amount' && typeB === 'fixed_amount') {
219
+ if (a.par_value !== b.par_value) {
220
+ var valueA = new Decimal(a.par_value || 0);
221
+ var valueB = new Decimal(b.par_value || 0);
222
+ return valueB.minus(valueA).toNumber(); // 金额大的在前
223
+ }
209
224
  }
210
- // 相同折扣的情况下,按照过期时间排序
225
+
226
+ // 3. 都是百分比时,折扣越大越优先(par_value越小越优先)
227
+ if (typeA === 'percent' && typeB === 'percent') {
228
+ if (a.par_value !== b.par_value) {
229
+ var _valueA = new Decimal(100).minus(a.par_value || 0);
230
+ var _valueB = new Decimal(100).minus(b.par_value || 0);
231
+ return _valueB.minus(_valueA).toNumber(); // 折扣大的在前
232
+ }
233
+ }
234
+
235
+ // 相同类型和金额的情况下,按照过期时间排序
211
236
  return compareByExpireTime(a, b);
212
237
  }
213
238
 
@@ -291,7 +316,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
291
316
 
292
317
  // 判断优惠券是否适用于该商品
293
318
  if (isAvailableProduct && isLimitedProduct) {
294
- var _discountApplicabilit;
319
+ var _discountApplicabilit, _discount$metadata;
295
320
  // 记录此优惠券适用的商品
296
321
  (_discountApplicabilit = discountApplicability.get(discount.id)) === null || _discountApplicabilit === void 0 || _discountApplicabilit.push(product.id);
297
322
 
@@ -303,6 +328,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
303
328
  type: discountType,
304
329
  tag: discountType,
305
330
  discount: {
331
+ discount_card_type: discount === null || discount === void 0 || (_discount$metadata = discount.metadata) === null || _discount$metadata === void 0 ? void 0 : _discount$metadata.discount_card_type,
306
332
  resource_id: discount.id,
307
333
  title: discount.format_title,
308
334
  original_amount: product.origin_total,
@@ -444,7 +470,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
444
470
  }));
445
471
  }
446
472
  for (var _i = 0; _i < splitCount; _i++) {
447
- var _product$discount_lis12, _originProduct$_produ;
473
+ var _product$discount_lis12, _originProduct$_produ, _selectedDiscount$met;
448
474
  // 如果用过折扣卡,也就不存在拆分的情况了,这里直接使用上面计算出来的折扣卡
449
475
  var _selectedDiscount = selectedDiscountCard || applicableDiscounts[_i];
450
476
  // 标记优惠券为已使用
@@ -465,12 +491,13 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
465
491
  }
466
492
 
467
493
  // 计算使用折扣卡/商品券以后,单个商品的总 total
468
- var targetProductTotal = _selectedDiscount.tag === 'good_pass' ? new Decimal(productOriginTotal).minus(new Decimal(product.price || 0)).toNumber() : new Decimal(100).minus(_selectedDiscount.par_value || 0).div(100).mul(new Decimal(productOriginTotal)).toNumber();
494
+ var targetProductTotal = getDiscountAmount(_selectedDiscount, productOriginTotal, product.price);
469
495
  var discountType = _selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : _selectedDiscount.tag;
470
496
  var discountDetail = {
471
497
  amount: new Decimal(productOriginTotal).minus(new Decimal(targetProductTotal)).toNumber(),
472
498
  type: discountType,
473
499
  discount: {
500
+ discount_card_type: _selectedDiscount === null || _selectedDiscount === void 0 || (_selectedDiscount$met = _selectedDiscount.metadata) === null || _selectedDiscount$met === void 0 ? void 0 : _selectedDiscount$met.discount_card_type,
474
501
  resource_id: _selectedDiscount.id,
475
502
  title: _selectedDiscount.format_title,
476
503
  original_amount: productOriginTotal,
@@ -25,6 +25,7 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
25
25
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
26
26
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
27
27
  import { BaseModule } from "../../modules/BaseModule";
28
+ import Decimal from 'decimal.js';
28
29
  import { OrderModule } from "../../modules/Order";
29
30
  import { PaymentModule } from "../../modules/Payment";
30
31
  import { CheckoutStatus, CheckoutStep, CheckoutHooks, CheckoutErrorType } from "./types";
@@ -1820,9 +1821,9 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
1820
1821
  case 21:
1821
1822
  syncResult = _context25.sent;
1822
1823
  console.log('[Checkout] EFTPOS 支付后订单同步完成 (已标记为手动同步):', {
1823
- 订单ID: syncResult.orderId,
1824
- 是否已同步: this.store.isOrderSynced,
1825
- 后端响应: syncResult.response
1824
+ orderId: syncResult.orderId,
1825
+ isOrderSynced: this.store.isOrderSynced,
1826
+ backendResponse: syncResult.response
1826
1827
  });
1827
1828
  _context25.next = 30;
1828
1829
  break;
@@ -1935,8 +1936,8 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
1935
1936
  // 如果当前订单ID是真实ID,但获取到的订单ID是虚拟ID,需要保护真实ID
1936
1937
  if (isCurrentOrderReal && isVirtualOrderId(updatedOrder.order_id)) {
1937
1938
  console.warn('[Checkout] deletePaymentItemAsync: 检测到订单ID回退,保护真实订单ID:', {
1938
- 当前真实ID: currentOrderId,
1939
- 获取到的虚拟ID: updatedOrder.order_id
1939
+ currentRealId: currentOrderId,
1940
+ retrievedVirtualId: updatedOrder.order_id
1940
1941
  });
1941
1942
  updatedOrder.order_id = currentOrderId; // 恢复真实的订单ID
1942
1943
  }
@@ -2052,8 +2053,8 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
2052
2053
  // 如果当前订单ID是真实ID,但获取到的订单ID是虚拟ID,需要保护真实ID
2053
2054
  if (isCurrentOrderReal && isVirtualOrderId(updatedOrder.order_id)) {
2054
2055
  console.warn('[Checkout] updateVoucherPaymentItemsAsync: 检测到订单ID回退,保护真实订单ID:', {
2055
- 当前真实ID: currentOrderId,
2056
- 获取到的虚拟ID: updatedOrder.order_id
2056
+ currentRealId: currentOrderId,
2057
+ retrievedVirtualId: updatedOrder.order_id
2057
2058
  });
2058
2059
  updatedOrder.order_id = currentOrderId; // 恢复真实的订单ID
2059
2060
  }
@@ -2311,8 +2312,8 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
2311
2312
  return this.calculateRemainingAmountAsync();
2312
2313
  case 5:
2313
2314
  remainingAmount = _context30.sent;
2314
- remainingValue = parseFloat(remainingAmount);
2315
- if (!(remainingValue > 0)) {
2315
+ remainingValue = new Decimal(remainingAmount);
2316
+ if (!remainingValue.gt(0)) {
2316
2317
  _context30.next = 9;
2317
2318
  break;
2318
2319
  }
@@ -2428,11 +2429,11 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
2428
2429
  finalOrderId = this.store.currentOrder.order_id;
2429
2430
  finalIsVirtual = isVirtualOrderId(finalOrderId);
2430
2431
  console.log('[Checkout] manualSyncOrderAsync 最终状态验证:', {
2431
- 返回的订单ID: syncResult.orderId,
2432
- 存储的订单ID: finalOrderId,
2433
- 存储的ID是否虚拟: finalIsVirtual,
2434
- 是否一致: syncResult.orderId === finalOrderId,
2435
- 同步状态: this.store.isOrderSynced
2432
+ returnedOrderId: syncResult.orderId,
2433
+ storedOrderId: finalOrderId,
2434
+ storedIdIsVirtual: finalIsVirtual,
2435
+ isConsistent: syncResult.orderId === finalOrderId,
2436
+ syncStatus: this.store.isOrderSynced
2436
2437
  });
2437
2438
  if (finalIsVirtual) {
2438
2439
  console.error('[Checkout] 严重警告:手动同步完成后订单ID仍为虚拟ID!');
@@ -2691,10 +2692,10 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
2691
2692
  // 验证最终状态
2692
2693
  finalOrderId = this.store.currentOrder.order_id;
2693
2694
  console.log('[Checkout] saveForLaterPaymentAsync 最终状态验证:', {
2694
- 返回的订单ID: syncResult.orderId,
2695
- 存储的订单ID: finalOrderId,
2696
- 是否一致: syncResult.orderId === finalOrderId,
2697
- 同步状态: this.store.isOrderSynced
2695
+ returnedOrderId: syncResult.orderId,
2696
+ storedOrderId: finalOrderId,
2697
+ isConsistent: syncResult.orderId === finalOrderId,
2698
+ syncStatus: this.store.isOrderSynced
2698
2699
  });
2699
2700
  return _context33.abrupt("return", {
2700
2701
  success: true,
@@ -3114,58 +3115,78 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
3114
3115
  return this.calculateRemainingAmountAsync();
3115
3116
  case 6:
3116
3117
  remainingAmountStr = _context39.sent;
3117
- remainingAmount = parseFloat(remainingAmountStr);
3118
- cashAmount = parseFloat(String(paymentItem.amount));
3118
+ // 15.66
3119
+ remainingAmount = new Decimal(remainingAmountStr);
3120
+ cashAmount = new Decimal(String(paymentItem.amount)); // 15.7
3119
3121
  console.log('[Checkout] 现金支付处理:', {
3120
- cashAmount: cashAmount,
3121
- remainingAmount: remainingAmount,
3122
- needsChange: cashAmount > remainingAmount
3122
+ cashAmount: cashAmount.toNumber(),
3123
+ remainingAmount: remainingAmount.toNumber(),
3124
+ needsChange: cashAmount.gt(remainingAmount)
3123
3125
  });
3124
3126
 
3125
3127
  // 如果现金金额小于等于剩余待付金额,无需找零
3126
- if (!(cashAmount <= remainingAmount)) {
3128
+ if (!cashAmount.lte(remainingAmount)) {
3127
3129
  _context39.next = 12;
3128
3130
  break;
3129
3131
  }
3130
3132
  return _context39.abrupt("return", paymentItem);
3131
3133
  case 12:
3132
- // 计算找零金额
3133
- changeAmount = cashAmount - remainingAmount;
3134
+ // 使用 Decimal.js 安全计算找零金额
3135
+ changeAmount = cashAmount.sub(remainingAmount); // 如果还有 rounding_amount 的配置,要判断是否和 changeAmount 相等
3136
+ if (!(Number(paymentItem.rounding_amount) > 0)) {
3137
+ _context39.next = 19;
3138
+ break;
3139
+ }
3140
+ if (!(Number(paymentItem.rounding_amount) === changeAmount.toNumber())) {
3141
+ _context39.next = 18;
3142
+ break;
3143
+ }
3144
+ return _context39.abrupt("return", paymentItem);
3145
+ case 18:
3146
+ // 如果不等于,则remainingAmount需要加上 rounding_amount,避免这里被改为未舍入金额
3147
+ remainingAmount = remainingAmount.add(new Decimal(paymentItem.rounding_amount || '0'));
3148
+ case 19:
3134
3149
  console.log('[Checkout] 现金支付需要找零:', {
3135
- actualPaidAmount: cashAmount,
3136
- chargedAmount: remainingAmount,
3137
- changeGivenAmount: changeAmount
3150
+ actualPaidAmount: cashAmount.toFixed(2),
3151
+ chargedAmount: remainingAmount.toFixed(2),
3152
+ changeGivenAmount: changeAmount.toFixed(2)
3138
3153
  });
3139
3154
 
3140
3155
  // 创建包含找零信息的支付项
3141
3156
  processedPaymentItem = _objectSpread(_objectSpread({}, paymentItem), {}, {
3142
- amount: remainingAmount,
3143
- // 将 amount 设置为剩余待付金额
3157
+ amount: remainingAmount.toFixed(2),
3158
+ // 将 amount 设置为剩余待付金额,保留2位小数
3144
3159
  metadata: _objectSpread(_objectSpread({}, paymentItem.metadata), {}, {
3145
- actual_paid_amount: cashAmount,
3160
+ actual_paid_amount: cashAmount.toNumber(),
3146
3161
  // 实付金额
3147
- change_given_amount: changeAmount // 找零金额
3162
+ change_given_amount: changeAmount.toNumber() // 找零金额
3148
3163
  })
3149
3164
  });
3150
3165
  this.logInfo('Cash payment with change processed', {
3151
- originalAmount: cashAmount,
3152
- chargedAmount: remainingAmount,
3153
- changeAmount: changeAmount,
3166
+ originalAmount: cashAmount.toFixed(2),
3167
+ chargedAmount: remainingAmount.toFixed(2),
3168
+ changeAmount: changeAmount.toFixed(2),
3154
3169
  paymentCode: paymentItem.code,
3155
- paymentType: paymentItem.type
3170
+ paymentType: paymentItem.type,
3171
+ // 额外的精度验证信息
3172
+ decimalPrecisionCheck: {
3173
+ cashAmountPrecise: cashAmount.toString(),
3174
+ remainingAmountPrecise: remainingAmount.toString(),
3175
+ changeAmountPrecise: changeAmount.toString()
3176
+ }
3156
3177
  });
3157
3178
  return _context39.abrupt("return", processedPaymentItem);
3158
- case 19:
3159
- _context39.prev = 19;
3179
+ case 25:
3180
+ _context39.prev = 25;
3160
3181
  _context39.t0 = _context39["catch"](3);
3161
3182
  console.error('[Checkout] 处理现金支付项时出错:', _context39.t0);
3162
3183
  // 出错时返回原始支付项,避免中断支付流程
3163
3184
  return _context39.abrupt("return", paymentItem);
3164
- case 23:
3185
+ case 29:
3165
3186
  case "end":
3166
3187
  return _context39.stop();
3167
3188
  }
3168
- }, _callee39, this, [[3, 19]]);
3189
+ }, _callee39, this, [[3, 25]]);
3169
3190
  }));
3170
3191
  function processCashPaymentItem(_x28) {
3171
3192
  return _processCashPaymentItem.apply(this, arguments);
@@ -3456,25 +3477,33 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
3456
3477
  };
3457
3478
  })
3458
3479
  });
3480
+
3481
+ // 使用 Decimal.js 进行安全的金额计算
3459
3482
  paidAmount = payments.filter(function (payment) {
3460
3483
  return payment.status !== 'voided';
3461
3484
  }) // 只计算未撤销的支付项
3462
3485
  .reduce(function (sum, payment) {
3463
- var amount = parseFloat(payment.amount || '0');
3464
- var roundingAmount = parseFloat(payment.rounding_amount || '0');
3486
+ var amount = new Decimal(payment.amount || '0');
3487
+ var roundingAmount = new Decimal(payment.rounding_amount || '0');
3465
3488
 
3466
- // 计算实际支付有效金额:
3489
+ // 使用 Decimal.js 计算实际支付有效金额:
3467
3490
  // 当 rounding_amount 为负数时,表示抹掉的金额,应该按绝对值加到实际支付中
3468
3491
  // 例如:amount=15, rounding_amount=-0.2,实际相当于支付了15.2(抹掉了0.2元的零头)
3469
- var effectiveAmount = amount + Math.abs(roundingAmount);
3492
+ var effectiveAmount = amount.add(roundingAmount.abs());
3470
3493
  console.log("[Checkout] \u8BA1\u7B97\u652F\u4ED8\u9879: ".concat(payment.code), {
3471
- 原始金额: amount,
3472
- 抹零金额: roundingAmount,
3473
- 有效金额: effectiveAmount,
3474
- 说明: roundingAmount !== 0 ? "\u62B9\u96F6\u91D1\u989D ".concat(roundingAmount, " \u5143\uFF0C\u6709\u6548\u652F\u4ED8\u589E\u52A0 ").concat(Math.abs(roundingAmount), " \u5143") : '无抹零'
3494
+ originalAmount: amount.toFixed(2),
3495
+ roundingAmount: roundingAmount.toFixed(2),
3496
+ effectiveAmount: effectiveAmount.toFixed(2),
3497
+ description: !roundingAmount.isZero() ? "\u62B9\u96F6\u91D1\u989D ".concat(roundingAmount.toFixed(2), " \u5143\uFF0C\u6709\u6548\u652F\u4ED8\u589E\u52A0 ").concat(roundingAmount.abs().toFixed(2), " \u5143") : '无抹零',
3498
+ // Decimal 精度验证
3499
+ preciseCalculationValues: {
3500
+ amount: amount.toString(),
3501
+ roundingAmount: roundingAmount.toString(),
3502
+ effectiveAmount: effectiveAmount.toString()
3503
+ }
3475
3504
  });
3476
- return sum + effectiveAmount;
3477
- }, 0);
3505
+ return sum.add(effectiveAmount);
3506
+ }, new Decimal(0));
3478
3507
  result = paidAmount.toFixed(2);
3479
3508
  console.log('[Checkout] calculatePaidAmountAsync: 计算结果 =', result);
3480
3509
  return _context42.abrupt("return", result);
@@ -3502,7 +3531,7 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
3502
3531
  key: "calculateRemainingAmountAsync",
3503
3532
  value: (function () {
3504
3533
  var _calculateRemainingAmountAsync = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee43() {
3505
- var totalAmount, paidAmount, remainingAmount, result;
3534
+ var totalAmount, paidAmountStr, paidAmount, remainingAmount, result;
3506
3535
  return _regeneratorRuntime().wrap(function _callee43$(_context43) {
3507
3536
  while (1) switch (_context43.prev = _context43.next) {
3508
3537
  case 0:
@@ -3513,25 +3542,32 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
3513
3542
  console.log('[Checkout] calculateRemainingAmountAsync: 没有当前订单');
3514
3543
  return _context43.abrupt("return", '0.00');
3515
3544
  case 3:
3516
- totalAmount = parseFloat(this.store.currentOrder.total_amount || '0');
3517
- _context43.t0 = parseFloat;
3518
- _context43.next = 7;
3545
+ // 使用 Decimal.js 进行安全的金额计算
3546
+ totalAmount = new Decimal(this.store.currentOrder.total_amount || '0');
3547
+ _context43.next = 6;
3519
3548
  return this.calculatePaidAmountAsync();
3520
- case 7:
3521
- _context43.t1 = _context43.sent;
3522
- paidAmount = (0, _context43.t0)(_context43.t1);
3523
- remainingAmount = totalAmount - paidAmount;
3524
- result = Math.max(0, remainingAmount).toFixed(2);
3549
+ case 6:
3550
+ paidAmountStr = _context43.sent;
3551
+ paidAmount = new Decimal(paidAmountStr);
3552
+ remainingAmount = totalAmount.sub(paidAmount); // 确保剩余金额不为负数
3553
+ result = Decimal.max(0, remainingAmount).toFixed(2);
3525
3554
  console.log('[Checkout] calculateRemainingAmountAsync: 计算详情:', {
3526
3555
  orderUuid: this.store.currentOrder.uuid,
3527
3556
  totalAmount: totalAmount.toFixed(2),
3528
3557
  paidAmount: paidAmount.toFixed(2),
3529
3558
  calculatedRemaining: remainingAmount.toFixed(2),
3530
3559
  finalResult: result,
3531
- 说明: '已支付金额包含抹零计算(amount + |rounding_amount|)'
3560
+ description: '已支付金额包含抹零计算(amount + |rounding_amount|)',
3561
+ // Decimal 精度验证
3562
+ preciseCalculationValues: {
3563
+ totalAmount: totalAmount.toString(),
3564
+ paidAmount: paidAmount.toString(),
3565
+ remainingAmount: remainingAmount.toString(),
3566
+ resultAfterMax: Decimal.max(0, remainingAmount).toString()
3567
+ }
3532
3568
  });
3533
3569
  return _context43.abrupt("return", result);
3534
- case 13:
3570
+ case 12:
3535
3571
  case "end":
3536
3572
  return _context43.stop();
3537
3573
  }
@@ -3706,8 +3742,8 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
3706
3742
  return this.calculateRemainingAmountAsync();
3707
3743
  case 5:
3708
3744
  remainingAmount = _context46.sent;
3709
- remainingValue = parseFloat(remainingAmount); // 当剩余金额小于等于0时,认为订单已完成支付
3710
- if (!(remainingValue <= 0)) {
3745
+ remainingValue = new Decimal(remainingAmount); // 当剩余金额小于等于0时,认为订单已完成支付
3746
+ if (!remainingValue.lte(0)) {
3711
3747
  _context46.next = 29;
3712
3748
  break;
3713
3749
  }
@@ -4224,8 +4260,8 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
4224
4260
  beforeManualUpdate = this.store.currentOrder.order_id;
4225
4261
  this.store.currentOrder.order_id = realOrderId;
4226
4262
  console.log('[Checkout] 手动设置订单ID:', {
4227
- 替换前: beforeManualUpdate,
4228
- 替换后: this.store.currentOrder.order_id,
4263
+ beforeReplacement: beforeManualUpdate,
4264
+ afterReplacement: this.store.currentOrder.order_id,
4229
4265
  目标ID: realOrderId
4230
4266
  });
4231
4267
  }
@@ -4258,10 +4294,10 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
4258
4294
  finalOrderId = this.store.currentOrder.order_id;
4259
4295
  finalIsVirtual = isVirtualOrderId(finalOrderId || '');
4260
4296
  console.log("[Checkout] ".concat(syncType).concat(operation, "\u8BA2\u5355\u5230\u540E\u7AEF\u5B8C\u6210"), {
4261
- 返回的订单ID: realOrderId,
4262
- 当前存储的订单ID: finalOrderId,
4263
- 是否还是虚拟ID: finalIsVirtual,
4264
- 是否同步: this.store.isOrderSynced
4297
+ returnedOrderId: realOrderId,
4298
+ currentStoredOrderId: finalOrderId,
4299
+ isStillVirtualId: finalIsVirtual,
4300
+ isSynced: this.store.isOrderSynced
4265
4301
  });
4266
4302
 
4267
4303
  // 如果最终状态不正确,发出警告
@@ -1 +1,12 @@
1
+ import { Discount } from "../../modules/Discount/types";
1
2
  export declare const uniqueById: <T>(arr: T[], key?: string) => T[];
3
+ /**
4
+ * 获取折扣金额 基于折扣卡类型计算
5
+ * 商品券:直接返回商品价格
6
+ * 折扣卡:根据折扣卡类型计算 固定金额:直接返回折扣卡金额 百分比:根据折扣卡金额计算
7
+ * @param discount
8
+ * @param total
9
+ * @param price
10
+ * @returns
11
+ */
12
+ export declare const getDiscountAmount: (discount: Discount, total: number, price: number) => number;
@@ -1,7 +1,36 @@
1
+ import Decimal from "decimal.js";
1
2
  export var uniqueById = function uniqueById(arr) {
2
3
  var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'id';
3
4
  var seen = new Set();
4
5
  return arr.filter(function (item) {
5
6
  return !seen.has(item[key]) && seen.add(item[key]);
6
7
  });
8
+ };
9
+
10
+ /**
11
+ * 获取折扣金额 基于折扣卡类型计算
12
+ * 商品券:直接返回商品价格
13
+ * 折扣卡:根据折扣卡类型计算 固定金额:直接返回折扣卡金额 百分比:根据折扣卡金额计算
14
+ * @param discount
15
+ * @param total
16
+ * @param price
17
+ * @returns
18
+ */
19
+ export var getDiscountAmount = function getDiscountAmount(discount, total, price) {
20
+ var _discount$metadata;
21
+ // 商品券
22
+ if (discount.tag === 'good_pass') {
23
+ return new Decimal(total).minus(new Decimal(price || 0)).toNumber();
24
+ }
25
+
26
+ // 判断是否是固定金额
27
+ var isFixedAmount = (discount === null || discount === void 0 || (_discount$metadata = discount.metadata) === null || _discount$metadata === void 0 ? void 0 : _discount$metadata.discount_card_type) === 'fixed_amount';
28
+
29
+ // 固定金额 小于0时返回0
30
+ if (isFixedAmount) {
31
+ return Math.max(new Decimal(total).minus(new Decimal(discount.par_value || 0)).toNumber(), 0);
32
+ }
33
+
34
+ // 百分比:根据折扣卡金额计算
35
+ return new Decimal(100).minus(discount.par_value || 0).div(100).mul(new Decimal(total)).toNumber();
7
36
  };
@@ -44,6 +44,7 @@ __export(cartProduct_exports, {
44
44
  module.exports = __toCommonJS(cartProduct_exports);
45
45
  var import_decimal = __toESM(require("decimal.js"));
46
46
  var import_utils = require("../../Product/utils");
47
+ var import_utils2 = require("../../../solution/ShopDiscount/utils");
47
48
  var handleVariantProduct = (product) => {
48
49
  var _a;
49
50
  if (product == null ? void 0 : product.product_variant_id) {
@@ -183,9 +184,15 @@ var getProductTotalPrice = (params) => {
183
184
  }
184
185
  if (discounts == null ? void 0 : discounts.length) {
185
186
  discounts.forEach((currentValue) => {
187
+ var _a;
186
188
  if (currentValue.type !== "good_pass") {
187
- const discountPrice = new import_decimal.default(100).minus(currentValue.discount.percent || 0).div(100).mul(new import_decimal.default(price || 0)).toFixed(2);
188
- price = Number(discountPrice);
189
+ price = (0, import_utils2.getDiscountAmount)({
190
+ tag: currentValue.type,
191
+ par_value: currentValue.discount.percent,
192
+ metadata: {
193
+ discount_card_type: (_a = currentValue == null ? void 0 : currentValue.discount) == null ? void 0 : _a.discount_card_type
194
+ }
195
+ }, price, price);
189
196
  }
190
197
  });
191
198
  }
@@ -70,6 +70,9 @@ export interface Discount {
70
70
  limited_relation_product_data: Limitedrelationproductdata;
71
71
  balance: string;
72
72
  format_title: Formattitle;
73
+ metadata?: {
74
+ discount_card_type?: 'fixed_amount' | 'percent';
75
+ };
73
76
  product: Product;
74
77
  type: "product" | 'good_pass';
75
78
  resource_id?: number;
@@ -132,6 +132,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
132
132
  return !discount.isManualSelect;
133
133
  });
134
134
  const sortedDiscountList = [...filteredDiscountList].sort((a, b) => {
135
+ var _a, _b;
135
136
  if (a.tag === "good_pass" && b.tag !== "good_pass")
136
137
  return -1;
137
138
  if (b.tag === "good_pass" && a.tag !== "good_pass")
@@ -139,10 +140,25 @@ var RulesModule = class extends import_BaseModule.BaseModule {
139
140
  if (a.tag === "good_pass" && b.tag === "good_pass") {
140
141
  return compareByExpireTime(a, b);
141
142
  } else if (a.tag === "product_discount_card" && b.tag === "product_discount_card") {
142
- if (a.par_value !== b.par_value) {
143
- const valueA = new import_decimal.default(100).minus(a.par_value || 0);
144
- const valueB = new import_decimal.default(100).minus(b.par_value || 0);
145
- return valueA.minus(valueB).toNumber();
143
+ const typeA = ((_a = a.metadata) == null ? void 0 : _a.discount_card_type) || "percent";
144
+ const typeB = ((_b = b.metadata) == null ? void 0 : _b.discount_card_type) || "percent";
145
+ if (typeA === "fixed_amount" && typeB === "percent")
146
+ return -1;
147
+ if (typeA === "percent" && typeB === "fixed_amount")
148
+ return 1;
149
+ if (typeA === "fixed_amount" && typeB === "fixed_amount") {
150
+ if (a.par_value !== b.par_value) {
151
+ const valueA = new import_decimal.default(a.par_value || 0);
152
+ const valueB = new import_decimal.default(b.par_value || 0);
153
+ return valueB.minus(valueA).toNumber();
154
+ }
155
+ }
156
+ if (typeA === "percent" && typeB === "percent") {
157
+ if (a.par_value !== b.par_value) {
158
+ const valueA = new import_decimal.default(100).minus(a.par_value || 0);
159
+ const valueB = new import_decimal.default(100).minus(b.par_value || 0);
160
+ return valueB.minus(valueA).toNumber();
161
+ }
146
162
  }
147
163
  return compareByExpireTime(a, b);
148
164
  }
@@ -182,7 +198,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
182
198
  sortedProductList.forEach((originProduct) => {
183
199
  const product = this.hooks.getProduct(originProduct);
184
200
  addModeDiscount.forEach((discount) => {
185
- var _a, _b, _c;
201
+ var _a, _b, _c, _d;
186
202
  const limitedData = discount == null ? void 0 : discount.limited_relation_product_data;
187
203
  const isLimitedProduct = limitedData.type === "product_all" || limitedData.product_ids && limitedData.product_ids.includes(product.id);
188
204
  const isAvailableProduct = !((product == null ? void 0 : product.booking_id) && ((_a = product == null ? void 0 : product.discount_list) == null ? void 0 : _a.length) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.every((discount2) => discount2.id && ["good_pass", "discount_card", "product_discount_card"].includes(discount2.tag || discount2.type))));
@@ -195,6 +211,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
195
211
  type: discountType,
196
212
  tag: discountType,
197
213
  discount: {
214
+ discount_card_type: (_d = discount == null ? void 0 : discount.metadata) == null ? void 0 : _d.discount_card_type,
198
215
  resource_id: discount.id,
199
216
  title: discount.format_title,
200
217
  original_amount: product.origin_total,
@@ -212,7 +229,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
212
229
  });
213
230
  console.log(sortedProductList, "sortedProductListsortedProductList");
214
231
  sortedProductList.forEach((originProduct, i) => {
215
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
232
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
216
233
  const product = this.hooks.getProduct(originProduct);
217
234
  if ((product == null ? void 0 : product.booking_id) && ((_a = product.discount_list) == null ? void 0 : _a.length) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.every((discount) => discount.id && ["good_pass", "discount_card", "product_discount_card"].includes(discount.tag || discount.type)))) {
218
235
  processedProductsMap.set(product._id, [originProduct]);
@@ -322,12 +339,13 @@ var RulesModule = class extends import_BaseModule.BaseModule {
322
339
  if (Number(((_i = originProduct == null ? void 0 : originProduct._productInit) == null ? void 0 : _i.original_price) || 0) > 0 && product.origin_total && product.total && product.origin_total !== product.total) {
323
340
  productOriginTotal = product.total;
324
341
  }
325
- const targetProductTotal = selectedDiscount2.tag === "good_pass" ? new import_decimal.default(productOriginTotal).minus(new import_decimal.default(product.price || 0)).toNumber() : new import_decimal.default(100).minus(selectedDiscount2.par_value || 0).div(100).mul(new import_decimal.default(productOriginTotal)).toNumber();
342
+ const targetProductTotal = (0, import_utils.getDiscountAmount)(selectedDiscount2, productOriginTotal, product.price);
326
343
  const discountType = selectedDiscount2.tag === "product_discount_card" ? "discount_card" : selectedDiscount2.tag;
327
344
  const discountDetail = {
328
345
  amount: new import_decimal.default(productOriginTotal).minus(new import_decimal.default(targetProductTotal)).toNumber(),
329
346
  type: discountType,
330
347
  discount: {
348
+ discount_card_type: (_j = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _j.discount_card_type,
331
349
  resource_id: selectedDiscount2.id,
332
350
  title: selectedDiscount2.format_title,
333
351
  original_amount: productOriginTotal,
@@ -1,6 +1,8 @@
1
+ var __create = Object.create;
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
4
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
7
  var __export = (target, all) => {
6
8
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  return to;
16
18
  };
17
19
  var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/solution/Checkout/index.ts
@@ -24,6 +34,7 @@ __export(Checkout_exports, {
24
34
  });
25
35
  module.exports = __toCommonJS(Checkout_exports);
26
36
  var import_BaseModule = require("../../modules/BaseModule");
37
+ var import_decimal = __toESM(require("decimal.js"));
27
38
  var import_Order = require("../../modules/Order");
28
39
  var import_Payment = require("../../modules/Payment");
29
40
  var import_types = require("./types");
@@ -1077,9 +1088,9 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
1077
1088
  try {
1078
1089
  const syncResult = await this.syncOrderToBackendWithReturn(true);
1079
1090
  console.log("[Checkout] EFTPOS 支付后订单同步完成 (已标记为手动同步):", {
1080
- 订单ID: syncResult.orderId,
1081
- 是否已同步: this.store.isOrderSynced,
1082
- 后端响应: syncResult.response
1091
+ orderId: syncResult.orderId,
1092
+ isOrderSynced: this.store.isOrderSynced,
1093
+ backendResponse: syncResult.response
1083
1094
  });
1084
1095
  } catch (error) {
1085
1096
  console.error("[Checkout] EFTPOS 支付后订单同步失败:", error);
@@ -1156,8 +1167,8 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
1156
1167
  console.warn(
1157
1168
  "[Checkout] deletePaymentItemAsync: 检测到订单ID回退,保护真实订单ID:",
1158
1169
  {
1159
- 当前真实ID: currentOrderId,
1160
- 获取到的虚拟ID: updatedOrder.order_id
1170
+ currentRealId: currentOrderId,
1171
+ retrievedVirtualId: updatedOrder.order_id
1161
1172
  }
1162
1173
  );
1163
1174
  updatedOrder.order_id = currentOrderId;
@@ -1245,8 +1256,8 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
1245
1256
  console.warn(
1246
1257
  "[Checkout] updateVoucherPaymentItemsAsync: 检测到订单ID回退,保护真实订单ID:",
1247
1258
  {
1248
- 当前真实ID: currentOrderId,
1249
- 获取到的虚拟ID: updatedOrder.order_id
1259
+ currentRealId: currentOrderId,
1260
+ retrievedVirtualId: updatedOrder.order_id
1250
1261
  }
1251
1262
  );
1252
1263
  updatedOrder.order_id = currentOrderId;
@@ -1414,8 +1425,8 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
1414
1425
  return false;
1415
1426
  }
1416
1427
  const remainingAmount = await this.calculateRemainingAmountAsync();
1417
- const remainingValue = parseFloat(remainingAmount);
1418
- if (remainingValue > 0) {
1428
+ const remainingValue = new import_decimal.default(remainingAmount);
1429
+ if (remainingValue.gt(0)) {
1419
1430
  return false;
1420
1431
  }
1421
1432
  const currentPayments = await this.payment.getPaymentItemsAsync(
@@ -1490,11 +1501,11 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
1490
1501
  const finalOrderId = this.store.currentOrder.order_id;
1491
1502
  const finalIsVirtual = (0, import_utils.isVirtualOrderId)(finalOrderId);
1492
1503
  console.log("[Checkout] manualSyncOrderAsync 最终状态验证:", {
1493
- 返回的订单ID: syncResult.orderId,
1494
- 存储的订单ID: finalOrderId,
1495
- 存储的ID是否虚拟: finalIsVirtual,
1496
- 是否一致: syncResult.orderId === finalOrderId,
1497
- 同步状态: this.store.isOrderSynced
1504
+ returnedOrderId: syncResult.orderId,
1505
+ storedOrderId: finalOrderId,
1506
+ storedIdIsVirtual: finalIsVirtual,
1507
+ isConsistent: syncResult.orderId === finalOrderId,
1508
+ syncStatus: this.store.isOrderSynced
1498
1509
  });
1499
1510
  if (finalIsVirtual) {
1500
1511
  console.error("[Checkout] 严重警告:手动同步完成后订单ID仍为虚拟ID!");
@@ -1678,10 +1689,10 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
1678
1689
  });
1679
1690
  const finalOrderId = this.store.currentOrder.order_id;
1680
1691
  console.log("[Checkout] saveForLaterPaymentAsync 最终状态验证:", {
1681
- 返回的订单ID: syncResult.orderId,
1682
- 存储的订单ID: finalOrderId,
1683
- 是否一致: syncResult.orderId === finalOrderId,
1684
- 同步状态: this.store.isOrderSynced
1692
+ returnedOrderId: syncResult.orderId,
1693
+ storedOrderId: finalOrderId,
1694
+ isConsistent: syncResult.orderId === finalOrderId,
1695
+ syncStatus: this.store.isOrderSynced
1685
1696
  });
1686
1697
  return {
1687
1698
  success: true,
@@ -1934,40 +1945,53 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
1934
1945
  }
1935
1946
  try {
1936
1947
  const remainingAmountStr = await this.calculateRemainingAmountAsync();
1937
- const remainingAmount = parseFloat(remainingAmountStr);
1938
- const cashAmount = parseFloat(String(paymentItem.amount));
1948
+ let remainingAmount = new import_decimal.default(remainingAmountStr);
1949
+ const cashAmount = new import_decimal.default(String(paymentItem.amount));
1939
1950
  console.log("[Checkout] 现金支付处理:", {
1940
- cashAmount,
1941
- remainingAmount,
1942
- needsChange: cashAmount > remainingAmount
1951
+ cashAmount: cashAmount.toNumber(),
1952
+ remainingAmount: remainingAmount.toNumber(),
1953
+ needsChange: cashAmount.gt(remainingAmount)
1943
1954
  });
1944
- if (cashAmount <= remainingAmount) {
1955
+ if (cashAmount.lte(remainingAmount)) {
1945
1956
  return paymentItem;
1946
1957
  }
1947
- const changeAmount = cashAmount - remainingAmount;
1958
+ const changeAmount = cashAmount.sub(remainingAmount);
1959
+ if (Number(paymentItem.rounding_amount) > 0) {
1960
+ if (Number(paymentItem.rounding_amount) === changeAmount.toNumber()) {
1961
+ return paymentItem;
1962
+ } else {
1963
+ remainingAmount = remainingAmount.add(new import_decimal.default(paymentItem.rounding_amount || "0"));
1964
+ }
1965
+ }
1948
1966
  console.log("[Checkout] 现金支付需要找零:", {
1949
- actualPaidAmount: cashAmount,
1950
- chargedAmount: remainingAmount,
1951
- changeGivenAmount: changeAmount
1967
+ actualPaidAmount: cashAmount.toFixed(2),
1968
+ chargedAmount: remainingAmount.toFixed(2),
1969
+ changeGivenAmount: changeAmount.toFixed(2)
1952
1970
  });
1953
1971
  const processedPaymentItem = {
1954
1972
  ...paymentItem,
1955
- amount: remainingAmount,
1956
- // 将 amount 设置为剩余待付金额
1973
+ amount: remainingAmount.toFixed(2),
1974
+ // 将 amount 设置为剩余待付金额,保留2位小数
1957
1975
  metadata: {
1958
1976
  ...paymentItem.metadata,
1959
- actual_paid_amount: cashAmount,
1977
+ actual_paid_amount: cashAmount.toNumber(),
1960
1978
  // 实付金额
1961
- change_given_amount: changeAmount
1979
+ change_given_amount: changeAmount.toNumber()
1962
1980
  // 找零金额
1963
1981
  }
1964
1982
  };
1965
1983
  this.logInfo("Cash payment with change processed", {
1966
- originalAmount: cashAmount,
1967
- chargedAmount: remainingAmount,
1968
- changeAmount,
1984
+ originalAmount: cashAmount.toFixed(2),
1985
+ chargedAmount: remainingAmount.toFixed(2),
1986
+ changeAmount: changeAmount.toFixed(2),
1969
1987
  paymentCode: paymentItem.code,
1970
- paymentType: paymentItem.type
1988
+ paymentType: paymentItem.type,
1989
+ // 额外的精度验证信息
1990
+ decimalPrecisionCheck: {
1991
+ cashAmountPrecise: cashAmount.toString(),
1992
+ remainingAmountPrecise: remainingAmount.toString(),
1993
+ changeAmountPrecise: changeAmount.toString()
1994
+ }
1971
1995
  });
1972
1996
  return processedPaymentItem;
1973
1997
  } catch (error) {
@@ -2116,17 +2140,23 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
2116
2140
  }))
2117
2141
  });
2118
2142
  const paidAmount = payments.filter((payment) => payment.status !== "voided").reduce((sum, payment) => {
2119
- const amount = parseFloat(payment.amount || "0");
2120
- const roundingAmount = parseFloat(payment.rounding_amount || "0");
2121
- const effectiveAmount = amount + Math.abs(roundingAmount);
2143
+ const amount = new import_decimal.default(payment.amount || "0");
2144
+ const roundingAmount = new import_decimal.default(payment.rounding_amount || "0");
2145
+ const effectiveAmount = amount.add(roundingAmount.abs());
2122
2146
  console.log(`[Checkout] 计算支付项: ${payment.code}`, {
2123
- 原始金额: amount,
2124
- 抹零金额: roundingAmount,
2125
- 有效金额: effectiveAmount,
2126
- 说明: roundingAmount !== 0 ? `抹零金额 ${roundingAmount} 元,有效支付增加 ${Math.abs(roundingAmount)} 元` : "无抹零"
2147
+ originalAmount: amount.toFixed(2),
2148
+ roundingAmount: roundingAmount.toFixed(2),
2149
+ effectiveAmount: effectiveAmount.toFixed(2),
2150
+ description: !roundingAmount.isZero() ? `抹零金额 ${roundingAmount.toFixed(2)} 元,有效支付增加 ${roundingAmount.abs().toFixed(2)} 元` : "无抹零",
2151
+ // Decimal 精度验证
2152
+ preciseCalculationValues: {
2153
+ amount: amount.toString(),
2154
+ roundingAmount: roundingAmount.toString(),
2155
+ effectiveAmount: effectiveAmount.toString()
2156
+ }
2127
2157
  });
2128
- return sum + effectiveAmount;
2129
- }, 0);
2158
+ return sum.add(effectiveAmount);
2159
+ }, new import_decimal.default(0));
2130
2160
  const result = paidAmount.toFixed(2);
2131
2161
  console.log("[Checkout] calculatePaidAmountAsync: 计算结果 =", result);
2132
2162
  return result;
@@ -2143,17 +2173,25 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
2143
2173
  console.log("[Checkout] calculateRemainingAmountAsync: 没有当前订单");
2144
2174
  return "0.00";
2145
2175
  }
2146
- const totalAmount = parseFloat(this.store.currentOrder.total_amount || "0");
2147
- const paidAmount = parseFloat(await this.calculatePaidAmountAsync());
2148
- const remainingAmount = totalAmount - paidAmount;
2149
- const result = Math.max(0, remainingAmount).toFixed(2);
2176
+ const totalAmount = new import_decimal.default(this.store.currentOrder.total_amount || "0");
2177
+ const paidAmountStr = await this.calculatePaidAmountAsync();
2178
+ const paidAmount = new import_decimal.default(paidAmountStr);
2179
+ const remainingAmount = totalAmount.sub(paidAmount);
2180
+ const result = import_decimal.default.max(0, remainingAmount).toFixed(2);
2150
2181
  console.log("[Checkout] calculateRemainingAmountAsync: 计算详情:", {
2151
2182
  orderUuid: this.store.currentOrder.uuid,
2152
2183
  totalAmount: totalAmount.toFixed(2),
2153
2184
  paidAmount: paidAmount.toFixed(2),
2154
2185
  calculatedRemaining: remainingAmount.toFixed(2),
2155
2186
  finalResult: result,
2156
- 说明: "已支付金额包含抹零计算(amount + |rounding_amount|)"
2187
+ description: "已支付金额包含抹零计算(amount + |rounding_amount|)",
2188
+ // Decimal 精度验证
2189
+ preciseCalculationValues: {
2190
+ totalAmount: totalAmount.toString(),
2191
+ paidAmount: paidAmount.toString(),
2192
+ remainingAmount: remainingAmount.toString(),
2193
+ resultAfterMax: import_decimal.default.max(0, remainingAmount).toString()
2194
+ }
2157
2195
  });
2158
2196
  return result;
2159
2197
  }
@@ -2240,8 +2278,8 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
2240
2278
  return;
2241
2279
  }
2242
2280
  const remainingAmount = await this.calculateRemainingAmountAsync();
2243
- const remainingValue = parseFloat(remainingAmount);
2244
- if (remainingValue <= 0) {
2281
+ const remainingValue = new import_decimal.default(remainingAmount);
2282
+ if (remainingValue.lte(0)) {
2245
2283
  const totalAmount = this.store.currentOrder.total_amount;
2246
2284
  const paidAmount = await this.calculatePaidAmountAsync();
2247
2285
  console.log("[Checkout] 检测到订单支付完成:", {
@@ -2598,8 +2636,8 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
2598
2636
  const beforeManualUpdate = this.store.currentOrder.order_id;
2599
2637
  this.store.currentOrder.order_id = realOrderId;
2600
2638
  console.log("[Checkout] 手动设置订单ID:", {
2601
- 替换前: beforeManualUpdate,
2602
- 替换后: this.store.currentOrder.order_id,
2639
+ beforeReplacement: beforeManualUpdate,
2640
+ afterReplacement: this.store.currentOrder.order_id,
2603
2641
  目标ID: realOrderId
2604
2642
  });
2605
2643
  }
@@ -2621,10 +2659,10 @@ var CheckoutImpl = class extends import_BaseModule.BaseModule {
2621
2659
  const finalOrderId = this.store.currentOrder.order_id;
2622
2660
  const finalIsVirtual = (0, import_utils.isVirtualOrderId)(finalOrderId || "");
2623
2661
  console.log(`[Checkout] ${syncType}${operation}订单到后端完成`, {
2624
- 返回的订单ID: realOrderId,
2625
- 当前存储的订单ID: finalOrderId,
2626
- 是否还是虚拟ID: finalIsVirtual,
2627
- 是否同步: this.store.isOrderSynced
2662
+ returnedOrderId: realOrderId,
2663
+ currentStoredOrderId: finalOrderId,
2664
+ isStillVirtualId: finalIsVirtual,
2665
+ isSynced: this.store.isOrderSynced
2628
2666
  });
2629
2667
  if (finalIsVirtual && !isUpdateOperation) {
2630
2668
  console.warn(
@@ -1 +1,12 @@
1
+ import { Discount } from "../../modules/Discount/types";
1
2
  export declare const uniqueById: <T>(arr: T[], key?: string) => T[];
3
+ /**
4
+ * 获取折扣金额 基于折扣卡类型计算
5
+ * 商品券:直接返回商品价格
6
+ * 折扣卡:根据折扣卡类型计算 固定金额:直接返回折扣卡金额 百分比:根据折扣卡金额计算
7
+ * @param discount
8
+ * @param total
9
+ * @param price
10
+ * @returns
11
+ */
12
+ export declare const getDiscountAmount: (discount: Discount, total: number, price: number) => number;
@@ -1,6 +1,8 @@
1
+ var __create = Object.create;
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
4
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
7
  var __export = (target, all) => {
6
8
  for (var name in all)
@@ -14,19 +16,41 @@ var __copyProps = (to, from, except, desc) => {
14
16
  }
15
17
  return to;
16
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
+ ));
17
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
28
 
19
29
  // src/solution/ShopDiscount/utils.ts
20
30
  var utils_exports = {};
21
31
  __export(utils_exports, {
32
+ getDiscountAmount: () => getDiscountAmount,
22
33
  uniqueById: () => uniqueById
23
34
  });
24
35
  module.exports = __toCommonJS(utils_exports);
36
+ var import_decimal = __toESM(require("decimal.js"));
25
37
  var uniqueById = (arr, key = "id") => {
26
38
  const seen = /* @__PURE__ */ new Set();
27
39
  return arr.filter((item) => !seen.has(item[key]) && seen.add(item[key]));
28
40
  };
41
+ var getDiscountAmount = (discount, total, price) => {
42
+ var _a;
43
+ if (discount.tag === "good_pass") {
44
+ return new import_decimal.default(total).minus(new import_decimal.default(price || 0)).toNumber();
45
+ }
46
+ const isFixedAmount = ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.discount_card_type) === "fixed_amount";
47
+ if (isFixedAmount) {
48
+ return Math.max(new import_decimal.default(total).minus(new import_decimal.default(discount.par_value || 0)).toNumber(), 0);
49
+ }
50
+ return new import_decimal.default(100).minus(discount.par_value || 0).div(100).mul(new import_decimal.default(total)).toNumber();
51
+ };
29
52
  // Annotate the CommonJS export names for ESM import in node:
30
53
  0 && (module.exports = {
54
+ getDiscountAmount,
31
55
  uniqueById
32
56
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "1.0.62",
4
+ "version": "1.0.64",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",