@pisell/pisellos 2.3.100 → 2.3.102
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/dataVariant/evaluator.d.ts +18 -2
- package/dist/model/strategy/adapter/dataVariant/evaluator.js +287 -101
- package/dist/model/strategy/adapter/dataVariant/type.d.ts +25 -0
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/modules/Discount/index.d.ts +2 -0
- package/dist/modules/Discount/index.js +38 -5
- package/dist/modules/Discount/types.d.ts +11 -0
- package/dist/modules/Order/index.d.ts +14 -0
- package/dist/modules/Order/index.js +617 -368
- package/dist/modules/Order/types.d.ts +11 -3
- package/dist/modules/Order/utils/virtualSettlement.d.ts +63 -0
- package/dist/modules/Order/utils/virtualSettlement.js +284 -0
- package/dist/modules/Order/utils.d.ts +1 -0
- package/dist/modules/Order/utils.js +63 -24
- package/dist/modules/Product/types.d.ts +23 -0
- package/dist/modules/Rules/index.d.ts +5 -0
- package/dist/modules/Rules/index.js +27 -12
- package/dist/modules/SalesSummary/index.d.ts +1 -0
- package/dist/modules/SalesSummary/index.js +4 -3
- package/dist/modules/SalesSummary/types.d.ts +1 -0
- package/dist/modules/SalesSummary/utils.d.ts +1 -0
- package/dist/modules/SalesSummary/utils.js +21 -1
- package/dist/solution/BaseSales/index.d.ts +10 -1
- package/dist/solution/BaseSales/index.js +1099 -784
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +72 -9
- package/dist/solution/BookingByStep/index.d.ts +2 -2
- package/dist/solution/BookingTicket/utils/addProductDecision.js +2 -1
- package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +137 -6
- package/lib/model/strategy/adapter/dataVariant/type.d.ts +25 -0
- package/lib/modules/Discount/index.d.ts +2 -0
- package/lib/modules/Discount/index.js +31 -2
- package/lib/modules/Discount/types.d.ts +11 -0
- package/lib/modules/Order/index.d.ts +14 -0
- package/lib/modules/Order/index.js +195 -15
- package/lib/modules/Order/types.d.ts +11 -3
- package/lib/modules/Order/utils/virtualSettlement.d.ts +63 -0
- package/lib/modules/Order/utils/virtualSettlement.js +262 -0
- package/lib/modules/Order/utils.d.ts +1 -0
- package/lib/modules/Order/utils.js +57 -20
- package/lib/modules/Product/types.d.ts +23 -0
- package/lib/modules/Rules/index.d.ts +5 -0
- package/lib/modules/Rules/index.js +20 -11
- package/lib/modules/SalesSummary/index.d.ts +1 -0
- package/lib/modules/SalesSummary/index.js +4 -2
- package/lib/modules/SalesSummary/types.d.ts +1 -0
- package/lib/modules/SalesSummary/utils.d.ts +1 -0
- package/lib/modules/SalesSummary/utils.js +17 -1
- package/lib/solution/BaseSales/index.d.ts +10 -1
- package/lib/solution/BaseSales/index.js +211 -9
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +38 -0
- package/lib/solution/BookingByStep/index.d.ts +2 -2
- package/lib/solution/BookingTicket/utils/addProductDecision.js +1 -0
- package/package.json +1 -1
|
@@ -18,6 +18,7 @@ var _manualProductDiscount = require("./utils/manualProductDiscount");
|
|
|
18
18
|
var _bundleDiscountHydration = require("./utils/bundleDiscountHydration");
|
|
19
19
|
var _orderCollectionIdentity = require("./utils/orderCollectionIdentity");
|
|
20
20
|
var _discountProductLineIdentity = require("./utils/discountProductLineIdentity");
|
|
21
|
+
var _virtualSettlement = require("./utils/virtualSettlement");
|
|
21
22
|
var _Discount = require("../Discount");
|
|
22
23
|
var _Rules = require("../Rules");
|
|
23
24
|
var _types2 = require("../Rules/types");
|
|
@@ -298,6 +299,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
298
299
|
this.store.tempOrder = null;
|
|
299
300
|
this.store.summary = (0, _utils.createEmptySummary)();
|
|
300
301
|
this.store.availableWalletIds = [];
|
|
302
|
+
this.store.virtualCurrencyList = [];
|
|
301
303
|
this.store.lastOrderInfo = undefined;
|
|
302
304
|
this.store.syncState = undefined;
|
|
303
305
|
this.store.discountList = [];
|
|
@@ -310,6 +312,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
310
312
|
if (!Array.isArray(this.store.availableWalletIds)) {
|
|
311
313
|
this.store.availableWalletIds = [];
|
|
312
314
|
}
|
|
315
|
+
if (!Array.isArray(this.store.virtualCurrencyList)) {
|
|
316
|
+
this.store.virtualCurrencyList = [];
|
|
317
|
+
}
|
|
313
318
|
this.request = this.core.getPlugin('request');
|
|
314
319
|
const appPlugin = this.core.getPlugin('app');
|
|
315
320
|
if (!appPlugin) {
|
|
@@ -364,6 +369,12 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
364
369
|
this.otherParams = otherParams;
|
|
365
370
|
}
|
|
366
371
|
|
|
372
|
+
/** PC/H5 属于在线店铺;其它或缺失平台统一沿用 POS 行为。 */
|
|
373
|
+
isOnlineStorePlatform() {
|
|
374
|
+
const platform = String(this.otherParams?.platform || '').trim().toLowerCase();
|
|
375
|
+
return platform === 'pc' || platform === 'h5';
|
|
376
|
+
}
|
|
377
|
+
|
|
367
378
|
/**
|
|
368
379
|
* 记录信息日志
|
|
369
380
|
*/
|
|
@@ -451,6 +462,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
451
462
|
with_wallet_pass_holder: 1,
|
|
452
463
|
with_available_wallet_flag: 1,
|
|
453
464
|
with_available_wallet_pass_flag: 1,
|
|
465
|
+
with_virtual_currency: 1,
|
|
454
466
|
request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
455
467
|
...(orderId ? {
|
|
456
468
|
order_id: orderId
|
|
@@ -458,6 +470,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
458
470
|
});
|
|
459
471
|
const discountList = prepareConfigResult?.discountList;
|
|
460
472
|
this.store.availableWalletIds = prepareConfigResult?.availableWalletIds || [];
|
|
473
|
+
this.store.virtualCurrencyList = prepareConfigResult?.virtualCurrencyList || [];
|
|
461
474
|
if (discountList) {
|
|
462
475
|
const currentDiscountList = this.store.discount?.getDiscountList() || [];
|
|
463
476
|
const currentEditDiscounts = currentDiscountList.filter(discount => discount?.isEditMode);
|
|
@@ -485,6 +498,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
485
498
|
getAvailableWalletIds() {
|
|
486
499
|
return Array.isArray(this.store.availableWalletIds) ? [...this.store.availableWalletIds] : [];
|
|
487
500
|
}
|
|
501
|
+
getVirtualCurrencyList() {
|
|
502
|
+
return (0, _lodashEs.cloneDeep)(this.store.virtualCurrencyList || []);
|
|
503
|
+
}
|
|
488
504
|
async syncScannedDiscountsToOriginalDiscountList(discountList) {
|
|
489
505
|
const scanDiscounts = (discountList || []).filter(discount => discount?.isScan);
|
|
490
506
|
if (!scanDiscounts.length) return;
|
|
@@ -508,6 +524,16 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
508
524
|
});
|
|
509
525
|
}
|
|
510
526
|
async scanCode(code, customerId) {
|
|
527
|
+
if (this.isActiveVirtualSettlementOrder(this.store.tempOrder)) {
|
|
528
|
+
return {
|
|
529
|
+
type: 'clientCalc',
|
|
530
|
+
isAvailable: false,
|
|
531
|
+
isAccepted: false,
|
|
532
|
+
discountList: [],
|
|
533
|
+
scannedDiscountList: [],
|
|
534
|
+
unavailableReason: _types2.UnavailableReason.ProductNotApplicable
|
|
535
|
+
};
|
|
536
|
+
}
|
|
511
537
|
const resultDiscountWithReason = (await this.store.discount?.batchSearch(code, {
|
|
512
538
|
customerId
|
|
513
539
|
})) || {
|
|
@@ -603,6 +629,14 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
603
629
|
// 也需要让 Rules.calcDiscount 把 DiscountModule 的 isSelected / isAvailable /
|
|
604
630
|
// appliedProductDetails / savedAmount 复位。
|
|
605
631
|
if (!tempOrder) return;
|
|
632
|
+
if (this.isActiveVirtualSettlementOrder(tempOrder)) {
|
|
633
|
+
tempOrder.products = (0, _virtualSettlement.normalizeVirtualSettlementProducts)(tempOrder.products);
|
|
634
|
+
tempOrder.discount_list = [];
|
|
635
|
+
tempOrder.shop_discount = '0.00';
|
|
636
|
+
void this.store.discount?.setDiscountList([]);
|
|
637
|
+
void this.store.discount?.setOriginalDiscountList([]);
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
606
640
|
this.syncLinkedBookingHoldersToProducts(tempOrder);
|
|
607
641
|
delete tempOrder.discount_list;
|
|
608
642
|
const discountList = this.store.discount?.getDiscountList() || [];
|
|
@@ -700,6 +734,10 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
700
734
|
if (!tempOrder) {
|
|
701
735
|
return;
|
|
702
736
|
}
|
|
737
|
+
if (this.isActiveVirtualSettlementOrder(tempOrder)) {
|
|
738
|
+
tempOrder.products = (0, _virtualSettlement.normalizeVirtualSettlementProducts)(tempOrder.products);
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
703
741
|
const strategyConfigs = this.promotionEvaluator.getStrategyConfigs?.();
|
|
704
742
|
if (Array.isArray(strategyConfigs) && strategyConfigs.length === 0) {
|
|
705
743
|
return;
|
|
@@ -1830,7 +1868,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1830
1868
|
return product;
|
|
1831
1869
|
}
|
|
1832
1870
|
sanitizeTempOrderProducts(tempOrder) {
|
|
1833
|
-
tempOrder.products = (tempOrder.products || []).map(product => this.sanitizeOrderProductForTempOrder(product));
|
|
1871
|
+
tempOrder.products = (tempOrder.products || []).map(product => this.sanitizeOrderProductForTempOrder(this.normalizeVirtualSettlementProductIfEnabled(product)));
|
|
1872
|
+
this.syncTempOrderSettlementState(tempOrder);
|
|
1834
1873
|
(0, _discountProductLineIdentity.ensureUniqueProductLineUids)(tempOrder);
|
|
1835
1874
|
}
|
|
1836
1875
|
ensureExtend(tempOrder) {
|
|
@@ -2151,6 +2190,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2151
2190
|
products: summaryProducts,
|
|
2152
2191
|
isPriceIncludeTax: tempOrder.is_price_include_tax,
|
|
2153
2192
|
shopDiscount: tempOrder.shop_discount,
|
|
2193
|
+
virtualSettlementMode: this.shouldUseVirtualSettlementSummary(tempOrder),
|
|
2154
2194
|
...(this.otherParams?.channel ? {
|
|
2155
2195
|
channel: this.otherParams.channel
|
|
2156
2196
|
} : {})
|
|
@@ -2619,6 +2659,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2619
2659
|
const nextCustomerId = tempOrder.customer_id ?? null;
|
|
2620
2660
|
if (String(previousCustomerId ?? '') !== String(nextCustomerId ?? '')) {
|
|
2621
2661
|
this.store.availableWalletIds = [];
|
|
2662
|
+
this.store.virtualCurrencyList = [];
|
|
2622
2663
|
(0, _utils.clearTempOrderHolderAssignments)(tempOrder);
|
|
2623
2664
|
this.clearCustomerBoundDiscounts(tempOrder);
|
|
2624
2665
|
this.applyDiscount();
|
|
@@ -2657,6 +2698,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2657
2698
|
tempOrder.customer = null;
|
|
2658
2699
|
if (tempOrder._extend) delete tempOrder._extend.customerSnapshot;
|
|
2659
2700
|
this.store.availableWalletIds = [];
|
|
2701
|
+
this.store.virtualCurrencyList = [];
|
|
2660
2702
|
this.clearCustomerBoundDiscounts(tempOrder);
|
|
2661
2703
|
this.applyDiscount();
|
|
2662
2704
|
this.persistTempOrder();
|
|
@@ -2976,6 +3018,78 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2976
3018
|
const bookingUid = product?.booking_uid ?? product?.metadata?.booking_uid;
|
|
2977
3019
|
return bookingUid !== undefined && bookingUid !== null && String(bookingUid) !== '';
|
|
2978
3020
|
}
|
|
3021
|
+
isMultiCurrencySettlementEnabled() {
|
|
3022
|
+
return this.otherParams?.enableMultiCurrencySettlement === true;
|
|
3023
|
+
}
|
|
3024
|
+
isActiveVirtualSettlementOrder(tempOrder) {
|
|
3025
|
+
return this.isMultiCurrencySettlementEnabled() && (0, _virtualSettlement.isVirtualSettlementOrder)(tempOrder);
|
|
3026
|
+
}
|
|
3027
|
+
shouldUseVirtualSettlementSummary(tempOrder) {
|
|
3028
|
+
return this.isActiveVirtualSettlementOrder(tempOrder) || tempOrder?.metadata?.currency_settlement_config?.settlement_type === 'virtual_currency';
|
|
3029
|
+
}
|
|
3030
|
+
normalizeVirtualSettlementProductIfEnabled(product) {
|
|
3031
|
+
return this.isMultiCurrencySettlementEnabled() ? (0, _virtualSettlement.normalizeVirtualSettlementOrderProduct)(product) : product;
|
|
3032
|
+
}
|
|
3033
|
+
assertAndLockProductSettlement(tempOrder, product) {
|
|
3034
|
+
if (!this.isMultiCurrencySettlementEnabled()) return;
|
|
3035
|
+
const currentKey = (0, _virtualSettlement.getTempOrderSettlementKey)(tempOrder);
|
|
3036
|
+
const incomingKey = (0, _virtualSettlement.getSettlementKey)((0, _virtualSettlement.getSelectedSettlementSnapshot)(product)) || 'legal_currency';
|
|
3037
|
+
if (currentKey && currentKey !== incomingKey) {
|
|
3038
|
+
throw new _virtualSettlement.OrderSettlementConflictError(currentKey, incomingKey);
|
|
3039
|
+
}
|
|
3040
|
+
const snapshot = (0, _virtualSettlement.getSelectedSettlementSnapshot)(product);
|
|
3041
|
+
if (snapshot?.settlement_type === 'virtual_currency' && tempOrder.customer_id && Number(tempOrder.customer_id) !== 1) {
|
|
3042
|
+
const currencyProductId = Number(snapshot.currency_product_id);
|
|
3043
|
+
const asset = (this.store.virtualCurrencyList || []).find(item => Number(item?.product_id) === currencyProductId);
|
|
3044
|
+
if (!asset) {
|
|
3045
|
+
throw new _virtualSettlement.VirtualCurrencyAssetNotFoundError(currencyProductId);
|
|
3046
|
+
}
|
|
3047
|
+
const existedAmount = tempOrder.products.reduce((sum, item) => sum.plus(new _decimal.default(item.selling_price || 0).times(item.num || 1)), new _decimal.default(0));
|
|
3048
|
+
const requiredAmount = existedAmount.plus(new _decimal.default(snapshot.price || 0).times(product.num || 1));
|
|
3049
|
+
const balance = new _decimal.default(asset.balance || 0);
|
|
3050
|
+
if (balance.lt(requiredAmount)) {
|
|
3051
|
+
throw new _virtualSettlement.VirtualCurrencyBalanceError(balance.toFixed(2), requiredAmount.toFixed(2));
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
(0, _virtualSettlement.applyTempOrderSettlementState)(tempOrder, snapshot || {
|
|
3055
|
+
settlement_type: 'legal_currency',
|
|
3056
|
+
price: product.selling_price ?? product.original_price ?? product.payment_price ?? 0,
|
|
3057
|
+
unit_label: tempOrder.currency_code,
|
|
3058
|
+
symbol: tempOrder.currency_symbol,
|
|
3059
|
+
amount_format: tempOrder.currency_format
|
|
3060
|
+
});
|
|
3061
|
+
}
|
|
3062
|
+
syncTempOrderSettlementState(tempOrder) {
|
|
3063
|
+
if (!this.isMultiCurrencySettlementEnabled()) return;
|
|
3064
|
+
tempOrder.metadata = tempOrder.metadata || {};
|
|
3065
|
+
if (!tempOrder.products.length) {
|
|
3066
|
+
(0, _virtualSettlement.releaseTempOrderSettlementState)(tempOrder);
|
|
3067
|
+
return;
|
|
3068
|
+
}
|
|
3069
|
+
const snapshot = (0, _virtualSettlement.getTempOrderSettlementSnapshot)(tempOrder);
|
|
3070
|
+
if (snapshot) {
|
|
3071
|
+
(0, _virtualSettlement.applyTempOrderSettlementState)(tempOrder, snapshot);
|
|
3072
|
+
return;
|
|
3073
|
+
}
|
|
3074
|
+
tempOrder.metadata.cart_settlement_key = 'legal_currency';
|
|
3075
|
+
}
|
|
3076
|
+
prepareVirtualSettlementTempOrder(tempOrder) {
|
|
3077
|
+
if (!this.isMultiCurrencySettlementEnabled()) return;
|
|
3078
|
+
this.syncTempOrderSettlementState(tempOrder);
|
|
3079
|
+
if (!this.isActiveVirtualSettlementOrder(tempOrder)) return;
|
|
3080
|
+
tempOrder.products = (0, _virtualSettlement.normalizeVirtualSettlementProducts)(tempOrder.products);
|
|
3081
|
+
tempOrder.discount_list = [];
|
|
3082
|
+
tempOrder.shop_discount = '0.00';
|
|
3083
|
+
tempOrder.surcharge_fee = '0.00';
|
|
3084
|
+
tempOrder.surcharges = [];
|
|
3085
|
+
const virtualOrder = tempOrder;
|
|
3086
|
+
virtualOrder.discount_amount = '0.00';
|
|
3087
|
+
virtualOrder.product_tax_fee = '0.00';
|
|
3088
|
+
virtualOrder.tax_fee = '0.00';
|
|
3089
|
+
virtualOrder.shipping_fee = '0.00';
|
|
3090
|
+
virtualOrder.shipping_tax_fee = '0.00';
|
|
3091
|
+
virtualOrder.tip_fee = '0.00';
|
|
3092
|
+
}
|
|
2979
3093
|
|
|
2980
3094
|
// ─── TempOrder: 商品 CRUD ───
|
|
2981
3095
|
|
|
@@ -2987,13 +3101,15 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2987
3101
|
*/
|
|
2988
3102
|
async finalizeProductOrderMutation(tempOrder, options) {
|
|
2989
3103
|
this.syncTempOrderHolderFromBookings(tempOrder);
|
|
2990
|
-
|
|
3104
|
+
this.prepareVirtualSettlementTempOrder(tempOrder);
|
|
3105
|
+
const isVirtualSettlement = this.isActiveVirtualSettlementOrder(tempOrder);
|
|
3106
|
+
if (!options?.skipEditDiscountConfigRefresh && !isVirtualSettlement) {
|
|
2991
3107
|
await this.ensureEditDiscountConfigForProductChange(tempOrder);
|
|
2992
3108
|
}
|
|
2993
|
-
if (!options?.skipDiscountRecalculation) {
|
|
3109
|
+
if (!options?.skipDiscountRecalculation && !isVirtualSettlement) {
|
|
2994
3110
|
await this.applyPromotion();
|
|
2995
3111
|
}
|
|
2996
|
-
if (!options?.skipDiscountRecalculation) {
|
|
3112
|
+
if (!options?.skipDiscountRecalculation && !isVirtualSettlement) {
|
|
2997
3113
|
this.applyDiscount();
|
|
2998
3114
|
}
|
|
2999
3115
|
this.sanitizeTempOrderProducts(tempOrder);
|
|
@@ -3021,9 +3137,10 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3021
3137
|
booking
|
|
3022
3138
|
}) : null;
|
|
3023
3139
|
const productToAdd = linked?.product || product;
|
|
3140
|
+
this.assertAndLockProductSettlement(tempOrder, productToAdd);
|
|
3024
3141
|
const disableMerge = options?.disableMerge === true;
|
|
3025
3142
|
const incomingFingerprint = disableMerge ? '' : (0, _utils3.buildProductLineFingerprint)((0, _utils.getProductSkuOptions)(productToAdd), productToAdd.product_bundle);
|
|
3026
|
-
const normalizedIncoming = (0, _utils.mergeOrderProductDisplayFields)(productToAdd, (0, _utils3.normalizeOrderProduct)(productToAdd));
|
|
3143
|
+
const normalizedIncoming = this.normalizeVirtualSettlementProductIfEnabled((0, _utils.mergeOrderProductDisplayFields)(productToAdd, (0, _utils3.normalizeOrderProduct)(productToAdd)));
|
|
3027
3144
|
if (disableMerge) {
|
|
3028
3145
|
normalizedIncoming.metadata = {
|
|
3029
3146
|
...(normalizedIncoming.metadata || {}),
|
|
@@ -3084,13 +3201,13 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3084
3201
|
} else {
|
|
3085
3202
|
const targetProduct = matchedProduct;
|
|
3086
3203
|
const targetUid = targetProduct.metadata?.unique_identification_number;
|
|
3087
|
-
const normalizedProduct = (0, _utils.mergeOrderProductDisplayFields)(targetProduct, (0, _utils3.normalizeOrderProduct)({
|
|
3204
|
+
const normalizedProduct = this.normalizeVirtualSettlementProductIfEnabled((0, _utils.mergeOrderProductDisplayFields)(targetProduct, (0, _utils3.normalizeOrderProduct)({
|
|
3088
3205
|
...productToAdd,
|
|
3089
3206
|
metadata: {
|
|
3090
3207
|
...(productToAdd.metadata || {}),
|
|
3091
3208
|
unique_identification_number: targetUid
|
|
3092
3209
|
}
|
|
3093
|
-
}));
|
|
3210
|
+
})));
|
|
3094
3211
|
normalizedProduct.discount_list = (0, _utils.normalizeOrderProductDiscountList)(normalizedProduct.discount_list);
|
|
3095
3212
|
const nextNum = (0, _utils3.getSafeProductNum)(targetProduct.num + normalizedProduct.num);
|
|
3096
3213
|
tempOrder.products[matchedIndex] = {
|
|
@@ -3498,7 +3615,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3498
3615
|
}
|
|
3499
3616
|
// normalizeOrderProduct 幂等:v2 metadata 存在 → 保留 main_product_* 折扣重算 composite;
|
|
3500
3617
|
// 否则 → 把顶层 selling_price 视作 source,派生 main_product_* 并写 price_schema_version: 2。
|
|
3501
|
-
let normalizedProduct = (0, _utils.mergeOrderProductDisplayFields)(nextProduct, (0, _utils3.normalizeOrderProduct)(nextProduct));
|
|
3618
|
+
let normalizedProduct = this.normalizeVirtualSettlementProductIfEnabled((0, _utils.mergeOrderProductDisplayFields)(nextProduct, (0, _utils3.normalizeOrderProduct)(nextProduct)));
|
|
3502
3619
|
normalizedProduct.discount_list = (0, _utils.normalizeOrderProductDiscountList)(normalizedProduct.discount_list);
|
|
3503
3620
|
const preservedBookingUid = nextProduct.booking_uid || nextProduct.metadata?.booking_uid || targetProduct.booking_uid || targetProduct.metadata?.booking_uid;
|
|
3504
3621
|
if (!booking && preservedBookingUid) {
|
|
@@ -3615,18 +3732,38 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3615
3732
|
throw new Error('[Order] 目标商品不存在,无法更新数量');
|
|
3616
3733
|
}
|
|
3617
3734
|
const targetProduct = tempOrder.products[productIndex];
|
|
3618
|
-
const normalizedProduct = (0, _utils3.normalizeOrderProduct)({
|
|
3735
|
+
const normalizedProduct = this.normalizeVirtualSettlementProductIfEnabled((0, _utils3.normalizeOrderProduct)({
|
|
3619
3736
|
...targetProduct,
|
|
3620
3737
|
num: (0, _utils3.getSafeProductNum)(num),
|
|
3621
3738
|
metadata: {
|
|
3622
3739
|
...(targetProduct.metadata || {}),
|
|
3623
3740
|
unique_identification_number: targetProduct.metadata?.unique_identification_number || unique_identification_number
|
|
3624
3741
|
}
|
|
3625
|
-
});
|
|
3742
|
+
}));
|
|
3626
3743
|
normalizedProduct.discount_list = (0, _utils.normalizeOrderProductDiscountList)(normalizedProduct.discount_list);
|
|
3744
|
+
const settlementSnapshot = (0, _virtualSettlement.getSelectedSettlementSnapshot)(normalizedProduct);
|
|
3745
|
+
if (this.isMultiCurrencySettlementEnabled() && settlementSnapshot?.settlement_type === 'virtual_currency' && tempOrder.customer_id && Number(tempOrder.customer_id) !== 1) {
|
|
3746
|
+
const currencyProductId = Number(settlementSnapshot.currency_product_id);
|
|
3747
|
+
const asset = (this.store.virtualCurrencyList || []).find(item => Number(item?.product_id) === currencyProductId);
|
|
3748
|
+
if (!asset) {
|
|
3749
|
+
throw new _virtualSettlement.VirtualCurrencyAssetNotFoundError(currencyProductId);
|
|
3750
|
+
}
|
|
3751
|
+
const requiredAmount = tempOrder.products.reduce((sum, item, index) => {
|
|
3752
|
+
const current = index === productIndex ? normalizedProduct : item;
|
|
3753
|
+
const currentSnapshot = (0, _virtualSettlement.getSelectedSettlementSnapshot)(current);
|
|
3754
|
+
return sum.plus(new _decimal.default(currentSnapshot?.price || current.selling_price || 0).times(current.num || 1));
|
|
3755
|
+
}, new _decimal.default(0));
|
|
3756
|
+
const balance = new _decimal.default(asset.balance || 0);
|
|
3757
|
+
if (balance.lt(requiredAmount)) {
|
|
3758
|
+
throw new _virtualSettlement.VirtualCurrencyBalanceError(balance.toFixed(2), requiredAmount.toFixed(2));
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3627
3761
|
tempOrder.products[productIndex] = normalizedProduct;
|
|
3628
|
-
|
|
3629
|
-
this.
|
|
3762
|
+
this.prepareVirtualSettlementTempOrder(tempOrder);
|
|
3763
|
+
if (!this.isActiveVirtualSettlementOrder(tempOrder)) {
|
|
3764
|
+
await this.applyPromotion();
|
|
3765
|
+
this.applyDiscount();
|
|
3766
|
+
}
|
|
3630
3767
|
this.sanitizeTempOrderProducts(tempOrder);
|
|
3631
3768
|
await this.recalculateSummary({
|
|
3632
3769
|
createIfMissing: true
|
|
@@ -3780,6 +3917,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3780
3917
|
this.ensureSalesNotesLoadedForMutation(tempOrder);
|
|
3781
3918
|
tempOrder.products = [];
|
|
3782
3919
|
tempOrder.bookings = [];
|
|
3920
|
+
(0, _virtualSettlement.releaseTempOrderSettlementState)(tempOrder);
|
|
3783
3921
|
this.removeSalesNotesForMissingProductLines(tempOrder);
|
|
3784
3922
|
this.syncTempOrderHolderFromBookings(tempOrder);
|
|
3785
3923
|
if (tempOrder._extend && typeof tempOrder._extend === 'object') {
|
|
@@ -3799,6 +3937,41 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3799
3937
|
return tempOrder;
|
|
3800
3938
|
}
|
|
3801
3939
|
|
|
3940
|
+
/**
|
|
3941
|
+
* 切换购物车结算单位时清理所有会影响新币种的订单状态,但保留当前客户。
|
|
3942
|
+
*/
|
|
3943
|
+
async clearOrderForSettlementSwitch() {
|
|
3944
|
+
const tempOrder = this.ensureTempOrder();
|
|
3945
|
+
this.ensureSalesNotesLoadedForMutation(tempOrder);
|
|
3946
|
+
tempOrder.products = [];
|
|
3947
|
+
tempOrder.bookings = [];
|
|
3948
|
+
this.removeSalesNotesForMissingProductLines(tempOrder);
|
|
3949
|
+
tempOrder.discount_list = [];
|
|
3950
|
+
tempOrder.payments = [];
|
|
3951
|
+
tempOrder.refunds = [];
|
|
3952
|
+
tempOrder.shop_discount = '0.00';
|
|
3953
|
+
tempOrder.surcharges = [];
|
|
3954
|
+
(0, _virtualSettlement.releaseTempOrderSettlementState)(tempOrder);
|
|
3955
|
+
this.syncTempOrderHolderFromBookings(tempOrder);
|
|
3956
|
+
if (tempOrder._extend && typeof tempOrder._extend === 'object') {
|
|
3957
|
+
tempOrder._extend = {
|
|
3958
|
+
...tempOrder._extend,
|
|
3959
|
+
productsByUid: {}
|
|
3960
|
+
};
|
|
3961
|
+
}
|
|
3962
|
+
await this.store.discount?.setDiscountList([]);
|
|
3963
|
+
await this.store.discount?.setOriginalDiscountList([]);
|
|
3964
|
+
this.hasActiveCustomerBoundDiscount = false;
|
|
3965
|
+
this.lastUnfulfilledPromotions = [];
|
|
3966
|
+
this.lastGiftActions = null;
|
|
3967
|
+
await this.recalculateSummary({
|
|
3968
|
+
createIfMissing: true
|
|
3969
|
+
});
|
|
3970
|
+
this.persistTempOrder();
|
|
3971
|
+
this.logInfo('clearOrderForSettlementSwitch success', {});
|
|
3972
|
+
return tempOrder;
|
|
3973
|
+
}
|
|
3974
|
+
|
|
3802
3975
|
// ─── TempOrder: 提交 ───
|
|
3803
3976
|
|
|
3804
3977
|
buildCurrentSubmitPayloadForLocalPrint(params) {
|
|
@@ -3888,9 +4061,14 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3888
4061
|
}
|
|
3889
4062
|
async runSubmitTempOrder(params) {
|
|
3890
4063
|
const tempOrder = this.ensureTempOrder();
|
|
4064
|
+
this.prepareVirtualSettlementTempOrder(tempOrder);
|
|
4065
|
+
const isOnlineStorePlatform = this.isOnlineStorePlatform();
|
|
3891
4066
|
const shouldConfirmPendingVoucherPayments = params?.confirmPendingVoucherPayments !== false;
|
|
3892
4067
|
const hasPaymentOverride = params?.payments !== undefined;
|
|
3893
|
-
|
|
4068
|
+
let preparedPaymentOverride;
|
|
4069
|
+
if (hasPaymentOverride) {
|
|
4070
|
+
preparedPaymentOverride = isOnlineStorePlatform ? params?.payments || [] : this.prepareVoucherPaymentsForSubmit(params?.payments || [], shouldConfirmPendingVoucherPayments);
|
|
4071
|
+
}
|
|
3894
4072
|
if (!hasPaymentOverride) {
|
|
3895
4073
|
if (shouldConfirmPendingVoucherPayments) {
|
|
3896
4074
|
this.confirmPendingVoucherPayments({
|
|
@@ -3910,6 +4088,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3910
4088
|
})) || this.store.summary || (0, _utils.createEmptySummary)();
|
|
3911
4089
|
const effectiveCacheId = params?.cacheId ?? this.cacheId;
|
|
3912
4090
|
const hasPaymentStatusOverride = params?.paymentStatus !== undefined;
|
|
4091
|
+
const shouldOverridePaymentStatus = hasPaymentStatusOverride && !isOnlineStorePlatform && !shouldConfirmPendingVoucherPayments;
|
|
3913
4092
|
const hasSmallTicketDataFlagOverride = params?.smallTicketDataFlag !== undefined;
|
|
3914
4093
|
const enhancePayload = hasPaymentOverride || hasPaymentStatusOverride || hasSmallTicketDataFlagOverride || params?.enhancePayload ? (payload, ctx) => {
|
|
3915
4094
|
const nextPayload = {
|
|
@@ -3917,7 +4096,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3917
4096
|
...(hasPaymentOverride ? {
|
|
3918
4097
|
payments: preparedPaymentOverride || []
|
|
3919
4098
|
} : {}),
|
|
3920
|
-
...(
|
|
4099
|
+
...(shouldOverridePaymentStatus ? {
|
|
3921
4100
|
payment_status: params?.paymentStatus
|
|
3922
4101
|
} : {}),
|
|
3923
4102
|
...(hasSmallTicketDataFlagOverride ? {
|
|
@@ -3937,6 +4116,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3937
4116
|
type: submitSnapshot.type ?? params?.type,
|
|
3938
4117
|
summary: latestSummary,
|
|
3939
4118
|
request_unique_idempotency_token: params?.request_unique_idempotency_token,
|
|
4119
|
+
includePaymentStatus: !isOnlineStorePlatform,
|
|
3940
4120
|
enhance: enhancePayload
|
|
3941
4121
|
});
|
|
3942
4122
|
if (params?.syncMode) {
|
|
@@ -4868,7 +5048,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4868
5048
|
};
|
|
4869
5049
|
if (result.metadata) delete result.metadata.price_schema_version;
|
|
4870
5050
|
const restored = (0, _bundleDiscountHydration.restoreHydratedBundleDiscounts)(result, _utils.normalizeOrderProductDiscountList);
|
|
4871
|
-
return this.sanitizeOrderProductForTempOrder(restored);
|
|
5051
|
+
return this.sanitizeOrderProductForTempOrder(this.normalizeVirtualSettlementProductIfEnabled(restored));
|
|
4872
5052
|
}
|
|
4873
5053
|
getLastOrderInfo() {
|
|
4874
5054
|
return this.store?.lastOrderInfo;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CartItem } from '../Cart/types';
|
|
2
2
|
import type { DiscountModule } from '../Discount';
|
|
3
3
|
import type { RulesModule } from '../Rules';
|
|
4
|
-
import type { Discount } from '../Discount/types';
|
|
4
|
+
import type { Discount, VirtualCurrencyAsset } from '../Discount/types';
|
|
5
5
|
import type { UnavailableReason } from '../Rules/types';
|
|
6
6
|
import type { SubmitPayloadEnhancer } from './utils';
|
|
7
7
|
import type { PaymentItem } from '../Payment/types';
|
|
@@ -205,6 +205,7 @@ export interface OrderProduct extends OrderProductIdentity {
|
|
|
205
205
|
gift_card?: number;
|
|
206
206
|
selling_price: string;
|
|
207
207
|
original_price: string;
|
|
208
|
+
payment_price?: string;
|
|
208
209
|
tax_fee: string;
|
|
209
210
|
is_charge_tax: number;
|
|
210
211
|
discount_list: OrderProductDiscountItem[];
|
|
@@ -353,6 +354,7 @@ export interface OrderTempOrder {
|
|
|
353
354
|
notes: SalesNote[];
|
|
354
355
|
bookings: any[];
|
|
355
356
|
payments: any[];
|
|
357
|
+
refunds?: any[];
|
|
356
358
|
surcharges: any[];
|
|
357
359
|
discount_list?: any[];
|
|
358
360
|
relation_forms: any[];
|
|
@@ -372,8 +374,9 @@ export interface OrderSubmitProduct extends Omit<OrderProduct, 'unique_identific
|
|
|
372
374
|
payment_price: string;
|
|
373
375
|
product_sku: OrderProductSku;
|
|
374
376
|
}
|
|
375
|
-
export interface OrderSubmitPayload extends Omit<OrderTempOrder, 'platform' | 'products' | 'notes' | '_extend' | 'customer' | 'discount_list' | 'created_at'> {
|
|
377
|
+
export interface OrderSubmitPayload extends Omit<OrderTempOrder, 'platform' | 'products' | 'notes' | '_extend' | 'customer' | 'discount_list' | 'created_at' | 'payment_status'> {
|
|
376
378
|
platform: string;
|
|
379
|
+
payment_status?: string;
|
|
377
380
|
created_at?: string | undefined;
|
|
378
381
|
request_unique_idempotency_token?: string;
|
|
379
382
|
form_record_ids?: Array<{
|
|
@@ -392,6 +395,7 @@ export interface OrderState {
|
|
|
392
395
|
syncState?: OrderSyncState;
|
|
393
396
|
discountList: any[];
|
|
394
397
|
availableWalletIds?: number[];
|
|
398
|
+
virtualCurrencyList?: VirtualCurrencyAsset[];
|
|
395
399
|
discount: DiscountModule | null;
|
|
396
400
|
rules: RulesModule | null;
|
|
397
401
|
}
|
|
@@ -530,7 +534,7 @@ export interface SubmitSalesOrderParams {
|
|
|
530
534
|
sales_channel: string;
|
|
531
535
|
order_sales_channel: string;
|
|
532
536
|
status: string;
|
|
533
|
-
payment_status
|
|
537
|
+
payment_status?: string;
|
|
534
538
|
shipping_status: string;
|
|
535
539
|
customer_id: number | null;
|
|
536
540
|
customer_name: string;
|
|
@@ -794,6 +798,8 @@ export interface OrderModuleAPI {
|
|
|
794
798
|
addNewOrder: () => Promise<OrderTempOrder>;
|
|
795
799
|
restoreOrder: () => OrderTempOrder;
|
|
796
800
|
getOrderProducts: () => OrderProduct[];
|
|
801
|
+
getVirtualCurrencyList: () => VirtualCurrencyAsset[];
|
|
802
|
+
clearOrderForSettlementSwitch: () => Promise<OrderTempOrder>;
|
|
797
803
|
getOrderSummary: () => Promise<OrderSummary>;
|
|
798
804
|
recalculateSummary: (options?: {
|
|
799
805
|
createIfMissing?: boolean;
|
|
@@ -864,6 +870,8 @@ export interface OrderModuleAPI {
|
|
|
864
870
|
isTempOrderPersistEnabled: () => boolean;
|
|
865
871
|
/** 提交 tempOrder 变更并触发 `{moduleName}:changed` 事件 */
|
|
866
872
|
notifyTempOrderChanged: () => void;
|
|
873
|
+
/** PC/H5 为在线店铺;其它或缺失平台统一按 POS 处理。 */
|
|
874
|
+
isOnlineStorePlatform: () => boolean;
|
|
867
875
|
submitTempOrder: <T = any>(params?: {
|
|
868
876
|
cacheId?: string;
|
|
869
877
|
platform?: string;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { OrderProduct, OrderTempOrder } from '../types';
|
|
2
|
+
export interface SelectedSettlementSnapshot extends Record<string, any> {
|
|
3
|
+
settlement_type: 'legal_currency' | 'virtual_currency';
|
|
4
|
+
currency_product_id?: number;
|
|
5
|
+
price: string | number;
|
|
6
|
+
unit_label?: any;
|
|
7
|
+
symbol?: any;
|
|
8
|
+
amount_format?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface LegalCurrencySnapshot {
|
|
11
|
+
currency_code: string;
|
|
12
|
+
currency_symbol: string;
|
|
13
|
+
currency_format: string;
|
|
14
|
+
}
|
|
15
|
+
export interface CurrencyDisplaySnapshot {
|
|
16
|
+
amount_format: string;
|
|
17
|
+
symbol: unknown;
|
|
18
|
+
unit_label: unknown;
|
|
19
|
+
}
|
|
20
|
+
export declare function buildCurrencyDisplaySnapshot(snapshot: Pick<SelectedSettlementSnapshot, 'amount_format' | 'symbol' | 'unit_label'>): CurrencyDisplaySnapshot;
|
|
21
|
+
export declare function resolveSettlementDisplayValue(value: unknown): string;
|
|
22
|
+
export declare class OrderSettlementConflictError extends Error {
|
|
23
|
+
readonly currentSettlementKey: string;
|
|
24
|
+
readonly incomingSettlementKey: string;
|
|
25
|
+
readonly code = "ORDER_SETTLEMENT_CONFLICT";
|
|
26
|
+
constructor(currentSettlementKey: string, incomingSettlementKey: string);
|
|
27
|
+
}
|
|
28
|
+
export declare class VirtualCurrencyAssetNotFoundError extends Error {
|
|
29
|
+
readonly currencyProductId: number;
|
|
30
|
+
readonly code = "VIRTUAL_CURRENCY_ASSET_NOT_FOUND";
|
|
31
|
+
constructor(currencyProductId: number);
|
|
32
|
+
}
|
|
33
|
+
export declare class VirtualCurrencyBalanceError extends Error {
|
|
34
|
+
readonly balance: string;
|
|
35
|
+
readonly requiredAmount: string;
|
|
36
|
+
readonly code = "VIRTUAL_CURRENCY_BALANCE_INSUFFICIENT";
|
|
37
|
+
constructor(balance: string, requiredAmount: string);
|
|
38
|
+
}
|
|
39
|
+
export declare function getSelectedSettlementSnapshot(product: Partial<OrderProduct> | null | undefined): SelectedSettlementSnapshot | null;
|
|
40
|
+
export declare function getTempOrderSettlementSnapshot(tempOrder: OrderTempOrder | null | undefined): SelectedSettlementSnapshot | null;
|
|
41
|
+
export declare function isVirtualSettlementProduct(product: Partial<OrderProduct> | null | undefined): boolean;
|
|
42
|
+
export declare function getSettlementKey(snapshot: SelectedSettlementSnapshot | null | undefined): string | null;
|
|
43
|
+
export declare function getTempOrderSettlementKey(tempOrder: OrderTempOrder | null | undefined): string | null;
|
|
44
|
+
export declare function isVirtualSettlementOrder(tempOrder: OrderTempOrder | null | undefined): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* 详情展示识别同时支持已提交订单的 currency_settlement_config。
|
|
47
|
+
* cart_settlement_* 是交易过程内部状态,服务端详情不保证返回。
|
|
48
|
+
*/
|
|
49
|
+
export declare function isVirtualSettlementDisplayOrder(tempOrder: OrderTempOrder | null | undefined): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* 将购物车锁定的结算单位提升为订单级状态。
|
|
52
|
+
* 商品行快照同时负责价格归一化和生成订单级多语言展示快照;
|
|
53
|
+
* 交易中的即时展示仍统一读取 tempOrder.currency_*。
|
|
54
|
+
*/
|
|
55
|
+
export declare function applyTempOrderSettlementState(tempOrder: OrderTempOrder, snapshot: SelectedSettlementSnapshot): void;
|
|
56
|
+
/** 清空购物车结算锁,并恢复进入虚拟币结算前的店铺法币。 */
|
|
57
|
+
export declare function releaseTempOrderSettlementState(tempOrder: OrderTempOrder): void;
|
|
58
|
+
/**
|
|
59
|
+
* 将已选择虚拟币的订单商品行固化为最终价语义。
|
|
60
|
+
* 函数幂等,可安全用于加车、合并、hydrate 和提交前兜底。
|
|
61
|
+
*/
|
|
62
|
+
export declare function normalizeVirtualSettlementOrderProduct<T extends Partial<OrderProduct>>(product: T): T;
|
|
63
|
+
export declare function normalizeVirtualSettlementProducts<T extends Partial<OrderProduct>>(products: T[]): T[];
|