@pisell/pisellos 2.3.67 → 2.3.69
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/walletPass/evaluator.js +0 -1
- package/dist/model/strategy/adapter/walletPass/utils.js +0 -2
- package/dist/modules/BaseModule.d.ts +1 -0
- package/dist/modules/BaseModule.js +24 -28
- package/dist/modules/Customer/index.d.ts +4 -0
- package/dist/modules/Customer/index.js +91 -59
- package/dist/modules/Customer/types.d.ts +2 -0
- package/dist/modules/Order/index.d.ts +22 -2
- package/dist/modules/Order/index.js +313 -142
- package/dist/modules/Order/types.d.ts +13 -1
- package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +15 -0
- package/dist/modules/Order/utils/orderCollectionIdentity.js +75 -0
- package/dist/modules/Order/utils.js +0 -1
- package/dist/modules/Payment/index.d.ts +4 -0
- package/dist/modules/Payment/index.js +14 -4
- package/dist/modules/Payment/walletpass.js +52 -18
- package/dist/modules/Rules/index.js +46 -31
- package/dist/server/index.js +3 -6
- package/dist/server/modules/order/index.d.ts +1 -0
- package/dist/server/modules/order/index.js +252 -93
- package/dist/server/utils/small-ticket.js +2 -1
- package/dist/solution/BaseSales/index.d.ts +13 -1
- package/dist/solution/BaseSales/index.js +903 -831
- package/dist/solution/BaseSales/utils.js +31 -20
- package/dist/solution/BookingTicket/index.d.ts +7 -1
- package/dist/solution/BookingTicket/index.js +310 -224
- package/dist/solution/ScanOrder/utils.js +31 -20
- package/dist/solution/UnifiedBookingSales/index.d.ts +25 -0
- package/dist/solution/UnifiedBookingSales/index.js +640 -321
- package/dist/solution/UnifiedBookingSales/types.d.ts +7 -0
- package/lib/model/strategy/adapter/walletPass/evaluator.js +0 -1
- package/lib/model/strategy/adapter/walletPass/utils.js +0 -1
- package/lib/modules/BaseModule.d.ts +1 -0
- package/lib/modules/BaseModule.js +24 -37
- package/lib/modules/Customer/index.d.ts +4 -0
- package/lib/modules/Customer/index.js +11 -0
- package/lib/modules/Customer/types.d.ts +2 -0
- package/lib/modules/Order/index.d.ts +22 -2
- package/lib/modules/Order/index.js +212 -54
- package/lib/modules/Order/types.d.ts +13 -1
- package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +15 -0
- package/lib/modules/Order/utils/orderCollectionIdentity.js +70 -0
- package/lib/modules/Order/utils.js +0 -1
- package/lib/modules/Payment/index.d.ts +4 -0
- package/lib/modules/Payment/index.js +7 -0
- package/lib/modules/Payment/walletpass.js +27 -2
- package/lib/modules/Rules/index.js +17 -1
- package/lib/server/index.js +3 -6
- package/lib/server/modules/order/index.d.ts +1 -0
- package/lib/server/modules/order/index.js +66 -2
- package/lib/server/utils/small-ticket.js +1 -1
- package/lib/solution/BaseSales/index.d.ts +13 -1
- package/lib/solution/BaseSales/index.js +61 -18
- package/lib/solution/BaseSales/utils.js +29 -18
- package/lib/solution/BookingTicket/index.d.ts +7 -1
- package/lib/solution/BookingTicket/index.js +65 -14
- package/lib/solution/ScanOrder/utils.js +29 -18
- package/lib/solution/UnifiedBookingSales/index.d.ts +25 -0
- package/lib/solution/UnifiedBookingSales/index.js +188 -0
- package/lib/solution/UnifiedBookingSales/types.d.ts +7 -0
- package/package.json +1 -1
|
@@ -1206,7 +1206,6 @@ function productRequiresFormSubject(tempOrder, product) {
|
|
|
1206
1206
|
}
|
|
1207
1207
|
function resolveIsFormSubject(tempOrder, product) {
|
|
1208
1208
|
var _a;
|
|
1209
|
-
debugger;
|
|
1210
1209
|
if (((_a = tempOrder == null ? void 0 : tempOrder.holder) == null ? void 0 : _a.type) === "form")
|
|
1211
1210
|
return true;
|
|
1212
1211
|
if (product)
|
|
@@ -41,6 +41,10 @@ export declare class PaymentModule extends BaseModule implements Module, Payment
|
|
|
41
41
|
* paymentModule.updateOtherParams({ fatherModule: 'bookingTicket' });
|
|
42
42
|
*/
|
|
43
43
|
updateOtherParams(params: Record<string, any>): void;
|
|
44
|
+
/**
|
|
45
|
+
* 获取标准化后的宿主平台标识,供支付子能力做平台边界判断。
|
|
46
|
+
*/
|
|
47
|
+
getPlatform(): string;
|
|
44
48
|
private getPaymentNumberAppData;
|
|
45
49
|
/**
|
|
46
50
|
* 记录信息日志
|
|
@@ -139,6 +139,13 @@ var PaymentModule = class extends import_BaseModule.BaseModule {
|
|
|
139
139
|
updateOtherParams(params) {
|
|
140
140
|
this.otherParams = params || {};
|
|
141
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* 获取标准化后的宿主平台标识,供支付子能力做平台边界判断。
|
|
144
|
+
*/
|
|
145
|
+
getPlatform() {
|
|
146
|
+
var _a;
|
|
147
|
+
return String(((_a = this.otherParams) == null ? void 0 : _a.platform) || "").trim().toLowerCase();
|
|
148
|
+
}
|
|
142
149
|
getPaymentNumberAppData(key) {
|
|
143
150
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
144
151
|
const getData = (_b = (_a = this.appPlugin) == null ? void 0 : _a.getData) == null ? void 0 : _b.call(_a);
|
|
@@ -109,6 +109,16 @@ function mergeWalletAssets(...groups) {
|
|
|
109
109
|
});
|
|
110
110
|
return merged;
|
|
111
111
|
}
|
|
112
|
+
function orderWalletAssetsByIds(assets, orderedIds) {
|
|
113
|
+
const assetByKey = new Map(
|
|
114
|
+
assets.map((asset) => [getWalletAssetKey(asset), asset])
|
|
115
|
+
);
|
|
116
|
+
const orderedKeys = new Set(orderedIds.map((id) => String(id)));
|
|
117
|
+
return [
|
|
118
|
+
...orderedIds.map((id) => assetByKey.get(String(id))).filter((asset) => asset !== void 0),
|
|
119
|
+
...assets.filter((asset) => !orderedKeys.has(getWalletAssetKey(asset)))
|
|
120
|
+
];
|
|
121
|
+
}
|
|
112
122
|
function createInitialWalletAssetsState() {
|
|
113
123
|
return {
|
|
114
124
|
status: "idle",
|
|
@@ -543,7 +553,6 @@ var WalletPassPaymentImpl = class {
|
|
|
543
553
|
vouchers: allList
|
|
544
554
|
});
|
|
545
555
|
const { recommended, transformList, noApplicableVoucher, recommendedAmount } = res;
|
|
546
|
-
console.log(res, "resres12");
|
|
547
556
|
this.walletRecommendList = recommended;
|
|
548
557
|
this.walletInitData = {
|
|
549
558
|
transformList,
|
|
@@ -606,8 +615,12 @@ var WalletPassPaymentImpl = class {
|
|
|
606
615
|
const customerWalletPassList = Array.isArray(
|
|
607
616
|
responseData == null ? void 0 : responseData.customer_wallet_pass_list
|
|
608
617
|
) ? responseData.customer_wallet_pass_list : [];
|
|
609
|
-
const
|
|
618
|
+
const orderedRecalculateList = orderWalletAssetsByIds(
|
|
610
619
|
recalculateList,
|
|
620
|
+
selectedIds
|
|
621
|
+
);
|
|
622
|
+
const allList = mergeWalletAssets(
|
|
623
|
+
orderedRecalculateList,
|
|
611
624
|
customerWalletPassList
|
|
612
625
|
);
|
|
613
626
|
const walletPassEvaluator = (_b = (_a = this.paymentModule.window) == null ? void 0 : _a.getWalletPassEvaluator) == null ? void 0 : _b.call(_a);
|
|
@@ -709,6 +722,18 @@ var WalletPassPaymentImpl = class {
|
|
|
709
722
|
this.paymentModule.logInfo("[WalletPass] 商品列表为空,跳过获取用户识别码列表");
|
|
710
723
|
return [];
|
|
711
724
|
}
|
|
725
|
+
const platform = this.paymentModule.getPlatform();
|
|
726
|
+
if (platform === "pc" || platform === "h5") {
|
|
727
|
+
this.userIdentificationCodes = [];
|
|
728
|
+
this.emitEvent(import_types.WalletPassHooks.OnUserIdentificationCodesUpdated, {
|
|
729
|
+
userIdentificationCodes: []
|
|
730
|
+
});
|
|
731
|
+
this.paymentModule.logInfo(
|
|
732
|
+
"[WalletPass] 用户端平台跳过获取用户识别码列表",
|
|
733
|
+
{ platform }
|
|
734
|
+
);
|
|
735
|
+
return [];
|
|
736
|
+
}
|
|
712
737
|
if (typeof newParams.payment_order_id === "string" && newParams.payment_order_id.startsWith("LOCAL_")) {
|
|
713
738
|
newParams.payment_order_id = void 0;
|
|
714
739
|
}
|
|
@@ -865,10 +865,26 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
865
865
|
);
|
|
866
866
|
}) : void 0;
|
|
867
867
|
const explicitlySelectedDiscountCard = explicitlySelectedDiscount && (explicitlySelectedDiscount.tag || explicitlySelectedDiscount.type) !== "good_pass" ? explicitlySelectedDiscount : void 0;
|
|
868
|
+
const appliedDiscountCardIds = new Set(
|
|
869
|
+
(product.discount_list || []).filter(
|
|
870
|
+
(item) => ["discount_card", "product_discount_card"].includes(
|
|
871
|
+
(item == null ? void 0 : item.tag) || (item == null ? void 0 : item.type)
|
|
872
|
+
)
|
|
873
|
+
).map(
|
|
874
|
+
(item) => {
|
|
875
|
+
var _a3;
|
|
876
|
+
return ((_a3 = item == null ? void 0 : item.discount) == null ? void 0 : _a3.resource_id) ?? (item == null ? void 0 : item.resource_id) ?? (item == null ? void 0 : item.id);
|
|
877
|
+
}
|
|
878
|
+
).filter((id) => id !== void 0 && id !== null).map(String)
|
|
879
|
+
);
|
|
880
|
+
const appliedDiscountCard = (options == null ? void 0 : options.scan) ? void 0 : applicableDiscounts.find((discount) => {
|
|
881
|
+
const discountType = discount.tag || discount.type;
|
|
882
|
+
return discount.isSelected === true && ["discount_card", "product_discount_card"].includes(discountType) && appliedDiscountCardIds.has(String(discount.id));
|
|
883
|
+
});
|
|
868
884
|
const scannedSelectedDiscountCard = applicableDiscounts.find(
|
|
869
885
|
(n) => n.isScan && n.isSelected && (n.tag || n.type) !== "good_pass"
|
|
870
886
|
);
|
|
871
|
-
const selectedDiscountCard = explicitlySelectedDiscountCard || scannedSelectedDiscountCard;
|
|
887
|
+
const selectedDiscountCard = explicitlySelectedDiscountCard || appliedDiscountCard || scannedSelectedDiscountCard;
|
|
872
888
|
const selectedDiscount = explicitlySelectedDiscount || selectedDiscountCard || applicableDiscounts[0];
|
|
873
889
|
const prioritizedApplicableDiscounts = explicitlySelectedDiscount && (explicitlySelectedDiscount.tag || explicitlySelectedDiscount.type) === "good_pass" ? [
|
|
874
890
|
explicitlySelectedDiscount,
|
package/lib/server/index.js
CHANGED
|
@@ -3887,9 +3887,7 @@ var Server = class {
|
|
|
3887
3887
|
checkoutData,
|
|
3888
3888
|
order: pendingOrder,
|
|
3889
3889
|
response: pendingResult,
|
|
3890
|
-
requireFullyPaid: true
|
|
3891
|
-
// 自动小票固定使用 print_all 的收据类型 0,不随订单 type 改成券/手环类型 99。
|
|
3892
|
-
isManualPrint: true
|
|
3890
|
+
requireFullyPaid: true
|
|
3893
3891
|
});
|
|
3894
3892
|
}
|
|
3895
3893
|
await this.dispatchCheckoutSyncTask({
|
|
@@ -3947,9 +3945,8 @@ var Server = class {
|
|
|
3947
3945
|
checkoutData: syncResult.checkoutData,
|
|
3948
3946
|
order: syncedOrder,
|
|
3949
3947
|
response: syncResult.normalizedResponse,
|
|
3950
|
-
requireFullyPaid: true
|
|
3948
|
+
requireFullyPaid: true
|
|
3951
3949
|
// print_all 的 type=0 是收据打印;不要沿用同步成功后的券/手环打印 type=99。
|
|
3952
|
-
isManualPrint: true
|
|
3953
3950
|
});
|
|
3954
3951
|
}
|
|
3955
3952
|
return response;
|
|
@@ -4126,7 +4123,7 @@ var Server = class {
|
|
|
4126
4123
|
var _a, _b, _c, _d, _e;
|
|
4127
4124
|
if (((_b = (_a = this.core.context) == null ? void 0 : _a.getPlatform) == null ? void 0 : _b.call(_a)) !== "android")
|
|
4128
4125
|
return true;
|
|
4129
|
-
return ((_e = (_d = (_c = this.app) == null ? void 0 : _c.storage) == null ? void 0 : _d.getStorage) == null ? void 0 : _e.call(_d, AUTO_PRINT_STORAGE_KEY))
|
|
4126
|
+
return ((_e = (_d = (_c = this.app) == null ? void 0 : _c.storage) == null ? void 0 : _d.getStorage) == null ? void 0 : _e.call(_d, AUTO_PRINT_STORAGE_KEY)) !== "false";
|
|
4130
4127
|
}
|
|
4131
4128
|
shouldBuildSmallTicketData(order) {
|
|
4132
4129
|
if (!order || typeof order !== "object")
|
|
@@ -283,6 +283,7 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
283
283
|
* // => 'S-1001'
|
|
284
284
|
*/
|
|
285
285
|
private getOrderStorageKey;
|
|
286
|
+
private getPersistedOrderStorageKey;
|
|
286
287
|
private getOrderIdentityMatchKeys;
|
|
287
288
|
private doOrdersShareIdentity;
|
|
288
289
|
private findOrderIndexByIdentity;
|
|
@@ -39,6 +39,7 @@ var import_orderCollectionIdentity = require("../../../modules/Order/utils/order
|
|
|
39
39
|
var import_types = require("./types");
|
|
40
40
|
var import_payment_utils = require("../../../modules/Order/payment-utils");
|
|
41
41
|
var INDEXDB_STORE_NAME = "orders";
|
|
42
|
+
var ORDER_STORAGE_KEY_FIELD = "__order_storage_key";
|
|
42
43
|
var ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY = "server_order_last_full_fetch_at";
|
|
43
44
|
var ORDER_LAST_FULL_FETCH_SHOP_ID_STORAGE_KEY = "server_order_last_full_fetch_shop_id";
|
|
44
45
|
var ORDER_SYNC_THROTTLE_MS_STORAGE_KEY = "order_sync_throttle_ms";
|
|
@@ -1628,6 +1629,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1628
1629
|
const patchedOrders = [];
|
|
1629
1630
|
const remoteProductMembershipChanges = [];
|
|
1630
1631
|
const forceWriteStorageKeys = /* @__PURE__ */ new Set();
|
|
1632
|
+
const storageKeyMigrations = [];
|
|
1631
1633
|
const mergeActions = {};
|
|
1632
1634
|
const existingProductsHaveStableIdentity = this.store.list.map(
|
|
1633
1635
|
(order) => this.doProductsHaveStableMembershipIdentity(
|
|
@@ -1652,6 +1654,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1652
1654
|
const mergeKey = storageKey || (fresh.order_id !== void 0 && fresh.order_id !== null ? this.getIdKey(fresh.order_id) : "");
|
|
1653
1655
|
if (matchIndex >= 0) {
|
|
1654
1656
|
const existingOrder = updatedList[matchIndex];
|
|
1657
|
+
const previousStorageKey = this.getPersistedOrderStorageKey(existingOrder);
|
|
1655
1658
|
if (this.isPendingSyncOrder(existingOrder) && this.isRemoteEchoMergeSource(source)) {
|
|
1656
1659
|
this.logInfo("mergeOrdersToStore-跳过 pending 订单远端覆盖", {
|
|
1657
1660
|
source,
|
|
@@ -1713,6 +1716,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1713
1716
|
}
|
|
1714
1717
|
}
|
|
1715
1718
|
}
|
|
1719
|
+
const nextStorageKey = this.getOrderStorageKey(mergedOrder);
|
|
1720
|
+
if (previousStorageKey && nextStorageKey && previousStorageKey !== nextStorageKey) {
|
|
1721
|
+
storageKeyMigrations.push({
|
|
1722
|
+
orderId: mergedOrder.order_id ?? existingOrder.order_id ?? fresh.order_id ?? null,
|
|
1723
|
+
from: previousStorageKey,
|
|
1724
|
+
to: nextStorageKey
|
|
1725
|
+
});
|
|
1726
|
+
}
|
|
1716
1727
|
updatedList[adjustedMatchIndex] = mergedOrder;
|
|
1717
1728
|
existingProductsHaveStableIdentity[adjustedMatchIndex] = mergedProductsHaveStableIdentity;
|
|
1718
1729
|
if (membershipChange) {
|
|
@@ -1750,7 +1761,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1750
1761
|
patchedOrders,
|
|
1751
1762
|
source,
|
|
1752
1763
|
mergeActions,
|
|
1753
|
-
{},
|
|
1764
|
+
{ storageKeyMigrations },
|
|
1754
1765
|
forceWriteStorageKeys
|
|
1755
1766
|
);
|
|
1756
1767
|
this.logInfo("mergeOrdersToStore-结束", {
|
|
@@ -1955,6 +1966,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1955
1966
|
}
|
|
1956
1967
|
return "";
|
|
1957
1968
|
}
|
|
1969
|
+
getPersistedOrderStorageKey(order) {
|
|
1970
|
+
const persistedStorageKey = order == null ? void 0 : order[ORDER_STORAGE_KEY_FIELD];
|
|
1971
|
+
if (persistedStorageKey !== void 0 && persistedStorageKey !== null && persistedStorageKey !== "") {
|
|
1972
|
+
return String(persistedStorageKey);
|
|
1973
|
+
}
|
|
1974
|
+
return this.getOrderStorageKey(order);
|
|
1975
|
+
}
|
|
1958
1976
|
getOrderIdentityMatchKeys(order) {
|
|
1959
1977
|
return this.getOrderIdentityEntries(order).map((entry) => `${entry.field}:${entry.key}`);
|
|
1960
1978
|
}
|
|
@@ -2442,7 +2460,18 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2442
2460
|
throw new Error("订单 SQLite 数据库未初始化");
|
|
2443
2461
|
return;
|
|
2444
2462
|
}
|
|
2445
|
-
const
|
|
2463
|
+
const migrationTargetStorageKeys = new Set(
|
|
2464
|
+
(options.storageKeyMigrations || []).map((migration) => migration.to)
|
|
2465
|
+
);
|
|
2466
|
+
const ordersSnapshot = (0, import_lodash_es.cloneDeep)(orders).map((order) => this.normalizeOrderCollectionsForIngress(order, `${source}.sqliteIngress`)).map((order) => {
|
|
2467
|
+
const storageKey = this.getOrderStorageKey(order);
|
|
2468
|
+
if (!storageKey || !migrationTargetStorageKeys.has(storageKey))
|
|
2469
|
+
return order;
|
|
2470
|
+
return {
|
|
2471
|
+
...order,
|
|
2472
|
+
[ORDER_STORAGE_KEY_FIELD]: storageKey
|
|
2473
|
+
};
|
|
2474
|
+
}).filter((order) => this.getOrderStorageKey(order));
|
|
2446
2475
|
if (ordersSnapshot.length === 0) {
|
|
2447
2476
|
return;
|
|
2448
2477
|
}
|
|
@@ -2459,6 +2488,17 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2459
2488
|
if (compactedToWrite.length === 0) {
|
|
2460
2489
|
return;
|
|
2461
2490
|
}
|
|
2491
|
+
const writtenStorageKeys = new Set(
|
|
2492
|
+
compactedToWrite.map((order) => this.getOrderStorageKey(order)).filter(Boolean)
|
|
2493
|
+
);
|
|
2494
|
+
const storageKeyMigrations = /* @__PURE__ */ new Map();
|
|
2495
|
+
for (const migration of options.storageKeyMigrations || []) {
|
|
2496
|
+
if (!writtenStorageKeys.has(migration.to))
|
|
2497
|
+
continue;
|
|
2498
|
+
if (writtenStorageKeys.has(migration.from))
|
|
2499
|
+
continue;
|
|
2500
|
+
storageKeyMigrations.set(migration.from, migration);
|
|
2501
|
+
}
|
|
2462
2502
|
try {
|
|
2463
2503
|
await this.runInOrderSQLiteSaveQueue(async () => {
|
|
2464
2504
|
let writeMethod = "none";
|
|
@@ -2482,6 +2522,30 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2482
2522
|
throw new Error("订单 SQLite 数据库不支持写入");
|
|
2483
2523
|
}
|
|
2484
2524
|
this.recordRecentSqliteWrite(source, compactedToWrite);
|
|
2525
|
+
if (writeMethod !== "none") {
|
|
2526
|
+
for (const migration of storageKeyMigrations.values()) {
|
|
2527
|
+
try {
|
|
2528
|
+
await this.dbManager.delete(INDEXDB_STORE_NAME, migration.from);
|
|
2529
|
+
this.recentSqliteWriteByStorageKey.delete(migration.from);
|
|
2530
|
+
for (const order of orders) {
|
|
2531
|
+
if (this.getOrderStorageKey(order) !== migration.to)
|
|
2532
|
+
continue;
|
|
2533
|
+
const orderRecord = order;
|
|
2534
|
+
if (String(orderRecord[ORDER_STORAGE_KEY_FIELD] ?? "") !== migration.from)
|
|
2535
|
+
continue;
|
|
2536
|
+
orderRecord[ORDER_STORAGE_KEY_FIELD] = migration.to;
|
|
2537
|
+
}
|
|
2538
|
+
} catch (error) {
|
|
2539
|
+
this.logError("删除订单旧 SQLite storage key 失败", {
|
|
2540
|
+
source,
|
|
2541
|
+
order_id: migration.orderId,
|
|
2542
|
+
oldStorageKey: migration.from,
|
|
2543
|
+
newStorageKey: migration.to,
|
|
2544
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2545
|
+
});
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2485
2549
|
this.logInfo("patchOrdersInSQLite-完成", {
|
|
2486
2550
|
source,
|
|
2487
2551
|
count: compactedToWrite.length,
|
|
@@ -562,7 +562,7 @@ function buildOptionTitleSuffix(options) {
|
|
|
562
562
|
function formatBundlePrice(bundle, currencySymbol) {
|
|
563
563
|
const value = bundle.bundle_selling_price ?? bundle.bundle_sum_price ?? bundle.price ?? 0;
|
|
564
564
|
const amount = new import_decimal.default(toMoneyNumber(value));
|
|
565
|
-
const isNegative = bundle.price_type === "markdown"
|
|
565
|
+
const isNegative = bundle.price_type === "markdown";
|
|
566
566
|
if (isNegative)
|
|
567
567
|
return `-${currencySymbol}${amount.abs().toFixed(2)}`;
|
|
568
568
|
return formatMoney(amount, currencySymbol);
|
|
@@ -119,6 +119,15 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
119
119
|
* application_code 仅作为接口兼容字段,不能替代 channel / business_code。
|
|
120
120
|
*/
|
|
121
121
|
private getPriceQueryStrategyContext;
|
|
122
|
+
/**
|
|
123
|
+
* 子类可在商品重报价前准备客户维度的策略上下文,例如等待 Wallet/优惠资产加载。
|
|
124
|
+
*/
|
|
125
|
+
protected prepareProductPriceQueryContext(_customerId?: number | string): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* 默认保留 BaseSales 的 legacy quotation 行为;已由 /product/query 统一完成
|
|
128
|
+
* 智能定价与报价合并的业务可在子类中覆盖,避免二次覆盖权威价格。
|
|
129
|
+
*/
|
|
130
|
+
protected preferAuthoritativeProductQueryPrice(): boolean;
|
|
122
131
|
private getPriceQuerySchedule;
|
|
123
132
|
private loadProductsForPriceQuery;
|
|
124
133
|
private loadProductForPriceQuery;
|
|
@@ -141,7 +150,9 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
141
150
|
* const params = this.buildSubModuleOtherParams();
|
|
142
151
|
* this.core.registerModule(orderModule, { otherParams: params });
|
|
143
152
|
*/
|
|
144
|
-
protected
|
|
153
|
+
protected isSessionStoragePersistEnabled(): boolean;
|
|
154
|
+
protected shouldUseSessionStorageForSubModule(_moduleName?: string): boolean;
|
|
155
|
+
protected buildSubModuleOtherParams(moduleName?: string): Record<string, any>;
|
|
145
156
|
/**
|
|
146
157
|
* 将父级 otherParams 的变更显式同步给已注册的子模块。
|
|
147
158
|
*
|
|
@@ -434,6 +445,7 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
434
445
|
transformBaseProductToOrderProduct(params: TransformBaseProductToOrderProductParams): import("./utils/transformBaseProductToOrderProduct").BaseProductOrderProductInput | null;
|
|
435
446
|
calculateProductBookingPrice(params: BaseSalesCalculateProductBookingPriceParams): Promise<BaseSalesProductBookingPriceResult>;
|
|
436
447
|
getQuotationCustomerScopeInfo(): BaseSalesQuotationCustomerScopeInfo;
|
|
448
|
+
private hasSmartPricingStrategies;
|
|
437
449
|
shouldRecalculateProductBookingPricesForContextChange(params: BaseSalesPriceRecalculationContextChange): boolean;
|
|
438
450
|
calculateProductBookingPrices(paramsList: BaseSalesCalculateProductBookingPriceParams[]): Promise<BaseSalesProductBookingPriceResult[]>;
|
|
439
451
|
addProductToOrder(product: Partial<BaseSalesOrderProduct> & BaseSalesOrderProductIdentity, booking?: AddProductBookingInput, options?: AddProductToOrderOptions): Promise<import("../../modules/Order/types").OrderProduct[]>;
|
|
@@ -591,7 +591,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
591
591
|
});
|
|
592
592
|
});
|
|
593
593
|
}
|
|
594
|
-
async hydrateLatestLoadedSalesDetail(record, loadSequence) {
|
|
594
|
+
async hydrateLatestLoadedSalesDetail(record, loadSequence, hydrateSource) {
|
|
595
595
|
let hydratedSales = null;
|
|
596
596
|
let skippedBeforeHydrate = false;
|
|
597
597
|
const hydrateTask = async () => {
|
|
@@ -601,9 +601,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
601
601
|
}
|
|
602
602
|
if (!this.store.order)
|
|
603
603
|
throw new Error("order 模块未初始化");
|
|
604
|
-
const sales = await this.store.order.hydrateTempOrderFromRecord(
|
|
605
|
-
|
|
606
|
-
|
|
604
|
+
const sales = await this.store.order.hydrateTempOrderFromRecord(
|
|
605
|
+
record,
|
|
606
|
+
hydrateSource === "sessionStorage" ? { recalcOnHydrate: true, source: "sessionStorage" } : { recalcOnHydrate: false }
|
|
607
|
+
);
|
|
607
608
|
hydratedSales = sales;
|
|
608
609
|
if (loadSequence !== this.salesDetailLoadSequence)
|
|
609
610
|
return;
|
|
@@ -733,8 +734,24 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
733
734
|
if (businessCode !== void 0 && businessCode !== null && String(businessCode).trim() !== "") {
|
|
734
735
|
strategyContext.business_code = String(businessCode).trim();
|
|
735
736
|
}
|
|
737
|
+
const availableWalletIds = this.getAvailableWalletIds();
|
|
738
|
+
if (availableWalletIds.length > 0 && !Array.isArray(strategyContext.available_wallet_ids)) {
|
|
739
|
+
strategyContext.available_wallet_ids = availableWalletIds;
|
|
740
|
+
}
|
|
736
741
|
return strategyContext;
|
|
737
742
|
}
|
|
743
|
+
/**
|
|
744
|
+
* 子类可在商品重报价前准备客户维度的策略上下文,例如等待 Wallet/优惠资产加载。
|
|
745
|
+
*/
|
|
746
|
+
async prepareProductPriceQueryContext(_customerId) {
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* 默认保留 BaseSales 的 legacy quotation 行为;已由 /product/query 统一完成
|
|
750
|
+
* 智能定价与报价合并的业务可在子类中覆盖,避免二次覆盖权威价格。
|
|
751
|
+
*/
|
|
752
|
+
preferAuthoritativeProductQueryPrice() {
|
|
753
|
+
return false;
|
|
754
|
+
}
|
|
738
755
|
getPriceQuerySchedule(params) {
|
|
739
756
|
const booking = params.booking || {};
|
|
740
757
|
if (typeof booking.start_date === "string" && booking.start_date.trim()) {
|
|
@@ -927,12 +944,18 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
927
944
|
* const params = this.buildSubModuleOtherParams();
|
|
928
945
|
* this.core.registerModule(orderModule, { otherParams: params });
|
|
929
946
|
*/
|
|
930
|
-
|
|
947
|
+
isSessionStoragePersistEnabled() {
|
|
948
|
+
return Boolean(this.cacheId);
|
|
949
|
+
}
|
|
950
|
+
shouldUseSessionStorageForSubModule(_moduleName) {
|
|
951
|
+
return this.isSessionStoragePersistEnabled();
|
|
952
|
+
}
|
|
953
|
+
buildSubModuleOtherParams(moduleName) {
|
|
931
954
|
return {
|
|
932
955
|
...this.otherParams,
|
|
933
956
|
salesSummaryModuleName: `${this.name}_salesSummary`,
|
|
934
957
|
fatherModule: this.name,
|
|
935
|
-
openCache: this.
|
|
958
|
+
openCache: this.shouldUseSessionStorageForSubModule(moduleName),
|
|
936
959
|
cacheId: this.cacheId
|
|
937
960
|
};
|
|
938
961
|
}
|
|
@@ -943,7 +966,6 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
943
966
|
* await this.syncOtherParamsToSubModules({ channel: 'pos' });
|
|
944
967
|
*/
|
|
945
968
|
async syncOtherParamsToSubModules(changedParams, { cover = false } = {}) {
|
|
946
|
-
const nextSubModuleOtherParams = this.buildSubModuleOtherParams();
|
|
947
969
|
await Promise.all(
|
|
948
970
|
Object.entries(this.store).map(async ([moduleName, subModule]) => {
|
|
949
971
|
if (this.reusedSharedSubModuleNames.has(moduleName)) {
|
|
@@ -953,6 +975,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
953
975
|
if (!targetModule || typeof targetModule.updateOtherParams !== "function") {
|
|
954
976
|
return;
|
|
955
977
|
}
|
|
978
|
+
const nextSubModuleOtherParams = this.buildSubModuleOtherParams(moduleName);
|
|
956
979
|
await targetModule.updateOtherParams(nextSubModuleOtherParams, {
|
|
957
980
|
changedParams,
|
|
958
981
|
cover
|
|
@@ -965,14 +988,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
965
988
|
* sessionStorage 损坏时静默忽略,按空状态注册。
|
|
966
989
|
*/
|
|
967
990
|
readSessionCacheData() {
|
|
968
|
-
|
|
991
|
+
const cacheId = this.cacheId;
|
|
992
|
+
if (!cacheId || !this.isSessionStoragePersistEnabled() || !this.window) {
|
|
969
993
|
return {};
|
|
994
|
+
}
|
|
970
995
|
try {
|
|
971
996
|
const sessionData = this.window.sessionStorage.getItem(this.name);
|
|
972
997
|
if (!sessionData)
|
|
973
998
|
return {};
|
|
974
999
|
const data = JSON.parse(sessionData);
|
|
975
|
-
return data && data[
|
|
1000
|
+
return data && data[cacheId] || {};
|
|
976
1001
|
} catch {
|
|
977
1002
|
return {};
|
|
978
1003
|
}
|
|
@@ -1074,9 +1099,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1074
1099
|
const hooks = this.getSubModuleHooks(step);
|
|
1075
1100
|
this.store[step] = targetModule;
|
|
1076
1101
|
this.core.registerModule(targetModule, {
|
|
1077
|
-
initialState: (targetCacheData == null ? void 0 : targetCacheData[targetModule.name]) || {},
|
|
1102
|
+
initialState: this.shouldUseSessionStorageForSubModule(step) ? (targetCacheData == null ? void 0 : targetCacheData[targetModule.name]) || {} : {},
|
|
1078
1103
|
...hooks ? { hooks } : {},
|
|
1079
|
-
otherParams: this.buildSubModuleOtherParams()
|
|
1104
|
+
otherParams: this.buildSubModuleOtherParams(step)
|
|
1080
1105
|
});
|
|
1081
1106
|
});
|
|
1082
1107
|
if (this.store.schedule && !this.isScheduleListLoaded(this.store.schedule)) {
|
|
@@ -1143,17 +1168,21 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1143
1168
|
const message = loadedRecord && (loadedRecord.message || loadedRecord.msg) || `加载销售详情失败: ${lookup}`;
|
|
1144
1169
|
throw new Error(message);
|
|
1145
1170
|
}
|
|
1146
|
-
const
|
|
1147
|
-
|
|
1148
|
-
);
|
|
1171
|
+
const loadedSalesDetail = preloadedSalesDetail ?? loadedRecord.data;
|
|
1172
|
+
const shouldFilterPendingPayments = params.hydrateSource !== "sessionStorage";
|
|
1173
|
+
const remoteRecord = shouldFilterPendingPayments ? filterPendingPaymentsFromLoadedSalesDetail(loadedSalesDetail) : loadedSalesDetail;
|
|
1149
1174
|
const currentTempOrder = params.merge ? this.store.order.getTempOrder() : null;
|
|
1150
1175
|
const mergedRecord = params.merge ? mergeSalesDetailRecordWithTempOrder(
|
|
1151
1176
|
currentTempOrder,
|
|
1152
1177
|
remoteRecord,
|
|
1153
1178
|
"preserve-local"
|
|
1154
1179
|
) : remoteRecord;
|
|
1155
|
-
const record = filterPendingPaymentsFromLoadedSalesDetail(mergedRecord);
|
|
1156
|
-
return await this.hydrateLatestLoadedSalesDetail(
|
|
1180
|
+
const record = shouldFilterPendingPayments ? filterPendingPaymentsFromLoadedSalesDetail(mergedRecord) : mergedRecord;
|
|
1181
|
+
return await this.hydrateLatestLoadedSalesDetail(
|
|
1182
|
+
record,
|
|
1183
|
+
loadSequence,
|
|
1184
|
+
params.hydrateSource
|
|
1185
|
+
);
|
|
1157
1186
|
} finally {
|
|
1158
1187
|
this.salesDetailLoadInFlightCount = Math.max(
|
|
1159
1188
|
0,
|
|
@@ -3116,6 +3145,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3116
3145
|
async calculateProductBookingPrice(params) {
|
|
3117
3146
|
const quotation = this.store.quotation;
|
|
3118
3147
|
const customerId = params.customer_id ?? this.getCurrentOrderCustomerId();
|
|
3148
|
+
await this.prepareProductPriceQueryContext(customerId);
|
|
3119
3149
|
const authoritativeProduct = await this.loadProductForPriceQuery(params, customerId);
|
|
3120
3150
|
const product = this.mergeProductForPriceQuery(params.product, authoritativeProduct);
|
|
3121
3151
|
await this.loadQuotationForPriceQuery({
|
|
@@ -3128,7 +3158,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3128
3158
|
product,
|
|
3129
3159
|
fallback_price: authoritativeProduct ? void 0 : params.fallback_price,
|
|
3130
3160
|
customer_id: customerId,
|
|
3131
|
-
quotation
|
|
3161
|
+
quotation: authoritativeProduct && this.preferAuthoritativeProductQueryPrice() ? void 0 : quotation
|
|
3132
3162
|
});
|
|
3133
3163
|
}
|
|
3134
3164
|
getQuotationCustomerScopeInfo() {
|
|
@@ -3165,11 +3195,23 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3165
3195
|
quotationScopes
|
|
3166
3196
|
};
|
|
3167
3197
|
}
|
|
3198
|
+
hasSmartPricingStrategies() {
|
|
3199
|
+
var _a, _b;
|
|
3200
|
+
const evaluator = (_b = (_a = this.core) == null ? void 0 : _a.context) == null ? void 0 : _b.dataVariantEvaluator;
|
|
3201
|
+
if (!evaluator || typeof evaluator.getStrategyConfigs !== "function") {
|
|
3202
|
+
return false;
|
|
3203
|
+
}
|
|
3204
|
+
const configs = evaluator.getStrategyConfigs();
|
|
3205
|
+
return Array.isArray(configs) && configs.length > 0;
|
|
3206
|
+
}
|
|
3168
3207
|
shouldRecalculateProductBookingPricesForContextChange(params) {
|
|
3169
3208
|
const scopeInfo = this.getQuotationCustomerScopeInfo();
|
|
3170
3209
|
const scopedCustomerIds = new Set(scopeInfo.customerIds.map((id) => String(id)));
|
|
3171
3210
|
const previousCustomerId = this.normalizePriceContextCustomerId(params.previousCustomerId);
|
|
3172
3211
|
const nextCustomerId = this.normalizePriceContextCustomerId(params.nextCustomerId);
|
|
3212
|
+
if (this.hasSmartPricingStrategies()) {
|
|
3213
|
+
return previousCustomerId !== nextCustomerId;
|
|
3214
|
+
}
|
|
3173
3215
|
const previousInScope = previousCustomerId ? scopedCustomerIds.has(previousCustomerId) : false;
|
|
3174
3216
|
const nextInScope = nextCustomerId ? scopedCustomerIds.has(nextCustomerId) : false;
|
|
3175
3217
|
let shouldRecalculate = false;
|
|
@@ -3190,6 +3232,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3190
3232
|
return [];
|
|
3191
3233
|
const quotation = this.store.quotation;
|
|
3192
3234
|
const customerId = ((_a = paramsList[0]) == null ? void 0 : _a.customer_id) ?? this.getCurrentOrderCustomerId();
|
|
3235
|
+
await this.prepareProductPriceQueryContext(customerId);
|
|
3193
3236
|
const productMapsByGroup = /* @__PURE__ */ new Map();
|
|
3194
3237
|
const groups = /* @__PURE__ */ new Map();
|
|
3195
3238
|
paramsList.forEach((params) => {
|
|
@@ -3247,7 +3290,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3247
3290
|
product,
|
|
3248
3291
|
fallback_price: authoritativeProduct ? void 0 : params.fallback_price,
|
|
3249
3292
|
customer_id: customerId,
|
|
3250
|
-
quotation
|
|
3293
|
+
quotation: authoritativeProduct && this.preferAuthoritativeProductQueryPrice() ? void 0 : quotation
|
|
3251
3294
|
});
|
|
3252
3295
|
});
|
|
3253
3296
|
}
|
|
@@ -60,33 +60,44 @@ function createEmptySummary() {
|
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
function buildProductLineFingerprint(productOptionItem, productBundle) {
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
63
|
+
const normalizeOptions = (options) => {
|
|
64
|
+
const optionArr = Array.isArray(options) ? options : [];
|
|
65
|
+
return optionArr.map((item) => ({
|
|
66
|
+
option_group_item_id: Number(item == null ? void 0 : item.option_group_item_id) || 0,
|
|
67
|
+
option_group_id: Number(item == null ? void 0 : item.option_group_id) || 0,
|
|
68
|
+
num: typeof (item == null ? void 0 : item.num) === "number" && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1,
|
|
69
|
+
price: String((item == null ? void 0 : item.add_price) ?? (item == null ? void 0 : item.price) ?? "")
|
|
70
|
+
})).sort((p, q) => {
|
|
71
|
+
if (p.option_group_item_id !== q.option_group_item_id) {
|
|
72
|
+
return p.option_group_item_id - q.option_group_item_id;
|
|
73
|
+
}
|
|
74
|
+
if (p.option_group_id !== q.option_group_id) {
|
|
75
|
+
return p.option_group_id - q.option_group_id;
|
|
76
|
+
}
|
|
77
|
+
if (p.num !== q.num)
|
|
78
|
+
return p.num - q.num;
|
|
79
|
+
return p.price.localeCompare(q.price);
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
const normalizedOpts = normalizeOptions(productOptionItem);
|
|
79
83
|
const bundleArr = Array.isArray(productBundle) ? productBundle : [];
|
|
80
84
|
const normalizedBundles = bundleArr.map((item) => ({
|
|
81
85
|
bundle_id: Number((item == null ? void 0 : item.bundle_id) ?? (item == null ? void 0 : item.id) ?? 0) || 0,
|
|
82
86
|
product_id: Number(item == null ? void 0 : item.product_id) || 0,
|
|
83
|
-
|
|
87
|
+
product_variant_id: Number((item == null ? void 0 : item.bundle_variant_id) ?? (item == null ? void 0 : item.product_variant_id)) || 0,
|
|
88
|
+
num: typeof (item == null ? void 0 : item.num) === "number" && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1,
|
|
89
|
+
option: normalizeOptions(item == null ? void 0 : item.option)
|
|
84
90
|
})).sort((p, q) => {
|
|
85
91
|
if (p.bundle_id !== q.bundle_id)
|
|
86
92
|
return p.bundle_id - q.bundle_id;
|
|
87
93
|
if (p.product_id !== q.product_id)
|
|
88
94
|
return p.product_id - q.product_id;
|
|
89
|
-
|
|
95
|
+
if (p.product_variant_id !== q.product_variant_id) {
|
|
96
|
+
return p.product_variant_id - q.product_variant_id;
|
|
97
|
+
}
|
|
98
|
+
if (p.num !== q.num)
|
|
99
|
+
return p.num - q.num;
|
|
100
|
+
return JSON.stringify(p.option).localeCompare(JSON.stringify(q.option));
|
|
90
101
|
});
|
|
91
102
|
return JSON.stringify([normalizedOpts, normalizedBundles]);
|
|
92
103
|
}
|
|
@@ -29,6 +29,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
29
29
|
private addTimeProductsCatalog;
|
|
30
30
|
private orderCustomerDiscountRefreshInFlight;
|
|
31
31
|
private orderCustomerDiscountRefreshCustomerId;
|
|
32
|
+
private orderCustomerPromotionRefreshInFlight;
|
|
32
33
|
private loadOpenDataConfigInFlight;
|
|
33
34
|
/**
|
|
34
35
|
* 在 BaseSales 默认模块清单(products/order/salesSummary/schedule)基础上追加 customer + bookingContext。
|
|
@@ -63,6 +64,8 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
63
64
|
scanPromotionCode(code: string, customerId?: number): Promise<BaseSalesScanCodeResult>;
|
|
64
65
|
private hydrateOrderCustomerFromScanDiscounts;
|
|
65
66
|
private getDiscountCustomerId;
|
|
67
|
+
resolveCustomerById(customerId: string | number): Promise<ICustomer | null>;
|
|
68
|
+
/** 兼容既有优惠码扫码逻辑。 */
|
|
66
69
|
private resolveCustomerByDiscountCustomerId;
|
|
67
70
|
private findCustomerById;
|
|
68
71
|
private normalizeCustomer;
|
|
@@ -282,7 +285,10 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
282
285
|
restoreOrder(): Promise<import("../../modules/Order/types").OrderTempOrder>;
|
|
283
286
|
/** 内部:基于 OrderModule 当前状态构造一份 OrderCustomerChangePayload。 */
|
|
284
287
|
private buildOrderCustomerPayload;
|
|
285
|
-
|
|
288
|
+
protected refreshDiscountConfigAfterOrderCustomerChange(customerId: number | null): Promise<void>;
|
|
289
|
+
protected waitForOrderCustomerPromotionRefresh(): Promise<void>;
|
|
290
|
+
protected prepareProductPriceQueryContext(customerId?: number | string): Promise<void>;
|
|
291
|
+
protected preferAuthoritativeProductQueryPrice(): boolean;
|
|
286
292
|
/**
|
|
287
293
|
* 获取客户分页信息
|
|
288
294
|
* @returns 分页信息
|