@pisell/pisellos 2.3.43 → 2.3.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/modules/Order/index.d.ts +2 -1
- package/dist/modules/Order/index.js +73 -28
- package/dist/modules/Order/types.d.ts +2 -0
- package/dist/modules/Payment/walletpass.d.ts +10 -3
- package/dist/modules/Payment/walletpass.js +425 -282
- package/dist/modules/Rules/index.d.ts +2 -0
- package/dist/modules/Rules/index.js +61 -57
- package/dist/solution/BaseSales/index.js +6 -3
- package/dist/solution/BaseSales/types.d.ts +3 -1
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +6 -3
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +6 -3
- package/dist/solution/BookingTicket/types.d.ts +1 -0
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +3 -3
- package/dist/solution/VenueBooking/index.d.ts +1 -0
- package/lib/model/strategy/adapter/promotion/index.js +51 -0
- package/lib/modules/Order/index.d.ts +2 -1
- package/lib/modules/Order/index.js +46 -7
- package/lib/modules/Order/types.d.ts +2 -0
- package/lib/modules/Payment/walletpass.d.ts +10 -3
- package/lib/modules/Payment/walletpass.js +218 -56
- package/lib/modules/Rules/index.d.ts +2 -0
- package/lib/modules/Rules/index.js +8 -3
- package/lib/solution/BaseSales/index.js +1 -0
- package/lib/solution/BaseSales/types.d.ts +3 -1
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +3 -2
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +1 -0
- package/lib/solution/BookingTicket/types.d.ts +1 -0
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +2 -2
- package/lib/solution/VenueBooking/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/model/strategy/adapter/promotion/index.ts
|
|
30
|
+
var promotion_exports = {};
|
|
31
|
+
__export(promotion_exports, {
|
|
32
|
+
BUY_X_GET_Y_FREE_STRATEGY: () => import_examples.BUY_X_GET_Y_FREE_STRATEGY,
|
|
33
|
+
ITEM_REWARD_STRATEGY: () => import_examples.ITEM_REWARD_STRATEGY,
|
|
34
|
+
PromotionAdapter: () => import_adapter.PromotionAdapter,
|
|
35
|
+
PromotionEvaluator: () => import_evaluator.PromotionEvaluator,
|
|
36
|
+
X_ITEMS_FOR_Y_PRICE_STRATEGY: () => import_examples.X_ITEMS_FOR_Y_PRICE_STRATEGY,
|
|
37
|
+
default: () => import_adapter2.default
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(promotion_exports);
|
|
40
|
+
var import_evaluator = require("./evaluator");
|
|
41
|
+
var import_adapter = require("./adapter");
|
|
42
|
+
var import_adapter2 = __toESM(require("./adapter"));
|
|
43
|
+
var import_examples = require("./examples");
|
|
44
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
45
|
+
0 && (module.exports = {
|
|
46
|
+
BUY_X_GET_Y_FREE_STRATEGY,
|
|
47
|
+
ITEM_REWARD_STRATEGY,
|
|
48
|
+
PromotionAdapter,
|
|
49
|
+
PromotionEvaluator,
|
|
50
|
+
X_ITEMS_FOR_Y_PRICE_STRATEGY
|
|
51
|
+
});
|
|
@@ -81,6 +81,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
81
81
|
private ensureEditDiscountConfigForProductChange;
|
|
82
82
|
scanCode(code: string, customerId?: number): Promise<{
|
|
83
83
|
isAvailable: boolean;
|
|
84
|
+
isAccepted?: boolean;
|
|
84
85
|
discountList: Discount[];
|
|
85
86
|
type: 'server' | 'clientCalc';
|
|
86
87
|
unavailableReason?: UnavailableReason;
|
|
@@ -486,7 +487,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
486
487
|
generateIdempotencyToken(): string;
|
|
487
488
|
syncPaymentsToOrder<T = any>(params: SyncPaymentsToOrderParams): Promise<SyncPaymentsToOrderResult<T>>;
|
|
488
489
|
createOrder(params: CommitOrderParams['query']): {
|
|
489
|
-
type: "
|
|
490
|
+
type: "virtual" | "appointment_booking";
|
|
490
491
|
platform: string;
|
|
491
492
|
sales_channel: string;
|
|
492
493
|
order_sales_channel: string;
|
|
@@ -70,6 +70,24 @@ function isManualProductDiscountProduct(product) {
|
|
|
70
70
|
}
|
|
71
71
|
var ORDER_PAYMENT_STATUS_PAID = "paid";
|
|
72
72
|
var ORDER_PAYMENT_STATUS_PENDING = "payment_pending";
|
|
73
|
+
var CUSTOMER_PROMOTION_DISCOUNT_TAGS = /* @__PURE__ */ new Set([
|
|
74
|
+
"good_pass",
|
|
75
|
+
"product_discount_card",
|
|
76
|
+
"discount_card"
|
|
77
|
+
]);
|
|
78
|
+
function isCustomerPromotionDiscount(discount) {
|
|
79
|
+
return CUSTOMER_PROMOTION_DISCOUNT_TAGS.has(
|
|
80
|
+
String((discount == null ? void 0 : discount.tag) || (discount == null ? void 0 : discount.type) || "").toLowerCase()
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
function markScannedDiscounts(discountList, scannedDiscountList) {
|
|
84
|
+
const scannedIds = new Set(
|
|
85
|
+
scannedDiscountList.map((discount) => discount == null ? void 0 : discount.id).filter((id) => id !== void 0 && id !== null).map(String)
|
|
86
|
+
);
|
|
87
|
+
return discountList.map(
|
|
88
|
+
(discount) => scannedIds.has(String(discount == null ? void 0 : discount.id)) ? { ...discount, isScan: true } : discount
|
|
89
|
+
);
|
|
90
|
+
}
|
|
73
91
|
function isVoucherPaymentRecord(payment) {
|
|
74
92
|
return (payment == null ? void 0 : payment.voucher_id) !== void 0 && Number(payment.voucher_id) !== 0;
|
|
75
93
|
}
|
|
@@ -122,6 +140,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
122
140
|
const type = (item == null ? void 0 : item.type) ?? (item == null ? void 0 : item.tag);
|
|
123
141
|
if (!type || type === "product")
|
|
124
142
|
continue;
|
|
143
|
+
const isDiscountCard = type === "discount_card" || type === "product_discount_card";
|
|
125
144
|
const resourceId = ((_a = item == null ? void 0 : item.discount) == null ? void 0 : _a.resource_id) ?? (item == null ? void 0 : item.resource_id) ?? (item == null ? void 0 : item.discount_id) ?? (item == null ? void 0 : item.order_discount_id);
|
|
126
145
|
if (resourceId === void 0 || resourceId === null || resourceId === "")
|
|
127
146
|
continue;
|
|
@@ -144,7 +163,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
144
163
|
if (existed) {
|
|
145
164
|
existed.amount = Number(existed.amount || 0) + amount;
|
|
146
165
|
existed.used_par_value = String(Number(existed.used_par_value || 0) + amount);
|
|
147
|
-
|
|
166
|
+
if (!isDiscountCard) {
|
|
167
|
+
existed.balance = String(Number(existed.balance || 0) + amount);
|
|
168
|
+
}
|
|
148
169
|
const productIds = Array.isArray((_f = existed.limited_relation_product_data) == null ? void 0 : _f.product_ids) ? existed.limited_relation_product_data.product_ids : [];
|
|
149
170
|
if ((product == null ? void 0 : product.product_id) !== void 0 && (product == null ? void 0 : product.product_id) !== null && !productIds.includes(product.product_id)) {
|
|
150
171
|
existed.limited_relation_product_data = {
|
|
@@ -181,7 +202,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
181
202
|
filter: 0,
|
|
182
203
|
exclude_product_ids: []
|
|
183
204
|
},
|
|
184
|
-
balance: String((item == null ? void 0 : item.amount) ?? "0"),
|
|
205
|
+
balance: isDiscountCard ? void 0 : String((item == null ? void 0 : item.amount) ?? "0"),
|
|
185
206
|
format_title: title,
|
|
186
207
|
product: {
|
|
187
208
|
id: (product == null ? void 0 : product.product_id) ?? 0,
|
|
@@ -528,7 +549,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
528
549
|
});
|
|
529
550
|
}
|
|
530
551
|
async scanCode(code, customerId) {
|
|
531
|
-
var _a, _b, _c, _d;
|
|
552
|
+
var _a, _b, _c, _d, _e;
|
|
532
553
|
const resultDiscountWithReason = await ((_a = this.store.discount) == null ? void 0 : _a.batchSearch(code, { customerId })) || { discountList: [], unavailableReasonKey: null };
|
|
533
554
|
const { discountList: resultDiscountList, unavailableReasonKey } = resultDiscountWithReason;
|
|
534
555
|
const rulesModule = this.store.rules;
|
|
@@ -536,6 +557,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
536
557
|
return {
|
|
537
558
|
type: "clientCalc",
|
|
538
559
|
isAvailable: false,
|
|
560
|
+
isAccepted: false,
|
|
539
561
|
discountList: this.getDiscountList(),
|
|
540
562
|
scannedDiscountList: resultDiscountList,
|
|
541
563
|
unavailableReason: import_types2.UnavailableReason.Unknown
|
|
@@ -545,6 +567,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
545
567
|
return {
|
|
546
568
|
type: "server",
|
|
547
569
|
isAvailable: false,
|
|
570
|
+
isAccepted: false,
|
|
548
571
|
discountList: this.getDiscountList(),
|
|
549
572
|
scannedDiscountList: resultDiscountList,
|
|
550
573
|
unavailableReasonKey
|
|
@@ -560,13 +583,19 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
560
583
|
return {
|
|
561
584
|
type: "clientCalc",
|
|
562
585
|
isAvailable: true,
|
|
586
|
+
isAccepted: true,
|
|
563
587
|
discountList: this.getDiscountList(),
|
|
564
588
|
scannedDiscountList: resultDiscountList
|
|
565
589
|
};
|
|
566
590
|
}
|
|
567
591
|
const tempOrder = this.store.tempOrder;
|
|
568
592
|
const holders = ((_b = tempOrder == null ? void 0 : tempOrder.holder) == null ? void 0 : _b.form_record) || [];
|
|
569
|
-
const {
|
|
593
|
+
const {
|
|
594
|
+
isAvailable,
|
|
595
|
+
discountList: newDiscountList,
|
|
596
|
+
evaluatedDiscountList,
|
|
597
|
+
unavailableReason
|
|
598
|
+
} = rulesModule.isDiscountListAvailable({
|
|
570
599
|
productList: (tempOrder == null ? void 0 : tempOrder.products) || [],
|
|
571
600
|
oldDiscountList: this.getDiscountList(),
|
|
572
601
|
newDiscountList: withScanList,
|
|
@@ -574,15 +603,25 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
574
603
|
holders,
|
|
575
604
|
isFormSubject: (product) => (0, import_utils.resolveIsFormSubject)(tempOrder, product)
|
|
576
605
|
}) || { isAvailable: false, discountList: this.getDiscountList() };
|
|
577
|
-
|
|
578
|
-
|
|
606
|
+
const shouldRetainForLater = !isAvailable && unavailableReason === import_types2.UnavailableReason.ProductNotApplicable && withScanList.some(isCustomerPromotionDiscount);
|
|
607
|
+
const normalizedNewDiscountList = newDiscountList ? markScannedDiscounts(newDiscountList, withScanList) : void 0;
|
|
608
|
+
const retainedDiscountList = evaluatedDiscountList ? markScannedDiscounts(evaluatedDiscountList, withScanList) : normalizedNewDiscountList;
|
|
609
|
+
let resolvedDiscountList = normalizedNewDiscountList || this.getDiscountList();
|
|
610
|
+
if (isAvailable && normalizedNewDiscountList) {
|
|
611
|
+
await ((_d = this.store.discount) == null ? void 0 : _d.setDiscountList(normalizedNewDiscountList));
|
|
579
612
|
this.applyDiscount();
|
|
580
613
|
await this.syncScannedDiscountsToOriginalDiscountList(this.getDiscountList());
|
|
614
|
+
resolvedDiscountList = this.getDiscountList();
|
|
615
|
+
} else if (shouldRetainForLater && retainedDiscountList) {
|
|
616
|
+
await ((_e = this.store.discount) == null ? void 0 : _e.setDiscountList(retainedDiscountList));
|
|
617
|
+
await this.syncScannedDiscountsToOriginalDiscountList(this.getDiscountList());
|
|
618
|
+
resolvedDiscountList = this.getDiscountList();
|
|
581
619
|
}
|
|
582
620
|
return {
|
|
583
621
|
type: "clientCalc",
|
|
584
622
|
isAvailable: isAvailable || false,
|
|
585
|
-
|
|
623
|
+
isAccepted: Boolean(isAvailable || shouldRetainForLater),
|
|
624
|
+
discountList: resolvedDiscountList,
|
|
586
625
|
scannedDiscountList: resultDiscountList,
|
|
587
626
|
unavailableReason
|
|
588
627
|
};
|
|
@@ -165,6 +165,8 @@ export interface OrderCustomerChangePayload {
|
|
|
165
165
|
}
|
|
166
166
|
export interface OrderScanCodeResult {
|
|
167
167
|
isAvailable: boolean;
|
|
168
|
+
/** 卡券已加入当前订单折扣列表,但不一定能立即应用。 */
|
|
169
|
+
isAccepted?: boolean;
|
|
168
170
|
discountList: Discount[];
|
|
169
171
|
scannedDiscountList: Discount[];
|
|
170
172
|
type: 'server' | 'clientCalc';
|
|
@@ -21,11 +21,13 @@ export declare class WalletPassPaymentImpl implements WalletPassPayment {
|
|
|
21
21
|
private emitEvent;
|
|
22
22
|
private publishWalletAssetsState;
|
|
23
23
|
private recalculateWalletAssets;
|
|
24
|
+
/** 获取当前缓存中所有支付类 Wallet 资产的扫码 code。 */
|
|
25
|
+
private getSearchedWalletAssetCodes;
|
|
24
26
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
+
* 用订单重算接口返回的数据更新扫码 Wallet 缓存。
|
|
28
|
+
* 接口暂时缺失某个扫码 code 时继续保留旧值,避免列表闪空。
|
|
27
29
|
*/
|
|
28
|
-
private
|
|
30
|
+
private syncSearchedWalletAssets;
|
|
29
31
|
/**
|
|
30
32
|
* 生成钱包API默认参数
|
|
31
33
|
* 根据业务数据生成标准的钱包API参数,并存储在模块中
|
|
@@ -67,6 +69,11 @@ export declare class WalletPassPaymentImpl implements WalletPassPayment {
|
|
|
67
69
|
noApplicableVoucher: any[];
|
|
68
70
|
products: any[];
|
|
69
71
|
}>;
|
|
72
|
+
/**
|
|
73
|
+
* 商品或订单金额变化后,使用聚合接口一次重算已选与剩余 WalletPass。
|
|
74
|
+
* Walk-In 不发送 customer_id;会员才携带真实 customer_id。
|
|
75
|
+
*/
|
|
76
|
+
private aggregateRecalculateWalletAssetsAsync;
|
|
70
77
|
getWalletPassRecommendListAsync(params: WalletDeductionRecommendParams): Promise<WalletRecommendItem[]>;
|
|
71
78
|
formatWalletPassList2PreparePayments(list: WalletRecommendItem[]): {
|
|
72
79
|
voucher_id: number;
|
|
@@ -41,6 +41,11 @@ function getWalletAssetKey(assetOrId) {
|
|
|
41
41
|
const id = assetOrId && typeof assetOrId === "object" ? getWalletAssetId(assetOrId) : assetOrId;
|
|
42
42
|
return id === void 0 || id === null ? "" : String(id);
|
|
43
43
|
}
|
|
44
|
+
function matchesWalletAssetCode(asset, normalizedCode) {
|
|
45
|
+
return [asset == null ? void 0 : asset.code, asset == null ? void 0 : asset.encoded].some(
|
|
46
|
+
(identifier) => String(identifier ?? "").trim() === normalizedCode
|
|
47
|
+
);
|
|
48
|
+
}
|
|
44
49
|
function isWalletAssetAvailable(asset) {
|
|
45
50
|
if (!asset)
|
|
46
51
|
return false;
|
|
@@ -150,12 +155,10 @@ var WalletPassPaymentImpl = class {
|
|
|
150
155
|
const committedKeys = new Set(
|
|
151
156
|
this.walletAssetsState.committedIds.map((id) => String(id))
|
|
152
157
|
);
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
);
|
|
156
|
-
const requested = items.filter(
|
|
157
|
-
(item) => requestedKeys.has(getWalletAssetKey(item)) && isWalletAssetAvailable(item)
|
|
158
|
+
const itemsByKey = new Map(
|
|
159
|
+
items.map((item) => [getWalletAssetKey(item), item])
|
|
158
160
|
);
|
|
161
|
+
const requested = requestedIds.map((id) => String(id)).filter((id) => !committedKeys.has(id)).map((id) => itemsByKey.get(id)).filter((item) => item && isWalletAssetAvailable(item));
|
|
159
162
|
let nextItems = items;
|
|
160
163
|
let selectedItems = requested;
|
|
161
164
|
const evaluator = (_b = (_a = this.paymentModule.window) == null ? void 0 : _a.getWalletPassEvaluator) == null ? void 0 : _b.call(_a);
|
|
@@ -201,57 +204,40 @@ var WalletPassPaymentImpl = class {
|
|
|
201
204
|
error: null
|
|
202
205
|
});
|
|
203
206
|
}
|
|
207
|
+
/** 获取当前缓存中所有支付类 Wallet 资产的扫码 code。 */
|
|
208
|
+
getSearchedWalletAssetCodes() {
|
|
209
|
+
const cachedAssets = this.searchResults.filter(isWalletPaymentAsset);
|
|
210
|
+
const seenCodes = /* @__PURE__ */ new Set();
|
|
211
|
+
return cachedAssets.map((item) => String((item == null ? void 0 : item.code) || "").trim()).filter((code) => {
|
|
212
|
+
const normalizedCode = code.toUpperCase();
|
|
213
|
+
if (!normalizedCode || seenCodes.has(normalizedCode))
|
|
214
|
+
return false;
|
|
215
|
+
seenCodes.add(normalizedCode);
|
|
216
|
+
return true;
|
|
217
|
+
});
|
|
218
|
+
}
|
|
204
219
|
/**
|
|
205
|
-
*
|
|
206
|
-
*
|
|
220
|
+
* 用订单重算接口返回的数据更新扫码 Wallet 缓存。
|
|
221
|
+
* 接口暂时缺失某个扫码 code 时继续保留旧值,避免列表闪空。
|
|
207
222
|
*/
|
|
208
|
-
|
|
223
|
+
syncSearchedWalletAssets(refreshedCandidates) {
|
|
209
224
|
const cachedAssets = this.searchResults.filter(isWalletPaymentAsset);
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
cachedAssets.map((item) => String((item == null ? void 0 : item.code) || "").trim()).filter(Boolean)
|
|
213
|
-
)
|
|
214
|
-
];
|
|
215
|
-
if (searchCodes.length === 0)
|
|
216
|
-
return cachedAssets;
|
|
217
|
-
const preparePayments = this.formatWalletPassList2PreparePayments(
|
|
218
|
-
this.walletAssetsState.selectedItems
|
|
219
|
-
);
|
|
220
|
-
const refreshedGroups = await Promise.all(
|
|
221
|
-
searchCodes.map(async (searchCode) => {
|
|
222
|
-
try {
|
|
223
|
-
const result = await this.searchIdentificationCodeAsync(
|
|
224
|
-
{
|
|
225
|
-
...this.walletParams || {},
|
|
226
|
-
code: searchCode,
|
|
227
|
-
prepare_payments: preparePayments
|
|
228
|
-
},
|
|
229
|
-
{ noCache: true }
|
|
230
|
-
);
|
|
231
|
-
return {
|
|
232
|
-
searchCode,
|
|
233
|
-
items: result.type === "normalCode" ? result.data.filter(isWalletPaymentAsset) : []
|
|
234
|
-
};
|
|
235
|
-
} catch (error) {
|
|
236
|
-
this.paymentModule.logWarning(
|
|
237
|
-
"[WalletPass] 重验扫码 Wallet 资产失败,保留旧结果",
|
|
238
|
-
{
|
|
239
|
-
code: searchCode,
|
|
240
|
-
error: error instanceof Error ? error.message : String(error)
|
|
241
|
-
}
|
|
242
|
-
);
|
|
243
|
-
return { searchCode, items: [] };
|
|
244
|
-
}
|
|
245
|
-
})
|
|
225
|
+
const searchedCodeKeys = new Set(
|
|
226
|
+
this.getSearchedWalletAssetCodes().map((code) => code.toUpperCase())
|
|
246
227
|
);
|
|
247
|
-
if (
|
|
228
|
+
if (searchedCodeKeys.size === 0)
|
|
248
229
|
return cachedAssets;
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
230
|
+
const refreshedAssets = refreshedCandidates.filter(
|
|
231
|
+
(item) => isWalletPaymentAsset(item) && searchedCodeKeys.has(
|
|
232
|
+
String((item == null ? void 0 : item.code) || "").trim().toUpperCase()
|
|
233
|
+
)
|
|
252
234
|
);
|
|
253
|
-
const refreshedAssets = refreshedGroups.flatMap((group) => group.items);
|
|
254
235
|
if (refreshedAssets.length > 0) {
|
|
236
|
+
const replacedCodes = new Set(
|
|
237
|
+
refreshedAssets.map(
|
|
238
|
+
(item) => String((item == null ? void 0 : item.code) || "").trim().toUpperCase()
|
|
239
|
+
)
|
|
240
|
+
);
|
|
255
241
|
this.searchResults = [
|
|
256
242
|
...this.searchResults.filter(
|
|
257
243
|
(item) => !replacedCodes.has(String((item == null ? void 0 : item.code) || "").trim().toUpperCase())
|
|
@@ -259,7 +245,10 @@ var WalletPassPaymentImpl = class {
|
|
|
259
245
|
...refreshedAssets
|
|
260
246
|
];
|
|
261
247
|
}
|
|
262
|
-
return mergeWalletAssets(
|
|
248
|
+
return mergeWalletAssets(
|
|
249
|
+
cachedAssets,
|
|
250
|
+
refreshedAssets
|
|
251
|
+
);
|
|
263
252
|
}
|
|
264
253
|
/**
|
|
265
254
|
* 生成钱包API默认参数
|
|
@@ -468,6 +457,96 @@ var WalletPassPaymentImpl = class {
|
|
|
468
457
|
throw error;
|
|
469
458
|
}
|
|
470
459
|
}
|
|
460
|
+
/**
|
|
461
|
+
* 商品或订单金额变化后,使用聚合接口一次重算已选与剩余 WalletPass。
|
|
462
|
+
* Walk-In 不发送 customer_id;会员才携带真实 customer_id。
|
|
463
|
+
*/
|
|
464
|
+
async aggregateRecalculateWalletAssetsAsync(businessData, selectedIds) {
|
|
465
|
+
var _a, _b;
|
|
466
|
+
const walletParams = this.generateWalletParams(businessData);
|
|
467
|
+
const customerId = Number(walletParams.customer_id || 0);
|
|
468
|
+
const requestParams = {
|
|
469
|
+
ids: selectedIds.map((id) => String(id)),
|
|
470
|
+
exact_codes: this.getSearchedWalletAssetCodes(),
|
|
471
|
+
order_product_amount: walletParams.order_product_amount,
|
|
472
|
+
order_expect_amount: walletParams.order_expect_amount,
|
|
473
|
+
order_wait_pay_amount: walletParams.order_wait_pay_amount,
|
|
474
|
+
products: walletParams.products,
|
|
475
|
+
available: 2,
|
|
476
|
+
filter_prepare_wallet_pass: 1,
|
|
477
|
+
sale_channel: walletParams.sale_channel || "pos"
|
|
478
|
+
};
|
|
479
|
+
if (customerId > 1) {
|
|
480
|
+
requestParams.customer_id = customerId;
|
|
481
|
+
}
|
|
482
|
+
const response = await this.paymentModule.request.post(
|
|
483
|
+
"/machinecode/prepare/deduction/aggregate-recalculate",
|
|
484
|
+
requestParams
|
|
485
|
+
);
|
|
486
|
+
const responseData = response == null ? void 0 : response.data;
|
|
487
|
+
const hasAggregateLists = responseData && (Object.prototype.hasOwnProperty.call(
|
|
488
|
+
responseData,
|
|
489
|
+
"recalculate_list"
|
|
490
|
+
) || Object.prototype.hasOwnProperty.call(
|
|
491
|
+
responseData,
|
|
492
|
+
"customer_wallet_pass_list"
|
|
493
|
+
));
|
|
494
|
+
if (!hasAggregateLists) {
|
|
495
|
+
throw new Error("WalletPass aggregate response is missing list data");
|
|
496
|
+
}
|
|
497
|
+
const recalculateList = Array.isArray(responseData == null ? void 0 : responseData.recalculate_list) ? responseData.recalculate_list : [];
|
|
498
|
+
const customerWalletPassList = Array.isArray(
|
|
499
|
+
responseData == null ? void 0 : responseData.customer_wallet_pass_list
|
|
500
|
+
) ? responseData.customer_wallet_pass_list : [];
|
|
501
|
+
const allList = mergeWalletAssets(
|
|
502
|
+
recalculateList,
|
|
503
|
+
customerWalletPassList
|
|
504
|
+
);
|
|
505
|
+
const walletPassEvaluator = (_b = (_a = this.paymentModule.window) == null ? void 0 : _a.getWalletPassEvaluator) == null ? void 0 : _b.call(_a);
|
|
506
|
+
const evaluated = (walletPassEvaluator == null ? void 0 : walletPassEvaluator.getRecommendedVouchers) ? walletPassEvaluator.getRecommendedVouchers({
|
|
507
|
+
orderTotalAmount: walletParams.order_wait_pay_amount,
|
|
508
|
+
products: walletParams.products,
|
|
509
|
+
vouchers: allList
|
|
510
|
+
}) : {
|
|
511
|
+
recommended: [],
|
|
512
|
+
transformList: allList.filter(isWalletAssetAvailable),
|
|
513
|
+
noApplicableVoucher: allList.filter(
|
|
514
|
+
(item) => !isWalletAssetAvailable(item)
|
|
515
|
+
)
|
|
516
|
+
};
|
|
517
|
+
const returnedSelectedKeys = new Set(
|
|
518
|
+
recalculateList.filter(isWalletAssetAvailable).map((item) => getWalletAssetKey(item))
|
|
519
|
+
);
|
|
520
|
+
const authoritativeSelectedIds = selectedIds.filter(
|
|
521
|
+
(id) => returnedSelectedKeys.has(String(id))
|
|
522
|
+
);
|
|
523
|
+
this.walletRecommendList = evaluated.recommended || [];
|
|
524
|
+
this.userIdentificationCodes = allList;
|
|
525
|
+
this.emitEvent(import_types.WalletPassHooks.OnUserIdentificationCodesUpdated, {
|
|
526
|
+
userIdentificationCodes: this.userIdentificationCodes
|
|
527
|
+
});
|
|
528
|
+
this.walletInitData = {
|
|
529
|
+
transformList: evaluated.transformList || [],
|
|
530
|
+
noApplicableVoucher: evaluated.noApplicableVoucher || [],
|
|
531
|
+
products: walletParams.products || []
|
|
532
|
+
};
|
|
533
|
+
this.paymentModule.logInfo(
|
|
534
|
+
"[WalletPass] 聚合重算 WalletPass 完成",
|
|
535
|
+
{
|
|
536
|
+
selected_count: recalculateList.length,
|
|
537
|
+
remaining_count: customerWalletPassList.length,
|
|
538
|
+
searched_codes_count: requestParams.exact_codes.length
|
|
539
|
+
}
|
|
540
|
+
);
|
|
541
|
+
return {
|
|
542
|
+
walletRecommendList: this.walletRecommendList,
|
|
543
|
+
userIdentificationCodes: this.userIdentificationCodes,
|
|
544
|
+
transformList: evaluated.transformList || [],
|
|
545
|
+
noApplicableVoucher: evaluated.noApplicableVoucher || [],
|
|
546
|
+
products: walletParams.products || [],
|
|
547
|
+
authoritativeSelectedIds
|
|
548
|
+
};
|
|
549
|
+
}
|
|
471
550
|
async getWalletPassRecommendListAsync(params) {
|
|
472
551
|
var _a;
|
|
473
552
|
try {
|
|
@@ -681,6 +760,7 @@ var WalletPassPaymentImpl = class {
|
|
|
681
760
|
* 推荐结果只作为可用性/金额计算输入,不会自动成为 selectedIds。
|
|
682
761
|
*/
|
|
683
762
|
async refreshWalletAssetsFromBusinessAsync(businessData, options = {}) {
|
|
763
|
+
var _a;
|
|
684
764
|
const requestSequence = ++this.walletAssetsRequestSequence;
|
|
685
765
|
const nextCustomerId = businessData.customer_id;
|
|
686
766
|
const previousCustomerId = this.walletAssetsState.customerId;
|
|
@@ -697,6 +777,44 @@ var WalletPassPaymentImpl = class {
|
|
|
697
777
|
);
|
|
698
778
|
const selectedIds = preserveSelection ? [...this.walletAssetsState.selectedIds] : [];
|
|
699
779
|
const selectionSources = preserveSelection ? { ...this.walletAssetsState.selectionSources } : {};
|
|
780
|
+
if (!((_a = businessData.products) == null ? void 0 : _a.length)) {
|
|
781
|
+
this.generateWalletParams(businessData);
|
|
782
|
+
const restoredSearchedAssets = this.searchResults.filter(isWalletPaymentAsset).map((item) => ({
|
|
783
|
+
...item,
|
|
784
|
+
actualDeduction: 0,
|
|
785
|
+
deductionDetails: [],
|
|
786
|
+
_available_max_amount: 0,
|
|
787
|
+
_unified_available_status: 0,
|
|
788
|
+
_wallet_asset_recommended: false
|
|
789
|
+
}));
|
|
790
|
+
this.walletRecommendList = [];
|
|
791
|
+
this.userIdentificationCodes = [];
|
|
792
|
+
this.walletInitData = {
|
|
793
|
+
transformList: [],
|
|
794
|
+
noApplicableVoucher: restoredSearchedAssets,
|
|
795
|
+
products: []
|
|
796
|
+
};
|
|
797
|
+
this.walletAssetsCalculationContext = {
|
|
798
|
+
orderTotalAmount: 0,
|
|
799
|
+
products: []
|
|
800
|
+
};
|
|
801
|
+
this.emitEvent(import_types.WalletPassHooks.OnUserIdentificationCodesUpdated, {
|
|
802
|
+
userIdentificationCodes: []
|
|
803
|
+
});
|
|
804
|
+
return this.publishWalletAssetsState({
|
|
805
|
+
status: "ready",
|
|
806
|
+
customerId: nextCustomerId,
|
|
807
|
+
items: mergeWalletAssets(
|
|
808
|
+
restoredSearchedAssets,
|
|
809
|
+
committedItems
|
|
810
|
+
),
|
|
811
|
+
selectedIds: [],
|
|
812
|
+
selectedItems: [],
|
|
813
|
+
selectionSources: {},
|
|
814
|
+
totalSelectedAmount: 0,
|
|
815
|
+
error: null
|
|
816
|
+
});
|
|
817
|
+
}
|
|
700
818
|
this.publishWalletAssetsState({
|
|
701
819
|
status: "loading",
|
|
702
820
|
customerId: nextCustomerId,
|
|
@@ -708,9 +826,13 @@ var WalletPassPaymentImpl = class {
|
|
|
708
826
|
error: null
|
|
709
827
|
});
|
|
710
828
|
try {
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
|
|
829
|
+
const searchedWalletAssetCodes = preserveSelection ? this.getSearchedWalletAssetCodes() : [];
|
|
830
|
+
const useAggregateRecalculate = preserveSelection && (selectedIds.length > 0 || searchedWalletAssetCodes.length > 0);
|
|
831
|
+
const aggregateResult = useAggregateRecalculate ? await this.aggregateRecalculateWalletAssetsAsync(
|
|
832
|
+
businessData,
|
|
833
|
+
selectedIds
|
|
834
|
+
) : null;
|
|
835
|
+
const result = aggregateResult || await this.initializeWalletDataFromBusinessAsync(businessData);
|
|
714
836
|
if (requestSequence !== this.walletAssetsRequestSequence) {
|
|
715
837
|
return this.getWalletAssetsState();
|
|
716
838
|
}
|
|
@@ -718,7 +840,27 @@ var WalletPassPaymentImpl = class {
|
|
|
718
840
|
orderTotalAmount: Number(businessData.order_wait_pay_amount || 0),
|
|
719
841
|
products: result.products || businessData.products || []
|
|
720
842
|
};
|
|
721
|
-
const
|
|
843
|
+
const authoritativeSelectedIds = (aggregateResult == null ? void 0 : aggregateResult.authoritativeSelectedIds) || selectedIds;
|
|
844
|
+
if (aggregateResult) {
|
|
845
|
+
const returnedAggregateKeys = new Set(
|
|
846
|
+
[
|
|
847
|
+
...result.transformList || [],
|
|
848
|
+
...result.noApplicableVoucher || []
|
|
849
|
+
].map((item) => getWalletAssetKey(item))
|
|
850
|
+
);
|
|
851
|
+
const missingSelectedKeys = new Set(
|
|
852
|
+
selectedIds.map((id) => String(id)).filter((id) => !returnedAggregateKeys.has(id))
|
|
853
|
+
);
|
|
854
|
+
if (missingSelectedKeys.size > 0) {
|
|
855
|
+
this.searchResults = this.searchResults.filter(
|
|
856
|
+
(item) => !missingSelectedKeys.has(getWalletAssetKey(item))
|
|
857
|
+
);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
const searchedWalletAssets = preserveSelection ? this.syncSearchedWalletAssets([
|
|
861
|
+
...result.transformList || [],
|
|
862
|
+
...result.noApplicableVoucher || []
|
|
863
|
+
]) : [];
|
|
722
864
|
if (requestSequence !== this.walletAssetsRequestSequence) {
|
|
723
865
|
return this.getWalletAssetsState();
|
|
724
866
|
}
|
|
@@ -728,7 +870,7 @@ var WalletPassPaymentImpl = class {
|
|
|
728
870
|
)
|
|
729
871
|
);
|
|
730
872
|
const items = mergeWalletAssets(
|
|
731
|
-
preserveSelection ? this.walletAssetsState.selectedItems : [],
|
|
873
|
+
preserveSelection && !aggregateResult ? this.walletAssetsState.selectedItems : [],
|
|
732
874
|
searchedWalletAssets,
|
|
733
875
|
result.transformList || [],
|
|
734
876
|
result.noApplicableVoucher || []
|
|
@@ -738,7 +880,7 @@ var WalletPassPaymentImpl = class {
|
|
|
738
880
|
getWalletAssetKey(asset)
|
|
739
881
|
)
|
|
740
882
|
}));
|
|
741
|
-
const latestSelectedIds = preserveSelection ?
|
|
883
|
+
const latestSelectedIds = preserveSelection ? authoritativeSelectedIds : [];
|
|
742
884
|
const latestSelectionSources = preserveSelection ? { ...this.walletAssetsState.selectionSources } : {};
|
|
743
885
|
return this.recalculateWalletAssets(
|
|
744
886
|
items,
|
|
@@ -749,6 +891,15 @@ var WalletPassPaymentImpl = class {
|
|
|
749
891
|
if (requestSequence !== this.walletAssetsRequestSequence) {
|
|
750
892
|
return this.getWalletAssetsState();
|
|
751
893
|
}
|
|
894
|
+
this.paymentModule.logError(
|
|
895
|
+
"[WalletPass] 刷新共享钱包资产失败,保留刷新前状态",
|
|
896
|
+
error,
|
|
897
|
+
{
|
|
898
|
+
customer_id: businessData.customer_id,
|
|
899
|
+
selected_ids: selectedIds,
|
|
900
|
+
searched_codes: this.getSearchedWalletAssetCodes()
|
|
901
|
+
}
|
|
902
|
+
);
|
|
752
903
|
return this.publishWalletAssetsState({
|
|
753
904
|
status: "error",
|
|
754
905
|
items: preserveSelection ? this.walletAssetsState.items : committedItems,
|
|
@@ -841,6 +992,17 @@ var WalletPassPaymentImpl = class {
|
|
|
841
992
|
state: this.getWalletAssetsState()
|
|
842
993
|
};
|
|
843
994
|
}
|
|
995
|
+
const selectedAsset = this.walletAssetsState.selectedItems.find(
|
|
996
|
+
(asset2) => matchesWalletAssetCode(asset2, normalizedCode)
|
|
997
|
+
);
|
|
998
|
+
if (selectedAsset) {
|
|
999
|
+
return {
|
|
1000
|
+
type: "normalCode",
|
|
1001
|
+
asset: selectedAsset,
|
|
1002
|
+
selected: true,
|
|
1003
|
+
state: this.getWalletAssetsState()
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
844
1006
|
this.walletAssetsRequestSequence += 1;
|
|
845
1007
|
const result = await this.searchIdentificationCodeAsync({
|
|
846
1008
|
...this.walletParams || {},
|
|
@@ -27,6 +27,8 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
|
|
|
27
27
|
}): {
|
|
28
28
|
isAvailable: boolean;
|
|
29
29
|
discountList: Discount[];
|
|
30
|
+
/** 完整规则计算后的列表;调用方可用于保留暂时无适用商品的扫码卡券。 */
|
|
31
|
+
evaluatedDiscountList?: Discount[];
|
|
30
32
|
productList: any[];
|
|
31
33
|
unavailableReason?: UnavailableReason;
|
|
32
34
|
};
|
|
@@ -94,7 +94,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
94
94
|
productList
|
|
95
95
|
};
|
|
96
96
|
}
|
|
97
|
-
if (productList.every((item) => {
|
|
97
|
+
if (productList.length > 0 && productList.every((item) => {
|
|
98
98
|
var _a;
|
|
99
99
|
const product = this.hooks.getProduct(item);
|
|
100
100
|
return product.booking_id && (((_a = product.discount_list) == null ? void 0 : _a.length) || product.total == 0);
|
|
@@ -152,6 +152,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
152
152
|
return {
|
|
153
153
|
isAvailable: hasApplicableDiscount,
|
|
154
154
|
discountList: hasApplicableDiscount ? result.discountList : oldDiscountList,
|
|
155
|
+
evaluatedDiscountList: result.discountList,
|
|
155
156
|
productList: hasApplicableDiscount ? result.productList : productList,
|
|
156
157
|
unavailableReason
|
|
157
158
|
};
|
|
@@ -181,9 +182,13 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
181
182
|
getUnavailableReason(discountList, productList) {
|
|
182
183
|
var _a;
|
|
183
184
|
for (const discount of discountList) {
|
|
184
|
-
|
|
185
|
+
const bookingTimes = productList.length ? productList.map((item) => {
|
|
185
186
|
const product = this.hooks.getProduct(item);
|
|
186
|
-
|
|
187
|
+
return ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format(
|
|
188
|
+
"YYYY-MM-DD HH:mm:ss"
|
|
189
|
+
);
|
|
190
|
+
}) : [(0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")];
|
|
191
|
+
for (const bookingTime of bookingTimes) {
|
|
187
192
|
const filteredList = (0, import_utils.filterDiscountListByBookingTime)([discount], bookingTime);
|
|
188
193
|
if (filteredList.length === 0) {
|
|
189
194
|
return import_types.UnavailableReason.TimeLimit;
|
|
@@ -1719,6 +1719,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1719
1719
|
}
|
|
1720
1720
|
return {
|
|
1721
1721
|
isAvailable: raw.isAvailable,
|
|
1722
|
+
...raw.isAccepted !== void 0 ? { isAccepted: raw.isAccepted } : {},
|
|
1722
1723
|
type: raw.type,
|
|
1723
1724
|
unavailableReason: raw.unavailableReason,
|
|
1724
1725
|
scannedDiscountList: raw.scannedDiscountList
|
|
@@ -439,8 +439,10 @@ export interface BaseSalesAddLogParams extends BaseSalesLogInput {
|
|
|
439
439
|
/** BaseSales.scanPromotionCode 对外的轻量结果(UI 可用 getDiscountList 或 scannedDiscountList 补 Holder) */
|
|
440
440
|
export interface BaseSalesScanCodeResult {
|
|
441
441
|
isAvailable: boolean;
|
|
442
|
+
/** 卡券已加入 Promotion;false 时可能是无效、过期或已使用。 */
|
|
443
|
+
isAccepted?: boolean;
|
|
442
444
|
type?: 'server' | string;
|
|
443
445
|
unavailableReason?: 'time_limit' | string;
|
|
444
|
-
/** batchSearch 原始结果;
|
|
446
|
+
/** batchSearch 原始结果;Holder 补全等流程可从这里读取原始卡券。 */
|
|
445
447
|
scannedDiscountList?: Discount[];
|
|
446
448
|
}
|