@pisell/pisellos 2.2.308 → 2.2.310
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/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
- package/dist/model/strategy/adapter/walletPass/evaluator.js +4 -2
- package/dist/modules/BookingContext/index.js +4 -4
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +58 -19
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +24 -12
- package/dist/modules/Customer/index.js +6 -3
- package/dist/modules/Customer/types.d.ts +2 -0
- package/dist/modules/Discount/availability.d.ts +7 -0
- package/dist/modules/Discount/availability.js +49 -0
- package/dist/modules/Discount/entitlementPass.d.ts +34 -0
- package/dist/modules/Discount/entitlementPass.js +147 -0
- package/dist/modules/Discount/index.d.ts +2 -2
- package/dist/modules/Discount/index.js +37 -151
- package/dist/modules/Discount/types.d.ts +36 -5
- package/dist/modules/OpenData/index.d.ts +1 -1
- package/dist/modules/OpenData/index.js +21 -12
- package/dist/modules/Order/index.d.ts +33 -4
- package/dist/modules/Order/index.js +830 -411
- package/dist/modules/Order/types.d.ts +17 -0
- package/dist/modules/Order/utils/orderCollectionIdentity.js +16 -12
- package/dist/modules/Order/utils/weighedProduct.d.ts +12 -0
- package/dist/modules/Order/utils/weighedProduct.js +94 -0
- package/dist/modules/Order/utils.d.ts +14 -2
- package/dist/modules/Order/utils.js +280 -79
- package/dist/modules/Payment/index.d.ts +0 -5
- package/dist/modules/Payment/index.js +35 -85
- package/dist/modules/Payment/types.d.ts +21 -1
- package/dist/modules/Payment/types.js +2 -0
- package/dist/modules/Payment/walletpass.d.ts +1 -1
- package/dist/modules/Payment/walletpass.js +80 -47
- package/dist/modules/ProductList/index.js +18 -5
- package/dist/modules/Rules/index.d.ts +2 -2
- package/dist/modules/Rules/index.js +484 -188
- package/dist/modules/Rules/types.d.ts +6 -0
- package/dist/server/index.js +8 -5
- package/dist/server/modules/order/index.js +6 -0
- package/dist/server/modules/order/types.d.ts +12 -0
- package/dist/server/modules/payment/index.d.ts +25 -6
- package/dist/server/modules/payment/index.js +660 -133
- package/dist/server/utils/small-ticket.d.ts +8 -5
- package/dist/server/utils/small-ticket.js +1269 -199
- package/dist/solution/BaseSales/index.d.ts +11 -2
- package/dist/solution/BaseSales/index.js +1463 -1173
- package/dist/solution/BaseSales/types.d.ts +7 -3
- package/dist/solution/BaseSales/utils/cartPromotion.js +141 -126
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +40 -25
- package/dist/solution/BaseSales/utils.js +3 -2
- package/dist/solution/BookingTicket/index.d.ts +11 -2
- package/dist/solution/BookingTicket/index.js +663 -542
- package/dist/solution/BookingTicket/types.d.ts +5 -1
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +2 -0
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +338 -147
- package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +8 -4
- package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +6 -0
- package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.js +19 -6
- package/dist/solution/ScanOrder/utils.js +3 -2
- package/dist/solution/ShopDiscount/index.d.ts +2 -0
- package/dist/solution/ShopDiscount/index.js +99 -42
- package/dist/solution/ShopDiscount/utils.d.ts +4 -2
- package/dist/solution/ShopDiscount/utils.js +43 -23
- package/dist/solution/UnifiedBookingSales/index.d.ts +2 -2
- package/dist/solution/UnifiedBookingSales/index.js +5 -5
- package/dist/utils/os-private-payload.d.ts +5 -0
- package/dist/utils/os-private-payload.js +17 -0
- package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
- package/lib/model/strategy/adapter/walletPass/evaluator.js +2 -0
- package/lib/modules/BookingContext/index.js +3 -3
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +35 -6
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +13 -6
- package/lib/modules/Customer/index.js +5 -1
- package/lib/modules/Customer/types.d.ts +2 -0
- package/lib/modules/Discount/availability.d.ts +7 -0
- package/lib/modules/Discount/availability.js +43 -0
- package/lib/modules/Discount/entitlementPass.d.ts +34 -0
- package/lib/modules/Discount/entitlementPass.js +141 -0
- package/lib/modules/Discount/index.d.ts +2 -2
- package/lib/modules/Discount/index.js +23 -129
- package/lib/modules/Discount/types.d.ts +36 -5
- package/lib/modules/OpenData/index.d.ts +1 -1
- package/lib/modules/OpenData/index.js +11 -2
- package/lib/modules/Order/index.d.ts +33 -4
- package/lib/modules/Order/index.js +411 -81
- package/lib/modules/Order/types.d.ts +17 -0
- package/lib/modules/Order/utils/orderCollectionIdentity.js +14 -11
- package/lib/modules/Order/utils/weighedProduct.d.ts +12 -0
- package/lib/modules/Order/utils/weighedProduct.js +89 -0
- package/lib/modules/Order/utils.d.ts +14 -2
- package/lib/modules/Order/utils.js +189 -5
- package/lib/modules/Payment/index.d.ts +0 -5
- package/lib/modules/Payment/index.js +3 -28
- package/lib/modules/Payment/types.d.ts +21 -1
- package/lib/modules/Payment/types.js +1 -0
- package/lib/modules/Payment/walletpass.d.ts +1 -1
- package/lib/modules/Payment/walletpass.js +29 -9
- package/lib/modules/ProductList/index.js +14 -1
- package/lib/modules/Rules/index.d.ts +2 -2
- package/lib/modules/Rules/index.js +361 -112
- package/lib/modules/Rules/types.d.ts +6 -0
- package/lib/server/index.js +8 -5
- package/lib/server/modules/order/index.js +6 -0
- package/lib/server/modules/order/types.d.ts +12 -0
- package/lib/server/modules/payment/index.d.ts +25 -6
- package/lib/server/modules/payment/index.js +350 -78
- package/lib/server/utils/small-ticket.d.ts +8 -5
- package/lib/server/utils/small-ticket.js +1009 -121
- package/lib/solution/BaseSales/index.d.ts +11 -2
- package/lib/solution/BaseSales/index.js +164 -30
- package/lib/solution/BaseSales/types.d.ts +7 -3
- package/lib/solution/BaseSales/utils/cartPromotion.js +12 -4
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +24 -9
- package/lib/solution/BaseSales/utils.js +2 -1
- package/lib/solution/BookingTicket/index.d.ts +11 -2
- package/lib/solution/BookingTicket/index.js +103 -41
- package/lib/solution/BookingTicket/types.d.ts +5 -1
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +2 -0
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +174 -42
- package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +8 -4
- package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +6 -0
- package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +11 -3
- package/lib/solution/ScanOrder/utils.js +2 -1
- package/lib/solution/ShopDiscount/index.d.ts +2 -0
- package/lib/solution/ShopDiscount/index.js +55 -9
- package/lib/solution/ShopDiscount/utils.d.ts +4 -2
- package/lib/solution/ShopDiscount/utils.js +42 -25
- package/lib/solution/UnifiedBookingSales/index.d.ts +2 -2
- package/lib/solution/UnifiedBookingSales/index.js +5 -5
- package/lib/utils/os-private-payload.d.ts +5 -0
- package/lib/utils/os-private-payload.js +22 -0
- package/package.json +1 -1
|
@@ -8,7 +8,10 @@ var _BaseModule = require("../BaseModule");
|
|
|
8
8
|
var _types = require("./types");
|
|
9
9
|
var _utils = require("./utils");
|
|
10
10
|
var _utils2 = require("../Product/utils");
|
|
11
|
+
var _weighedProduct = require("./utils/weighedProduct");
|
|
11
12
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
13
|
+
var _availability = require("../Discount/availability");
|
|
14
|
+
var _osPrivatePayload = require("../../utils/os-private-payload");
|
|
12
15
|
var _salesNotes = require("./salesNotes");
|
|
13
16
|
var _paymentUtils = require("./payment-utils");
|
|
14
17
|
var _paymentNumber = require("../../utils/payment-number");
|
|
@@ -21,6 +24,7 @@ var _discountProductLineIdentity = require("./utils/discountProductLineIdentity"
|
|
|
21
24
|
var _virtualSettlement = require("./utils/virtualSettlement");
|
|
22
25
|
var _Discount = require("../Discount");
|
|
23
26
|
var _Rules = require("../Rules");
|
|
27
|
+
var _entitlementPass = require("../Discount/entitlementPass");
|
|
24
28
|
var _types2 = require("../Rules/types");
|
|
25
29
|
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
26
30
|
var _lodashEs = require("lodash-es");
|
|
@@ -40,9 +44,27 @@ function isSameDiscountList(left, right) {
|
|
|
40
44
|
function isManualProductDiscountProduct(product) {
|
|
41
45
|
return (0, _manualProductDiscount.hasManualProductDiscountFlag)(product?.metadata) || (product?.discount_list || []).some(item => item?.type === 'product');
|
|
42
46
|
}
|
|
47
|
+
function syncReducedEntitlementPassUsageCount(discountList, previousQuantity, nextQuantity) {
|
|
48
|
+
if (!Array.isArray(discountList)) return discountList;
|
|
49
|
+
const previousCount = (0, _utils3.getSafeProductNum)(previousQuantity);
|
|
50
|
+
const nextCount = (0, _utils3.getSafeProductNum)(nextQuantity);
|
|
51
|
+
if (nextCount >= previousCount) return discountList;
|
|
52
|
+
return discountList.map(discount => {
|
|
53
|
+
if (!(0, _entitlementPass.isEntitlementPass)(discount)) return discount;
|
|
54
|
+
const rawUsageCount = Number(discount?.metadata?.num ?? previousCount);
|
|
55
|
+
const usageCount = Number.isFinite(rawUsageCount) ? Math.max(Math.floor(rawUsageCount), 0) : previousCount;
|
|
56
|
+
return {
|
|
57
|
+
...discount,
|
|
58
|
+
metadata: {
|
|
59
|
+
...(discount?.metadata || {}),
|
|
60
|
+
num: Math.min(usageCount, nextCount)
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
}
|
|
43
65
|
const ORDER_PAYMENT_STATUS_PAID = 'paid';
|
|
44
66
|
const ORDER_PAYMENT_STATUS_PENDING = 'payment_pending';
|
|
45
|
-
const CUSTOMER_PROMOTION_DISCOUNT_TAGS = new Set(['good_pass', 'product_discount_card', 'discount_card']);
|
|
67
|
+
const CUSTOMER_PROMOTION_DISCOUNT_TAGS = new Set(['entitlement_pass', 'good_pass', 'product_discount_card', 'discount_card']);
|
|
46
68
|
function isCustomerPromotionDiscount(discount) {
|
|
47
69
|
return CUSTOMER_PROMOTION_DISCOUNT_TAGS.has(String(discount?.tag || discount?.type || '').toLowerCase());
|
|
48
70
|
}
|
|
@@ -72,12 +94,27 @@ function getVoucherPaymentLifecycleKey(payment) {
|
|
|
72
94
|
if (!isVoucherPaymentRecord(payment)) return null;
|
|
73
95
|
return `${String(payment.voucher_id)}::${String(payment.status || '')}`;
|
|
74
96
|
}
|
|
75
|
-
function
|
|
76
|
-
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
97
|
+
function getDiscountIdentityKey(discount) {
|
|
98
|
+
const id = discount?.id;
|
|
99
|
+
if (id === undefined || id === null || id === '') return null;
|
|
100
|
+
return String(id);
|
|
101
|
+
}
|
|
102
|
+
function mergeCommittedEntitlementWithRuntime(committed, runtime) {
|
|
103
|
+
const committedAppliedProductDetails = committed.committedAppliedProductDetails?.length ? committed.committedAppliedProductDetails : committed.appliedProductDetails || [];
|
|
104
|
+
return {
|
|
105
|
+
...committed,
|
|
106
|
+
...runtime,
|
|
107
|
+
id: runtime.id ?? committed.id,
|
|
108
|
+
tag: runtime.tag || committed.tag,
|
|
109
|
+
type: runtime.type || committed.type,
|
|
110
|
+
isEditMode: false,
|
|
111
|
+
isDisabled: runtime.isDisabled ?? false,
|
|
112
|
+
isSelected: runtime.isSelected ?? committed.isSelected,
|
|
113
|
+
isUsed: committed.isUsed || runtime.isUsed,
|
|
114
|
+
committedAppliedProductDetails: [...committedAppliedProductDetails],
|
|
115
|
+
applicableProductDetails: [...(committed.applicableProductDetails || []), ...(runtime.applicableProductDetails || [])],
|
|
116
|
+
appliedProductDetails: [...committedAppliedProductDetails, ...(runtime.appliedProductDetails || [])]
|
|
117
|
+
};
|
|
81
118
|
}
|
|
82
119
|
class OrderModule extends _BaseModule.BaseModule {
|
|
83
120
|
defaultName = 'order';
|
|
@@ -92,6 +129,10 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
92
129
|
openCache = false;
|
|
93
130
|
sessionStoragePersistEnabled = false;
|
|
94
131
|
sessionStorageRestoreRecord = null;
|
|
132
|
+
/** 只允许当前订单最新的 prepare/config 请求回写客户资产态。 */
|
|
133
|
+
customerWalletPrepareConfigEpoch = 0;
|
|
134
|
+
/** Payment 可能早于 prepare/config 返回;先按实例 ID 暂存卡号等待 Snapshot。 */
|
|
135
|
+
pointCardSnapshotCodeCandidates = new Map();
|
|
95
136
|
salesSummaryModuleName;
|
|
96
137
|
rulesHooksOverride;
|
|
97
138
|
moduleHooksOverride;
|
|
@@ -130,6 +171,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
130
171
|
const key = Number.isFinite(id) ? id : String(resourceId);
|
|
131
172
|
const title = item?.discount?.title ?? {};
|
|
132
173
|
const amount = Number(item?.amount || 0);
|
|
174
|
+
const encoded = item?.metadata?.encoded || item?.encoded || item?.discount?.encoded || '';
|
|
133
175
|
const discountCardType = item?.discount?.discount_card_type;
|
|
134
176
|
const parValue = isDiscountCard ? discountCardType === 'fixed_amount' ? item?.discount?.fixed_amount ?? item?.amount : item?.discount?.percent : '0';
|
|
135
177
|
const detail = {
|
|
@@ -140,11 +182,21 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
140
182
|
original_amount: String(item?.discount?.original_amount ?? item?.amount ?? '0'),
|
|
141
183
|
num: Number(item?.metadata?.num ?? product?.num ?? product?.product_quantity ?? 1) || 1,
|
|
142
184
|
metadata: item?.metadata,
|
|
143
|
-
discount:
|
|
185
|
+
discount: {
|
|
186
|
+
...(item?.discount || {}),
|
|
187
|
+
product_id: item?.discount?.product_id ?? product?.product_id
|
|
188
|
+
},
|
|
144
189
|
_num: Number(item?.metadata?.num ?? product?.num ?? product?.product_quantity ?? 1) || 1
|
|
145
190
|
};
|
|
146
191
|
const existed = discountMap.get(key);
|
|
147
192
|
if (existed) {
|
|
193
|
+
if (!existed.encoded && encoded) {
|
|
194
|
+
existed.encoded = encoded;
|
|
195
|
+
existed.metadata = {
|
|
196
|
+
...existed.metadata,
|
|
197
|
+
encoded
|
|
198
|
+
};
|
|
199
|
+
}
|
|
148
200
|
existed.amount = Number(existed.amount || 0) + amount;
|
|
149
201
|
existed.used_par_value = String(Number(existed.used_par_value || 0) + amount);
|
|
150
202
|
if (!isDiscountCard) {
|
|
@@ -164,8 +216,11 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
164
216
|
discountMap.set(key, {
|
|
165
217
|
id: key,
|
|
166
218
|
product_name: '',
|
|
167
|
-
encoded
|
|
168
|
-
code: '',
|
|
219
|
+
encoded,
|
|
220
|
+
code: item?.code || item?.discount?.code || '',
|
|
221
|
+
metadata: {
|
|
222
|
+
encoded
|
|
223
|
+
},
|
|
169
224
|
tag: type,
|
|
170
225
|
product_id: item?.discount?.discount_product_id ?? product?.product_id ?? 0,
|
|
171
226
|
relation_type: '',
|
|
@@ -456,13 +511,24 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
456
511
|
this.store.rules = rules;
|
|
457
512
|
}
|
|
458
513
|
createDefaultRulesHooks() {
|
|
459
|
-
return (0, _utils.createDefaultOrderRulesHooks)();
|
|
514
|
+
return (0, _utils.createDefaultOrderRulesHooks)(() => this.store.tempOrder?.bookings || []);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Stable across notifyTempOrderChanged's immutable copy, but changes when a
|
|
519
|
+
* different local/server order becomes current.
|
|
520
|
+
*/
|
|
521
|
+
getDiscountConfigOrderIdentityKey(tempOrder) {
|
|
522
|
+
const identity = this.getOrderIdentity();
|
|
523
|
+
return JSON.stringify([identity?.orderId ?? tempOrder?.order_id ?? '', tempOrder?.request_unique_idempotency_token ?? '', identity?.externalSaleNumber ?? tempOrder?.external_sale_number ?? '', identity?.localId ?? tempOrder?._extend?.localId ?? this.cacheId ?? '']);
|
|
460
524
|
}
|
|
461
525
|
|
|
462
526
|
// ─── Discount: 公共 API ───
|
|
463
527
|
|
|
464
528
|
async loadDiscountConfig(params) {
|
|
465
529
|
const orderId = params.orderId || this.store.tempOrder?.order_id || undefined;
|
|
530
|
+
const requestEpoch = ++this.customerWalletPrepareConfigEpoch;
|
|
531
|
+
const requestOrderIdentityKey = this.getDiscountConfigOrderIdentityKey(this.store.tempOrder);
|
|
466
532
|
const prepareConfigResult = await this.store.discount?.loadPrepareConfig({
|
|
467
533
|
customer_id: params.customerId,
|
|
468
534
|
action: params.action || (orderId ? 'edit' : 'create'),
|
|
@@ -471,38 +537,90 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
471
537
|
with_wallet_pass_holder: 1,
|
|
472
538
|
with_available_wallet_flag: 1,
|
|
473
539
|
with_available_wallet_pass_flag: 1,
|
|
540
|
+
with_entitlement_pass: 1,
|
|
541
|
+
filter_order_wallet_pass_usage: 0,
|
|
474
542
|
with_virtual_currency: 1,
|
|
475
543
|
request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
476
544
|
...(orderId ? {
|
|
477
545
|
order_id: orderId
|
|
478
546
|
} : {})
|
|
479
547
|
});
|
|
548
|
+
const isCurrentRequest = () => requestEpoch === this.customerWalletPrepareConfigEpoch && this.getDiscountConfigOrderIdentityKey(this.store.tempOrder) === requestOrderIdentityKey && String(this.store.tempOrder?.customer_id ?? '') === String(params.customerId);
|
|
549
|
+
if (!isCurrentRequest()) {
|
|
550
|
+
return this.getDiscountList();
|
|
551
|
+
}
|
|
480
552
|
const discountList = prepareConfigResult?.discountList;
|
|
481
|
-
this.store.availableWalletIds = prepareConfigResult?.availableWalletIds || [];
|
|
482
|
-
this.store.virtualCurrencyList = prepareConfigResult?.virtualCurrencyList || [];
|
|
483
553
|
if (prepareConfigResult) {
|
|
484
|
-
this.
|
|
485
|
-
orderId,
|
|
554
|
+
this.writeCustomerWalletSnapshotsFromPrepareConfig({
|
|
486
555
|
customerId: params.customerId,
|
|
487
|
-
|
|
556
|
+
availableWalletIds: prepareConfigResult.availableWalletIds || [],
|
|
557
|
+
availableWalletPassList: prepareConfigResult.availableWalletPassList || [],
|
|
558
|
+
virtualCurrencyList: prepareConfigResult.virtualCurrencyList || []
|
|
488
559
|
});
|
|
489
560
|
}
|
|
490
561
|
if (discountList) {
|
|
491
562
|
const currentDiscountList = this.store.discount?.getDiscountList() || [];
|
|
492
|
-
const
|
|
563
|
+
const currentCommittedDiscounts = currentDiscountList.filter(discount => discount?.isEditMode || discount?.committedAppliedProductDetails?.length);
|
|
493
564
|
const currentScanDiscounts = currentDiscountList.filter(discount => discount?.isScan);
|
|
494
|
-
const
|
|
565
|
+
const currentScanDiscountById = new Map(currentScanDiscounts.flatMap(discount => {
|
|
566
|
+
const id = getDiscountIdentityKey(discount);
|
|
567
|
+
return id === null ? [] : [[id, discount]];
|
|
568
|
+
}));
|
|
569
|
+
const committedDiscountById = new Map(currentCommittedDiscounts.flatMap(discount => {
|
|
570
|
+
const id = getDiscountIdentityKey(discount);
|
|
571
|
+
return id === null ? [] : [[id, discount]];
|
|
572
|
+
}));
|
|
573
|
+
const mergedCommittedDiscountIds = new Set();
|
|
574
|
+
const refreshedScanDiscountIds = new Set();
|
|
495
575
|
const runtimeDiscountIds = new Set();
|
|
496
|
-
const runtimeDiscounts = discountList.
|
|
497
|
-
|
|
498
|
-
if (
|
|
499
|
-
runtimeDiscountIds.
|
|
500
|
-
|
|
576
|
+
const runtimeDiscounts = discountList.flatMap(discount => {
|
|
577
|
+
const id = getDiscountIdentityKey(discount);
|
|
578
|
+
if (id === null) return [discount];
|
|
579
|
+
if (runtimeDiscountIds.has(id)) return [];
|
|
580
|
+
runtimeDiscountIds.add(id);
|
|
581
|
+
const currentScanDiscount = currentScanDiscountById.get(id);
|
|
582
|
+
if (currentScanDiscount && (!(0, _entitlementPass.isEntitlementPass)(currentScanDiscount) || !(0, _entitlementPass.isEntitlementPass)(discount))) {
|
|
583
|
+
return [];
|
|
584
|
+
}
|
|
585
|
+
const committedDiscount = committedDiscountById.get(id);
|
|
586
|
+
let nextDiscount = discount;
|
|
587
|
+
if (committedDiscount && (0, _entitlementPass.isEntitlementPass)(committedDiscount) && (0, _entitlementPass.isEntitlementPass)(discount)) {
|
|
588
|
+
mergedCommittedDiscountIds.add(id);
|
|
589
|
+
nextDiscount = mergeCommittedEntitlementWithRuntime(committedDiscount, discount);
|
|
590
|
+
}
|
|
591
|
+
if (currentScanDiscount) {
|
|
592
|
+
refreshedScanDiscountIds.add(id);
|
|
593
|
+
nextDiscount = {
|
|
594
|
+
...nextDiscount,
|
|
595
|
+
isScan: true,
|
|
596
|
+
isSelected: currentScanDiscount.isSelected ?? nextDiscount.isSelected,
|
|
597
|
+
isManualSelect: currentScanDiscount.isManualSelect ?? nextDiscount.isManualSelect
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
return [nextDiscount];
|
|
601
|
+
});
|
|
602
|
+
const retainedCommittedDiscounts = currentCommittedDiscounts.filter(discount => {
|
|
603
|
+
const id = getDiscountIdentityKey(discount);
|
|
604
|
+
return id === null || !mergedCommittedDiscountIds.has(id);
|
|
605
|
+
}).map(discount => discount.committedAppliedProductDetails?.length ? {
|
|
606
|
+
...discount,
|
|
607
|
+
isEditMode: true,
|
|
608
|
+
isDisabled: true,
|
|
609
|
+
isSelected: true,
|
|
610
|
+
isUsed: true,
|
|
611
|
+
appliedProductDetails: [...discount.committedAppliedProductDetails]
|
|
612
|
+
} : discount);
|
|
613
|
+
const retainedScanDiscounts = currentScanDiscounts.filter(discount => {
|
|
614
|
+
const id = getDiscountIdentityKey(discount);
|
|
615
|
+
return id === null || !refreshedScanDiscountIds.has(id);
|
|
501
616
|
});
|
|
502
|
-
const mergedDiscountList = [...
|
|
617
|
+
const mergedDiscountList = [...retainedCommittedDiscounts, ...retainedScanDiscounts, ...runtimeDiscounts];
|
|
618
|
+
if (!isCurrentRequest()) return this.getDiscountList();
|
|
503
619
|
await this.store.discount?.setOriginalDiscountList(mergedDiscountList);
|
|
620
|
+
if (!isCurrentRequest()) return this.getDiscountList();
|
|
504
621
|
await this.store.discount?.setDiscountList(mergedDiscountList);
|
|
505
622
|
}
|
|
623
|
+
if (!isCurrentRequest()) return this.getDiscountList();
|
|
506
624
|
if (params.apply !== false && this.store.tempOrder?.products?.length) {
|
|
507
625
|
this.applyDiscount();
|
|
508
626
|
}
|
|
@@ -517,6 +635,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
517
635
|
getVirtualCurrencyList() {
|
|
518
636
|
return (0, _lodashEs.cloneDeep)(this.store.virtualCurrencyList || []);
|
|
519
637
|
}
|
|
638
|
+
getCustomerWalletPrepareConfigEpoch() {
|
|
639
|
+
return this.customerWalletPrepareConfigEpoch;
|
|
640
|
+
}
|
|
520
641
|
async syncScannedDiscountsToOriginalDiscountList(discountList) {
|
|
521
642
|
const scanDiscounts = (discountList || []).filter(discount => discount?.isScan);
|
|
522
643
|
if (!scanDiscounts.length) return;
|
|
@@ -614,19 +735,34 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
614
735
|
isAvailable: false,
|
|
615
736
|
discountList: this.getDiscountList()
|
|
616
737
|
};
|
|
617
|
-
const
|
|
738
|
+
const scannedIds = new Set(withScanList.map(discount => String(discount.id)));
|
|
739
|
+
const evaluatedScannedDiscounts = (evaluatedDiscountList || withScanList).filter(discount => scannedIds.has(String(discount.id)) && isCustomerPromotionDiscount(discount) && !(0, _availability.getDiscountLifecycleReason)(discount));
|
|
740
|
+
const shouldRetainForLater = !isAvailable && evaluatedScannedDiscounts.length > 0;
|
|
618
741
|
const normalizedNewDiscountList = newDiscountList ? markScannedDiscounts(newDiscountList, withScanList) : undefined;
|
|
619
|
-
const retainedDiscountList = evaluatedDiscountList ? markScannedDiscounts(evaluatedDiscountList, withScanList) : normalizedNewDiscountList;
|
|
620
742
|
let resolvedDiscountList = normalizedNewDiscountList || this.getDiscountList();
|
|
621
743
|
if (isAvailable && normalizedNewDiscountList) {
|
|
622
744
|
await this.store.discount?.setDiscountList(normalizedNewDiscountList);
|
|
623
|
-
|
|
745
|
+
// 实际写回商品时沿用扫码试算的优先级,避免旧商品行的选卡覆盖本次扫码。
|
|
746
|
+
this.applyDiscount({
|
|
747
|
+
preferredEntitlementPassIds: withScanList.filter(discount => (0, _entitlementPass.isEntitlementPass)(discount)).map(discount => discount.id)
|
|
748
|
+
});
|
|
624
749
|
await this.syncScannedDiscountsToOriginalDiscountList(this.getDiscountList());
|
|
625
750
|
resolvedDiscountList = this.getDiscountList();
|
|
626
|
-
} else if (shouldRetainForLater
|
|
627
|
-
//
|
|
628
|
-
|
|
629
|
-
|
|
751
|
+
} else if (shouldRetainForLater) {
|
|
752
|
+
// 只合并本次识别的卡券;不把试算产生的其他选券状态写回订单。
|
|
753
|
+
const retainedDiscounts = new Map(this.getDiscountList().map(discount => [String(discount.id), discount]));
|
|
754
|
+
evaluatedScannedDiscounts.forEach(discount => {
|
|
755
|
+
retainedDiscounts.set(String(discount.id), {
|
|
756
|
+
...discount,
|
|
757
|
+
isScan: true,
|
|
758
|
+
isAvailable: false,
|
|
759
|
+
isSelected: false,
|
|
760
|
+
reasonCode: discount.reasonCode || 'product_not_applicable',
|
|
761
|
+
appliedProductDetails: [],
|
|
762
|
+
savedAmount: 0
|
|
763
|
+
});
|
|
764
|
+
});
|
|
765
|
+
await this.store.discount?.setDiscountList([...retainedDiscounts.values()]);
|
|
630
766
|
await this.syncScannedDiscountsToOriginalDiscountList(this.getDiscountList());
|
|
631
767
|
resolvedDiscountList = this.getDiscountList();
|
|
632
768
|
}
|
|
@@ -635,7 +771,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
635
771
|
isAvailable: isAvailable || false,
|
|
636
772
|
isAccepted: Boolean(isAvailable || shouldRetainForLater),
|
|
637
773
|
discountList: resolvedDiscountList,
|
|
638
|
-
scannedDiscountList:
|
|
774
|
+
scannedDiscountList: evaluatedScannedDiscounts,
|
|
639
775
|
unavailableReason
|
|
640
776
|
};
|
|
641
777
|
}
|
|
@@ -667,7 +803,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
667
803
|
isFormSubject: product => (0, _utils.resolveIsFormSubject)(tempOrder, product),
|
|
668
804
|
orderTotalAmount: Number(this.store.summary?.total_amount || 0)
|
|
669
805
|
}, {
|
|
670
|
-
reapplyBookingDiscountProductUids: options?.reapplyBookingDiscountProductUids
|
|
806
|
+
reapplyBookingDiscountProductUids: options?.reapplyBookingDiscountProductUids,
|
|
807
|
+
reapplyWeighedDiscountProductUids: options?.reapplyWeighedDiscountProductUids,
|
|
808
|
+
preferredEntitlementPassIds: options?.preferredEntitlementPassIds
|
|
671
809
|
});
|
|
672
810
|
if (result?.productList) {
|
|
673
811
|
const previousProductsByUid = (0, _utils.indexOrderProductsByUid)(tempOrder.products);
|
|
@@ -1005,31 +1143,106 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1005
1143
|
now: (0, _utils.formatDateTime)(new Date())
|
|
1006
1144
|
});
|
|
1007
1145
|
}
|
|
1008
|
-
|
|
1146
|
+
clearTempOrderCustomerWalletSnapshots(tempOrder) {
|
|
1009
1147
|
const orderMetaList = (0, _utils.normalizeOrderMetaList)(tempOrder.order_meta_list);
|
|
1010
1148
|
if (!orderMetaList) return;
|
|
1011
1149
|
const nextOrderMetaList = {
|
|
1012
1150
|
...orderMetaList
|
|
1013
1151
|
};
|
|
1014
1152
|
delete nextOrderMetaList.point_cards_snapshot;
|
|
1153
|
+
delete nextOrderMetaList.virtual_currency_snapshot;
|
|
1015
1154
|
if (Object.keys(nextOrderMetaList).length === 0) {
|
|
1016
1155
|
delete tempOrder.order_meta_list;
|
|
1017
1156
|
return;
|
|
1018
1157
|
}
|
|
1019
1158
|
tempOrder.order_meta_list = nextOrderMetaList;
|
|
1020
1159
|
}
|
|
1021
|
-
|
|
1160
|
+
clearCustomerWalletState(tempOrder) {
|
|
1161
|
+
this.clearCustomerWalletRuntimeState();
|
|
1162
|
+
this.clearTempOrderCustomerWalletSnapshots(tempOrder);
|
|
1163
|
+
}
|
|
1164
|
+
clearCustomerWalletRuntimeState() {
|
|
1165
|
+
this.customerWalletPrepareConfigEpoch += 1;
|
|
1166
|
+
this.pointCardSnapshotCodeCandidates.clear();
|
|
1167
|
+
this.store.availableWalletIds = [];
|
|
1168
|
+
this.store.virtualCurrencyList = [];
|
|
1169
|
+
}
|
|
1170
|
+
rememberPointCardSnapshotCodeCandidates(value) {
|
|
1171
|
+
(0, _utils.collectPointCardSnapshotCodeCandidates)(value).forEach(({
|
|
1172
|
+
id,
|
|
1173
|
+
code
|
|
1174
|
+
}) => {
|
|
1175
|
+
if (!this.pointCardSnapshotCodeCandidates.has(id)) {
|
|
1176
|
+
this.pointCardSnapshotCodeCandidates.set(id, code);
|
|
1177
|
+
}
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
getRememberedPointCardSnapshotCodeCandidates() {
|
|
1181
|
+
return [...this.pointCardSnapshotCodeCandidates].map(([id, code]) => ({
|
|
1182
|
+
id,
|
|
1183
|
+
code
|
|
1184
|
+
}));
|
|
1185
|
+
}
|
|
1186
|
+
getPointCardSnapshotOrderIdentityKey(identity) {
|
|
1187
|
+
if (identity?.externalSaleNumber) {
|
|
1188
|
+
return `external:${identity.externalSaleNumber}`;
|
|
1189
|
+
}
|
|
1190
|
+
if (identity?.orderId !== undefined && identity.orderId !== null) {
|
|
1191
|
+
return `order:${identity.orderId}`;
|
|
1192
|
+
}
|
|
1193
|
+
if (identity?.localId) return `local:${identity.localId}`;
|
|
1194
|
+
if (identity?.orderNumber) return `number:${identity.orderNumber}`;
|
|
1195
|
+
return '';
|
|
1196
|
+
}
|
|
1197
|
+
isPointCardSnapshotMergeContextCurrent(context) {
|
|
1198
|
+
if (!context) return true;
|
|
1199
|
+
if (context.customerId !== undefined && String(context.customerId ?? '') !== String(this.store.tempOrder?.customer_id ?? '')) {
|
|
1200
|
+
return false;
|
|
1201
|
+
}
|
|
1202
|
+
const expectedOrderKey = this.getPointCardSnapshotOrderIdentityKey(context.orderIdentity);
|
|
1203
|
+
return !expectedOrderKey || expectedOrderKey === this.getPointCardSnapshotOrderIdentityKey(this.getOrderIdentity());
|
|
1204
|
+
}
|
|
1205
|
+
writeCustomerWalletSnapshotsFromPrepareConfig(params) {
|
|
1022
1206
|
const tempOrder = this.store.tempOrder;
|
|
1023
1207
|
if (!tempOrder) return;
|
|
1024
1208
|
if (String(tempOrder.customer_id ?? '') !== String(params.customerId)) return;
|
|
1025
|
-
const
|
|
1026
|
-
|
|
1209
|
+
const currentOrderMetaList = (0, _utils.normalizeOrderMetaList)(tempOrder.order_meta_list);
|
|
1210
|
+
const virtualCurrencyList = Array.isArray(params.virtualCurrencyList) ? params.virtualCurrencyList : [];
|
|
1211
|
+
const snapshotsWithExistingCodes = (0, _utils.mergePointCardSnapshotCodes)(params.availableWalletPassList, currentOrderMetaList?.point_cards_snapshot);
|
|
1212
|
+
tempOrder.order_meta_list = {
|
|
1213
|
+
...(currentOrderMetaList || {}),
|
|
1214
|
+
point_cards_snapshot: (0, _utils.mergePointCardSnapshotCodes)(snapshotsWithExistingCodes, this.getRememberedPointCardSnapshotCodeCandidates()),
|
|
1215
|
+
virtual_currency_snapshot: (0, _utils.buildVirtualCurrencySnapshotFromList)(virtualCurrencyList)
|
|
1216
|
+
};
|
|
1217
|
+
this.store.availableWalletIds = [...params.availableWalletIds];
|
|
1218
|
+
this.store.virtualCurrencyList = (0, _lodashEs.cloneDeep)(virtualCurrencyList);
|
|
1219
|
+
this.persistTempOrder();
|
|
1220
|
+
this.saveDraftInBackground();
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
/**
|
|
1224
|
+
* 将 Payment WalletPass 返回的实例 code 回填到当前订单 Snapshot。
|
|
1225
|
+
* 这里只按资产 ID 补空值,不新增卡、不覆盖 prepare/config 冻结的余额。
|
|
1226
|
+
*/
|
|
1227
|
+
mergePointCardSnapshotCodes(walletPassList, context) {
|
|
1228
|
+
const tempOrder = this.store.tempOrder;
|
|
1229
|
+
const currentOrderMetaList = (0, _utils.normalizeOrderMetaList)(tempOrder?.order_meta_list);
|
|
1230
|
+
const currentSnapshots = currentOrderMetaList?.point_cards_snapshot || [];
|
|
1231
|
+
if (!tempOrder || !this.isPointCardSnapshotMergeContextCurrent(context)) {
|
|
1232
|
+
return currentSnapshots;
|
|
1233
|
+
}
|
|
1234
|
+
this.rememberPointCardSnapshotCodeCandidates(walletPassList);
|
|
1235
|
+
if (!currentSnapshots.length) return currentSnapshots;
|
|
1236
|
+
const nextSnapshots = (0, _utils.mergePointCardSnapshotCodes)(currentSnapshots, this.getRememberedPointCardSnapshotCodeCandidates());
|
|
1237
|
+
const hasChanged = nextSnapshots.some((snapshot, index) => snapshot.code !== currentSnapshots[index]?.code);
|
|
1238
|
+
if (!hasChanged) return currentSnapshots;
|
|
1027
1239
|
tempOrder.order_meta_list = {
|
|
1028
|
-
...(
|
|
1029
|
-
point_cards_snapshot:
|
|
1240
|
+
...(currentOrderMetaList || {}),
|
|
1241
|
+
point_cards_snapshot: nextSnapshots
|
|
1030
1242
|
};
|
|
1031
1243
|
this.persistTempOrder();
|
|
1032
1244
|
this.saveDraftInBackground();
|
|
1245
|
+
return nextSnapshots;
|
|
1033
1246
|
}
|
|
1034
1247
|
createExternalSaleNumber() {
|
|
1035
1248
|
const timestamp = (0, _dayjs.default)().format('YYYYMMDDHHmmssSSS');
|
|
@@ -1548,7 +1761,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1548
1761
|
const sku = product?.product_sku || {};
|
|
1549
1762
|
const metadata = product?.metadata || {};
|
|
1550
1763
|
const discountTypes = (product?.discount_list || []).map(discount => discount?.type ?? discount?.tag);
|
|
1551
|
-
const
|
|
1764
|
+
const fullCoveragePassType = discountTypes.find(type => ['entitlement_pass', 'good_pass'].includes(type));
|
|
1765
|
+
const extensionType = product?.extension_type || fullCoveragePassType || 'normal';
|
|
1552
1766
|
return {
|
|
1553
1767
|
product_id: product?.product_id ?? null,
|
|
1554
1768
|
product_variant_id: product?.product_variant_id ?? null,
|
|
@@ -1601,7 +1815,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1601
1815
|
const sku = product?.product_sku || {};
|
|
1602
1816
|
const metadata = product?.metadata || {};
|
|
1603
1817
|
const discountTypes = (product?.discount_list || []).map(discount => discount?.type ?? discount?.tag);
|
|
1604
|
-
const
|
|
1818
|
+
const fullCoveragePassType = discountTypes.find(type => ['entitlement_pass', 'good_pass'].includes(type));
|
|
1819
|
+
const extensionType = product?.extension_type || fullCoveragePassType || 'normal';
|
|
1605
1820
|
return {
|
|
1606
1821
|
product_id: product?.product_id ?? null,
|
|
1607
1822
|
product_variant_id: product?.product_variant_id ?? null,
|
|
@@ -1810,6 +2025,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1810
2025
|
const freshTempOrder = this.createDefaultTempOrderInstance();
|
|
1811
2026
|
this.ensureExternalSaleNumber(freshTempOrder);
|
|
1812
2027
|
this.store.tempOrder = freshTempOrder;
|
|
2028
|
+
this.clearCustomerWalletRuntimeState();
|
|
1813
2029
|
this.store.summary = (0, _utils.createEmptySummary)();
|
|
1814
2030
|
this.store.lastOrderInfo = undefined;
|
|
1815
2031
|
this.store.syncState = undefined;
|
|
@@ -1830,6 +2046,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1830
2046
|
ensureIdentity: false
|
|
1831
2047
|
});
|
|
1832
2048
|
this.store.tempOrder = nextTempOrder;
|
|
2049
|
+
this.clearCustomerWalletRuntimeState();
|
|
1833
2050
|
if (options?.recalculateSummary !== false) {
|
|
1834
2051
|
await this.recalculateSummary({
|
|
1835
2052
|
createIfMissing: false
|
|
@@ -2614,7 +2831,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2614
2831
|
}
|
|
2615
2832
|
isCustomerBoundDiscount(discount) {
|
|
2616
2833
|
const type = discount?.type ?? discount?.tag;
|
|
2617
|
-
return type === 'good_pass' || type === 'discount_card' || type === 'product_discount_card';
|
|
2834
|
+
return type === 'entitlement_pass' || type === 'good_pass' || type === 'discount_card' || type === 'product_discount_card';
|
|
2618
2835
|
}
|
|
2619
2836
|
shouldKeepCustomerBoundDiscountAfterCustomerChange(discount) {
|
|
2620
2837
|
return Boolean(discount?.isScan || discount?.isEditMode);
|
|
@@ -2699,9 +2916,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2699
2916
|
email: tempOrder.email
|
|
2700
2917
|
});
|
|
2701
2918
|
const nextCustomerId = tempOrder.customer_id ?? null;
|
|
2702
|
-
if (String(previousCustomerId ?? '') !== String(nextCustomerId ?? '')
|
|
2703
|
-
this.
|
|
2704
|
-
this.clearTempOrderPointCardSnapshot(tempOrder);
|
|
2919
|
+
if (String(previousCustomerId ?? '') !== String(nextCustomerId ?? '')) {
|
|
2920
|
+
this.clearCustomerWalletState(tempOrder);
|
|
2705
2921
|
}
|
|
2706
2922
|
this.persistTempOrder();
|
|
2707
2923
|
return {
|
|
@@ -2737,11 +2953,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2737
2953
|
}
|
|
2738
2954
|
const nextCustomerId = tempOrder.customer_id ?? null;
|
|
2739
2955
|
if (String(previousCustomerId ?? '') !== String(nextCustomerId ?? '')) {
|
|
2740
|
-
this.
|
|
2741
|
-
this.store.virtualCurrencyList = [];
|
|
2742
|
-
if (!hasPersistedOrderId(tempOrder.order_id)) {
|
|
2743
|
-
this.clearTempOrderPointCardSnapshot(tempOrder);
|
|
2744
|
-
}
|
|
2956
|
+
this.clearCustomerWalletState(tempOrder);
|
|
2745
2957
|
(0, _utils.clearTempOrderHolderAssignments)(tempOrder);
|
|
2746
2958
|
this.clearCustomerBoundDiscounts(tempOrder);
|
|
2747
2959
|
this.applyDiscount();
|
|
@@ -2779,11 +2991,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2779
2991
|
tempOrder.email = '';
|
|
2780
2992
|
tempOrder.customer = null;
|
|
2781
2993
|
if (tempOrder._extend) delete tempOrder._extend.customerSnapshot;
|
|
2782
|
-
this.
|
|
2783
|
-
this.store.virtualCurrencyList = [];
|
|
2784
|
-
if (!hasPersistedOrderId(tempOrder.order_id)) {
|
|
2785
|
-
this.clearTempOrderPointCardSnapshot(tempOrder);
|
|
2786
|
-
}
|
|
2994
|
+
this.clearCustomerWalletState(tempOrder);
|
|
2787
2995
|
this.clearCustomerBoundDiscounts(tempOrder);
|
|
2788
2996
|
this.applyDiscount();
|
|
2789
2997
|
this.persistTempOrder();
|
|
@@ -3246,17 +3454,35 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3246
3454
|
}
|
|
3247
3455
|
normalizedIncoming.discount_list = (0, _utils.normalizeOrderProductDiscountList)(normalizedIncoming.discount_list);
|
|
3248
3456
|
const hasIncomingGoodPass = this.hasGoodPassDiscount(normalizedIncoming);
|
|
3457
|
+
const hasIncomingEntitlementPass = this.hasEntitlementPassDiscount(normalizedIncoming);
|
|
3458
|
+
const isIncomingEntitlementAppend = this.isRuntimeEntitlementAppend(productToAdd, tempOrder);
|
|
3459
|
+
const isIncomingPersistedEntitlementPass = hasIncomingEntitlementPass && this.isPersistedProductLine(normalizedIncoming);
|
|
3249
3460
|
const hasIncomingProductNote = this.hasOrderProductLineNote(normalizedIncoming);
|
|
3250
3461
|
const hasIncomingManualProductDiscount = isManualProductDiscountProduct(normalizedIncoming);
|
|
3251
3462
|
const hasIncomingBookingUid = this.hasLinkedBookingUid(productToAdd) || this.hasLinkedBookingUid(normalizedIncoming);
|
|
3252
3463
|
const isIncomingCustomItem = productToAdd.metadata?.origin?.isCustomItem === true || productToAdd._origin?.isCustomItem === true;
|
|
3253
|
-
const shouldForceNewLine = disableMerge || !!booking ||
|
|
3254
|
-
const matchedIndex =
|
|
3464
|
+
const shouldForceNewLine = disableMerge || !!booking || hasIncomingGoodPass || isIncomingPersistedEntitlementPass || hasIncomingBookingUid || isIncomingCustomItem || isWeighingProduct;
|
|
3465
|
+
const matchedIndex = shouldForceNewLine ? -1 : tempOrder.products.findIndex(item => {
|
|
3255
3466
|
if (this.hasGoodPassDiscount(item)) return false;
|
|
3256
|
-
|
|
3257
|
-
if (
|
|
3258
|
-
|
|
3259
|
-
|
|
3467
|
+
const isRuntimeEntitlementPass = this.isRuntimeEntitlementAppend(item, tempOrder);
|
|
3468
|
+
if (isIncomingEntitlementAppend !== isRuntimeEntitlementPass) {
|
|
3469
|
+
return false;
|
|
3470
|
+
}
|
|
3471
|
+
if (isIncomingEntitlementAppend && this.isPersistedProductLine(item)) {
|
|
3472
|
+
return false;
|
|
3473
|
+
}
|
|
3474
|
+
const hasExistingProductNote = this.hasOrderProductLineNote(item);
|
|
3475
|
+
if ((hasIncomingProductNote || hasExistingProductNote) && (!isRuntimeEntitlementPass || String(normalizedIncoming.note || '').trim() !== String(item.note || '').trim())) {
|
|
3476
|
+
return false;
|
|
3477
|
+
}
|
|
3478
|
+
const hasExistingManualProductDiscount = isManualProductDiscountProduct(item);
|
|
3479
|
+
if (isRuntimeEntitlementPass && !this.hasSameEntitlementMergePriceConfig(normalizedIncoming, item)) {
|
|
3480
|
+
return false;
|
|
3481
|
+
}
|
|
3482
|
+
if ((hasIncomingManualProductDiscount || hasExistingManualProductDiscount) && !isRuntimeEntitlementPass) {
|
|
3483
|
+
return false;
|
|
3484
|
+
}
|
|
3485
|
+
if (this.isPersistedProductLine(item)) return false;
|
|
3260
3486
|
if (item.product_id !== productToAdd.product_id) return false;
|
|
3261
3487
|
if (item.product_variant_id !== productToAdd.product_variant_id) return false;
|
|
3262
3488
|
const existedFingerprint = (0, _utils3.buildProductLineFingerprint)((0, _utils.getProductSkuOptions)(item), item.product_bundle);
|
|
@@ -3557,17 +3783,51 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3557
3783
|
});
|
|
3558
3784
|
return tempOrder.products;
|
|
3559
3785
|
}
|
|
3560
|
-
|
|
3561
|
-
const
|
|
3562
|
-
if (hasMainGoodPass) return true;
|
|
3563
|
-
const bundleDiscountList = [];
|
|
3786
|
+
getFullCoveragePassDiscounts(product) {
|
|
3787
|
+
const discountList = [...(product.discount_list || [])];
|
|
3564
3788
|
(product.product_bundle || []).forEach(item => {
|
|
3565
|
-
|
|
3789
|
+
discountList.push(...(item?.discount_list || []));
|
|
3566
3790
|
});
|
|
3567
3791
|
(product?._extend?.other?.bundle || []).forEach(item => {
|
|
3568
|
-
|
|
3792
|
+
discountList.push(...(item?.discount_list || []));
|
|
3569
3793
|
});
|
|
3570
|
-
return
|
|
3794
|
+
return discountList.filter(item => (0, _entitlementPass.isFullCoveragePass)(item));
|
|
3795
|
+
}
|
|
3796
|
+
hasEntitlementPassDiscount(product) {
|
|
3797
|
+
return this.getFullCoveragePassDiscounts(product).some(item => (0, _entitlementPass.isEntitlementPass)(item));
|
|
3798
|
+
}
|
|
3799
|
+
hasGoodPassDiscount(product) {
|
|
3800
|
+
return this.getFullCoveragePassDiscounts(product).some(item => !(0, _entitlementPass.isEntitlementPass)(item));
|
|
3801
|
+
}
|
|
3802
|
+
isPersistedProductLine(product) {
|
|
3803
|
+
return product.order_detail_id !== undefined && product.order_detail_id !== null && product.order_detail_id !== '' || product.metadata?.is_edit_for_runtime === true;
|
|
3804
|
+
}
|
|
3805
|
+
isRuntimeEntitlementAppend(product, tempOrder) {
|
|
3806
|
+
if (this.isPersistedProductLine(product)) return false;
|
|
3807
|
+
const uid = product.metadata?.unique_identification_number ?? product.unique_identification_number;
|
|
3808
|
+
const storedOrigin = uid !== undefined && uid !== null && uid !== '' ? tempOrder._extend?.productsByUid?.[String(uid)]?.origin : undefined;
|
|
3809
|
+
return Boolean(product?._origin?.__entitlementPassRuntimeAppend === true || storedOrigin?.__entitlementPassRuntimeAppend === true);
|
|
3810
|
+
}
|
|
3811
|
+
hasSameEntitlementMergePriceConfig(incoming, existing) {
|
|
3812
|
+
const buildPriceConfig = product => {
|
|
3813
|
+
const metadata = product.metadata || {};
|
|
3814
|
+
const bundle = (product.product_bundle || []).map(item => ({
|
|
3815
|
+
bundle_id: item.bundle_id ?? item.id ?? null,
|
|
3816
|
+
bundle_product_id: item.bundle_product_id ?? item._bundle_product_id ?? item.product_id ?? null,
|
|
3817
|
+
bundle_variant_id: item.bundle_variant_id ?? item.product_variant_id ?? 0,
|
|
3818
|
+
price_type: item.price_type ?? item.custom_price_type ?? '',
|
|
3819
|
+
price_type_ext: item.price_type_ext ?? item.custom_price_type_ext ?? ''
|
|
3820
|
+
})).sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
|
|
3821
|
+
return JSON.stringify({
|
|
3822
|
+
original_price: this.normalizeFingerprintMoney(product.original_price),
|
|
3823
|
+
source_product_price: this.normalizeFingerprintMoney(metadata.source_product_price),
|
|
3824
|
+
main_product_original_price: this.normalizeFingerprintMoney(metadata.main_product_original_price),
|
|
3825
|
+
price_override: this.normalizeFingerprintMoney(metadata.price_override),
|
|
3826
|
+
is_manual_discount: Boolean(metadata.is_manual_discount),
|
|
3827
|
+
bundle
|
|
3828
|
+
});
|
|
3829
|
+
};
|
|
3830
|
+
return buildPriceConfig(incoming) === buildPriceConfig(existing);
|
|
3571
3831
|
}
|
|
3572
3832
|
getBundleRuntimeIdentity(bundle) {
|
|
3573
3833
|
if (!bundle || typeof bundle !== 'object') return '';
|
|
@@ -3599,7 +3859,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3599
3859
|
};
|
|
3600
3860
|
});
|
|
3601
3861
|
}
|
|
3602
|
-
applyOrderProductUpdateToTempOrder(tempOrder, params) {
|
|
3862
|
+
applyOrderProductUpdateToTempOrder(tempOrder, params, reapplyWeighedDiscountProductUids) {
|
|
3603
3863
|
const {
|
|
3604
3864
|
product_id,
|
|
3605
3865
|
product_variant_id,
|
|
@@ -3672,7 +3932,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3672
3932
|
const previousLineFingerprint = (0, _utils3.buildProductLineFingerprint)((0, _utils.getProductSkuOptions)(targetProduct), targetProduct.product_bundle);
|
|
3673
3933
|
const nextLineFingerprint = (0, _utils3.buildProductLineFingerprint)((0, _utils.getProductSkuOptions)(nextProduct), nextProduct.product_bundle);
|
|
3674
3934
|
const callerChangesVariant = Number(product_variant_id || 0) !== Number(targetProduct.product_variant_id || 0);
|
|
3675
|
-
const
|
|
3935
|
+
const callerChangesWeighing = (0, _weighedProduct.getWeighedProductPriceFingerprint)(targetProduct.product_sku) !== (0, _weighedProduct.getWeighedProductPriceFingerprint)(nextProduct.product_sku);
|
|
3936
|
+
const callerChangesLineConfiguration = callerChangesVariant || callerChangesWeighing || previousLineFingerprint !== nextLineFingerprint;
|
|
3676
3937
|
const isPersistedOrderLine = targetProduct.order_detail_id !== undefined && targetProduct.order_detail_id !== null;
|
|
3677
3938
|
const callerChangesDiscountList = Array.isArray(updates?.discount_list) && updates.discount_list.length > 0 && !isSameDiscountList(updates.discount_list, targetProduct.discount_list);
|
|
3678
3939
|
const callerUpdatesManualPrice = updates?.metadata?.price_override !== undefined || updates?.metadata?.is_manual_discount !== undefined || updates?.metadata?.product_discount_reason !== undefined || callerChangesDiscountList;
|
|
@@ -3688,6 +3949,23 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3688
3949
|
};
|
|
3689
3950
|
return hasChangedPrice(updates.selling_price, targetProduct.selling_price) || hasChangedPrice(updates.original_price, targetProduct.original_price);
|
|
3690
3951
|
})();
|
|
3952
|
+
const weighedSourcePrice = callerChangesWeighing ? (0, _weighedProduct.resolveWeighedSourcePrice)(nextProduct.product_sku) : undefined;
|
|
3953
|
+
const hasResolvedWeighedPrice = weighedSourcePrice !== undefined;
|
|
3954
|
+
if (hasResolvedWeighedPrice && !callerUpdatesSourcePrice) {
|
|
3955
|
+
const nextMainOriginal = new _decimal.default(weighedSourcePrice).plus((0, _utils.sumOptionUnitPrice)((0, _utils.getProductSkuOptions)(nextProduct)));
|
|
3956
|
+
const previousMainOriginal = new _decimal.default(targetProduct.metadata?.main_product_original_price ?? targetProduct.original_price ?? 0);
|
|
3957
|
+
const previousMainSelling = new _decimal.default(targetProduct.metadata?.main_product_selling_price ?? targetProduct.selling_price ?? 0);
|
|
3958
|
+
// A manual final price remains fixed; other legacy discounts keep their amount
|
|
3959
|
+
// until Rules reapplies the currently selected wallet discount below.
|
|
3960
|
+
const nextMainSelling = isManualProductDiscountProduct(nextProduct) ? previousMainSelling : nextMainOriginal.minus(previousMainOriginal.minus(previousMainSelling));
|
|
3961
|
+
nextProduct.metadata = {
|
|
3962
|
+
...nextProduct.metadata,
|
|
3963
|
+
source_product_price: weighedSourcePrice,
|
|
3964
|
+
main_product_original_price: callerUpdatesMainOriginalPrice ? nextProduct.metadata.main_product_original_price : nextMainOriginal.toFixed(2),
|
|
3965
|
+
main_product_selling_price: callerUpdatesMainSellingPrice ? nextProduct.metadata.main_product_selling_price : _decimal.default.max(0, nextMainSelling).toFixed(2),
|
|
3966
|
+
price_schema_version: 2
|
|
3967
|
+
};
|
|
3968
|
+
}
|
|
3691
3969
|
if (isPersistedOrderLine && !callerChangesLineConfiguration && !callerUpdatesManualPrice && !callerAllowsBookingReprice) {
|
|
3692
3970
|
nextProduct.selling_price = targetProduct.selling_price;
|
|
3693
3971
|
nextProduct.original_price = targetProduct.original_price;
|
|
@@ -3704,17 +3982,17 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3704
3982
|
// 新配置只传了 source 时,不能把未传的 main_product_* 从旧行继承下来。
|
|
3705
3983
|
// 以新 source + 新 option 重建券前价;券后价未显式提供时保留旧主商品折扣额。
|
|
3706
3984
|
const previousMainOriginal = new _decimal.default(Number(targetProduct.metadata?.main_product_original_price) || 0);
|
|
3707
|
-
const previousMainSelling = new _decimal.default(Number(targetProduct.metadata?.main_product_selling_price
|
|
3985
|
+
const previousMainSelling = new _decimal.default(Number(targetProduct.metadata?.main_product_selling_price ?? previousMainOriginal.toNumber()));
|
|
3708
3986
|
const preservedDiscount = previousMainOriginal.minus(previousMainSelling);
|
|
3709
3987
|
const nextMainOriginal = new _decimal.default(Number(updates.metadata.source_product_price) || 0).plus((0, _utils.sumOptionUnitPrice)((0, _utils.getProductSkuOptions)(nextProduct)));
|
|
3710
3988
|
nextProduct.metadata = {
|
|
3711
3989
|
...(nextProduct.metadata || {}),
|
|
3712
3990
|
source_product_price: String(updates.metadata.source_product_price),
|
|
3713
3991
|
main_product_original_price: callerUpdatesMainOriginalPrice ? String(updates.metadata.main_product_original_price) : nextMainOriginal.toDecimalPlaces(2).toFixed(2),
|
|
3714
|
-
main_product_selling_price: callerUpdatesMainSellingPrice ? String(updates.metadata.main_product_selling_price) : nextMainOriginal.minus(preservedDiscount).toDecimalPlaces(2).toFixed(2),
|
|
3992
|
+
main_product_selling_price: callerUpdatesMainSellingPrice ? String(updates.metadata.main_product_selling_price) : hasResolvedWeighedPrice && isManualProductDiscountProduct(nextProduct) ? previousMainSelling.toFixed(2) : nextMainOriginal.minus(preservedDiscount).toDecimalPlaces(2).toFixed(2),
|
|
3715
3993
|
price_schema_version: 2
|
|
3716
3994
|
};
|
|
3717
|
-
} else if (callerChangesVariant && !callerUpdatesTopPrice && !callerUpdatesMainMeta) {
|
|
3995
|
+
} else if (callerChangesVariant && !hasResolvedWeighedPrice && !callerUpdatesTopPrice && !callerUpdatesMainMeta) {
|
|
3718
3996
|
// variant 已变化但 caller 没有显式报价时,旧 v2 metadata 不能继续充当权威价格源。
|
|
3719
3997
|
// 清理后由 normalize 优先读取 metadata.origin.variant 中新 variant 的目录价;
|
|
3720
3998
|
// 顶层 original/selling 的旧差额仍会作为 legacy discount 迁移到新价格。
|
|
@@ -3726,7 +4004,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3726
4004
|
delete nextProduct.metadata.main_product_selling_price;
|
|
3727
4005
|
delete nextProduct.metadata.main_product_original_price;
|
|
3728
4006
|
delete nextProduct.metadata.price_schema_version;
|
|
3729
|
-
} else if (callerChangesLineConfiguration && !callerUpdatesTopPrice && !callerUpdatesMainMeta) {
|
|
4007
|
+
} else if (callerChangesLineConfiguration && !hasResolvedWeighedPrice && !callerUpdatesTopPrice && !callerUpdatesMainMeta) {
|
|
3730
4008
|
// 仅 option / bundle 变化时,保留历史 source 和主商品折扣金额,
|
|
3731
4009
|
// 但必须让 original 与 selling 一起随新的 option 金额移动。
|
|
3732
4010
|
const previousOptionSum = (0, _utils.sumOptionUnitPrice)((0, _utils.getProductSkuOptions)(targetProduct));
|
|
@@ -3743,7 +4021,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3743
4021
|
main_product_selling_price: nextMainOriginal.minus(preservedDiscount).toDecimalPlaces(2).toFixed(2),
|
|
3744
4022
|
price_schema_version: 2
|
|
3745
4023
|
};
|
|
3746
|
-
} else if (callerUpdatesTopPrice && !callerUpdatesMainMeta) {
|
|
4024
|
+
} else if (callerUpdatesTopPrice && !callerUpdatesMainMeta && !hasResolvedWeighedPrice) {
|
|
3747
4025
|
const existedMeta = nextProduct.metadata || {};
|
|
3748
4026
|
nextProduct.metadata = {
|
|
3749
4027
|
...existedMeta
|
|
@@ -3753,10 +4031,41 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3753
4031
|
delete nextProduct.metadata.main_product_original_price;
|
|
3754
4032
|
delete nextProduct.metadata.price_schema_version;
|
|
3755
4033
|
}
|
|
4034
|
+
if (callerChangesLineConfiguration && (0, _weighedProduct.resolveWeighedSourcePrice)(nextProduct.product_sku) !== undefined && nextProduct.metadata.main_product_original_price != null && nextProduct.metadata.main_product_selling_price != null && isManualProductDiscountProduct(nextProduct)) {
|
|
4035
|
+
const originalPrice = (0, _utils.composeLinePrice)({
|
|
4036
|
+
mainPrice: nextProduct.metadata.main_product_original_price,
|
|
4037
|
+
bundle: (0, _weighedProduct.withOriginalBundleOptionPrices)(nextProduct.product_bundle),
|
|
4038
|
+
useOriginalBundle: true
|
|
4039
|
+
});
|
|
4040
|
+
const sellingPrice = (0, _utils.composeLinePrice)({
|
|
4041
|
+
mainPrice: nextProduct.metadata.main_product_selling_price,
|
|
4042
|
+
bundle: nextProduct.product_bundle
|
|
4043
|
+
});
|
|
4044
|
+
const previousManualDiscount = (0, _manualProductDiscount.findManualProductDiscountItem)(nextProduct.discount_list);
|
|
4045
|
+
nextProduct.original_price = originalPrice;
|
|
4046
|
+
nextProduct.metadata = {
|
|
4047
|
+
...nextProduct.metadata,
|
|
4048
|
+
origin: {
|
|
4049
|
+
...nextProduct.metadata.origin,
|
|
4050
|
+
_extend: {
|
|
4051
|
+
...nextProduct.metadata.origin?._extend,
|
|
4052
|
+
origin_total: Number(originalPrice)
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
4055
|
+
};
|
|
4056
|
+
nextProduct.discount_list = (0, _manualProductDiscount.mergeManualProductDiscountIntoList)(nextProduct.discount_list, (0, _manualProductDiscount.buildManualProductDiscountItem)({
|
|
4057
|
+
originTotal: Number(originalPrice),
|
|
4058
|
+
sellingTotal: Number(sellingPrice),
|
|
4059
|
+
quantity: nextProduct.num,
|
|
4060
|
+
message: previousManualDiscount?.discount.message,
|
|
4061
|
+
discountway: previousManualDiscount?.discount.discountway,
|
|
4062
|
+
discount_per: previousManualDiscount?.discount.discount_per
|
|
4063
|
+
}));
|
|
4064
|
+
}
|
|
3756
4065
|
// normalizeOrderProduct 幂等:v2 metadata 存在 → 保留 main_product_* 折扣重算 composite;
|
|
3757
4066
|
// 否则 → 把顶层 selling_price 视作 source,派生 main_product_* 并写 price_schema_version: 2。
|
|
3758
4067
|
let normalizedProduct = this.normalizeVirtualSettlementProductIfEnabled((0, _utils.mergeOrderProductDisplayFields)(nextProduct, (0, _utils3.normalizeOrderProduct)(nextProduct)));
|
|
3759
|
-
normalizedProduct.discount_list = (0, _utils.normalizeOrderProductDiscountList)(normalizedProduct.discount_list);
|
|
4068
|
+
normalizedProduct.discount_list = (0, _utils.normalizeOrderProductDiscountList)(isPersistedOrderLine ? syncReducedEntitlementPassUsageCount(normalizedProduct.discount_list, targetProduct.num, normalizedProduct.num) : normalizedProduct.discount_list);
|
|
3760
4069
|
const preservedBookingUid = nextProduct.booking_uid || nextProduct.metadata?.booking_uid || targetProduct.booking_uid || targetProduct.metadata?.booking_uid;
|
|
3761
4070
|
if (!booking && preservedBookingUid) {
|
|
3762
4071
|
normalizedProduct.booking_uid = preservedBookingUid;
|
|
@@ -3790,6 +4099,10 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3790
4099
|
};
|
|
3791
4100
|
tempOrder.bookings = [...(tempOrder.bookings || []), linked.booking];
|
|
3792
4101
|
}
|
|
4102
|
+
if (callerChangesWeighing && !isManualProductDiscountProduct(normalizedProduct)) {
|
|
4103
|
+
const uid = normalizedProduct.metadata?.unique_identification_number;
|
|
4104
|
+
if (uid) reapplyWeighedDiscountProductUids?.push(String(uid));
|
|
4105
|
+
}
|
|
3793
4106
|
tempOrder.products[productIndex] = normalizedProduct;
|
|
3794
4107
|
this.syncTempOrderHolderFromBookings(tempOrder);
|
|
3795
4108
|
this.captureProductRuntime(tempOrder, updates, tempOrder.products[productIndex], tempOrder.products[productIndex].metadata?.unique_identification_number);
|
|
@@ -3797,9 +4110,11 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3797
4110
|
}
|
|
3798
4111
|
async updateOrderProduct(params) {
|
|
3799
4112
|
const tempOrder = this.ensureTempOrder();
|
|
3800
|
-
const
|
|
4113
|
+
const reapplyWeighedDiscountProductUids = [];
|
|
4114
|
+
const updatedProductUid = this.applyOrderProductUpdateToTempOrder(tempOrder, params, reapplyWeighedDiscountProductUids);
|
|
3801
4115
|
const promotionPayload = await this.evaluatePromotion();
|
|
3802
4116
|
this.applyDiscount({
|
|
4117
|
+
reapplyWeighedDiscountProductUids,
|
|
3803
4118
|
reapplyBookingDiscountProductUids: params.allow_booking_discount_reapply && updatedProductUid ? [String(updatedProductUid)] : undefined
|
|
3804
4119
|
});
|
|
3805
4120
|
this.sanitizeTempOrderProducts(tempOrder);
|
|
@@ -3818,8 +4133,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3818
4133
|
if (!paramsList.length) {
|
|
3819
4134
|
return tempOrder.products;
|
|
3820
4135
|
}
|
|
4136
|
+
const reapplyWeighedDiscountProductUids = [];
|
|
3821
4137
|
const reapplyBookingDiscountProductUids = paramsList.reduce((acc, params) => {
|
|
3822
|
-
const updatedProductUid = this.applyOrderProductUpdateToTempOrder(tempOrder, params);
|
|
4138
|
+
const updatedProductUid = this.applyOrderProductUpdateToTempOrder(tempOrder, params, reapplyWeighedDiscountProductUids);
|
|
3823
4139
|
// 批量改预约时间时,延迟到最后一次折扣计算里统一恢复已选预约折扣卡。
|
|
3824
4140
|
if (params.allow_booking_discount_reapply && updatedProductUid) {
|
|
3825
4141
|
acc.push(String(updatedProductUid));
|
|
@@ -3827,6 +4143,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3827
4143
|
return acc;
|
|
3828
4144
|
}, []);
|
|
3829
4145
|
await this.finalizeAfterProductsMutation(tempOrder, {
|
|
4146
|
+
reapplyWeighedDiscountProductUids,
|
|
3830
4147
|
reapplyBookingDiscountProductUids: reapplyBookingDiscountProductUids.length ? reapplyBookingDiscountProductUids : undefined
|
|
3831
4148
|
});
|
|
3832
4149
|
this.logInfo('updateOrderProduct success', {
|
|
@@ -3873,6 +4190,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3873
4190
|
throw new Error('[Order] 目标商品不存在,无法更新数量');
|
|
3874
4191
|
}
|
|
3875
4192
|
const targetProduct = tempOrder.products[productIndex];
|
|
4193
|
+
const isPersistedOrderLine = targetProduct.order_detail_id !== undefined && targetProduct.order_detail_id !== null;
|
|
3876
4194
|
const normalizedProduct = this.normalizeVirtualSettlementProductIfEnabled((0, _utils3.normalizeOrderProduct)({
|
|
3877
4195
|
...targetProduct,
|
|
3878
4196
|
num: (0, _utils3.getSafeProductNum)(num),
|
|
@@ -3881,7 +4199,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3881
4199
|
unique_identification_number: targetProduct.metadata?.unique_identification_number || unique_identification_number
|
|
3882
4200
|
}
|
|
3883
4201
|
}));
|
|
3884
|
-
normalizedProduct.discount_list = (0, _utils.normalizeOrderProductDiscountList)(normalizedProduct.discount_list);
|
|
4202
|
+
normalizedProduct.discount_list = (0, _utils.normalizeOrderProductDiscountList)(isPersistedOrderLine ? syncReducedEntitlementPassUsageCount(normalizedProduct.discount_list, targetProduct.num, normalizedProduct.num) : normalizedProduct.discount_list);
|
|
3885
4203
|
const settlementSnapshot = (0, _virtualSettlement.getSelectedSettlementSnapshot)(normalizedProduct);
|
|
3886
4204
|
if (this.isMultiCurrencySettlementEnabled() && settlementSnapshot?.settlement_type === 'virtual_currency' && tempOrder.customer_id && Number(tempOrder.customer_id) !== 1) {
|
|
3887
4205
|
const currencyProductId = Number(settlementSnapshot.currency_product_id);
|
|
@@ -3958,7 +4276,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3958
4276
|
this.syncTempOrderHolderFromBookings(tempOrder);
|
|
3959
4277
|
const promotionPayload = await this.evaluatePromotion();
|
|
3960
4278
|
this.applyDiscount({
|
|
3961
|
-
reapplyBookingDiscountProductUids: options?.reapplyBookingDiscountProductUids
|
|
4279
|
+
reapplyBookingDiscountProductUids: options?.reapplyBookingDiscountProductUids,
|
|
4280
|
+
reapplyWeighedDiscountProductUids: options?.reapplyWeighedDiscountProductUids
|
|
3962
4281
|
});
|
|
3963
4282
|
this.sanitizeTempOrderProducts(tempOrder);
|
|
3964
4283
|
await this.recalculateSummary({
|
|
@@ -4680,11 +4999,21 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4680
4999
|
query
|
|
4681
5000
|
} = params;
|
|
4682
5001
|
const fetchUrl = url || '/order/sales/checkout';
|
|
4683
|
-
|
|
5002
|
+
const requestQuery = this.isSalesCheckoutHandledByOsServer(fetchUrl) ? query : (0, _osPrivatePayload.stripOsPrivatePayloadFields)(query);
|
|
5003
|
+
return this.request.post(fetchUrl, requestQuery, {
|
|
4684
5004
|
osServer: true,
|
|
4685
5005
|
customToast: () => {}
|
|
4686
5006
|
});
|
|
4687
5007
|
}
|
|
5008
|
+
isSalesCheckoutHandledByOsServer(fetchUrl) {
|
|
5009
|
+
const server = this.core?.server;
|
|
5010
|
+
if (!server || typeof server.hasRoute !== 'function') return false;
|
|
5011
|
+
const requestBaseUrl = String(this.request?.baseUrl || '/shop').replace(/\/+$/, '');
|
|
5012
|
+
if (!requestBaseUrl.startsWith('/')) return false;
|
|
5013
|
+
const normalizedFetchUrl = fetchUrl.startsWith('/') ? fetchUrl : `/${fetchUrl}`;
|
|
5014
|
+
const routePath = normalizedFetchUrl === requestBaseUrl || normalizedFetchUrl.startsWith(`${requestBaseUrl}/`) ? normalizedFetchUrl : `${requestBaseUrl}${normalizedFetchUrl}`;
|
|
5015
|
+
return server.hasRoute('post', routePath) === true;
|
|
5016
|
+
}
|
|
4688
5017
|
|
|
4689
5018
|
/**
|
|
4690
5019
|
* 发送支付链接邮件。
|
|
@@ -4773,6 +5102,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4773
5102
|
allowUnresolvedSalesNotes: isSessionStorageHydrate
|
|
4774
5103
|
});
|
|
4775
5104
|
this.store.tempOrder = nextTempOrder;
|
|
5105
|
+
this.clearCustomerWalletRuntimeState();
|
|
4776
5106
|
if (isSessionStorageHydrate) {
|
|
4777
5107
|
// 会话快照是未提交购物车,不应获得编辑订单的 saved/edit 标记与服务端基线。
|
|
4778
5108
|
const restoredSessionDiscounts = Array.isArray(raw.discount_list) ? (0, _lodashEs.cloneDeep)(raw.discount_list) : [];
|