@pisell/pisellos 2.2.273 → 2.2.275
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/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +12 -10
- package/dist/modules/Order/index.d.ts +7 -6
- package/dist/modules/Order/index.js +217 -115
- package/dist/modules/Order/types.d.ts +23 -3
- package/dist/modules/Order/types.js +11 -0
- package/dist/modules/Payment/index.js +1 -1
- package/dist/modules/Payment/types.d.ts +81 -4
- package/dist/modules/Payment/types.js +18 -3
- package/dist/modules/Payment/walletpass.d.ts +38 -1
- package/dist/modules/Payment/walletpass.js +917 -114
- package/dist/modules/Rules/index.d.ts +2 -0
- package/dist/modules/Rules/index.js +78 -64
- package/dist/modules/SalesSummary/utils.js +7 -1
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.js +27 -18
- package/dist/server/modules/index.d.ts +1 -1
- package/dist/server/modules/order/index.d.ts +16 -0
- package/dist/server/modules/order/index.js +964 -776
- package/dist/server/modules/order/types.d.ts +14 -0
- package/dist/server/modules/order/types.js +6 -0
- package/dist/solution/BaseSales/index.d.ts +80 -15
- package/dist/solution/BaseSales/index.js +1498 -444
- package/dist/solution/BaseSales/types.d.ts +55 -1
- package/dist/solution/BaseSales/types.js +2 -1
- package/dist/solution/BaseSales/utils/cartPromotion.js +8 -3
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +6 -3
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +12 -3
- package/dist/solution/BookingTicket/types.d.ts +4 -0
- package/dist/solution/BookingTicket/utils/cartView.js +44 -32
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +173 -83
- package/dist/solution/Sales/index.d.ts +1 -0
- package/dist/solution/Sales/index.js +16 -2
- package/dist/solution/VenueBooking/index.d.ts +1 -0
- package/lib/model/strategy/adapter/promotion/index.js +0 -51
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +3 -1
- package/lib/modules/Order/index.d.ts +7 -6
- package/lib/modules/Order/index.js +127 -20
- package/lib/modules/Order/types.d.ts +23 -3
- package/lib/modules/Payment/index.js +1 -1
- package/lib/modules/Payment/types.d.ts +81 -4
- package/lib/modules/Payment/types.js +4 -3
- package/lib/modules/Payment/walletpass.d.ts +38 -1
- package/lib/modules/Payment/walletpass.js +730 -21
- package/lib/modules/Rules/index.d.ts +2 -0
- package/lib/modules/Rules/index.js +24 -14
- package/lib/modules/SalesSummary/utils.js +5 -1
- package/lib/server/index.d.ts +4 -0
- package/lib/server/index.js +14 -6
- package/lib/server/modules/index.d.ts +1 -1
- package/lib/server/modules/order/index.d.ts +16 -0
- package/lib/server/modules/order/index.js +140 -4
- package/lib/server/modules/order/types.d.ts +14 -0
- package/lib/server/modules/order/types.js +1 -0
- package/lib/solution/BaseSales/index.d.ts +80 -15
- package/lib/solution/BaseSales/index.js +712 -48
- package/lib/solution/BaseSales/types.d.ts +55 -1
- package/lib/solution/BaseSales/types.js +2 -1
- package/lib/solution/BaseSales/utils/cartPromotion.js +8 -2
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +3 -2
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +4 -1
- package/lib/solution/BookingTicket/types.d.ts +4 -0
- package/lib/solution/BookingTicket/utils/cartView.js +43 -30
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +37 -5
- package/lib/solution/Sales/index.d.ts +1 -0
- package/lib/solution/Sales/index.js +15 -3
- package/lib/solution/VenueBooking/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -49,6 +49,88 @@ var import_Quotation = require("../../modules/Quotation");
|
|
|
49
49
|
var import_transformBaseProductToOrderProduct = require("./utils/transformBaseProductToOrderProduct");
|
|
50
50
|
var import_quotationPrice = require("./utils/quotationPrice");
|
|
51
51
|
var SERVER_ORDER_CHANGED_EVENT = "order:onOrdersChanged";
|
|
52
|
+
var WALLET_PAYMENT_CODE_BY_TAG = {
|
|
53
|
+
product_voucher: "PRODUCTVOUCHER",
|
|
54
|
+
gift_card: "GIFTCARD",
|
|
55
|
+
point_card: "POINTCARD"
|
|
56
|
+
};
|
|
57
|
+
function getSharedWalletAssetId(asset) {
|
|
58
|
+
return (asset == null ? void 0 : asset.id) ?? (asset == null ? void 0 : asset.voucher_id) ?? (asset == null ? void 0 : asset.code);
|
|
59
|
+
}
|
|
60
|
+
function getSharedWalletAssetAmount(asset) {
|
|
61
|
+
const value = (asset == null ? void 0 : asset.edit_current_amount) ?? (asset == null ? void 0 : asset._available_max_amount) ?? ((asset == null ? void 0 : asset.tag) === "point_card" ? asset == null ? void 0 : asset.recommended_usage_amount : asset == null ? void 0 : asset.available_max_amount) ?? (asset == null ? void 0 : asset.actualDeduction) ?? (asset == null ? void 0 : asset.amount) ?? 0;
|
|
62
|
+
const amount = Number(value);
|
|
63
|
+
return Number.isFinite(amount) && amount > 0 ? amount : 0;
|
|
64
|
+
}
|
|
65
|
+
function isRejectedSalesSubmitResult(result) {
|
|
66
|
+
var _a, _b;
|
|
67
|
+
const candidates = [
|
|
68
|
+
result,
|
|
69
|
+
result == null ? void 0 : result.data,
|
|
70
|
+
(_a = result == null ? void 0 : result.response) == null ? void 0 : _a.data,
|
|
71
|
+
(_b = result == null ? void 0 : result.response) == null ? void 0 : _b.body
|
|
72
|
+
];
|
|
73
|
+
return candidates.some((candidate) => {
|
|
74
|
+
if (!candidate || typeof candidate !== "object")
|
|
75
|
+
return false;
|
|
76
|
+
const responseCode = Number(candidate.code ?? candidate.statusCode);
|
|
77
|
+
if (Number.isFinite(responseCode) && responseCode >= 400)
|
|
78
|
+
return true;
|
|
79
|
+
if (candidate.status === false || candidate.success === false || candidate.result === false) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
return ["failed", "error"].includes(
|
|
83
|
+
String(candidate.status || "").toLowerCase()
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function getSalesSubmitErrorMessage(result) {
|
|
88
|
+
var _a, _b;
|
|
89
|
+
return (result == null ? void 0 : result.message) || (result == null ? void 0 : result.msg) || ((_a = result == null ? void 0 : result.data) == null ? void 0 : _a.message) || ((_b = result == null ? void 0 : result.data) == null ? void 0 : _b.msg) || "Wallet 支付确认失败";
|
|
90
|
+
}
|
|
91
|
+
function toWalletFundValue(value) {
|
|
92
|
+
try {
|
|
93
|
+
return new import_decimal.default(value || 0).toDecimalPlaces(2).toFixed(2);
|
|
94
|
+
} catch {
|
|
95
|
+
return "0.00";
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function subtractWalletFundValue(left, right) {
|
|
99
|
+
try {
|
|
100
|
+
return new import_decimal.default(left || 0).minus(right || 0).toDecimalPlaces(2).toFixed(2);
|
|
101
|
+
} catch {
|
|
102
|
+
return "0.00";
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function getSharedWalletPassUseValue(params) {
|
|
106
|
+
const { asset, amount, paymentMethod } = params;
|
|
107
|
+
const configuredValue = Number(asset == null ? void 0 : asset.wallet_pass_use_value);
|
|
108
|
+
if (Number.isFinite(configuredValue) && configuredValue > 0) {
|
|
109
|
+
return configuredValue;
|
|
110
|
+
}
|
|
111
|
+
const isPointCard = (asset == null ? void 0 : asset.tag) === "point_card" || paymentMethod.code === "POINTCARD";
|
|
112
|
+
const usageUnit = asset == null ? void 0 : asset.wallet_pass_usage_unit;
|
|
113
|
+
if (isPointCard && (usageUnit == null ? void 0 : usageUnit.points) && (usageUnit == null ? void 0 : usageUnit.price)) {
|
|
114
|
+
return new import_decimal.default(amount).div(usageUnit.price).mul(usageUnit.points).toDecimalPlaces(2, import_decimal.default.ROUND_DOWN).toNumber();
|
|
115
|
+
}
|
|
116
|
+
return amount;
|
|
117
|
+
}
|
|
118
|
+
function buildSharedWalletFundRecord(params) {
|
|
119
|
+
const { asset, amount, paymentMethod } = params;
|
|
120
|
+
const isPointCard = (asset == null ? void 0 : asset.tag) === "point_card" || paymentMethod.code === "POINTCARD";
|
|
121
|
+
const usingBeforeValue = (asset == null ? void 0 : asset.balance_par_value) ?? (asset == null ? void 0 : asset.balance) ?? (asset == null ? void 0 : asset.using_before_value) ?? 0;
|
|
122
|
+
const walletPassUseValue = getSharedWalletPassUseValue(params);
|
|
123
|
+
const usingValue = isPointCard ? walletPassUseValue : amount;
|
|
124
|
+
const walletPassName = (asset == null ? void 0 : asset.wallet_pass_name) || (asset == null ? void 0 : asset.format_title) || (asset == null ? void 0 : asset.product_name) || (asset == null ? void 0 : asset.name) || paymentMethod.name;
|
|
125
|
+
return {
|
|
126
|
+
voucher_id: (asset == null ? void 0 : asset.voucher_id) ?? (asset == null ? void 0 : asset.id),
|
|
127
|
+
wallet_pass_name: walletPassName && typeof walletPassName === "object" ? walletPassName : { default: walletPassName || "" },
|
|
128
|
+
code: (asset == null ? void 0 : asset.code) || (asset == null ? void 0 : asset.tag),
|
|
129
|
+
encoded: asset == null ? void 0 : asset.encoded,
|
|
130
|
+
using_before_value: toWalletFundValue(usingBeforeValue),
|
|
131
|
+
using_after_value: subtractWalletFundValue(usingBeforeValue, usingValue)
|
|
132
|
+
};
|
|
133
|
+
}
|
|
52
134
|
function isBaseSalesManualProductDiscountProduct(product) {
|
|
53
135
|
var _a, _b;
|
|
54
136
|
return ((_a = product == null ? void 0 : product.metadata) == null ? void 0 : _a.is_manual_discount) === true || ((_b = product == null ? void 0 : product.metadata) == null ? void 0 : _b.is_manual_discount) === 1 || ((product == null ? void 0 : product.discount_list) || []).some((item) => (item == null ? void 0 : item.type) === "product");
|
|
@@ -348,6 +430,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
348
430
|
this.autoPaymentSyncTimer = null;
|
|
349
431
|
this.salesDetailLoadInFlightCount = 0;
|
|
350
432
|
this.salesDetailLoadSequence = 0;
|
|
433
|
+
this.walletAssetsRefreshSequence = 0;
|
|
351
434
|
this.salesDetailHydrateQueue = Promise.resolve();
|
|
352
435
|
this.serverOrderChangeUnsubscribe = null;
|
|
353
436
|
this.serverOrderChangeHydrateInFlight = null;
|
|
@@ -619,6 +702,36 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
619
702
|
return null;
|
|
620
703
|
return productId;
|
|
621
704
|
}
|
|
705
|
+
/**
|
|
706
|
+
* Change Time / customer reprice 必须沿用商品列表的渠道口径。
|
|
707
|
+
* SalesSdk Provider 通常将渠道存为 platform,因此不能只读取 otherParams.channel。
|
|
708
|
+
*/
|
|
709
|
+
getPriceQueryChannel(channel) {
|
|
710
|
+
var _a, _b, _c;
|
|
711
|
+
const strategyContext = ((_a = this.otherParams) == null ? void 0 : _a.strategy_context) && typeof this.otherParams.strategy_context === "object" ? this.otherParams.strategy_context : {};
|
|
712
|
+
const value = channel ?? strategyContext.channel ?? ((_b = this.otherParams) == null ? void 0 : _b.channel) ?? ((_c = this.otherParams) == null ? void 0 : _c.platform);
|
|
713
|
+
if (value === void 0 || value === null || String(value).trim() === "") {
|
|
714
|
+
return void 0;
|
|
715
|
+
}
|
|
716
|
+
return String(value).trim();
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* /product/query 的智能定价评估只读取 strategy_context;
|
|
720
|
+
* application_code 仅作为接口兼容字段,不能替代 channel / business_code。
|
|
721
|
+
*/
|
|
722
|
+
getPriceQueryStrategyContext(channel) {
|
|
723
|
+
var _a, _b, _c;
|
|
724
|
+
const inherited = ((_a = this.otherParams) == null ? void 0 : _a.strategy_context) && typeof this.otherParams.strategy_context === "object" ? this.otherParams.strategy_context : {};
|
|
725
|
+
const strategyContext = { ...inherited };
|
|
726
|
+
const resolvedChannel = this.getPriceQueryChannel(channel);
|
|
727
|
+
const businessCode = strategyContext.business_code ?? ((_b = this.otherParams) == null ? void 0 : _b.businessCode) ?? ((_c = this.otherParams) == null ? void 0 : _c.business_code);
|
|
728
|
+
if (resolvedChannel)
|
|
729
|
+
strategyContext.channel = resolvedChannel;
|
|
730
|
+
if (businessCode !== void 0 && businessCode !== null && String(businessCode).trim() !== "") {
|
|
731
|
+
strategyContext.business_code = String(businessCode).trim();
|
|
732
|
+
}
|
|
733
|
+
return strategyContext;
|
|
734
|
+
}
|
|
622
735
|
getPriceQuerySchedule(params) {
|
|
623
736
|
const booking = params.booking || {};
|
|
624
737
|
if (typeof booking.start_date === "string" && booking.start_date.trim()) {
|
|
@@ -646,13 +759,15 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
646
759
|
};
|
|
647
760
|
}
|
|
648
761
|
async loadProductsForPriceQuery(params) {
|
|
649
|
-
var _a
|
|
762
|
+
var _a;
|
|
650
763
|
const ids = Array.from(new Set(
|
|
651
764
|
params.ids.filter((id) => Number.isFinite(id))
|
|
652
765
|
));
|
|
653
766
|
const productsById = /* @__PURE__ */ new Map();
|
|
654
767
|
if (!ids.length || !this.request)
|
|
655
768
|
return productsById;
|
|
769
|
+
const channel = this.getPriceQueryChannel(params.channel);
|
|
770
|
+
const strategyContext = this.getPriceQueryStrategyContext(channel);
|
|
656
771
|
try {
|
|
657
772
|
const response = await this.request.post("/product/query", {
|
|
658
773
|
ids,
|
|
@@ -664,13 +779,14 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
664
779
|
customer_id: params.customerId,
|
|
665
780
|
schedule_date: params.schedule.schedule_date,
|
|
666
781
|
schedule_datetime: params.schedule.schedule_datetime,
|
|
667
|
-
application_code:
|
|
782
|
+
application_code: channel,
|
|
783
|
+
...Object.keys(strategyContext).length ? { strategy_context: strategyContext } : {}
|
|
668
784
|
}, {
|
|
669
785
|
osServer: true,
|
|
670
786
|
customToast: () => {
|
|
671
787
|
}
|
|
672
788
|
});
|
|
673
|
-
const list = ((
|
|
789
|
+
const list = ((_a = response == null ? void 0 : response.data) == null ? void 0 : _a.list) || (response == null ? void 0 : response.list) || [];
|
|
674
790
|
if (!Array.isArray(list))
|
|
675
791
|
return productsById;
|
|
676
792
|
list.forEach((item) => {
|
|
@@ -993,6 +1109,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
993
1109
|
this.paymentNumberDevicePrefix = null;
|
|
994
1110
|
this.queuedServerOrderChanges = [];
|
|
995
1111
|
this.salesDetailLoadSequence += 1;
|
|
1112
|
+
this.walletAssetsRefreshSequence += 1;
|
|
996
1113
|
await this.core.effects.emit(`${this.name}:onDestroy`, {});
|
|
997
1114
|
super.destroy();
|
|
998
1115
|
}
|
|
@@ -1107,10 +1224,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1107
1224
|
const result = ((_a = this.store.order) == null ? void 0 : _a.getTempOrder()) || null;
|
|
1108
1225
|
return result;
|
|
1109
1226
|
}
|
|
1110
|
-
async replaceTempOrder(tempOrder) {
|
|
1227
|
+
async replaceTempOrder(tempOrder, options) {
|
|
1111
1228
|
if (!this.store.order)
|
|
1112
1229
|
throw new Error("order 模块未初始化");
|
|
1113
|
-
const nextTempOrder = await this.store.order.replaceTempOrder(tempOrder);
|
|
1230
|
+
const nextTempOrder = await this.store.order.replaceTempOrder(tempOrder, options);
|
|
1114
1231
|
await this.effectsEmit("onTempOrderReplaced", { tempOrder: nextTempOrder });
|
|
1115
1232
|
return nextTempOrder;
|
|
1116
1233
|
}
|
|
@@ -1209,6 +1326,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1209
1326
|
// 重置 tempOrder 与与上一单强相关的运行态(resource/entryPaxNumber/enabledReservationRuleProducts),
|
|
1210
1327
|
// 适用于从支付页通过 react-router 跳回继续下单时清理残留数据
|
|
1211
1328
|
async restoreOrder() {
|
|
1329
|
+
var _a;
|
|
1212
1330
|
try {
|
|
1213
1331
|
if (!this.store.order) {
|
|
1214
1332
|
throw new Error("scanOrder 解决方案需要 order 模块支持");
|
|
@@ -1217,6 +1335,12 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1217
1335
|
this.currentSalesDetail = null;
|
|
1218
1336
|
this.discountConfigCacheKey = null;
|
|
1219
1337
|
this.hasManualDiscountSelection = false;
|
|
1338
|
+
const wallet = (_a = this.store.payment) == null ? void 0 : _a.wallet;
|
|
1339
|
+
if (wallet) {
|
|
1340
|
+
this.walletAssetsRefreshSequence += 1;
|
|
1341
|
+
wallet.clearAllCache();
|
|
1342
|
+
await this.publishWalletAssetsState(wallet.getWalletAssetsState());
|
|
1343
|
+
}
|
|
1220
1344
|
await this.effectsEmit("onTempOrderReplaced", { tempOrder });
|
|
1221
1345
|
if (this.syncAppDataToTempOrder(tempOrder) && this.isTempOrderPersistEnabled()) {
|
|
1222
1346
|
this.store.order.persistTempOrder();
|
|
@@ -1629,6 +1753,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1629
1753
|
}
|
|
1630
1754
|
return {
|
|
1631
1755
|
isAvailable: raw.isAvailable,
|
|
1756
|
+
...raw.isAccepted !== void 0 ? { isAccepted: raw.isAccepted } : {},
|
|
1632
1757
|
type: raw.type,
|
|
1633
1758
|
unavailableReason: raw.unavailableReason,
|
|
1634
1759
|
scannedDiscountList: raw.scannedDiscountList
|
|
@@ -2206,7 +2331,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2206
2331
|
confirmPendingVoucherPayments() {
|
|
2207
2332
|
if (!this.store.order)
|
|
2208
2333
|
throw new Error("order 模块未初始化");
|
|
2209
|
-
|
|
2334
|
+
const payments = this.store.order.confirmPendingVoucherPayments();
|
|
2335
|
+
if (this.store.payment) {
|
|
2336
|
+
const committed = this.getCommittedWalletAssets();
|
|
2337
|
+
const state = this.store.payment.wallet.setCommittedWalletAssets(
|
|
2338
|
+
committed.ids,
|
|
2339
|
+
committed.assets
|
|
2340
|
+
);
|
|
2341
|
+
void this.publishWalletAssetsState(state);
|
|
2342
|
+
}
|
|
2343
|
+
return payments;
|
|
2210
2344
|
}
|
|
2211
2345
|
discardPendingVoucherPayments() {
|
|
2212
2346
|
if (!this.store.order)
|
|
@@ -2267,24 +2401,14 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2267
2401
|
});
|
|
2268
2402
|
return walletProducts;
|
|
2269
2403
|
}
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
if (!this.store.payment)
|
|
2274
|
-
throw new Error("payment 模块未初始化");
|
|
2275
|
-
const snapshot = this.store.order.getOrderSnapshot();
|
|
2404
|
+
buildWalletInitBusinessData(params) {
|
|
2405
|
+
var _a;
|
|
2406
|
+
const snapshot = (_a = this.store.order) == null ? void 0 : _a.getOrderSnapshot();
|
|
2276
2407
|
const tempOrder = snapshot == null ? void 0 : snapshot.tempOrder;
|
|
2277
2408
|
const amount = snapshot == null ? void 0 : snapshot.amount;
|
|
2278
|
-
if (!tempOrder || !amount)
|
|
2279
|
-
return
|
|
2280
|
-
|
|
2281
|
-
userIdentificationCodes: [],
|
|
2282
|
-
transformList: [],
|
|
2283
|
-
noApplicableVoucher: [],
|
|
2284
|
-
products: []
|
|
2285
|
-
};
|
|
2286
|
-
}
|
|
2287
|
-
const walletBusinessData = {
|
|
2409
|
+
if (!tempOrder || !amount)
|
|
2410
|
+
return null;
|
|
2411
|
+
return {
|
|
2288
2412
|
customer_id: tempOrder.customer_id ? Number(tempOrder.customer_id) : void 0,
|
|
2289
2413
|
holder: tempOrder.holder,
|
|
2290
2414
|
amountInfo: {
|
|
@@ -2298,11 +2422,29 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2298
2422
|
is_price_include_tax: tempOrder.is_price_include_tax ?? this.otherParams.is_price_include_tax ?? 1,
|
|
2299
2423
|
...snapshot.identity.orderId ? { payment_order_id: String(snapshot.identity.orderId) } : {}
|
|
2300
2424
|
};
|
|
2425
|
+
}
|
|
2426
|
+
async initWalletData(params) {
|
|
2427
|
+
var _a;
|
|
2428
|
+
if (!this.store.order)
|
|
2429
|
+
throw new Error("order 模块未初始化");
|
|
2430
|
+
if (!this.store.payment)
|
|
2431
|
+
throw new Error("payment 模块未初始化");
|
|
2432
|
+
const snapshot = this.store.order.getOrderSnapshot();
|
|
2433
|
+
const walletBusinessData = this.buildWalletInitBusinessData(params);
|
|
2434
|
+
if (!walletBusinessData) {
|
|
2435
|
+
return {
|
|
2436
|
+
walletRecommendList: [],
|
|
2437
|
+
userIdentificationCodes: [],
|
|
2438
|
+
transformList: [],
|
|
2439
|
+
noApplicableVoucher: [],
|
|
2440
|
+
products: []
|
|
2441
|
+
};
|
|
2442
|
+
}
|
|
2301
2443
|
const result = await this.store.payment.wallet.initializeWalletDataFromBusinessAsync(
|
|
2302
2444
|
walletBusinessData
|
|
2303
2445
|
);
|
|
2304
2446
|
await this.core.effects.emit(`${this.name}:onWalletDataInitialized`, {
|
|
2305
|
-
orderId: snapshot.identity.orderId,
|
|
2447
|
+
orderId: (_a = snapshot == null ? void 0 : snapshot.identity) == null ? void 0 : _a.orderId,
|
|
2306
2448
|
customerId: walletBusinessData.customer_id,
|
|
2307
2449
|
walletBusinessData: {
|
|
2308
2450
|
customer_id: walletBusinessData.customer_id,
|
|
@@ -2313,6 +2455,208 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2313
2455
|
});
|
|
2314
2456
|
return result;
|
|
2315
2457
|
}
|
|
2458
|
+
getCommittedWalletAssets() {
|
|
2459
|
+
var _a, _b;
|
|
2460
|
+
const payments = ((_b = (_a = this.store.order) == null ? void 0 : _a.getOrderPayments) == null ? void 0 : _b.call(_a)) || [];
|
|
2461
|
+
const committed = payments.filter((payment) => {
|
|
2462
|
+
const voucherId = payment == null ? void 0 : payment.voucher_id;
|
|
2463
|
+
if (voucherId === void 0 || voucherId === null || voucherId === 0) {
|
|
2464
|
+
return false;
|
|
2465
|
+
}
|
|
2466
|
+
return (payment == null ? void 0 : payment.status) === "paid" || (payment == null ? void 0 : payment.isSynced) === true || (payment == null ? void 0 : payment.order_payment_id) !== void 0 && (payment == null ? void 0 : payment.order_payment_id) !== null && (payment == null ? void 0 : payment.order_payment_id) !== "";
|
|
2467
|
+
});
|
|
2468
|
+
return {
|
|
2469
|
+
ids: committed.map((payment) => payment.voucher_id),
|
|
2470
|
+
assets: committed.map((payment) => {
|
|
2471
|
+
var _a2;
|
|
2472
|
+
const fundRecord = (payment == null ? void 0 : payment.fund_record) || {};
|
|
2473
|
+
const walletPassName = fundRecord.wallet_pass_name;
|
|
2474
|
+
const title = walletPassName && typeof walletPassName === "object" ? walletPassName.default || Object.values(walletPassName)[0] : walletPassName;
|
|
2475
|
+
const code = String((payment == null ? void 0 : payment.code) || "").toUpperCase();
|
|
2476
|
+
const tag = ((_a2 = Object.entries(WALLET_PAYMENT_CODE_BY_TAG).find(
|
|
2477
|
+
([, paymentCode]) => paymentCode === code
|
|
2478
|
+
)) == null ? void 0 : _a2[0]) || fundRecord.tag;
|
|
2479
|
+
return {
|
|
2480
|
+
id: payment.voucher_id,
|
|
2481
|
+
voucher_id: payment.voucher_id,
|
|
2482
|
+
code: fundRecord.code,
|
|
2483
|
+
tag,
|
|
2484
|
+
product_name: title || payment.name,
|
|
2485
|
+
name: title || payment.name,
|
|
2486
|
+
amount: Number(payment.amount || 0),
|
|
2487
|
+
_available_max_amount: Number(payment.amount || 0),
|
|
2488
|
+
unified_available_status: 1,
|
|
2489
|
+
_unified_available_status: 1,
|
|
2490
|
+
_committed_payment: payment
|
|
2491
|
+
};
|
|
2492
|
+
})
|
|
2493
|
+
};
|
|
2494
|
+
}
|
|
2495
|
+
async publishWalletAssetsState(state) {
|
|
2496
|
+
await this.effectsEmit(import_types.BaseSalesHookNames.onWalletAssetsStateChanged, {
|
|
2497
|
+
state
|
|
2498
|
+
});
|
|
2499
|
+
return state;
|
|
2500
|
+
}
|
|
2501
|
+
async syncSelectedWalletAssets(state) {
|
|
2502
|
+
if (!this.store.order || !this.store.payment) {
|
|
2503
|
+
throw new Error("订单或支付模块未初始化");
|
|
2504
|
+
}
|
|
2505
|
+
let paymentMethods = this.getPaymentMethods();
|
|
2506
|
+
if (!paymentMethods.length && state.selectedItems.length) {
|
|
2507
|
+
paymentMethods = await this.getPaymentMethodsAsync();
|
|
2508
|
+
}
|
|
2509
|
+
const methodByCode = new Map(
|
|
2510
|
+
paymentMethods.map((method) => [String(method.code || "").toUpperCase(), method])
|
|
2511
|
+
);
|
|
2512
|
+
const preparePayments = this.store.payment.wallet.formatWalletPassList2PreparePayments(
|
|
2513
|
+
state.selectedItems
|
|
2514
|
+
);
|
|
2515
|
+
const selectedAssetById = new Map(
|
|
2516
|
+
state.selectedItems.map((asset) => [
|
|
2517
|
+
String(getSharedWalletAssetId(asset)),
|
|
2518
|
+
asset
|
|
2519
|
+
])
|
|
2520
|
+
);
|
|
2521
|
+
const voucherPayments = preparePayments.flatMap((item) => {
|
|
2522
|
+
const asset = selectedAssetById.get(String(item.voucher_id));
|
|
2523
|
+
const paymentCode = WALLET_PAYMENT_CODE_BY_TAG[String(item.tag || (asset == null ? void 0 : asset.tag) || "")] || String(item.tag || (asset == null ? void 0 : asset.tag) || "").toUpperCase();
|
|
2524
|
+
const paymentMethod = methodByCode.get(paymentCode);
|
|
2525
|
+
const formattedAmount = Number(item.amount);
|
|
2526
|
+
const amount = Number.isFinite(formattedAmount) && formattedAmount > 0 ? formattedAmount : getSharedWalletAssetAmount(asset);
|
|
2527
|
+
if (!asset || !paymentMethod || !Number.isFinite(amount) || amount <= 0) {
|
|
2528
|
+
return [];
|
|
2529
|
+
}
|
|
2530
|
+
const walletPassUseValue = getSharedWalletPassUseValue({
|
|
2531
|
+
asset,
|
|
2532
|
+
amount,
|
|
2533
|
+
paymentMethod
|
|
2534
|
+
});
|
|
2535
|
+
return [
|
|
2536
|
+
{
|
|
2537
|
+
amount: amount.toFixed(2),
|
|
2538
|
+
code: paymentMethod.code,
|
|
2539
|
+
custom_payment_id: paymentMethod.id,
|
|
2540
|
+
name: paymentMethod.name,
|
|
2541
|
+
type: paymentMethod.type,
|
|
2542
|
+
voucher_id: item.voucher_id,
|
|
2543
|
+
wallet_pass_usage_unit: item.wallet_pass_usage_unit,
|
|
2544
|
+
wallet_pass_use_value: walletPassUseValue,
|
|
2545
|
+
fund_record: buildSharedWalletFundRecord({
|
|
2546
|
+
asset,
|
|
2547
|
+
amount,
|
|
2548
|
+
paymentMethod
|
|
2549
|
+
})
|
|
2550
|
+
}
|
|
2551
|
+
];
|
|
2552
|
+
});
|
|
2553
|
+
const payments = this.updateVoucherOrderPayments(voucherPayments, {
|
|
2554
|
+
status: "payment_pending"
|
|
2555
|
+
});
|
|
2556
|
+
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
2557
|
+
return payments;
|
|
2558
|
+
}
|
|
2559
|
+
/** 读取购物车与 Shared Checkout 共用的钱包资产状态。 */
|
|
2560
|
+
getWalletAssetsState() {
|
|
2561
|
+
if (!this.store.payment)
|
|
2562
|
+
throw new Error("payment 模块未初始化");
|
|
2563
|
+
return this.store.payment.wallet.getWalletAssetsState();
|
|
2564
|
+
}
|
|
2565
|
+
/** 导出 Shared Checkout 跨运行时恢复所需的钱包状态与搜索缓存。 */
|
|
2566
|
+
exportWalletAssetsSnapshot() {
|
|
2567
|
+
if (!this.store.payment)
|
|
2568
|
+
throw new Error("payment 模块未初始化");
|
|
2569
|
+
return this.store.payment.wallet.exportWalletAssetsSnapshot();
|
|
2570
|
+
}
|
|
2571
|
+
/** 配置仅影响 Wallet Assets,不改变 Promotion/Voucher 选择流程。 */
|
|
2572
|
+
configureWalletAssetsBehavior(options) {
|
|
2573
|
+
if (!this.store.payment)
|
|
2574
|
+
throw new Error("payment 模块未初始化");
|
|
2575
|
+
this.store.payment.wallet.configureWalletAssetsBehavior(options);
|
|
2576
|
+
}
|
|
2577
|
+
/**
|
|
2578
|
+
* 恢复 Shared Checkout 钱包快照,并把选择重新同步为订单 pending payment。
|
|
2579
|
+
*/
|
|
2580
|
+
async importWalletAssetsSnapshot(snapshot) {
|
|
2581
|
+
if (!this.store.payment)
|
|
2582
|
+
throw new Error("payment 模块未初始化");
|
|
2583
|
+
const state = this.store.payment.wallet.importWalletAssetsSnapshot(snapshot);
|
|
2584
|
+
await this.syncSelectedWalletAssets(state);
|
|
2585
|
+
return this.publishWalletAssetsState(state);
|
|
2586
|
+
}
|
|
2587
|
+
/**
|
|
2588
|
+
* 基于当前订单快照刷新钱包资产。商品变化保留并重验选择;客户变化强制清空。
|
|
2589
|
+
*/
|
|
2590
|
+
async refreshWalletAssets(params) {
|
|
2591
|
+
if (!this.store.order)
|
|
2592
|
+
throw new Error("order 模块未初始化");
|
|
2593
|
+
if (!this.store.payment)
|
|
2594
|
+
throw new Error("payment 模块未初始化");
|
|
2595
|
+
const refreshSequence = ++this.walletAssetsRefreshSequence;
|
|
2596
|
+
const wallet = this.store.payment.wallet;
|
|
2597
|
+
const businessData = this.buildWalletInitBusinessData(params);
|
|
2598
|
+
if (!businessData) {
|
|
2599
|
+
wallet.clearAllCache();
|
|
2600
|
+
const emptyState = wallet.getWalletAssetsState();
|
|
2601
|
+
this.updateVoucherOrderPayments([], { status: "payment_pending" });
|
|
2602
|
+
return this.publishWalletAssetsState(emptyState);
|
|
2603
|
+
}
|
|
2604
|
+
const previousState = wallet.getWalletAssetsState();
|
|
2605
|
+
const hasPreviousWalletContext = previousState.status !== "idle" || previousState.items.length > 0 || previousState.selectedIds.length > 0 || previousState.customerId !== void 0;
|
|
2606
|
+
const customerChanged = hasPreviousWalletContext && String(previousState.customerId ?? "") !== String(businessData.customer_id ?? "");
|
|
2607
|
+
if (customerChanged) {
|
|
2608
|
+
const clearedState = wallet.clearWalletAssetSelection();
|
|
2609
|
+
this.updateVoucherOrderPayments([], { status: "payment_pending" });
|
|
2610
|
+
await this.publishWalletAssetsState(clearedState);
|
|
2611
|
+
}
|
|
2612
|
+
const refreshTask = wallet.refreshWalletAssetsFromBusinessAsync(
|
|
2613
|
+
businessData,
|
|
2614
|
+
{
|
|
2615
|
+
preserveSelection: (params == null ? void 0 : params.preserveSelection) !== false && !customerChanged
|
|
2616
|
+
}
|
|
2617
|
+
);
|
|
2618
|
+
await this.publishWalletAssetsState(wallet.getWalletAssetsState());
|
|
2619
|
+
let state = await refreshTask;
|
|
2620
|
+
if (refreshSequence !== this.walletAssetsRefreshSequence) {
|
|
2621
|
+
return wallet.getWalletAssetsState();
|
|
2622
|
+
}
|
|
2623
|
+
if (state.status !== "error") {
|
|
2624
|
+
const committed = this.getCommittedWalletAssets();
|
|
2625
|
+
state = wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
2626
|
+
}
|
|
2627
|
+
await this.syncSelectedWalletAssets(state);
|
|
2628
|
+
return this.publishWalletAssetsState(state);
|
|
2629
|
+
}
|
|
2630
|
+
/** 选择或取消单张钱包资产,并立即同步 pending wallet payments。 */
|
|
2631
|
+
async selectWalletAsset(params) {
|
|
2632
|
+
if (!this.store.payment)
|
|
2633
|
+
throw new Error("payment 模块未初始化");
|
|
2634
|
+
const state = this.store.payment.wallet.selectWalletAsset(params.assetId, {
|
|
2635
|
+
selected: params.selected,
|
|
2636
|
+
source: params.source
|
|
2637
|
+
});
|
|
2638
|
+
await this.syncSelectedWalletAssets(state);
|
|
2639
|
+
return this.publishWalletAssetsState(state);
|
|
2640
|
+
}
|
|
2641
|
+
/** 扫码精确查券;仅可用资产会被自动选中。 */
|
|
2642
|
+
async scanWalletAsset(code) {
|
|
2643
|
+
if (!this.store.payment)
|
|
2644
|
+
throw new Error("payment 模块未初始化");
|
|
2645
|
+
const result = await this.store.payment.wallet.scanWalletAssetAsync(code);
|
|
2646
|
+
if (result.type === "normalCode") {
|
|
2647
|
+
await this.syncSelectedWalletAssets(result.state);
|
|
2648
|
+
await this.publishWalletAssetsState(result.state);
|
|
2649
|
+
}
|
|
2650
|
+
return result;
|
|
2651
|
+
}
|
|
2652
|
+
/** 清空全部未确认钱包选择,已支付钱包项由 Order 模块继续保留。 */
|
|
2653
|
+
async clearWalletAssetSelection() {
|
|
2654
|
+
if (!this.store.payment)
|
|
2655
|
+
throw new Error("payment 模块未初始化");
|
|
2656
|
+
const state = this.store.payment.wallet.clearWalletAssetSelection();
|
|
2657
|
+
await this.syncSelectedWalletAssets(state);
|
|
2658
|
+
return this.publishWalletAssetsState(state);
|
|
2659
|
+
}
|
|
2316
2660
|
/**
|
|
2317
2661
|
* 更新当前订单客户字段。
|
|
2318
2662
|
*
|
|
@@ -2349,29 +2693,349 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2349
2693
|
getPaymentMethods() {
|
|
2350
2694
|
return [...this.paymentMethodsCache];
|
|
2351
2695
|
}
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2696
|
+
findCashPaymentMethod(paymentMethods) {
|
|
2697
|
+
return paymentMethods.find((method) => {
|
|
2698
|
+
const identifiers = [method == null ? void 0 : method.code, method == null ? void 0 : method.type, method == null ? void 0 : method.tag].map(
|
|
2699
|
+
(value) => String(value || "").toUpperCase()
|
|
2700
|
+
);
|
|
2701
|
+
return identifiers.includes("CASHMANUAL") && (method == null ? void 0 : method.enabled) !== false && (method == null ? void 0 : method.enable) !== false;
|
|
2702
|
+
});
|
|
2703
|
+
}
|
|
2704
|
+
getPendingWalletPaymentAmount(payments = ((_b) => (_b = ((_a) => (_a = this.store.order) == null ? void 0 : _a.getOrderPayments)()) == null ? void 0 : _b.call(_a))() || []) {
|
|
2705
|
+
return payments.reduce((total, payment) => {
|
|
2706
|
+
if ((payment == null ? void 0 : payment.status) !== "payment_pending" || (payment == null ? void 0 : payment.voucher_id) === void 0 || Number(payment.voucher_id) === 0) {
|
|
2707
|
+
return total;
|
|
2708
|
+
}
|
|
2709
|
+
try {
|
|
2710
|
+
return total.plus(payment.amount || 0).plus(payment.rounding_amount || 0);
|
|
2711
|
+
} catch {
|
|
2712
|
+
return total;
|
|
2713
|
+
}
|
|
2714
|
+
}, new import_decimal.default(0));
|
|
2715
|
+
}
|
|
2716
|
+
/** 读取现金 action 所需的支付方式、待付金额和快捷金额。 */
|
|
2717
|
+
async getCashPaymentConfig() {
|
|
2718
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2719
|
+
if (!this.store.payment)
|
|
2720
|
+
throw new Error("payment 模块未初始化");
|
|
2721
|
+
let paymentMethods = this.getPaymentMethods();
|
|
2722
|
+
let paymentMethod = this.findCashPaymentMethod(paymentMethods);
|
|
2723
|
+
if (!paymentMethod) {
|
|
2724
|
+
paymentMethods = await this.getPaymentMethodsAsync();
|
|
2725
|
+
paymentMethod = this.findCashPaymentMethod(paymentMethods);
|
|
2367
2726
|
}
|
|
2368
|
-
const
|
|
2727
|
+
const amountSnapshot = (_b = (_a = this.store.order) == null ? void 0 : _a.getOrderAmountSnapshot) == null ? void 0 : _b.call(_a);
|
|
2728
|
+
const pendingWalletAmount = this.getPendingWalletPaymentAmount();
|
|
2729
|
+
const amountDue = import_decimal.default.max(
|
|
2730
|
+
new import_decimal.default((amountSnapshot == null ? void 0 : amountSnapshot.amountGap) || 0).minus(pendingWalletAmount),
|
|
2731
|
+
0
|
|
2732
|
+
).toDecimalPlaces(2).toNumber();
|
|
2733
|
+
const currency = ((_e = (_d = (_c = this.store.order) == null ? void 0 : _c.getTempOrder) == null ? void 0 : _d.call(_c)) == null ? void 0 : _e.currency_code) || ((_f = this.otherParams) == null ? void 0 : _f.currency) || "USD";
|
|
2734
|
+
const recommendedAmounts = amountDue > 0 ? this.store.payment.cash.getRecommendedAmount(amountDue, currency) : [];
|
|
2369
2735
|
return {
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2736
|
+
available: Boolean(paymentMethod && amountDue > 0),
|
|
2737
|
+
paymentMethod,
|
|
2738
|
+
amountDue,
|
|
2739
|
+
recommendedAmounts
|
|
2373
2740
|
};
|
|
2374
2741
|
}
|
|
2742
|
+
/**
|
|
2743
|
+
* 确认足额覆盖订单的 pending Wallet 支付并提交订单。
|
|
2744
|
+
*
|
|
2745
|
+
* Order 模块在构造提交参数时将 pending voucher 转为 paid;只有提交成功后
|
|
2746
|
+
* 才同步 Wallet committed 状态。失败时恢复调用前 payments,允许用户重试。
|
|
2747
|
+
*/
|
|
2748
|
+
async confirmWalletPayment() {
|
|
2749
|
+
var _a, _b, _c, _d, _e;
|
|
2750
|
+
if (!this.store.order)
|
|
2751
|
+
throw new Error("order 模块未初始化");
|
|
2752
|
+
const beforePayments = (0, import_lodash_es.cloneDeep)(this.store.order.getOrderPayments());
|
|
2753
|
+
const pendingWalletAmount = this.getPendingWalletPaymentAmount(beforePayments);
|
|
2754
|
+
if (pendingWalletAmount.lte(0)) {
|
|
2755
|
+
throw new Error("当前订单没有待确认的 Wallet 支付");
|
|
2756
|
+
}
|
|
2757
|
+
const amountSnapshot = (_b = (_a = this.store.order).getOrderAmountSnapshot) == null ? void 0 : _b.call(_a);
|
|
2758
|
+
const effectiveAmountDue = import_decimal.default.max(
|
|
2759
|
+
new import_decimal.default((amountSnapshot == null ? void 0 : amountSnapshot.amountGap) || 0).minus(pendingWalletAmount),
|
|
2760
|
+
0
|
|
2761
|
+
);
|
|
2762
|
+
if (effectiveAmountDue.gt(0.01)) {
|
|
2763
|
+
throw new Error("Wallet 支付尚未覆盖全部待支付金额");
|
|
2764
|
+
}
|
|
2765
|
+
const beforePaymentStatus = (_c = this.store.order.getTempOrder()) == null ? void 0 : _c.payment_status;
|
|
2766
|
+
let submitResult;
|
|
2767
|
+
try {
|
|
2768
|
+
submitResult = await this.submitSalesOrder({
|
|
2769
|
+
smallTicketDataFlag: 1,
|
|
2770
|
+
confirmPendingVoucherPayments: true
|
|
2771
|
+
});
|
|
2772
|
+
if (isRejectedSalesSubmitResult(submitResult)) {
|
|
2773
|
+
throw new Error(getSalesSubmitErrorMessage(submitResult));
|
|
2774
|
+
}
|
|
2775
|
+
} catch (error) {
|
|
2776
|
+
this.store.order.setOrderPayments(beforePayments);
|
|
2777
|
+
const restoredTempOrder = this.store.order.getTempOrder();
|
|
2778
|
+
if (restoredTempOrder && beforePaymentStatus !== void 0) {
|
|
2779
|
+
restoredTempOrder.payment_status = beforePaymentStatus;
|
|
2780
|
+
this.store.order.persistTempOrder();
|
|
2781
|
+
}
|
|
2782
|
+
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
2783
|
+
throw error;
|
|
2784
|
+
}
|
|
2785
|
+
if (this.store.payment) {
|
|
2786
|
+
try {
|
|
2787
|
+
const committed = this.getCommittedWalletAssets();
|
|
2788
|
+
const walletState = this.store.payment.wallet.setCommittedWalletAssets(
|
|
2789
|
+
committed.ids,
|
|
2790
|
+
committed.assets
|
|
2791
|
+
);
|
|
2792
|
+
await this.publishWalletAssetsState(walletState);
|
|
2793
|
+
} catch (error) {
|
|
2794
|
+
this.logWarning("confirmWalletPayment: Wallet committed 状态同步失败", {
|
|
2795
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2796
|
+
});
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
const latestAmountSnapshot = (_e = (_d = this.store.order).getOrderAmountSnapshot) == null ? void 0 : _e.call(_d);
|
|
2800
|
+
return {
|
|
2801
|
+
submitResult,
|
|
2802
|
+
payments: this.store.order.getOrderPayments(),
|
|
2803
|
+
isOrderFullyPaid: new import_decimal.default(
|
|
2804
|
+
(latestAmountSnapshot == null ? void 0 : latestAmountSnapshot.amountGap) || 0
|
|
2805
|
+
).lte(0)
|
|
2806
|
+
};
|
|
2807
|
+
}
|
|
2808
|
+
/**
|
|
2809
|
+
* 购物车现金直付:写入现金记录并等待支付同步完成。
|
|
2810
|
+
* 同步失败会恢复调用前 payments(包含 Wallet pending 状态)。
|
|
2811
|
+
*/
|
|
2812
|
+
async payCash(params) {
|
|
2813
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2814
|
+
if (!this.store.order)
|
|
2815
|
+
throw new Error("order 模块未初始化");
|
|
2816
|
+
const amount = Number(params.amount || 0);
|
|
2817
|
+
if (!Number.isFinite(amount) || amount <= 0) {
|
|
2818
|
+
throw new Error("现金支付金额必须大于 0");
|
|
2819
|
+
}
|
|
2820
|
+
const config = await this.getCashPaymentConfig();
|
|
2821
|
+
const paymentMethod = config.paymentMethod;
|
|
2822
|
+
if (!paymentMethod)
|
|
2823
|
+
throw new Error("未找到可用的 CASHMANUAL 支付方式");
|
|
2824
|
+
if (config.amountDue <= 0)
|
|
2825
|
+
throw new Error("当前订单没有待支付金额");
|
|
2826
|
+
const roundingAmount = Number(params.roundingAmount || 0);
|
|
2827
|
+
const effectivePaymentAmount = new import_decimal.default(amount).minus(roundingAmount);
|
|
2828
|
+
if (effectivePaymentAmount.gt(new import_decimal.default(config.amountDue).plus(0.01))) {
|
|
2829
|
+
throw new Error("现金支付金额超过当前待支付金额");
|
|
2830
|
+
}
|
|
2831
|
+
const beforePayments = (0, import_lodash_es.cloneDeep)(this.store.order.getOrderPayments());
|
|
2832
|
+
const beforePaymentStatus = (_a = this.store.order.getTempOrder()) == null ? void 0 : _a.payment_status;
|
|
2833
|
+
const uniquePaymentNumber = (0, import_utils.createUuidV4)();
|
|
2834
|
+
const paymentTimestamp = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
|
|
2835
|
+
const actualPaidAmount = Number(params.actualPaidAmount ?? amount);
|
|
2836
|
+
const changeAmount = Number(params.changeAmount || 0);
|
|
2837
|
+
const shopWalletPassId = (_b = this.otherParams) == null ? void 0 : _b.shop_wallet_pass_id;
|
|
2838
|
+
if (!Number.isFinite(actualPaidAmount) || actualPaidAmount + 0.01 < amount) {
|
|
2839
|
+
throw new Error("顾客实收现金不能小于支付金额");
|
|
2840
|
+
}
|
|
2841
|
+
(_f = (_e = (_d = (_c = this.window) == null ? void 0 : _c.interaction) == null ? void 0 : _d.utils) == null ? void 0 : _e.postMessageToApp) == null ? void 0 : _f.call(_e, {
|
|
2842
|
+
module: "till",
|
|
2843
|
+
key: "open_till",
|
|
2844
|
+
data: { type: "cash" }
|
|
2845
|
+
});
|
|
2846
|
+
const payments = this.store.order.addOrderPayment({
|
|
2847
|
+
amount: amount.toFixed(2),
|
|
2848
|
+
code: paymentMethod.code,
|
|
2849
|
+
custom_payment_id: paymentMethod.id,
|
|
2850
|
+
name: paymentMethod.name,
|
|
2851
|
+
custom_payment_type: paymentMethod.type,
|
|
2852
|
+
voucher_id: 0,
|
|
2853
|
+
rounding_amount: roundingAmount.toFixed(2),
|
|
2854
|
+
metadata: {
|
|
2855
|
+
unique_payment_number: uniquePaymentNumber,
|
|
2856
|
+
...shopWalletPassId !== void 0 && shopWalletPassId !== null ? { shop_wallet_pass_id: shopWalletPassId } : {},
|
|
2857
|
+
actual_paid_amount: Number.isFinite(actualPaidAmount) ? actualPaidAmount : amount,
|
|
2858
|
+
change_given_amount: Number.isFinite(changeAmount) ? changeAmount : 0
|
|
2859
|
+
},
|
|
2860
|
+
payment_time: paymentTimestamp,
|
|
2861
|
+
created_at: paymentTimestamp
|
|
2862
|
+
});
|
|
2863
|
+
const payment = payments.find(
|
|
2864
|
+
(item) => {
|
|
2865
|
+
var _a2;
|
|
2866
|
+
return ((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.unique_payment_number) === uniquePaymentNumber;
|
|
2867
|
+
}
|
|
2868
|
+
);
|
|
2869
|
+
try {
|
|
2870
|
+
const syncResult = await this.syncPaymentsToOrder({
|
|
2871
|
+
payments,
|
|
2872
|
+
submitWhenPaid: true,
|
|
2873
|
+
smallTicketDataFlag: 1,
|
|
2874
|
+
confirmPendingVoucherPayments: true
|
|
2875
|
+
});
|
|
2876
|
+
if (this.store.payment) {
|
|
2877
|
+
const committed = this.getCommittedWalletAssets();
|
|
2878
|
+
const walletState = this.store.payment.wallet.setCommittedWalletAssets(
|
|
2879
|
+
committed.ids,
|
|
2880
|
+
committed.assets
|
|
2881
|
+
);
|
|
2882
|
+
await this.publishWalletAssetsState(walletState);
|
|
2883
|
+
}
|
|
2884
|
+
return {
|
|
2885
|
+
payment: payment || {},
|
|
2886
|
+
payments: this.store.order.getOrderPayments(),
|
|
2887
|
+
syncResult,
|
|
2888
|
+
isOrderFullyPaid: syncResult.isOrderFullyPaid
|
|
2889
|
+
};
|
|
2890
|
+
} catch (error) {
|
|
2891
|
+
this.store.order.setOrderPayments(beforePayments);
|
|
2892
|
+
const restoredTempOrder = this.store.order.getTempOrder();
|
|
2893
|
+
if (restoredTempOrder && beforePaymentStatus !== void 0) {
|
|
2894
|
+
restoredTempOrder.payment_status = beforePaymentStatus;
|
|
2895
|
+
this.store.order.persistTempOrder();
|
|
2896
|
+
}
|
|
2897
|
+
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
2898
|
+
throw error;
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
/**
|
|
2902
|
+
* 提交一次已由支付设备确认成功的非 Wallet 支付。
|
|
2903
|
+
*
|
|
2904
|
+
* 与 addOrderPayment 不同,本入口不会启动后台 fire-and-forget 同步;调用方会等待
|
|
2905
|
+
* 本次 payment、当前 pending Wallet 以及订单提交共同完成。任何同步失败都会恢复
|
|
2906
|
+
* 调用前的 payments 与 payment_status,便于 UI 安全解锁并重试。
|
|
2907
|
+
*/
|
|
2908
|
+
async commitPaymentMethodPayment(params) {
|
|
2909
|
+
var _a, _b, _c, _d;
|
|
2910
|
+
if (!this.store.order)
|
|
2911
|
+
throw new Error("order 模块未初始化");
|
|
2912
|
+
const amount = Number(params.amount || 0);
|
|
2913
|
+
if (!Number.isFinite(amount) || amount <= 0) {
|
|
2914
|
+
throw new Error("支付金额必须大于 0");
|
|
2915
|
+
}
|
|
2916
|
+
let paymentMethods = this.getPaymentMethods();
|
|
2917
|
+
const findPaymentMethod = () => {
|
|
2918
|
+
const methodCode = String(params.paymentMethodCode || "").toUpperCase();
|
|
2919
|
+
return paymentMethods.find((method) => {
|
|
2920
|
+
const idMatched = params.paymentMethodId !== void 0 && String(method.id) === String(params.paymentMethodId);
|
|
2921
|
+
const codeMatched = Boolean(methodCode) && String(method.code || "").toUpperCase() === methodCode;
|
|
2922
|
+
return (idMatched || codeMatched) && method.enabled !== false && method.enable !== false;
|
|
2923
|
+
});
|
|
2924
|
+
};
|
|
2925
|
+
let paymentMethod = findPaymentMethod();
|
|
2926
|
+
if (!paymentMethod) {
|
|
2927
|
+
paymentMethods = await this.getPaymentMethodsAsync();
|
|
2928
|
+
paymentMethod = findPaymentMethod();
|
|
2929
|
+
}
|
|
2930
|
+
if (!paymentMethod) {
|
|
2931
|
+
throw new Error(
|
|
2932
|
+
`未找到可用的支付方式:${params.paymentMethodCode || params.paymentMethodId || ""}`
|
|
2933
|
+
);
|
|
2934
|
+
}
|
|
2935
|
+
const amountSnapshot = (_b = (_a = this.store.order).getOrderAmountSnapshot) == null ? void 0 : _b.call(_a);
|
|
2936
|
+
const pendingWalletAmount = this.getPendingWalletPaymentAmount();
|
|
2937
|
+
const amountDue = import_decimal.default.max(
|
|
2938
|
+
new import_decimal.default((amountSnapshot == null ? void 0 : amountSnapshot.amountGap) || 0).minus(pendingWalletAmount),
|
|
2939
|
+
0
|
|
2940
|
+
);
|
|
2941
|
+
if (amountDue.lte(0))
|
|
2942
|
+
throw new Error("当前订单没有待支付金额");
|
|
2943
|
+
if (new import_decimal.default(amount).gt(amountDue.plus(0.01))) {
|
|
2944
|
+
throw new Error("支付金额超过当前待支付金额");
|
|
2945
|
+
}
|
|
2946
|
+
const beforePayments = (0, import_lodash_es.cloneDeep)(this.store.order.getOrderPayments());
|
|
2947
|
+
const beforePaymentStatus = (_c = this.store.order.getTempOrder()) == null ? void 0 : _c.payment_status;
|
|
2948
|
+
const paymentTimestamp = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
|
|
2949
|
+
const metadata = {
|
|
2950
|
+
...params.metadata || {},
|
|
2951
|
+
unique_payment_number: ((_d = params.metadata) == null ? void 0 : _d.unique_payment_number) || (0, import_utils.createUuidV4)()
|
|
2952
|
+
};
|
|
2953
|
+
const serviceCharge = params.serviceCharge ? {
|
|
2954
|
+
amount: String(params.serviceCharge.amount || 0),
|
|
2955
|
+
percentage: String(params.serviceCharge.percentage || 0)
|
|
2956
|
+
} : void 0;
|
|
2957
|
+
const serviceFee = serviceCharge ? new import_decimal.default(params.originAmount ?? amount).times(serviceCharge.percentage || 0).plus(serviceCharge.amount || 0).toDecimalPlaces(2).toFixed(2) : void 0;
|
|
2958
|
+
const payments = this.store.order.addOrderPayment({
|
|
2959
|
+
...params.paymentData || {},
|
|
2960
|
+
amount: amount.toFixed(2),
|
|
2961
|
+
...params.originAmount !== void 0 ? { origin_amount: Number(params.originAmount).toFixed(2) } : {},
|
|
2962
|
+
code: paymentMethod.code,
|
|
2963
|
+
custom_payment_id: paymentMethod.id,
|
|
2964
|
+
name: paymentMethod.name,
|
|
2965
|
+
custom_payment_type: paymentMethod.type,
|
|
2966
|
+
voucher_id: 0,
|
|
2967
|
+
...serviceCharge ? { service_charge: serviceCharge } : {},
|
|
2968
|
+
...serviceFee !== void 0 ? { service_fee: serviceFee } : {},
|
|
2969
|
+
metadata,
|
|
2970
|
+
payment_time: paymentTimestamp,
|
|
2971
|
+
created_at: paymentTimestamp
|
|
2972
|
+
});
|
|
2973
|
+
const payment = payments.find(
|
|
2974
|
+
(item) => {
|
|
2975
|
+
var _a2;
|
|
2976
|
+
return ((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.unique_payment_number) === metadata.unique_payment_number;
|
|
2977
|
+
}
|
|
2978
|
+
);
|
|
2979
|
+
try {
|
|
2980
|
+
const syncResult = await this.syncPaymentsToOrder({
|
|
2981
|
+
payments,
|
|
2982
|
+
submitWhenPaid: true,
|
|
2983
|
+
smallTicketDataFlag: 1,
|
|
2984
|
+
confirmPendingVoucherPayments: true
|
|
2985
|
+
});
|
|
2986
|
+
if (this.store.payment) {
|
|
2987
|
+
const committed = this.getCommittedWalletAssets();
|
|
2988
|
+
const walletState = this.store.payment.wallet.setCommittedWalletAssets(
|
|
2989
|
+
committed.ids,
|
|
2990
|
+
committed.assets
|
|
2991
|
+
);
|
|
2992
|
+
await this.publishWalletAssetsState(walletState);
|
|
2993
|
+
}
|
|
2994
|
+
return {
|
|
2995
|
+
payment: payment || {},
|
|
2996
|
+
payments: this.store.order.getOrderPayments(),
|
|
2997
|
+
syncResult,
|
|
2998
|
+
isOrderFullyPaid: syncResult.isOrderFullyPaid
|
|
2999
|
+
};
|
|
3000
|
+
} catch (error) {
|
|
3001
|
+
this.store.order.setOrderPayments(beforePayments);
|
|
3002
|
+
const restoredTempOrder = this.store.order.getTempOrder();
|
|
3003
|
+
if (restoredTempOrder && beforePaymentStatus !== void 0) {
|
|
3004
|
+
restoredTempOrder.payment_status = beforePaymentStatus;
|
|
3005
|
+
this.store.order.persistTempOrder();
|
|
3006
|
+
}
|
|
3007
|
+
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
3008
|
+
throw error;
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
3011
|
+
/**
|
|
3012
|
+
* 按当前店铺的现金舍入配置计算金额,供现金支付 UI 使用。
|
|
3013
|
+
*
|
|
3014
|
+
* 舍入开关取自 CASHMANUAL 支付方式;舍入规则取自
|
|
3015
|
+
* otherParams.order_rounding_setting,金额算法统一由 PaymentModule 维护。
|
|
3016
|
+
*/
|
|
3017
|
+
async roundAmount(params) {
|
|
3018
|
+
var _a, _b, _c;
|
|
3019
|
+
const amount = params.amount;
|
|
3020
|
+
const cashManualPayment = this.paymentMethodsCache.find(
|
|
3021
|
+
(paymentMethod) => paymentMethod.code === "CASHMANUAL"
|
|
3022
|
+
);
|
|
3023
|
+
if (!((_a = cashManualPayment == null ? void 0 : cashManualPayment.metadata) == null ? void 0 : _a.order_rounding_switch)) {
|
|
3024
|
+
return {
|
|
3025
|
+
originalAmount: amount.toString(),
|
|
3026
|
+
roundedAmount: amount.toString(),
|
|
3027
|
+
roundingDifference: "0.00"
|
|
3028
|
+
};
|
|
3029
|
+
}
|
|
3030
|
+
if (!this.payment) {
|
|
3031
|
+
throw new Error("payment 模块未初始化");
|
|
3032
|
+
}
|
|
3033
|
+
return this.payment.roundAmountAsync(
|
|
3034
|
+
amount,
|
|
3035
|
+
(_b = this.otherParams.order_rounding_setting) == null ? void 0 : _b.interval,
|
|
3036
|
+
(_c = this.otherParams.order_rounding_setting) == null ? void 0 : _c.type
|
|
3037
|
+
);
|
|
3038
|
+
}
|
|
2375
3039
|
/**
|
|
2376
3040
|
* 发送支付链接。
|
|
2377
3041
|
*
|
|
@@ -2540,11 +3204,11 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2540
3204
|
});
|
|
2541
3205
|
});
|
|
2542
3206
|
}
|
|
2543
|
-
async addProductToOrder(product, booking) {
|
|
3207
|
+
async addProductToOrder(product, booking, options) {
|
|
2544
3208
|
try {
|
|
2545
3209
|
if (!this.store.order)
|
|
2546
3210
|
throw new Error("order 模块未初始化");
|
|
2547
|
-
const products = await this.store.order.addProductToOrder(product, booking);
|
|
3211
|
+
const products = await this.store.order.addProductToOrder(product, booking, options);
|
|
2548
3212
|
return products;
|
|
2549
3213
|
} catch (error) {
|
|
2550
3214
|
throw error;
|
|
@@ -2620,17 +3284,17 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2620
3284
|
* @example
|
|
2621
3285
|
* await baseSales.removeProductsFromOrder([identityA, identityB]);
|
|
2622
3286
|
*/
|
|
2623
|
-
async removeProductsFromOrder(identities) {
|
|
3287
|
+
async removeProductsFromOrder(identities, options) {
|
|
2624
3288
|
try {
|
|
2625
3289
|
if (!this.store.order)
|
|
2626
3290
|
throw new Error("order 模块未初始化");
|
|
2627
|
-
return await this.store.order.removeProductsFromOrder(identities);
|
|
3291
|
+
return await this.store.order.removeProductsFromOrder(identities, options);
|
|
2628
3292
|
} catch (error) {
|
|
2629
3293
|
throw error;
|
|
2630
3294
|
}
|
|
2631
3295
|
}
|
|
2632
|
-
async removeProductFromOrder(identity) {
|
|
2633
|
-
return this.removeProductsFromOrder([identity]);
|
|
3296
|
+
async removeProductFromOrder(identity, options) {
|
|
3297
|
+
return this.removeProductsFromOrder([identity], options);
|
|
2634
3298
|
}
|
|
2635
3299
|
// ─── 促销/赠品 透传(迁移自 booking usePromotion) ────────────────
|
|
2636
3300
|
/**
|