@pisell/pisellos 2.2.153 → 2.2.154
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/core/index.js +1 -0
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/modules/Cart/utils/cartProduct.js +1 -1
- package/dist/modules/Order/index.d.ts +2 -0
- package/dist/modules/Order/index.js +231 -160
- package/dist/modules/Order/types.d.ts +19 -0
- package/dist/modules/Order/utils.js +7 -6
- package/dist/modules/Payment/index.d.ts +4 -0
- package/dist/modules/Payment/index.js +567 -505
- package/dist/modules/Payment/types.d.ts +29 -9
- package/dist/modules/SalesSummary/index.d.ts +7 -5
- package/dist/modules/SalesSummary/index.js +35 -11
- package/dist/plugins/app.d.ts +2 -0
- package/dist/server/index.d.ts +2 -5
- package/dist/server/index.js +58 -66
- package/dist/server/modules/index.d.ts +1 -1
- package/dist/server/modules/products/index.d.ts +12 -1
- package/dist/server/modules/products/index.js +169 -78
- package/dist/server/modules/products/types.d.ts +11 -0
- package/dist/server/modules/products/types.js +4 -0
- package/dist/server/utils/product.js +2 -2
- package/dist/solution/BaseSales/index.d.ts +26 -2
- package/dist/solution/BaseSales/index.js +342 -112
- package/dist/solution/BaseSales/types.d.ts +4 -4
- package/dist/solution/BaseSales/types.js +4 -4
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +62 -0
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +116 -0
- package/dist/solution/BaseSales/utils.js +3 -3
- package/dist/solution/BookingTicket/index.d.ts +11 -13
- package/dist/solution/BookingTicket/index.js +23 -37
- package/dist/solution/BookingTicket/types.d.ts +9 -6
- package/dist/solution/BookingTicket/types.js +6 -3
- package/dist/solution/BookingTicket/utils/cartView.d.ts +7 -12
- package/dist/solution/BookingTicket/utils/cartView.js +52 -14
- package/dist/solution/BookingTicket/utils/orderCustomer.d.ts +4 -0
- package/dist/solution/BookingTicket/utils/orderCustomer.js +31 -0
- package/dist/solution/Sales/index.d.ts +3 -0
- package/dist/solution/Sales/index.js +85 -43
- package/dist/solution/Sales/types.d.ts +3 -0
- package/dist/solution/ScanOrder/types.d.ts +4 -4
- package/dist/solution/ScanOrder/types.js +4 -4
- package/dist/solution/ScanOrder/utils.js +3 -3
- package/lib/core/index.js +1 -0
- package/lib/modules/Cart/utils/cartProduct.js +1 -1
- package/lib/modules/Order/index.d.ts +2 -0
- package/lib/modules/Order/index.js +39 -7
- package/lib/modules/Order/types.d.ts +19 -0
- package/lib/modules/Order/utils.js +4 -2
- package/lib/modules/Payment/index.d.ts +4 -0
- package/lib/modules/Payment/index.js +26 -2
- package/lib/modules/Payment/types.d.ts +29 -9
- package/lib/modules/SalesSummary/index.d.ts +7 -5
- package/lib/modules/SalesSummary/index.js +29 -9
- package/lib/plugins/app.d.ts +2 -0
- package/lib/server/index.d.ts +2 -5
- package/lib/server/index.js +38 -58
- package/lib/server/modules/index.d.ts +1 -1
- package/lib/server/modules/products/index.d.ts +12 -1
- package/lib/server/modules/products/index.js +69 -9
- package/lib/server/modules/products/types.d.ts +11 -0
- package/lib/server/utils/product.js +2 -2
- package/lib/solution/BaseSales/index.d.ts +26 -2
- package/lib/solution/BaseSales/index.js +169 -3
- package/lib/solution/BaseSales/types.d.ts +4 -4
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +62 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +155 -0
- package/lib/solution/BaseSales/utils.js +3 -3
- package/lib/solution/BookingTicket/index.d.ts +11 -13
- package/lib/solution/BookingTicket/index.js +17 -27
- package/lib/solution/BookingTicket/types.d.ts +9 -6
- package/lib/solution/BookingTicket/utils/cartView.d.ts +7 -12
- package/lib/solution/BookingTicket/utils/cartView.js +44 -18
- package/lib/solution/BookingTicket/utils/orderCustomer.d.ts +4 -0
- package/lib/solution/BookingTicket/utils/orderCustomer.js +58 -0
- package/lib/solution/Sales/index.d.ts +3 -0
- package/lib/solution/Sales/index.js +50 -15
- package/lib/solution/Sales/types.d.ts +3 -0
- package/lib/solution/ScanOrder/types.d.ts +4 -4
- package/lib/solution/ScanOrder/utils.js +3 -3
- package/package.json +1 -1
|
@@ -349,6 +349,18 @@ export interface EftposPayment {
|
|
|
349
349
|
/**
|
|
350
350
|
* 钱包支付接口
|
|
351
351
|
*/
|
|
352
|
+
export interface WalletInitializationResult {
|
|
353
|
+
walletRecommendList: WalletRecommendItem[];
|
|
354
|
+
userIdentificationCodes: UserIdentificationCodeItem[];
|
|
355
|
+
transformList: any[];
|
|
356
|
+
noApplicableVoucher: any[];
|
|
357
|
+
products: any[];
|
|
358
|
+
}
|
|
359
|
+
export interface WalletStoredInitData {
|
|
360
|
+
transformList: any[];
|
|
361
|
+
noApplicableVoucher: any[];
|
|
362
|
+
products: any[];
|
|
363
|
+
}
|
|
352
364
|
export interface WalletPassPayment {
|
|
353
365
|
/** 生成钱包API默认参数 */
|
|
354
366
|
generateWalletParams: (businessData: WalletInitBusinessData) => WalletDeductionRecommendParams;
|
|
@@ -357,21 +369,25 @@ export interface WalletPassPayment {
|
|
|
357
369
|
/** 清理已存储的钱包参数 */
|
|
358
370
|
clearStoredWalletParams: () => void;
|
|
359
371
|
/** 初始化钱包数据(从业务数据开始,内部生成参数) */
|
|
360
|
-
initializeWalletDataFromBusinessAsync: (businessData: WalletInitBusinessData) => Promise<
|
|
361
|
-
walletRecommendList: WalletRecommendItem[];
|
|
362
|
-
userIdentificationCodes: UserIdentificationCodeItem[];
|
|
363
|
-
}>;
|
|
372
|
+
initializeWalletDataFromBusinessAsync: (businessData: WalletInitBusinessData) => Promise<WalletInitializationResult>;
|
|
364
373
|
/** 初始化钱包数据(先获取推荐列表,再获取用户识别码列表) */
|
|
365
|
-
initializeWalletDataAsync: (baseParams: WalletDeductionRecommendParams) => Promise<
|
|
366
|
-
walletRecommendList: WalletRecommendItem[];
|
|
367
|
-
userIdentificationCodes: UserIdentificationCodeItem[];
|
|
368
|
-
}>;
|
|
374
|
+
initializeWalletDataAsync: (baseParams: WalletDeductionRecommendParams) => Promise<WalletInitializationResult>;
|
|
369
375
|
/** 获取钱包推荐扣款列表(异步获取并缓存) */
|
|
370
376
|
getWalletPassRecommendListAsync: (params: WalletDeductionRecommendParams) => Promise<WalletRecommendItem[]>;
|
|
371
377
|
/** 查询用户识别码列表(异步获取并缓存) */
|
|
372
378
|
getUserIdentificationCodeListAsync: (params: UserIdentificationCodeParams) => Promise<UserIdentificationCodeItem[]>;
|
|
373
379
|
/** 搜索识别码信息 */
|
|
374
|
-
searchIdentificationCodeAsync: (params: SearchIdentificationCodeParams
|
|
380
|
+
searchIdentificationCodeAsync: (params: SearchIdentificationCodeParams, config?: {
|
|
381
|
+
noCache?: boolean;
|
|
382
|
+
}) => Promise<SearchIdentificationCodeResult>;
|
|
383
|
+
/** 将推荐钱包列表转换为 prepare_payments */
|
|
384
|
+
formatWalletPassList2PreparePayments: (list: WalletRecommendItem[]) => {
|
|
385
|
+
voucher_id: number;
|
|
386
|
+
amount: number;
|
|
387
|
+
tag: string;
|
|
388
|
+
wallet_pass_usage_unit?: unknown;
|
|
389
|
+
wallet_pass_use_value?: string | number | null;
|
|
390
|
+
}[];
|
|
375
391
|
/** 获取缓存的搜索结果列表 */
|
|
376
392
|
getSearchResults: () => SearchIdentificationCodeItem[];
|
|
377
393
|
/** 根据识别码查找搜索结果 */
|
|
@@ -384,6 +400,10 @@ export interface WalletPassPayment {
|
|
|
384
400
|
clearWalletRecommendList: () => void;
|
|
385
401
|
/** 清除用户识别码列表 */
|
|
386
402
|
clearUserIdentificationCodes: () => void;
|
|
403
|
+
/** 获取缓存的钱包初始化数据 */
|
|
404
|
+
getStoredWalletInitData: () => WalletStoredInitData | null;
|
|
405
|
+
/** 清除缓存的钱包初始化数据 */
|
|
406
|
+
clearStoredWalletInitData: () => void;
|
|
387
407
|
/** 清除搜索结果缓存 */
|
|
388
408
|
clearSearchResults: () => void;
|
|
389
409
|
/** 清除所有缓存数据 */
|
|
@@ -5,20 +5,22 @@ export * from './types';
|
|
|
5
5
|
export declare class SalesSummaryModule extends BaseModule implements Module, SalesSummaryModuleAPI {
|
|
6
6
|
protected defaultName: string;
|
|
7
7
|
protected defaultVersion: string;
|
|
8
|
-
private
|
|
8
|
+
private appPlugin;
|
|
9
9
|
private store;
|
|
10
10
|
private request;
|
|
11
11
|
constructor(name?: string, version?: string);
|
|
12
12
|
initialize(core: PisellCore, options: ModuleOptions): Promise<void>;
|
|
13
13
|
getSurchargeList(): Promise<void>;
|
|
14
|
+
private getAppData;
|
|
15
|
+
private getTaxConfig;
|
|
14
16
|
getSummary(params: {
|
|
15
17
|
products: any[];
|
|
16
18
|
isPriceIncludeTax?: number;
|
|
17
19
|
taxRate?: number;
|
|
18
20
|
shopDiscount?: string | number;
|
|
19
21
|
}): Promise<{
|
|
20
|
-
tax_title:
|
|
21
|
-
tax_rate:
|
|
22
|
+
tax_title: string;
|
|
23
|
+
tax_rate: number | undefined;
|
|
22
24
|
product_quantity: number;
|
|
23
25
|
product_original_amount: string;
|
|
24
26
|
product_amount: string;
|
|
@@ -42,8 +44,8 @@ export declare class SalesSummaryModule extends BaseModule implements Module, Sa
|
|
|
42
44
|
pay_service_charge_amount: string;
|
|
43
45
|
is_price_include_tax?: number | undefined;
|
|
44
46
|
} | {
|
|
45
|
-
tax_title:
|
|
46
|
-
tax_rate:
|
|
47
|
+
tax_title: string;
|
|
48
|
+
tax_rate: number | undefined;
|
|
47
49
|
product_quantity: number;
|
|
48
50
|
product_original_amount: string;
|
|
49
51
|
product_amount: string;
|
|
@@ -27,6 +27,11 @@ var import_BaseModule = require("../BaseModule");
|
|
|
27
27
|
var import_Schedule = require("../Schedule");
|
|
28
28
|
var import_utils = require("./utils");
|
|
29
29
|
__reExport(SalesSummary_exports, require("./types"), module.exports);
|
|
30
|
+
var salesSummaryDataKeys = {
|
|
31
|
+
isPriceIncludeTax: "is_price_include_tax",
|
|
32
|
+
taxRate: "tax_rate",
|
|
33
|
+
taxTitle: "tax_title"
|
|
34
|
+
};
|
|
30
35
|
var SalesSummaryModule = class extends import_BaseModule.BaseModule {
|
|
31
36
|
constructor(name, version) {
|
|
32
37
|
super(name, version);
|
|
@@ -37,12 +42,12 @@ var SalesSummaryModule = class extends import_BaseModule.BaseModule {
|
|
|
37
42
|
var _a, _b;
|
|
38
43
|
this.core = core;
|
|
39
44
|
this.store = options.store;
|
|
40
|
-
this.
|
|
45
|
+
this.appPlugin = this.core.getPlugin("app");
|
|
41
46
|
this.request = this.core.getPlugin("request");
|
|
42
47
|
this.store.surchargeList = ((_a = options.initialState) == null ? void 0 : _a.surchargeList) || [];
|
|
43
48
|
this.store.summary = ((_b = options.initialState) == null ? void 0 : _b.summary) || (0, import_utils.createEmptySalesSummary)();
|
|
44
|
-
if (!this.
|
|
45
|
-
throw new Error("SalesSummaryModule 需要
|
|
49
|
+
if (!this.appPlugin) {
|
|
50
|
+
throw new Error("SalesSummaryModule 需要 app 插件支持");
|
|
46
51
|
}
|
|
47
52
|
if (!this.request) {
|
|
48
53
|
throw new Error("SalesSummaryModule 需要 request 插件支持");
|
|
@@ -66,10 +71,25 @@ var SalesSummaryModule = class extends import_BaseModule.BaseModule {
|
|
|
66
71
|
this.store.surchargeList = [];
|
|
67
72
|
}
|
|
68
73
|
}
|
|
74
|
+
getAppData(key) {
|
|
75
|
+
var _a, _b, _c, _d, _e, _f;
|
|
76
|
+
const getData = (_b = (_a = this.appPlugin).getData) == null ? void 0 : _b.call(_a);
|
|
77
|
+
if (typeof getData === "function")
|
|
78
|
+
return getData(key);
|
|
79
|
+
const app = this.appPlugin.getApp();
|
|
80
|
+
const coreData = (_f = (_d = (_c = app == null ? void 0 : app.models) == null ? void 0 : _c.getStore) == null ? void 0 : (_e = _d.call(_c)).getDataByModel) == null ? void 0 : _f.call(_e, "core", "core");
|
|
81
|
+
return coreData == null ? void 0 : coreData[key];
|
|
82
|
+
}
|
|
83
|
+
getTaxConfig() {
|
|
84
|
+
return {
|
|
85
|
+
isPriceIncludeTax: this.getAppData(salesSummaryDataKeys.isPriceIncludeTax),
|
|
86
|
+
taxRate: this.getAppData(salesSummaryDataKeys.taxRate),
|
|
87
|
+
taxTitle: this.getAppData(salesSummaryDataKeys.taxTitle)
|
|
88
|
+
};
|
|
89
|
+
}
|
|
69
90
|
async getSummary(params) {
|
|
70
|
-
var _a, _b;
|
|
71
91
|
const { products = [], isPriceIncludeTax, taxRate, shopDiscount } = params;
|
|
72
|
-
const
|
|
92
|
+
const taxConfig = this.getTaxConfig();
|
|
73
93
|
const summarySchedule = this.core.getModule(
|
|
74
94
|
`${this.name.split("_")[0]}_schedule`
|
|
75
95
|
);
|
|
@@ -83,8 +103,8 @@ var SalesSummaryModule = class extends import_BaseModule.BaseModule {
|
|
|
83
103
|
}
|
|
84
104
|
const summary = (0, import_utils.calculateSalesSummary)({
|
|
85
105
|
products,
|
|
86
|
-
isPriceIncludeTax: isPriceIncludeTax ??
|
|
87
|
-
taxRate: taxRate ??
|
|
106
|
+
isPriceIncludeTax: isPriceIncludeTax ?? taxConfig.isPriceIncludeTax ?? 1,
|
|
107
|
+
taxRate: taxRate ?? taxConfig.taxRate,
|
|
88
108
|
surchargeList: this.store.surchargeList,
|
|
89
109
|
scheduleById,
|
|
90
110
|
isInScheduleByDate: import_Schedule.ScheduleModule.isInScheduleByDate,
|
|
@@ -92,8 +112,8 @@ var SalesSummaryModule = class extends import_BaseModule.BaseModule {
|
|
|
92
112
|
});
|
|
93
113
|
const summaryWithTaxMeta = {
|
|
94
114
|
...summary,
|
|
95
|
-
tax_title:
|
|
96
|
-
tax_rate: taxRate ??
|
|
115
|
+
tax_title: taxConfig.taxTitle || "",
|
|
116
|
+
tax_rate: taxRate ?? taxConfig.taxRate
|
|
97
117
|
};
|
|
98
118
|
this.store.summary = summaryWithTaxMeta;
|
|
99
119
|
return summaryWithTaxMeta;
|
package/lib/plugins/app.d.ts
CHANGED
package/lib/server/index.d.ts
CHANGED
|
@@ -372,13 +372,10 @@ declare class Server {
|
|
|
372
372
|
*/
|
|
373
373
|
private recomputeAndNotifyBookingQuery;
|
|
374
374
|
/**
|
|
375
|
-
*
|
|
376
|
-
* @param products 所有商品列表
|
|
377
|
-
* @param activeMenuList 生效的餐牌列表
|
|
378
|
-
* @returns 过滤后的商品列表
|
|
375
|
+
* 根据餐牌配置提取轻量商品范围。
|
|
379
376
|
* @private
|
|
380
377
|
*/
|
|
381
|
-
private
|
|
378
|
+
private getProductScopeByMenuConfig;
|
|
382
379
|
/**
|
|
383
380
|
* 记录信息日志
|
|
384
381
|
* @param title 日志标题
|
package/lib/server/index.js
CHANGED
|
@@ -2060,16 +2060,16 @@ var Server = class {
|
|
|
2060
2060
|
if (product_id != null && Number.isFinite(Number(product_id))) {
|
|
2061
2061
|
const pid = Number(product_id);
|
|
2062
2062
|
const tPrice2 = performance.now();
|
|
2063
|
-
const
|
|
2063
|
+
const allProductsWithPrice = await this.products.getProductsWithPrice(schedule_date, {
|
|
2064
2064
|
scheduleModule: this.getSchedule()
|
|
2065
2065
|
}, {
|
|
2066
2066
|
changedIds: options == null ? void 0 : options.changedIds
|
|
2067
2067
|
});
|
|
2068
2068
|
(0, import_product.perfMark)("computeQuery.getProductsWithPrice(single)", performance.now() - tPrice2, {
|
|
2069
|
-
count:
|
|
2069
|
+
count: allProductsWithPrice.length,
|
|
2070
2070
|
productId: pid
|
|
2071
2071
|
});
|
|
2072
|
-
const published =
|
|
2072
|
+
const published = allProductsWithPrice.filter((p) => ((p == null ? void 0 : p.status) || "published") === "published");
|
|
2073
2073
|
const item = published.find((p) => Number(p.id) === pid) ?? null;
|
|
2074
2074
|
(0, import_product.perfMark)("computeProductQueryResult", performance.now() - tTotal, {
|
|
2075
2075
|
mode: "single",
|
|
@@ -2108,22 +2108,26 @@ var Server = class {
|
|
|
2108
2108
|
activeMenu: activeMenuList.length
|
|
2109
2109
|
});
|
|
2110
2110
|
}
|
|
2111
|
+
const tFilter = performance.now();
|
|
2112
|
+
const productScope = this.getProductScopeByMenuConfig(activeMenuList);
|
|
2113
|
+
const scopedProductIds = this.products.getProductIdsByScope(productScope);
|
|
2114
|
+
(0, import_product.perfMark)("computeQuery.filterByMenu", performance.now() - tFilter, {
|
|
2115
|
+
scopedProductCount: scopedProductIds.length,
|
|
2116
|
+
activeMenuCount: activeMenuList.length,
|
|
2117
|
+
isAllProducts: !!productScope.isAllProducts
|
|
2118
|
+
});
|
|
2111
2119
|
const tPrice = performance.now();
|
|
2112
|
-
|
|
2120
|
+
let filteredProducts = scopedProductIds.length > 0 ? await this.products.getProductsWithPrice(schedule_date, {
|
|
2113
2121
|
scheduleModule: this.getSchedule(),
|
|
2114
2122
|
schedule_datetime,
|
|
2115
2123
|
customer_id
|
|
2116
2124
|
}, {
|
|
2117
|
-
changedIds: options == null ? void 0 : options.changedIds
|
|
2118
|
-
|
|
2125
|
+
changedIds: options == null ? void 0 : options.changedIds,
|
|
2126
|
+
productIds: productScope.isAllProducts ? void 0 : scopedProductIds
|
|
2127
|
+
}) : [];
|
|
2119
2128
|
(0, import_product.perfMark)("computeQuery.getProductsWithPrice", performance.now() - tPrice, {
|
|
2120
|
-
count:
|
|
2121
|
-
|
|
2122
|
-
const tFilter = performance.now();
|
|
2123
|
-
let filteredProducts = this.filterProductsByMenuConfig(allProductsWithPrice, activeMenuList);
|
|
2124
|
-
(0, import_product.perfMark)("computeQuery.filterByMenu", performance.now() - tFilter, {
|
|
2125
|
-
before: allProductsWithPrice.length,
|
|
2126
|
-
after: filteredProducts.length
|
|
2129
|
+
count: filteredProducts.length,
|
|
2130
|
+
scopedProductCount: scopedProductIds.length
|
|
2127
2131
|
});
|
|
2128
2132
|
const tStatus = performance.now();
|
|
2129
2133
|
const beforeStatusCount = filteredProducts.length;
|
|
@@ -2141,12 +2145,12 @@ var Server = class {
|
|
|
2141
2145
|
});
|
|
2142
2146
|
(0, import_product.perfMark)("computeQuery.sort", performance.now() - tSort, { count: filteredProducts.length });
|
|
2143
2147
|
(0, import_product.perfMark)("computeProductQueryResult", performance.now() - tTotal, {
|
|
2144
|
-
|
|
2148
|
+
scopedProductCount: scopedProductIds.length,
|
|
2145
2149
|
filteredCount: filteredProducts.length,
|
|
2146
2150
|
activeMenuCount: activeMenuList.length
|
|
2147
2151
|
});
|
|
2148
2152
|
this.logInfo("computeProductQueryResult 完成", {
|
|
2149
|
-
|
|
2153
|
+
scopedProductCount: scopedProductIds.length,
|
|
2150
2154
|
filteredCount: filteredProducts.length,
|
|
2151
2155
|
activeMenuCount: activeMenuList.length
|
|
2152
2156
|
});
|
|
@@ -2249,29 +2253,25 @@ var Server = class {
|
|
|
2249
2253
|
}
|
|
2250
2254
|
}
|
|
2251
2255
|
/**
|
|
2252
|
-
*
|
|
2253
|
-
* @param products 所有商品列表
|
|
2254
|
-
* @param activeMenuList 生效的餐牌列表
|
|
2255
|
-
* @returns 过滤后的商品列表
|
|
2256
|
+
* 根据餐牌配置提取轻量商品范围。
|
|
2256
2257
|
* @private
|
|
2257
2258
|
*/
|
|
2258
|
-
|
|
2259
|
+
getProductScopeByMenuConfig(activeMenuList) {
|
|
2259
2260
|
if (!activeMenuList || activeMenuList.length === 0) {
|
|
2260
2261
|
console.log("[Server] 没有生效的餐牌,返回空数组");
|
|
2261
|
-
this.logInfo("
|
|
2262
|
-
productCount: products.length,
|
|
2262
|
+
this.logInfo("getProductScopeByMenuConfig: 没有生效的餐牌,返回空数组", {
|
|
2263
2263
|
activeMenuCount: 0
|
|
2264
2264
|
});
|
|
2265
|
-
return [];
|
|
2265
|
+
return { productIds: [], collectionIds: [] };
|
|
2266
2266
|
}
|
|
2267
|
-
|
|
2268
|
-
|
|
2267
|
+
const allowedProductIds = /* @__PURE__ */ new Set();
|
|
2268
|
+
const allowedCollectionIds = /* @__PURE__ */ new Set();
|
|
2269
2269
|
let hasProductAll = false;
|
|
2270
2270
|
for (const menu of activeMenuList) {
|
|
2271
2271
|
const config = menu.partyroom_package;
|
|
2272
2272
|
if (!config) {
|
|
2273
2273
|
console.warn("[Server] 餐牌缺少 partyroom_package 配置:", menu);
|
|
2274
|
-
this.logWarning("
|
|
2274
|
+
this.logWarning("getProductScopeByMenuConfig: 餐牌缺少 partyroom_package 配置", {
|
|
2275
2275
|
menuId: menu.form_record_id,
|
|
2276
2276
|
menuName: menu.name
|
|
2277
2277
|
});
|
|
@@ -2279,7 +2279,7 @@ var Server = class {
|
|
|
2279
2279
|
}
|
|
2280
2280
|
if (config.type === "product_all") {
|
|
2281
2281
|
console.log("[Server] 餐牌允许所有商品:", menu.name);
|
|
2282
|
-
this.logInfo("
|
|
2282
|
+
this.logInfo("getProductScopeByMenuConfig: 餐牌允许所有商品", {
|
|
2283
2283
|
menuId: menu.form_record_id,
|
|
2284
2284
|
menuName: menu.name,
|
|
2285
2285
|
configType: config.type
|
|
@@ -2291,7 +2291,7 @@ var Server = class {
|
|
|
2291
2291
|
const productIds = config.products.map((item) => item.product_id);
|
|
2292
2292
|
productIds.forEach((id) => id && allowedProductIds.add(id));
|
|
2293
2293
|
console.log("[Server] 餐牌允许指定商品 (product_ids):", menu.name, productIds);
|
|
2294
|
-
this.logInfo("
|
|
2294
|
+
this.logInfo("getProductScopeByMenuConfig: 餐牌允许指定商品", {
|
|
2295
2295
|
menuId: menu.form_record_id,
|
|
2296
2296
|
menuName: menu.name,
|
|
2297
2297
|
configType: config.type,
|
|
@@ -2302,7 +2302,7 @@ var Server = class {
|
|
|
2302
2302
|
const collectionIds = config.products.map((item) => item.product_collection_id);
|
|
2303
2303
|
collectionIds.forEach((id) => id && allowedCollectionIds.add(id));
|
|
2304
2304
|
console.log("[Server] 餐牌允许商品集合 (product_collection):", menu.name, collectionIds);
|
|
2305
|
-
this.logInfo("
|
|
2305
|
+
this.logInfo("getProductScopeByMenuConfig: 餐牌允许商品集合", {
|
|
2306
2306
|
menuId: menu.form_record_id,
|
|
2307
2307
|
menuName: menu.name,
|
|
2308
2308
|
configType: config.type,
|
|
@@ -2311,48 +2311,28 @@ var Server = class {
|
|
|
2311
2311
|
}
|
|
2312
2312
|
}
|
|
2313
2313
|
if (hasProductAll) {
|
|
2314
|
-
this.logInfo("
|
|
2315
|
-
|
|
2316
|
-
});
|
|
2317
|
-
return products;
|
|
2314
|
+
this.logInfo("getProductScopeByMenuConfig: 返回所有商品 scope(product_all)");
|
|
2315
|
+
return { isAllProducts: true };
|
|
2318
2316
|
}
|
|
2319
2317
|
if (allowedProductIds.size === 0 && allowedCollectionIds.size === 0) {
|
|
2320
2318
|
console.log("[Server] 没有允许的商品和集合");
|
|
2321
|
-
this.logWarning("
|
|
2322
|
-
productCount: products.length,
|
|
2319
|
+
this.logWarning("getProductScopeByMenuConfig: 没有允许的商品和集合", {
|
|
2323
2320
|
activeMenuCount: activeMenuList.length
|
|
2324
2321
|
});
|
|
2325
|
-
return [];
|
|
2322
|
+
return { productIds: [], collectionIds: [] };
|
|
2326
2323
|
}
|
|
2327
2324
|
const allowedProductIdsArray = Array.from(allowedProductIds);
|
|
2328
2325
|
const allowedCollectionIdsArray = Array.from(allowedCollectionIds);
|
|
2329
2326
|
console.log("[Server] 允许的商品 IDs:", allowedProductIdsArray);
|
|
2330
2327
|
console.log("[Server] 允许的集合 IDs:", allowedCollectionIdsArray);
|
|
2331
|
-
this.logInfo("
|
|
2328
|
+
this.logInfo("getProductScopeByMenuConfig: 收集到的允许规则", {
|
|
2332
2329
|
allowedProductCount: allowedProductIds.size,
|
|
2333
2330
|
allowedCollectionCount: allowedCollectionIds.size
|
|
2334
2331
|
});
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
if (allowedCollectionIds.size > 0 && Array.isArray(product.collection)) {
|
|
2340
|
-
const hasMatchingCollection = product.collection.some(
|
|
2341
|
-
(col) => allowedCollectionIds.has(col.id)
|
|
2342
|
-
);
|
|
2343
|
-
if (hasMatchingCollection) {
|
|
2344
|
-
return true;
|
|
2345
|
-
}
|
|
2346
|
-
}
|
|
2347
|
-
return false;
|
|
2348
|
-
});
|
|
2349
|
-
console.log("[Server] 过滤结果: 原始 %d 个,过滤后 %d 个", products.length, filteredProducts.length);
|
|
2350
|
-
this.logInfo("filterProductsByMenuConfig: 过滤完成", {
|
|
2351
|
-
originalCount: products.length,
|
|
2352
|
-
filteredCount: filteredProducts.length,
|
|
2353
|
-
removedCount: products.length - filteredProducts.length
|
|
2354
|
-
});
|
|
2355
|
-
return filteredProducts;
|
|
2332
|
+
return {
|
|
2333
|
+
productIds: allowedProductIdsArray,
|
|
2334
|
+
collectionIds: allowedCollectionIdsArray
|
|
2335
|
+
};
|
|
2356
2336
|
}
|
|
2357
2337
|
/**
|
|
2358
2338
|
* 记录信息日志
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* 包含新增的 Products、Menu、Quotation 和扩展的 Schedule 模块
|
|
4
4
|
*/
|
|
5
5
|
export { ProductsModule } from './products';
|
|
6
|
-
export type { ProductsState } from './products/types';
|
|
6
|
+
export type { ProductIdScope, ProductsState } from './products/types';
|
|
7
7
|
export { ProductsHooks } from './products/types';
|
|
8
8
|
export { MenuModule } from './menu';
|
|
9
9
|
export type { MenuState, MenuData } from './menu/types';
|
|
@@ -2,7 +2,7 @@ import { Module, PisellCore } from '../../../types';
|
|
|
2
2
|
import { BaseModule } from '../../../modules/BaseModule';
|
|
3
3
|
import { ProductData } from '../../../modules/Product/types';
|
|
4
4
|
import type { RouteDefinition } from '../../types';
|
|
5
|
-
import { ProductFormatter, ProductFormatterContext } from './types';
|
|
5
|
+
import { ProductIdScope, ProductFormatter, ProductFormatterContext } from './types';
|
|
6
6
|
/**
|
|
7
7
|
* Products 模块 - 用于获取和管理完整的商品详细数据
|
|
8
8
|
* 相比 ProductList 模块,Products 会获取所有详细信息并缓存
|
|
@@ -80,10 +80,12 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
80
80
|
* @param extraContext 额外的上下文数据(可选,由 Server 层传入)
|
|
81
81
|
* @param options 可选参数
|
|
82
82
|
* @param options.changedIds 变更的商品 IDs,非空时仅对这些商品增量执行 prepare 并更新缓存
|
|
83
|
+
* @param options.productIds 指定商品 IDs,仅对这些商品执行价格计算;不传则处理全量
|
|
83
84
|
* @returns 应用了价格的商品列表
|
|
84
85
|
*/
|
|
85
86
|
getProductsWithPrice(schedule_date: string, extraContext?: Partial<ProductFormatterContext>, options?: {
|
|
86
87
|
changedIds?: number[];
|
|
88
|
+
productIds?: number[];
|
|
87
89
|
}): Promise<ProductData[]>;
|
|
88
90
|
/**
|
|
89
91
|
* 准备带价格的商品数据(通过格式化器流程处理)
|
|
@@ -96,6 +98,11 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
96
98
|
*/
|
|
97
99
|
private prepareProductsWithPrice;
|
|
98
100
|
private getProductsPriceCacheKey;
|
|
101
|
+
private normalizeProductIds;
|
|
102
|
+
/**
|
|
103
|
+
* 按轻量范围返回商品 ID,不做 structuredClone。
|
|
104
|
+
*/
|
|
105
|
+
getProductIdsByScope(scope: ProductIdScope): number[];
|
|
99
106
|
/**
|
|
100
107
|
* 应用所有已注册的格式化器
|
|
101
108
|
* @param products 商品列表
|
|
@@ -173,6 +180,10 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
173
180
|
* 仅供内部 formatter 流程使用,因为 formatter 会创建新对象
|
|
174
181
|
*/
|
|
175
182
|
private getProductsRef;
|
|
183
|
+
/**
|
|
184
|
+
* 按 ID 从 Map 取商品引用,供内部 formatter 流程使用。
|
|
185
|
+
*/
|
|
186
|
+
private getProductsRefByIds;
|
|
176
187
|
/**
|
|
177
188
|
* 根据ID获取单个商品(从内存缓存)
|
|
178
189
|
* 使用 Map 快速查询,时间复杂度 O(1)
|
|
@@ -326,12 +326,16 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
326
326
|
* @param extraContext 额外的上下文数据(可选,由 Server 层传入)
|
|
327
327
|
* @param options 可选参数
|
|
328
328
|
* @param options.changedIds 变更的商品 IDs,非空时仅对这些商品增量执行 prepare 并更新缓存
|
|
329
|
+
* @param options.productIds 指定商品 IDs,仅对这些商品执行价格计算;不传则处理全量
|
|
329
330
|
* @returns 应用了价格的商品列表
|
|
330
331
|
*/
|
|
331
332
|
async getProductsWithPrice(schedule_date, extraContext, options) {
|
|
333
|
+
var _a;
|
|
332
334
|
const t0 = performance.now();
|
|
333
|
-
const
|
|
334
|
-
const
|
|
335
|
+
const scopedProductIds = this.normalizeProductIds(options == null ? void 0 : options.productIds);
|
|
336
|
+
const cacheKey = this.getProductsPriceCacheKey(schedule_date, extraContext, scopedProductIds);
|
|
337
|
+
const scopedProductIdSet = scopedProductIds ? new Set(scopedProductIds) : void 0;
|
|
338
|
+
const changedIds = scopedProductIdSet ? (_a = options == null ? void 0 : options.changedIds) == null ? void 0 : _a.filter((id) => scopedProductIdSet.has(id)) : options == null ? void 0 : options.changedIds;
|
|
335
339
|
if (this.productsPriceCache.has(cacheKey)) {
|
|
336
340
|
const cachedProducts = this.productsPriceCache.get(cacheKey);
|
|
337
341
|
if (changedIds && changedIds.length > 0) {
|
|
@@ -398,8 +402,15 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
398
402
|
});
|
|
399
403
|
return cachedProducts;
|
|
400
404
|
}
|
|
401
|
-
this.logInfo("商品价格缓存未命中,准备获取", {
|
|
402
|
-
|
|
405
|
+
this.logInfo("商品价格缓存未命中,准备获取", {
|
|
406
|
+
cacheKey,
|
|
407
|
+
scopedProductCount: scopedProductIds == null ? void 0 : scopedProductIds.length
|
|
408
|
+
});
|
|
409
|
+
const result = await this.prepareProductsWithPrice(
|
|
410
|
+
schedule_date,
|
|
411
|
+
extraContext,
|
|
412
|
+
scopedProductIds ? { productIds: scopedProductIds } : void 0
|
|
413
|
+
);
|
|
403
414
|
this.productsPriceCache.set(cacheKey, result);
|
|
404
415
|
this.logInfo("商品价格已缓存", {
|
|
405
416
|
cacheKey,
|
|
@@ -425,7 +436,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
425
436
|
var _a, _b;
|
|
426
437
|
const tTotal = performance.now();
|
|
427
438
|
const targetIds = options == null ? void 0 : options.productIds;
|
|
428
|
-
const isIncremental = targetIds
|
|
439
|
+
const isIncremental = Array.isArray(targetIds);
|
|
429
440
|
this.logInfo("prepareProductsWithPrice 开始处理", {
|
|
430
441
|
schedule_date,
|
|
431
442
|
mode: isIncremental ? "incremental" : "full",
|
|
@@ -435,8 +446,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
435
446
|
let products;
|
|
436
447
|
let ids;
|
|
437
448
|
if (isIncremental) {
|
|
438
|
-
|
|
439
|
-
products = this.getProductsRef().filter((p) => idSet.has(p.id));
|
|
449
|
+
products = this.getProductsRefByIds(targetIds);
|
|
440
450
|
ids = products.map((p) => p.id);
|
|
441
451
|
} else {
|
|
442
452
|
products = this.getProductsRef();
|
|
@@ -499,9 +509,47 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
499
509
|
}
|
|
500
510
|
return [];
|
|
501
511
|
}
|
|
502
|
-
getProductsPriceCacheKey(schedule_date, extraContext) {
|
|
512
|
+
getProductsPriceCacheKey(schedule_date, extraContext, productIds) {
|
|
503
513
|
const datetime = (extraContext == null ? void 0 : extraContext.schedule_datetime) || schedule_date;
|
|
504
|
-
|
|
514
|
+
const productScope = productIds ? `:products:${productIds.join(",")}` : "";
|
|
515
|
+
return `${datetime}:customer:${(extraContext == null ? void 0 : extraContext.customer_id) ?? ""}${productScope}`;
|
|
516
|
+
}
|
|
517
|
+
normalizeProductIds(productIds) {
|
|
518
|
+
if (!Array.isArray(productIds))
|
|
519
|
+
return void 0;
|
|
520
|
+
return Array.from(new Set(
|
|
521
|
+
productIds.map((id) => Number(id)).filter((id) => Number.isFinite(id))
|
|
522
|
+
)).sort((a, b) => a - b);
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* 按轻量范围返回商品 ID,不做 structuredClone。
|
|
526
|
+
*/
|
|
527
|
+
getProductIdsByScope(scope) {
|
|
528
|
+
const productIds = this.normalizeProductIds(scope.productIds) || [];
|
|
529
|
+
const collectionIds = this.normalizeProductIds(scope.collectionIds) || [];
|
|
530
|
+
if (scope.isAllProducts) {
|
|
531
|
+
return this.getProductsRef().map((product) => product.id);
|
|
532
|
+
}
|
|
533
|
+
if (productIds.length === 0 && collectionIds.length === 0)
|
|
534
|
+
return [];
|
|
535
|
+
const result = /* @__PURE__ */ new Set();
|
|
536
|
+
for (const id of productIds) {
|
|
537
|
+
if (this.store.map.has(id))
|
|
538
|
+
result.add(id);
|
|
539
|
+
}
|
|
540
|
+
if (collectionIds.length === 0)
|
|
541
|
+
return Array.from(result);
|
|
542
|
+
const collectionIdSet = new Set(collectionIds);
|
|
543
|
+
for (const product of this.getProductsRef()) {
|
|
544
|
+
if (result.has(product.id))
|
|
545
|
+
continue;
|
|
546
|
+
if (!Array.isArray(product.collection))
|
|
547
|
+
continue;
|
|
548
|
+
const isInCollection = product.collection.some((collection) => collectionIdSet.has(collection.id));
|
|
549
|
+
if (isInCollection)
|
|
550
|
+
result.add(product.id);
|
|
551
|
+
}
|
|
552
|
+
return Array.from(result);
|
|
505
553
|
}
|
|
506
554
|
/**
|
|
507
555
|
* 应用所有已注册的格式化器
|
|
@@ -776,6 +824,18 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
776
824
|
getProductsRef() {
|
|
777
825
|
return this.store.list;
|
|
778
826
|
}
|
|
827
|
+
/**
|
|
828
|
+
* 按 ID 从 Map 取商品引用,供内部 formatter 流程使用。
|
|
829
|
+
*/
|
|
830
|
+
getProductsRefByIds(ids) {
|
|
831
|
+
const products = [];
|
|
832
|
+
for (const id of ids) {
|
|
833
|
+
const product = this.store.map.get(id);
|
|
834
|
+
if (product)
|
|
835
|
+
products.push(product);
|
|
836
|
+
}
|
|
837
|
+
return products;
|
|
838
|
+
}
|
|
779
839
|
/**
|
|
780
840
|
* 根据ID获取单个商品(从内存缓存)
|
|
781
841
|
* 使用 Map 快速查询,时间复杂度 O(1)
|
|
@@ -17,6 +17,17 @@ export interface FormattedProductData extends ProductData {
|
|
|
17
17
|
/** 购物车详情值 */
|
|
18
18
|
cartDetailValue?: any;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* 商品轻量查询范围
|
|
22
|
+
*/
|
|
23
|
+
export interface ProductIdScope {
|
|
24
|
+
/** 是否返回全部商品 ID */
|
|
25
|
+
isAllProducts?: boolean;
|
|
26
|
+
/** 指定商品 ID */
|
|
27
|
+
productIds?: number[];
|
|
28
|
+
/** 指定商品集合 ID */
|
|
29
|
+
collectionIds?: number[];
|
|
30
|
+
}
|
|
20
31
|
/**
|
|
21
32
|
* 加载报价单商品价格参数
|
|
22
33
|
*/
|
|
@@ -195,7 +195,7 @@ var formatDataKey = (data) => {
|
|
|
195
195
|
}
|
|
196
196
|
if ((_a = _data == null ? void 0 : _data.option) == null ? void 0 : _a.length) {
|
|
197
197
|
for (const item of _data.option) {
|
|
198
|
-
let str = `_${item.option_group_id}_${item.
|
|
198
|
+
let str = `_${item.option_group_id}_${item.option_group_item_id}`;
|
|
199
199
|
key += str;
|
|
200
200
|
rowKey += `${str}_${item.quantity || item.num}`;
|
|
201
201
|
}
|
|
@@ -207,7 +207,7 @@ var formatDataKey = (data) => {
|
|
|
207
207
|
rowKey += `${str}_${item.quantity || item.num}`;
|
|
208
208
|
if (item == null ? void 0 : item.option) {
|
|
209
209
|
for (const opt of item.option) {
|
|
210
|
-
let str2 = `_${opt.option_group_id}_${opt.
|
|
210
|
+
let str2 = `_${opt.option_group_id}_${opt.option_group_item_id}`;
|
|
211
211
|
key += str2;
|
|
212
212
|
rowKey += `${str2}_${opt.quantity || opt.num}`;
|
|
213
213
|
}
|