@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.
- package/dist/modules/Cart/utils/cartProduct.js +9 -2
- package/dist/modules/Discount/types.d.ts +3 -0
- package/dist/modules/Rules/index.js +39 -12
- package/dist/solution/Checkout/index.js +106 -70
- package/dist/solution/ShopDiscount/utils.d.ts +11 -0
- package/dist/solution/ShopDiscount/utils.js +29 -0
- package/lib/modules/Cart/utils/cartProduct.js +9 -2
- package/lib/modules/Discount/types.d.ts +3 -0
- package/lib/modules/Rules/index.js +25 -7
- package/lib/solution/Checkout/index.js +96 -58
- package/lib/solution/ShopDiscount/utils.d.ts +11 -0
- package/lib/solution/ShopDiscount/utils.js +24 -0
- package/package.json +1 -1
|
@@ -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
|
|
196
|
-
price =
|
|
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
|
|
193
|
-
//
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
|
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
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
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
|
-
|
|
1939
|
-
|
|
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
|
-
|
|
2056
|
-
|
|
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 =
|
|
2315
|
-
if (!(
|
|
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
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
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
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
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
|
-
|
|
3118
|
-
|
|
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
|
|
3122
|
+
cashAmount: cashAmount.toNumber(),
|
|
3123
|
+
remainingAmount: remainingAmount.toNumber(),
|
|
3124
|
+
needsChange: cashAmount.gt(remainingAmount)
|
|
3123
3125
|
});
|
|
3124
3126
|
|
|
3125
3127
|
// 如果现金金额小于等于剩余待付金额,无需找零
|
|
3126
|
-
if (!(
|
|
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
|
|
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
|
|
3159
|
-
_context39.prev =
|
|
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
|
|
3185
|
+
case 29:
|
|
3165
3186
|
case "end":
|
|
3166
3187
|
return _context39.stop();
|
|
3167
3188
|
}
|
|
3168
|
-
}, _callee39, this, [[3,
|
|
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 =
|
|
3464
|
-
var roundingAmount =
|
|
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
|
|
3492
|
+
var effectiveAmount = amount.add(roundingAmount.abs());
|
|
3470
3493
|
console.log("[Checkout] \u8BA1\u7B97\u652F\u4ED8\u9879: ".concat(payment.code), {
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
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
|
|
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
|
-
|
|
3517
|
-
|
|
3518
|
-
_context43.next =
|
|
3545
|
+
// 使用 Decimal.js 进行安全的金额计算
|
|
3546
|
+
totalAmount = new Decimal(this.store.currentOrder.total_amount || '0');
|
|
3547
|
+
_context43.next = 6;
|
|
3519
3548
|
return this.calculatePaidAmountAsync();
|
|
3520
|
-
case
|
|
3521
|
-
|
|
3522
|
-
paidAmount =
|
|
3523
|
-
remainingAmount = totalAmount
|
|
3524
|
-
result =
|
|
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
|
-
|
|
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
|
|
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 =
|
|
3710
|
-
if (!(
|
|
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
|
-
|
|
4228
|
-
|
|
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
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
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
|
-
|
|
188
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return
|
|
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 =
|
|
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
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
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
|
-
|
|
1160
|
-
|
|
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
|
-
|
|
1249
|
-
|
|
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 =
|
|
1418
|
-
if (remainingValue
|
|
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
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
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
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
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
|
-
|
|
1938
|
-
const cashAmount =
|
|
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
|
|
1951
|
+
cashAmount: cashAmount.toNumber(),
|
|
1952
|
+
remainingAmount: remainingAmount.toNumber(),
|
|
1953
|
+
needsChange: cashAmount.gt(remainingAmount)
|
|
1943
1954
|
});
|
|
1944
|
-
if (cashAmount
|
|
1955
|
+
if (cashAmount.lte(remainingAmount)) {
|
|
1945
1956
|
return paymentItem;
|
|
1946
1957
|
}
|
|
1947
|
-
const changeAmount = cashAmount
|
|
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 =
|
|
2120
|
-
const roundingAmount =
|
|
2121
|
-
const effectiveAmount = amount
|
|
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
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
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
|
|
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 =
|
|
2147
|
-
const
|
|
2148
|
-
const
|
|
2149
|
-
const
|
|
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
|
-
|
|
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 =
|
|
2244
|
-
if (remainingValue
|
|
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
|
-
|
|
2602
|
-
|
|
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
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
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
|
});
|