@pisell/pisellos 2.2.230 → 2.2.232
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.js +44 -29
- package/dist/modules/Order/types.d.ts +14 -2
- package/dist/modules/Order/types.js +8 -1
- package/dist/modules/ProductList/index.d.ts +9 -12
- package/dist/modules/ProductList/index.js +122 -59
- package/dist/modules/ProductList/types.d.ts +14 -0
- package/dist/server/index.d.ts +21 -0
- package/dist/server/index.js +154 -34
- package/dist/server/utils/small-ticket.js +113 -29
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +9 -1
- package/dist/solution/BookingTicket/index.js +198 -158
- package/dist/solution/BookingTicket/types.d.ts +4 -0
- package/dist/solution/BookingTicket/utils/cartView.js +20 -6
- package/dist/solution/BookingTicket/utils/resolveBestAddTimePlan.d.ts +189 -0
- package/dist/solution/BookingTicket/utils/resolveBestAddTimePlan.js +429 -0
- package/lib/model/strategy/adapter/promotion/index.js +0 -49
- package/lib/modules/Order/index.js +18 -5
- package/lib/modules/Order/types.d.ts +14 -2
- package/lib/modules/ProductList/index.d.ts +9 -12
- package/lib/modules/ProductList/index.js +32 -4
- package/lib/modules/ProductList/types.d.ts +14 -0
- package/lib/server/index.d.ts +21 -0
- package/lib/server/index.js +107 -9
- package/lib/server/utils/small-ticket.js +78 -1
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +9 -1
- package/lib/solution/BookingTicket/index.js +20 -1
- package/lib/solution/BookingTicket/types.d.ts +4 -0
- package/lib/solution/BookingTicket/utils/cartView.js +14 -7
- package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.d.ts +189 -0
- package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +241 -0
- package/package.json +1 -1
|
@@ -1,49 +0,0 @@
|
|
|
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
|
-
PromotionAdapter: () => import_adapter.PromotionAdapter,
|
|
34
|
-
PromotionEvaluator: () => import_evaluator.PromotionEvaluator,
|
|
35
|
-
X_ITEMS_FOR_Y_PRICE_STRATEGY: () => import_examples.X_ITEMS_FOR_Y_PRICE_STRATEGY,
|
|
36
|
-
default: () => import_adapter2.default
|
|
37
|
-
});
|
|
38
|
-
module.exports = __toCommonJS(promotion_exports);
|
|
39
|
-
var import_evaluator = require("./evaluator");
|
|
40
|
-
var import_adapter = require("./adapter");
|
|
41
|
-
var import_adapter2 = __toESM(require("./adapter"));
|
|
42
|
-
var import_examples = require("./examples");
|
|
43
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
44
|
-
0 && (module.exports = {
|
|
45
|
-
BUY_X_GET_Y_FREE_STRATEGY,
|
|
46
|
-
PromotionAdapter,
|
|
47
|
-
PromotionEvaluator,
|
|
48
|
-
X_ITEMS_FOR_Y_PRICE_STRATEGY
|
|
49
|
-
});
|
|
@@ -534,6 +534,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
534
534
|
* - 不主动调用 applyDiscount / recalculateSummary,调用方负责跟进。
|
|
535
535
|
*/
|
|
536
536
|
async applyPromotion() {
|
|
537
|
+
var _a;
|
|
537
538
|
if (this.isApplyingPromotion) {
|
|
538
539
|
return;
|
|
539
540
|
}
|
|
@@ -585,27 +586,39 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
585
586
|
if (addAction.giftOptions.length === 1) {
|
|
586
587
|
const sameStrategy = result.products.find(
|
|
587
588
|
(p) => {
|
|
588
|
-
var
|
|
589
|
-
return ((_b = (
|
|
589
|
+
var _a2, _b;
|
|
590
|
+
return ((_b = (_a2 = p.metadata) == null ? void 0 : _a2._giftInfo) == null ? void 0 : _b.strategyId) === addAction.strategyId;
|
|
590
591
|
}
|
|
591
592
|
);
|
|
592
|
-
if (sameStrategy) {
|
|
593
|
+
if (sameStrategy && !sameStrategy.booking_uid && !((_a = sameStrategy.metadata) == null ? void 0 : _a.booking_uid)) {
|
|
593
594
|
sameStrategy.num = (Number(sameStrategy.num) || 0) + (addAction.giftCount || 1);
|
|
594
595
|
continue;
|
|
595
596
|
}
|
|
596
597
|
}
|
|
597
598
|
try {
|
|
598
|
-
const
|
|
599
|
+
const giftResult = await this.giftSelectResolver({
|
|
599
600
|
strategyId: addAction.strategyId,
|
|
600
601
|
strategyName: addAction.strategyName,
|
|
601
602
|
giftCount: addAction.giftCount,
|
|
602
603
|
giftOptions: addAction.giftOptions,
|
|
603
604
|
sourceProductIds: addAction.sourceProductIds
|
|
604
605
|
});
|
|
606
|
+
const giftProducts = Array.isArray(giftResult) ? giftResult : giftResult == null ? void 0 : giftResult.products;
|
|
607
|
+
const giftBookings = Array.isArray(giftResult) ? [] : (giftResult == null ? void 0 : giftResult.bookings) || [];
|
|
605
608
|
if (Array.isArray(giftProducts) && giftProducts.length > 0) {
|
|
606
|
-
for (const gp of giftProducts) {
|
|
609
|
+
for (const [index, gp] of giftProducts.entries()) {
|
|
607
610
|
if (!gp)
|
|
608
611
|
continue;
|
|
612
|
+
const booking = giftBookings[index];
|
|
613
|
+
if (booking) {
|
|
614
|
+
const linked = this.createLinkedProductAndBooking({
|
|
615
|
+
product: gp,
|
|
616
|
+
booking
|
|
617
|
+
});
|
|
618
|
+
result.products.push(linked.product);
|
|
619
|
+
tempOrder.bookings = [...tempOrder.bookings || [], linked.booking];
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
609
622
|
result.products.push(gp);
|
|
610
623
|
}
|
|
611
624
|
}
|
|
@@ -47,6 +47,18 @@ export interface OrderGiftSelectContext {
|
|
|
47
47
|
/** 触发此赠品的主商品 metadata.unique_identification_number 列表 */
|
|
48
48
|
sourceProductIds: string[];
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* 赠品 resolver 返回值。
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* return { products: [giftProduct], bookings: [giftBooking] };
|
|
55
|
+
*/
|
|
56
|
+
export interface OrderGiftSelectResult {
|
|
57
|
+
/** 完整赠品购物车行,必须带 metadata._giftInfo。 */
|
|
58
|
+
products: Partial<OrderProduct>[];
|
|
59
|
+
/** 预约赠品对应的 booking,按 products 下标一一关联。 */
|
|
60
|
+
bookings?: AddProductBookingInput[];
|
|
61
|
+
}
|
|
50
62
|
/**
|
|
51
63
|
* 赠品解析回调签名(SDK → OS 的返回值)。
|
|
52
64
|
*
|
|
@@ -54,9 +66,9 @@ export interface OrderGiftSelectContext {
|
|
|
54
66
|
* - 多选项:SDK 弹窗等用户确认后构造
|
|
55
67
|
* - 用户取消:抛错或返回空数组(OS 视为放弃本次添加)
|
|
56
68
|
*
|
|
57
|
-
*
|
|
69
|
+
* 返回数组时沿用旧协议,只写 tempOrder.products;返回对象时可同时写入预约 bookings。
|
|
58
70
|
*/
|
|
59
|
-
export type OrderGiftSelectResolver = (ctx: OrderGiftSelectContext) => Promise<Partial<OrderProduct>[] | null>;
|
|
71
|
+
export type OrderGiftSelectResolver = (ctx: OrderGiftSelectContext) => Promise<Partial<OrderProduct>[] | OrderGiftSelectResult | null>;
|
|
60
72
|
/** 未满足的促销策略(购物车底部 alert 渲染源) */
|
|
61
73
|
export interface OrderUnfulfilledPromotion {
|
|
62
74
|
strategyId: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Module, PisellCore } from '../../types';
|
|
2
2
|
import { BaseModule } from '../BaseModule';
|
|
3
|
+
import { ProductListLoadProductsParams } from './types';
|
|
3
4
|
import { ProductData } from '../Product/types';
|
|
4
5
|
export * from './types';
|
|
5
6
|
export declare class ProductList extends BaseModule implements Module {
|
|
@@ -18,18 +19,14 @@ export declare class ProductList extends BaseModule implements Module {
|
|
|
18
19
|
*/
|
|
19
20
|
updateOtherParams(params: Record<string, any>): void;
|
|
20
21
|
storeChange(path?: string, value?: any): Promise<void>;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
schedule_datetime?: string;
|
|
30
|
-
with_count?: string[];
|
|
31
|
-
with_schedule?: number;
|
|
32
|
-
}, options?: {
|
|
22
|
+
/**
|
|
23
|
+
* 获取加时商品列表。
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const products = await productList.getAddTimeProducts({ schedule_date: '2026-06-16' });
|
|
27
|
+
*/
|
|
28
|
+
getAddTimeProducts(params?: ProductListLoadProductsParams): Promise<any>;
|
|
29
|
+
loadProducts({ category_ids, product_ids, collection, menu_list_ids, customer_id: paramsCustomerId, with_count, schedule_datetime, schedule_date, cacheId, with_schedule, extension_type, status, }?: ProductListLoadProductsParams, options?: {
|
|
33
30
|
callback?: (result: any) => void;
|
|
34
31
|
subscriberId?: string;
|
|
35
32
|
}): Promise<any>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
7
|
var __export = (target, all) => {
|
|
6
8
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
return to;
|
|
16
18
|
};
|
|
17
19
|
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/modules/ProductList/index.ts
|
|
@@ -25,6 +35,7 @@ __export(ProductList_exports, {
|
|
|
25
35
|
module.exports = __toCommonJS(ProductList_exports);
|
|
26
36
|
var import_BaseModule = require("../BaseModule");
|
|
27
37
|
var import_lodash_es = require("lodash-es");
|
|
38
|
+
var import_dayjs = __toESM(require("dayjs"));
|
|
28
39
|
__reExport(ProductList_exports, require("./types"), module.exports);
|
|
29
40
|
var ProductList = class extends import_BaseModule.BaseModule {
|
|
30
41
|
constructor(name, version) {
|
|
@@ -58,6 +69,20 @@ var ProductList = class extends import_BaseModule.BaseModule {
|
|
|
58
69
|
}
|
|
59
70
|
async storeChange(path, value) {
|
|
60
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* 获取加时商品列表。
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* const products = await productList.getAddTimeProducts({ schedule_date: '2026-06-16' });
|
|
77
|
+
*/
|
|
78
|
+
async getAddTimeProducts(params = {}) {
|
|
79
|
+
return this.loadProducts({
|
|
80
|
+
schedule_date: (0, import_dayjs.default)().format("YYYY-MM-DD"),
|
|
81
|
+
status: "published",
|
|
82
|
+
...params,
|
|
83
|
+
extension_type: ["product_add_time"]
|
|
84
|
+
});
|
|
85
|
+
}
|
|
61
86
|
async loadProducts({
|
|
62
87
|
category_ids = [],
|
|
63
88
|
product_ids = [],
|
|
@@ -68,8 +93,10 @@ var ProductList = class extends import_BaseModule.BaseModule {
|
|
|
68
93
|
schedule_datetime,
|
|
69
94
|
schedule_date,
|
|
70
95
|
cacheId,
|
|
71
|
-
with_schedule
|
|
72
|
-
|
|
96
|
+
with_schedule,
|
|
97
|
+
extension_type,
|
|
98
|
+
status = "published"
|
|
99
|
+
} = {}, options) {
|
|
73
100
|
var _a, _b;
|
|
74
101
|
let userPlugin = this.core.getPlugin("user");
|
|
75
102
|
let customer_id = void 0;
|
|
@@ -92,7 +119,7 @@ var ProductList = class extends import_BaseModule.BaseModule {
|
|
|
92
119
|
"event_item"
|
|
93
120
|
],
|
|
94
121
|
with: ["category", "collection", "resourceRelation"],
|
|
95
|
-
status
|
|
122
|
+
status,
|
|
96
123
|
num: 500,
|
|
97
124
|
skip: 1,
|
|
98
125
|
customer_id,
|
|
@@ -107,7 +134,8 @@ var ProductList = class extends import_BaseModule.BaseModule {
|
|
|
107
134
|
application_code: (_b = this.otherParams) == null ? void 0 : _b.channel,
|
|
108
135
|
is_eject: 1,
|
|
109
136
|
with_schedule,
|
|
110
|
-
schedule_datetime
|
|
137
|
+
schedule_datetime,
|
|
138
|
+
extension_type
|
|
111
139
|
},
|
|
112
140
|
{ osServer: true, callback: options == null ? void 0 : options.callback, subscriberId: options == null ? void 0 : options.subscriberId, customToast: () => {
|
|
113
141
|
} }
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
import { ProductData } from '../Product/types';
|
|
2
|
+
export interface ProductListLoadProductsParams {
|
|
3
|
+
category_ids?: number[];
|
|
4
|
+
product_ids?: number[];
|
|
5
|
+
collection?: number | string[];
|
|
6
|
+
schedule_date?: string;
|
|
7
|
+
cacheId?: string;
|
|
8
|
+
customer_id?: number;
|
|
9
|
+
menu_list_ids?: number[];
|
|
10
|
+
schedule_datetime?: string;
|
|
11
|
+
with_count?: string[];
|
|
12
|
+
with_schedule?: number;
|
|
13
|
+
extension_type?: string[];
|
|
14
|
+
status?: string;
|
|
15
|
+
}
|
|
2
16
|
export interface ProductListData {
|
|
3
17
|
list: ProductData[];
|
|
4
18
|
selectProducts: ProductData[];
|
package/lib/server/index.d.ts
CHANGED
|
@@ -496,6 +496,27 @@ declare class Server {
|
|
|
496
496
|
* 从订单中展开 bookings,再按条件筛选 + 分页
|
|
497
497
|
*/
|
|
498
498
|
private computeBookingQueryResult;
|
|
499
|
+
/**
|
|
500
|
+
* 规范商品扩展类型过滤参数。
|
|
501
|
+
*
|
|
502
|
+
* @example
|
|
503
|
+
* const types = this.normalizeProductExtensionTypes(['product_add_time']);
|
|
504
|
+
*/
|
|
505
|
+
private normalizeProductExtensionTypes;
|
|
506
|
+
/**
|
|
507
|
+
* 请求包含 product_add_time 时,按传入 extension_type 数组配置过滤商品。
|
|
508
|
+
*
|
|
509
|
+
* @example
|
|
510
|
+
* const list = this.filterProductsByExtensionTypes(products, ['product_add_time']);
|
|
511
|
+
*/
|
|
512
|
+
private filterProductsByExtensionTypes;
|
|
513
|
+
/**
|
|
514
|
+
* 判断本次查询是否需要跳过餐牌过滤,直接按扩展类型拉商品。
|
|
515
|
+
*
|
|
516
|
+
* @example
|
|
517
|
+
* const skipMenu = this.shouldQueryProductsByExtensionTypes(['product_add_time']);
|
|
518
|
+
*/
|
|
519
|
+
private shouldQueryProductsByExtensionTypes;
|
|
499
520
|
/**
|
|
500
521
|
* 商品查询的核心计算逻辑(编排 Products、Menu、Schedule 模块)
|
|
501
522
|
* 供 handleProductQuery 首次返回及 pubsub 变更推送复用
|
package/lib/server/index.js
CHANGED
|
@@ -208,26 +208,27 @@ var Server = class {
|
|
|
208
208
|
*/
|
|
209
209
|
this.handleProductQuery = async ({ url, method, data, config }) => {
|
|
210
210
|
console.log("[Server] handleProductQuery:", url, method, data, config);
|
|
211
|
-
const { menu_list_ids, schedule_datetime, schedule_date, customer_id, ids } = data;
|
|
211
|
+
const { menu_list_ids, schedule_datetime, schedule_date, customer_id, ids, extension_type } = data;
|
|
212
212
|
const { callback, subscriberId } = config || {};
|
|
213
213
|
this.logInfo("handleProductQuery: 开始处理商品查询请求", {
|
|
214
214
|
menu_list_ids,
|
|
215
215
|
ids,
|
|
216
216
|
schedule_datetime,
|
|
217
217
|
schedule_date,
|
|
218
|
-
customer_id
|
|
218
|
+
customer_id,
|
|
219
|
+
extension_type
|
|
219
220
|
});
|
|
220
221
|
if (subscriberId && typeof callback === "function") {
|
|
221
222
|
this.productQuerySubscribers.set(subscriberId, {
|
|
222
223
|
callback,
|
|
223
|
-
context: { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id }
|
|
224
|
+
context: { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type }
|
|
224
225
|
});
|
|
225
226
|
this.logInfo("handleProductQuery: 已注册订阅者", {
|
|
226
227
|
subscriberId,
|
|
227
228
|
totalSubscribers: this.productQuerySubscribers.size
|
|
228
229
|
});
|
|
229
230
|
}
|
|
230
|
-
return this.computeProductQueryResult({ menu_list_ids, ids, schedule_date, schedule_datetime, customer_id });
|
|
231
|
+
return this.computeProductQueryResult({ menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type });
|
|
231
232
|
};
|
|
232
233
|
/**
|
|
233
234
|
* 按商品 id 查询单条(GET /shop/product/query/:productId)
|
|
@@ -2573,6 +2574,7 @@ var Server = class {
|
|
|
2573
2574
|
if (!(0, import_small_ticket.hasSmallTicketData)((_a = printableOrder.payment_info) == null ? void 0 : _a.small_ticket_data)) {
|
|
2574
2575
|
return { printed: false, order: printableOrder };
|
|
2575
2576
|
}
|
|
2577
|
+
debugger;
|
|
2576
2578
|
await this.dispatchPrintOtherReceiptTask({
|
|
2577
2579
|
checkoutData: params.checkoutData,
|
|
2578
2580
|
syncedOrder: printableOrder,
|
|
@@ -3470,6 +3472,38 @@ var Server = class {
|
|
|
3470
3472
|
status: true
|
|
3471
3473
|
};
|
|
3472
3474
|
}
|
|
3475
|
+
/**
|
|
3476
|
+
* 规范商品扩展类型过滤参数。
|
|
3477
|
+
*
|
|
3478
|
+
* @example
|
|
3479
|
+
* const types = this.normalizeProductExtensionTypes(['product_add_time']);
|
|
3480
|
+
*/
|
|
3481
|
+
normalizeProductExtensionTypes(extension_type) {
|
|
3482
|
+
if (!Array.isArray(extension_type))
|
|
3483
|
+
return [];
|
|
3484
|
+
return extension_type.map((item) => String(item || "").trim()).filter(Boolean);
|
|
3485
|
+
}
|
|
3486
|
+
/**
|
|
3487
|
+
* 请求包含 product_add_time 时,按传入 extension_type 数组配置过滤商品。
|
|
3488
|
+
*
|
|
3489
|
+
* @example
|
|
3490
|
+
* const list = this.filterProductsByExtensionTypes(products, ['product_add_time']);
|
|
3491
|
+
*/
|
|
3492
|
+
filterProductsByExtensionTypes(products, extension_type) {
|
|
3493
|
+
const extensionTypes = this.normalizeProductExtensionTypes(extension_type);
|
|
3494
|
+
if (!extensionTypes.includes("product_add_time"))
|
|
3495
|
+
return products;
|
|
3496
|
+
return products.filter((product) => extensionTypes.includes(String((product == null ? void 0 : product.extension_type) || "")));
|
|
3497
|
+
}
|
|
3498
|
+
/**
|
|
3499
|
+
* 判断本次查询是否需要跳过餐牌过滤,直接按扩展类型拉商品。
|
|
3500
|
+
*
|
|
3501
|
+
* @example
|
|
3502
|
+
* const skipMenu = this.shouldQueryProductsByExtensionTypes(['product_add_time']);
|
|
3503
|
+
*/
|
|
3504
|
+
shouldQueryProductsByExtensionTypes(extension_type) {
|
|
3505
|
+
return this.normalizeProductExtensionTypes(extension_type).includes("product_add_time");
|
|
3506
|
+
}
|
|
3473
3507
|
/**
|
|
3474
3508
|
* 商品查询的核心计算逻辑(编排 Products、Menu、Schedule 模块)
|
|
3475
3509
|
* 供 handleProductQuery 首次返回及 pubsub 变更推送复用
|
|
@@ -3479,7 +3513,7 @@ var Server = class {
|
|
|
3479
3513
|
*/
|
|
3480
3514
|
async computeProductQueryResult(context, options) {
|
|
3481
3515
|
const tTotal = performance.now();
|
|
3482
|
-
const { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, product_id } = context;
|
|
3516
|
+
const { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type, product_id } = context;
|
|
3483
3517
|
const queryIds = Array.isArray(ids) ? ids.map((id) => Number(id)).filter((id) => Number.isFinite(id)) : [];
|
|
3484
3518
|
this.logInfo("computeProductQueryResult 开始", {
|
|
3485
3519
|
menuListIdsCount: (menu_list_ids == null ? void 0 : menu_list_ids.length) ?? 0,
|
|
@@ -3487,6 +3521,7 @@ var Server = class {
|
|
|
3487
3521
|
schedule_datetime,
|
|
3488
3522
|
schedule_date,
|
|
3489
3523
|
customer_id,
|
|
3524
|
+
extension_type,
|
|
3490
3525
|
product_id,
|
|
3491
3526
|
changedIds: options == null ? void 0 : options.changedIds
|
|
3492
3527
|
});
|
|
@@ -3510,18 +3545,19 @@ var Server = class {
|
|
|
3510
3545
|
ids: uniqueIds
|
|
3511
3546
|
});
|
|
3512
3547
|
const filteredProducts2 = productsWithPrice.filter((p) => uniqueIds.includes(Number(p == null ? void 0 : p.id))).filter((p) => ((p == null ? void 0 : p.status) || "published") === "published");
|
|
3548
|
+
const extensionFilteredProducts = this.filterProductsByExtensionTypes(filteredProducts2, extension_type);
|
|
3513
3549
|
(0, import_product.perfMark)("computeProductQueryResult", performance.now() - tTotal, {
|
|
3514
3550
|
mode: "ids",
|
|
3515
3551
|
ids: uniqueIds,
|
|
3516
|
-
count:
|
|
3552
|
+
count: extensionFilteredProducts.length
|
|
3517
3553
|
});
|
|
3518
3554
|
this.logInfo("computeProductQueryResult 完成(ids)", {
|
|
3519
3555
|
ids: uniqueIds,
|
|
3520
|
-
count:
|
|
3556
|
+
count: extensionFilteredProducts.length
|
|
3521
3557
|
});
|
|
3522
3558
|
return {
|
|
3523
3559
|
code: 200,
|
|
3524
|
-
data: { list:
|
|
3560
|
+
data: { list: extensionFilteredProducts, count: extensionFilteredProducts.length },
|
|
3525
3561
|
message: "",
|
|
3526
3562
|
status: true
|
|
3527
3563
|
};
|
|
@@ -3538,7 +3574,10 @@ var Server = class {
|
|
|
3538
3574
|
count: allProductsWithPrice.length,
|
|
3539
3575
|
productId: pid
|
|
3540
3576
|
});
|
|
3541
|
-
const published =
|
|
3577
|
+
const published = this.filterProductsByExtensionTypes(
|
|
3578
|
+
allProductsWithPrice.filter((p) => ((p == null ? void 0 : p.status) || "published") === "published"),
|
|
3579
|
+
extension_type
|
|
3580
|
+
);
|
|
3542
3581
|
const item = published.find((p) => Number(p.id) === pid) ?? null;
|
|
3543
3582
|
(0, import_product.perfMark)("computeProductQueryResult", performance.now() - tTotal, {
|
|
3544
3583
|
mode: "single",
|
|
@@ -3556,6 +3595,57 @@ var Server = class {
|
|
|
3556
3595
|
status: true
|
|
3557
3596
|
};
|
|
3558
3597
|
}
|
|
3598
|
+
if (this.shouldQueryProductsByExtensionTypes(extension_type)) {
|
|
3599
|
+
const tPrice2 = performance.now();
|
|
3600
|
+
let filteredProducts2 = await this.products.getProductsWithPrice(schedule_date, {
|
|
3601
|
+
scheduleModule: this.getSchedule(),
|
|
3602
|
+
schedule_datetime,
|
|
3603
|
+
customer_id
|
|
3604
|
+
}, {
|
|
3605
|
+
changedIds: options == null ? void 0 : options.changedIds
|
|
3606
|
+
});
|
|
3607
|
+
(0, import_product.perfMark)("computeQuery.getProductsWithPrice(extensionType)", performance.now() - tPrice2, {
|
|
3608
|
+
count: filteredProducts2.length,
|
|
3609
|
+
extension_type
|
|
3610
|
+
});
|
|
3611
|
+
const tStatus2 = performance.now();
|
|
3612
|
+
const beforeStatusCount2 = filteredProducts2.length;
|
|
3613
|
+
filteredProducts2 = filteredProducts2.filter((p) => ((p == null ? void 0 : p.status) || "published") === "published");
|
|
3614
|
+
(0, import_product.perfMark)("computeQuery.filterByStatus(extensionType)", performance.now() - tStatus2, {
|
|
3615
|
+
before: beforeStatusCount2,
|
|
3616
|
+
after: filteredProducts2.length
|
|
3617
|
+
});
|
|
3618
|
+
const tExtensionType2 = performance.now();
|
|
3619
|
+
const beforeExtensionTypeCount2 = filteredProducts2.length;
|
|
3620
|
+
filteredProducts2 = this.filterProductsByExtensionTypes(filteredProducts2, extension_type);
|
|
3621
|
+
(0, import_product.perfMark)("computeQuery.filterByExtensionType(extensionType)", performance.now() - tExtensionType2, {
|
|
3622
|
+
before: beforeExtensionTypeCount2,
|
|
3623
|
+
after: filteredProducts2.length,
|
|
3624
|
+
extension_type
|
|
3625
|
+
});
|
|
3626
|
+
const tSort2 = performance.now();
|
|
3627
|
+
filteredProducts2 = filteredProducts2.sort((a, b) => {
|
|
3628
|
+
const sortDiff = Number(b.sort) - Number(a.sort);
|
|
3629
|
+
if (sortDiff !== 0)
|
|
3630
|
+
return sortDiff;
|
|
3631
|
+
return (a.title || "").localeCompare(b.title || "");
|
|
3632
|
+
});
|
|
3633
|
+
(0, import_product.perfMark)("computeQuery.sort(extensionType)", performance.now() - tSort2, { count: filteredProducts2.length });
|
|
3634
|
+
(0, import_product.perfMark)("computeProductQueryResult", performance.now() - tTotal, {
|
|
3635
|
+
mode: "extensionType",
|
|
3636
|
+
filteredCount: filteredProducts2.length
|
|
3637
|
+
});
|
|
3638
|
+
this.logInfo("computeProductQueryResult 完成(extension_type)", {
|
|
3639
|
+
filteredCount: filteredProducts2.length,
|
|
3640
|
+
extension_type
|
|
3641
|
+
});
|
|
3642
|
+
return {
|
|
3643
|
+
code: 200,
|
|
3644
|
+
data: { list: filteredProducts2, count: filteredProducts2.length },
|
|
3645
|
+
message: "",
|
|
3646
|
+
status: true
|
|
3647
|
+
};
|
|
3648
|
+
}
|
|
3559
3649
|
if (!this.menu) {
|
|
3560
3650
|
this.logError("computeProductQueryResult: Menu 模块未注册");
|
|
3561
3651
|
return { message: "Menu 模块未注册", data: { list: [], count: 0 } };
|
|
@@ -3605,6 +3695,14 @@ var Server = class {
|
|
|
3605
3695
|
before: beforeStatusCount,
|
|
3606
3696
|
after: filteredProducts.length
|
|
3607
3697
|
});
|
|
3698
|
+
const tExtensionType = performance.now();
|
|
3699
|
+
const beforeExtensionTypeCount = filteredProducts.length;
|
|
3700
|
+
filteredProducts = this.filterProductsByExtensionTypes(filteredProducts, extension_type);
|
|
3701
|
+
(0, import_product.perfMark)("computeQuery.filterByExtensionType", performance.now() - tExtensionType, {
|
|
3702
|
+
before: beforeExtensionTypeCount,
|
|
3703
|
+
after: filteredProducts.length,
|
|
3704
|
+
extension_type
|
|
3705
|
+
});
|
|
3608
3706
|
const tSort = performance.now();
|
|
3609
3707
|
filteredProducts = filteredProducts.sort((a, b) => {
|
|
3610
3708
|
const sortDiff = Number(b.sort) - Number(a.sort);
|
|
@@ -183,6 +183,7 @@ function buildProducts(order, locale, productMap) {
|
|
|
183
183
|
currencySymbol,
|
|
184
184
|
parentProduct
|
|
185
185
|
});
|
|
186
|
+
const resolvedVariant = resolveProductVariantText({ product, parentProduct, locale });
|
|
186
187
|
return {
|
|
187
188
|
product_title: productTitle,
|
|
188
189
|
product_quantity: quantity,
|
|
@@ -191,7 +192,7 @@ function buildProducts(order, locale, productMap) {
|
|
|
191
192
|
total_original_price: formatMoney(new import_decimal.default(toMoneyNumber(originalPrice)).mul(quantity), currencySymbol),
|
|
192
193
|
extension_list: Array.isArray(product.extension_list) ? product.extension_list : [],
|
|
193
194
|
...options.length ? { options } : {},
|
|
194
|
-
...
|
|
195
|
+
...resolvedVariant ? { variant: resolvedVariant } : {},
|
|
195
196
|
...Array.isArray(product.combinations) ? { combinations: product.combinations } : combinations.length ? { combinations } : {}
|
|
196
197
|
};
|
|
197
198
|
});
|
|
@@ -267,6 +268,82 @@ function resolveProductFromMap(productId, productMap) {
|
|
|
267
268
|
return null;
|
|
268
269
|
return productMap[productId] || productMap[String(productId)] || null;
|
|
269
270
|
}
|
|
271
|
+
function resolveProductVariantText(params) {
|
|
272
|
+
const { product, parentProduct, locale } = params;
|
|
273
|
+
if (product.variant)
|
|
274
|
+
return getLocalizedValue(product.variant, locale);
|
|
275
|
+
if (!parentProduct)
|
|
276
|
+
return "";
|
|
277
|
+
const productVariantId = product.product_variant_id ?? product.variant_id;
|
|
278
|
+
if (!isNonZeroId(productVariantId))
|
|
279
|
+
return "";
|
|
280
|
+
const matchedVariant = normalizeArray(parentProduct.variant).find((variant) => isSameId(variant.id, productVariantId));
|
|
281
|
+
if (!matchedVariant)
|
|
282
|
+
return "";
|
|
283
|
+
const resolvedFromSkuKey = resolveVariantTextFromSkuKey({
|
|
284
|
+
skuKey: matchedVariant.sku_key,
|
|
285
|
+
parentProduct,
|
|
286
|
+
locale
|
|
287
|
+
});
|
|
288
|
+
if (resolvedFromSkuKey)
|
|
289
|
+
return resolvedFromSkuKey;
|
|
290
|
+
return resolveVariantTextFromNameMap({
|
|
291
|
+
nameMap: matchedVariant.name || matchedVariant.title,
|
|
292
|
+
parentProduct,
|
|
293
|
+
locale
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
function resolveVariantTextFromSkuKey(params) {
|
|
297
|
+
const skuKey = stringify(params.skuKey);
|
|
298
|
+
if (!skuKey)
|
|
299
|
+
return "";
|
|
300
|
+
return skuKey.split("_").map((item) => {
|
|
301
|
+
const [groupPositionId, itemPositionId] = item.split(":");
|
|
302
|
+
return resolveVariantTextItem({
|
|
303
|
+
parentProduct: params.parentProduct,
|
|
304
|
+
groupPositionId,
|
|
305
|
+
itemPositionId,
|
|
306
|
+
locale: params.locale
|
|
307
|
+
});
|
|
308
|
+
}).filter(Boolean).join(",");
|
|
309
|
+
}
|
|
310
|
+
function resolveVariantTextFromNameMap(params) {
|
|
311
|
+
if (!params.nameMap || typeof params.nameMap !== "object")
|
|
312
|
+
return "";
|
|
313
|
+
return Object.entries(params.nameMap).map(([groupPositionId, value]) => {
|
|
314
|
+
const group = resolveVariantGroup(params.parentProduct, groupPositionId);
|
|
315
|
+
if (!group)
|
|
316
|
+
return "";
|
|
317
|
+
const groupName = getLocalizedValue(group.name, params.locale);
|
|
318
|
+
const itemName = getLocalizedValue(value, params.locale);
|
|
319
|
+
if (!groupName || !itemName)
|
|
320
|
+
return "";
|
|
321
|
+
return `${groupName}:${itemName}`;
|
|
322
|
+
}).filter(Boolean).join(",");
|
|
323
|
+
}
|
|
324
|
+
function resolveVariantTextItem(params) {
|
|
325
|
+
const group = resolveVariantGroup(params.parentProduct, params.groupPositionId);
|
|
326
|
+
const item = resolveVariantItem(group, params.itemPositionId);
|
|
327
|
+
if (!group || !item)
|
|
328
|
+
return "";
|
|
329
|
+
const groupName = getLocalizedValue(group.name, params.locale);
|
|
330
|
+
const itemName = getLocalizedValue(item.name, params.locale);
|
|
331
|
+
if (!groupName || !itemName)
|
|
332
|
+
return "";
|
|
333
|
+
return `${groupName}:${itemName}`;
|
|
334
|
+
}
|
|
335
|
+
function resolveVariantGroup(parentProduct, groupPositionId) {
|
|
336
|
+
return normalizeArray(parentProduct.variant_group).find(
|
|
337
|
+
(group) => isSameId(group.position_id, groupPositionId) || isSameId(group.id, groupPositionId)
|
|
338
|
+
) || null;
|
|
339
|
+
}
|
|
340
|
+
function resolveVariantItem(group, itemPositionId) {
|
|
341
|
+
if (!group)
|
|
342
|
+
return null;
|
|
343
|
+
return normalizeArray(group.variant_item).find(
|
|
344
|
+
(item) => isSameId(item.position_id, itemPositionId) || isSameId(item.id, itemPositionId)
|
|
345
|
+
) || null;
|
|
346
|
+
}
|
|
270
347
|
function getProductTitleSource(source, locale) {
|
|
271
348
|
if (!source || typeof source !== "object")
|
|
272
349
|
return "";
|
|
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
311
311
|
date: string;
|
|
312
312
|
status: string;
|
|
313
313
|
week: string;
|
|
314
|
-
weekNum: 0 |
|
|
314
|
+
weekNum: 0 | 1 | 5 | 4 | 2 | 3 | 6;
|
|
315
315
|
}[]>;
|
|
316
316
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
317
317
|
private getScheduleDataByIds;
|
|
@@ -121,6 +121,13 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
121
121
|
callback?: (result: any) => void;
|
|
122
122
|
subscriberId?: string;
|
|
123
123
|
}): Promise<any>;
|
|
124
|
+
/**
|
|
125
|
+
* 获取加时商品列表。
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* const products = await bookingTicket.getAddTimeProducts({ schedule_date: '2026-06-16' });
|
|
129
|
+
*/
|
|
130
|
+
getAddTimeProducts(params?: ILoadProductsParams): Promise<ProductData[]>;
|
|
124
131
|
/**
|
|
125
132
|
* 只读查询单商品详情:走 ProductList 报价查询,但不写 productCatalog、
|
|
126
133
|
* 不 emit onProductsLoaded、不修改 BookingDate。
|
|
@@ -312,7 +319,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
312
319
|
* 获取当前的客户搜索条件
|
|
313
320
|
* @returns 当前搜索条件
|
|
314
321
|
*/
|
|
315
|
-
getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "
|
|
322
|
+
getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
|
|
316
323
|
/**
|
|
317
324
|
* 获取客户列表状态(包含滚动加载相关状态)
|
|
318
325
|
* @returns 客户状态
|
|
@@ -504,6 +511,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
504
511
|
* ```
|
|
505
512
|
*/
|
|
506
513
|
handleGlobalScanCode(code: string, bridge?: GlobalScanHostBridge): Promise<GlobalScanHandleResult>;
|
|
514
|
+
resolveBestAddTimePlan(addTimeProducts: any[], targetMinutes: number): any;
|
|
507
515
|
/**
|
|
508
516
|
* 销毁模块:先调用父类(销毁所有 store 内子模块 + emit destroy + super.destroy()),
|
|
509
517
|
* 再清理 BookingTicket 自有资源(scan 监听 + scan 内存缓存)。
|