@pisell/pisellos 2.2.77 → 2.2.79

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.
Files changed (39) hide show
  1. package/dist/core/index.d.ts +2 -2
  2. package/dist/model/strategy/adapter/walletPass/evaluator.js +2 -1
  3. package/dist/model/strategy/adapter/walletPass/locales.js +3 -0
  4. package/dist/model/strategy/adapter/walletPass/type.d.ts +4 -0
  5. package/dist/model/strategy/adapter/walletPass/utils.js +108 -9
  6. package/dist/modules/ProductList/index.d.ts +3 -0
  7. package/dist/modules/ProductList/index.js +9 -7
  8. package/dist/plugins/request.d.ts +2 -0
  9. package/dist/server/index.d.ts +27 -2
  10. package/dist/server/index.js +499 -295
  11. package/dist/server/modules/products/index.d.ts +101 -3
  12. package/dist/server/modules/products/index.js +1378 -242
  13. package/dist/server/modules/products/types.d.ts +24 -1
  14. package/dist/server/modules/products/types.js +3 -0
  15. package/dist/server/utils/product.d.ts +1 -0
  16. package/dist/server/utils/product.js +35 -25
  17. package/dist/solution/BookingTicket/index.d.ts +9 -1
  18. package/dist/solution/BookingTicket/index.js +41 -28
  19. package/dist/types/index.d.ts +3 -0
  20. package/lib/core/index.d.ts +2 -2
  21. package/lib/model/strategy/adapter/walletPass/evaluator.js +2 -1
  22. package/lib/model/strategy/adapter/walletPass/locales.js +3 -0
  23. package/lib/model/strategy/adapter/walletPass/type.d.ts +4 -0
  24. package/lib/model/strategy/adapter/walletPass/utils.js +68 -8
  25. package/lib/modules/ProductList/index.d.ts +3 -0
  26. package/lib/modules/ProductList/index.js +2 -2
  27. package/lib/plugins/request.d.ts +2 -0
  28. package/lib/server/index.d.ts +27 -2
  29. package/lib/server/index.js +172 -95
  30. package/lib/server/modules/products/index.d.ts +101 -3
  31. package/lib/server/modules/products/index.js +595 -52
  32. package/lib/server/modules/products/types.d.ts +24 -1
  33. package/lib/server/modules/products/types.js +1 -0
  34. package/lib/server/utils/product.d.ts +1 -0
  35. package/lib/server/utils/product.js +27 -11
  36. package/lib/solution/BookingTicket/index.d.ts +9 -1
  37. package/lib/solution/BookingTicket/index.js +10 -2
  38. package/lib/types/index.d.ts +3 -0
  39. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { Plugin, PluginOptions, Module, ModuleOptions, PisellCore, PisellOSOptions, BusinessContext, ModuleContextConfig, InitializeServerOptions } from '../types';
1
+ import { Plugin, PluginOptions, Module, ModuleOptions, PisellCore, PisellOSOptions, BusinessContext, ModuleContextConfig, ServerOptions, InitializeServerOptions } from '../types';
2
2
  import { EffectsManager } from '../effects';
3
3
  /**
4
4
  * pisell OS 核心实现
@@ -11,7 +11,7 @@ declare class PisellOSCore implements PisellCore {
11
11
  private debug;
12
12
  context: BusinessContext;
13
13
  server: any;
14
- private serverOptions?;
14
+ serverOptions?: ServerOptions;
15
15
  constructor(options?: PisellOSOptions);
16
16
  private initialize;
17
17
  /**
@@ -19,7 +19,8 @@ var defaultStrategyMetadataCustom = {
19
19
  maxUsagePerOrder: 0,
20
20
  allowCrossProduct: true,
21
21
  applicableProductLimit: 0,
22
- deductTaxAndFee: true
22
+ deductTaxAndFee: true,
23
+ maxPassesPerItem: 0
23
24
  };
24
25
 
25
26
  /**
@@ -3,6 +3,7 @@ export var locales = {
3
3
  'not_meet_the_required_conditions': '未达到使用条件',
4
4
  'exceeds_the_maximum_deduction_limit': '超出最大抵扣金额限制',
5
5
  'usage_limit_reached': '已达到使用次数上限',
6
+ 'max_passes_per_item_reached': '该商品已达到卡券使用上限',
6
7
  'not_available_for_this_channel': '当前渠道不可使用',
7
8
  'not_valid_for_this_order_type': '当前订单类型不适用'
8
9
  },
@@ -10,6 +11,7 @@ export var locales = {
10
11
  'not_meet_the_required_conditions': 'Not meet the required conditions.',
11
12
  'exceeds_the_maximum_deduction_limit': 'Exceeds the maximum deduction limit.',
12
13
  'usage_limit_reached': 'Usage limit reached.',
14
+ 'max_passes_per_item_reached': 'Max passes per item reached.',
13
15
  'not_available_for_this_channel': 'Not available for this channel.',
14
16
  'not_valid_for_this_order_type': 'Not valid for this order type.'
15
17
  },
@@ -17,6 +19,7 @@ export var locales = {
17
19
  'not_meet_the_required_conditions': '未達使用條件',
18
20
  'exceeds_the_maximum_deduction_limit': '超出最大抵扣金額限制',
19
21
  'usage_limit_reached': '已達使用次數上限',
22
+ 'max_passes_per_item_reached': '該商品已達卡券使用上限',
20
23
  'not_available_for_this_channel': '當前渠道不可使用',
21
24
  'not_valid_for_this_order_type': '當前訂單類型不適用'
22
25
  }
@@ -41,6 +41,8 @@ export interface Voucher {
41
41
  allowCrossProduct: boolean;
42
42
  /** 可用商品数量上限 (仅多商品) 默认为0,表示不限制商品数量。 */
43
43
  applicableProductLimit: number;
44
+ /** 单商品可用卡券上限(同一 Wallet Pass 商品生成的卡券对同一商品行最多抵扣次数)。默认为 0,表示不限制。 */
45
+ maxPassesPerItem: number;
44
46
  };
45
47
  }
46
48
  /**
@@ -127,6 +129,8 @@ export interface EvaluatorInput {
127
129
  allowCrossProduct: boolean;
128
130
  /** 可用商品数量上限 (仅多商品) 默认为0,表示不限制商品数量。 */
129
131
  applicableProductLimit: number;
132
+ /** 单商品可用卡券上限(同一 Wallet Pass 商品生成的卡券对同一商品行最多抵扣次数)。默认为 0,表示不限制。 */
133
+ maxPassesPerItem: number;
130
134
  }>[];
131
135
  }
132
136
  /**
@@ -118,8 +118,33 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
118
118
  var productsCopy = expandProductsWithBundleItems(products, true);
119
119
  var remainingOrderAmount = new Decimal(orderTotalAmount); // 订单剩余应付金额
120
120
 
121
+ // ========== 辅助工具:maxPassesPerItem(单商品可用卡券上限)追踪 ==========
122
+ // 获取指定 Wallet Pass 商品对指定订单商品行的已用卡券次数
123
+ var getItemPassUsage = function getItemPassUsage(usageMap, walletPassProductId, orderItemProductId) {
124
+ var _usageMap$get;
125
+ return ((_usageMap$get = usageMap.get(walletPassProductId)) === null || _usageMap$get === void 0 ? void 0 : _usageMap$get.get(orderItemProductId)) || 0;
126
+ };
127
+
128
+ // 更新指定 Wallet Pass 商品对指定订单商品行的已用卡券次数 +1
129
+ var incrementItemPassUsage = function incrementItemPassUsage(usageMap, walletPassProductId, orderItemProductId) {
130
+ if (!usageMap.has(walletPassProductId)) {
131
+ usageMap.set(walletPassProductId, new Map());
132
+ }
133
+ var innerMap = usageMap.get(walletPassProductId);
134
+ innerMap.set(orderItemProductId, (innerMap.get(orderItemProductId) || 0) + 1);
135
+ };
136
+
137
+ // 按 maxPassesPerItem 过滤商品:排除已达到单商品可用卡券上限的商品
138
+ var filterByMaxPassesPerItem = function filterByMaxPassesPerItem(products, usageMap, walletPassProductId, maxPassesPerItem) {
139
+ if (maxPassesPerItem <= 0) return products; // 0 = 不限制
140
+ return products.filter(function (p) {
141
+ return getItemPassUsage(usageMap, walletPassProductId, p.product_id) < maxPassesPerItem;
142
+ });
143
+ };
144
+ // ================================================================
145
+
121
146
  // 辅助函数:计算单张券的 _available_max_amount
122
- var calculateAvailableMaxAmount = function calculateAvailableMaxAmount(voucher, productsData) {
147
+ var calculateAvailableMaxAmount = function calculateAvailableMaxAmount(voucher, productsData, itemPassUsage) {
123
148
  var config = voucher.config;
124
149
  var _ref2 = config !== null && config !== void 0 ? config : {},
125
150
  _ref2$maxDeductionAmo = _ref2.maxDeductionAmount,
@@ -129,7 +154,9 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
129
154
  _ref2$applicableProdu = _ref2.applicableProductLimit,
130
155
  applicableProductLimit = _ref2$applicableProdu === void 0 ? 0 : _ref2$applicableProdu,
131
156
  _ref2$deductTaxAndFee = _ref2.deductTaxAndFee,
132
- deductTaxAndFee = _ref2$deductTaxAndFee === void 0 ? true : _ref2$deductTaxAndFee;
157
+ deductTaxAndFee = _ref2$deductTaxAndFee === void 0 ? true : _ref2$deductTaxAndFee,
158
+ _ref2$maxPassesPerIte = _ref2.maxPassesPerItem,
159
+ maxPassesPerItem = _ref2$maxPassesPerIte === void 0 ? 0 : _ref2$maxPassesPerIte;
133
160
 
134
161
  // 根据 deductTaxAndFee 配置获取推荐金额
135
162
  var recommendedAmount = getRecommendedAmount(voucher);
@@ -145,6 +172,11 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
145
172
  var applicableProducts = getApplicableProducts(voucher, productsData).filter(function (p) {
146
173
  return p[amountField].greaterThan(0);
147
174
  });
175
+
176
+ // 按 maxPassesPerItem 过滤:排除已达到单商品可用卡券上限的商品
177
+ if (itemPassUsage) {
178
+ applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsage, voucher.product_id, maxPassesPerItem);
179
+ }
148
180
  if (applicableProducts.length === 0) {
149
181
  return new Decimal(0);
150
182
  }
@@ -202,7 +234,7 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
202
234
  };
203
235
 
204
236
  // 辅助函数:判断券是否可用,返回可用性和原因代码
205
- var isVoucherAvailable = function isVoucherAvailable(voucher, productsData, usedVoucherCounts) {
237
+ var isVoucherAvailable = function isVoucherAvailable(voucher, productsData, usedVoucherCounts, itemPassUsage) {
206
238
  var config = voucher.config,
207
239
  id = voucher.id,
208
240
  product_id = voucher.product_id;
@@ -245,6 +277,25 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
245
277
  };
246
278
  }
247
279
  }
280
+
281
+ // 检查 maxPassesPerItem:如果所有适用商品都已达到单商品可用卡券上限,则不可用
282
+ var maxPassesPerItem = (config === null || config === void 0 ? void 0 : config.maxPassesPerItem) || 0;
283
+ if (maxPassesPerItem > 0 && itemPassUsage) {
284
+ var _config$deductTaxAndF3;
285
+ var deductTaxAndFee = (_config$deductTaxAndF3 = config === null || config === void 0 ? void 0 : config.deductTaxAndFee) !== null && _config$deductTaxAndF3 !== void 0 ? _config$deductTaxAndF3 : true;
286
+ var amountField = deductTaxAndFee ? 'remainingAmountWithTax' : 'remainingAmountPure';
287
+ var availableAfterPassLimit = getApplicableProducts(voucher, productsData).filter(function (p) {
288
+ return p[amountField].greaterThan(0);
289
+ }).filter(function (p) {
290
+ return getItemPassUsage(itemPassUsage, product_id, p.product_id) < maxPassesPerItem;
291
+ });
292
+ if (availableAfterPassLimit.length === 0) {
293
+ return {
294
+ isAvailable: false,
295
+ reasonCode: 'max_passes_per_item_reached'
296
+ };
297
+ }
298
+ }
248
299
  return {
249
300
  isAvailable: true
250
301
  };
@@ -272,6 +323,8 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
272
323
  // 重置商品余额追踪(同时维护含税和不含税两个金额池)
273
324
  var productsForRecommendation = expandProductsWithBundleItems(products, true);
274
325
  remainingOrderAmount = new Decimal(orderTotalAmount);
326
+ // 追踪推荐阶段每个 Wallet Pass 商品对每个订单商品行的已使用卡券次数
327
+ var itemPassUsageMap = new Map();
275
328
 
276
329
  /**
277
330
  // 分类券:未跨商品券 vs 跨商品券
@@ -302,7 +355,7 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
302
355
  // 处理单张券的抵扣
303
356
  var applyVoucher = function applyVoucher(voucher) {
304
357
  // 检查是否可用
305
- var availabilityCheck = isVoucherAvailable(voucher, productsForRecommendation, usedVoucherCounts);
358
+ var availabilityCheck = isVoucherAvailable(voucher, productsForRecommendation, usedVoucherCounts, itemPassUsageMap);
306
359
  if (!availabilityCheck.isAvailable) {
307
360
  return false;
308
361
  }
@@ -317,7 +370,9 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
317
370
  _ref3$applicableProdu = _ref3.applicableProductLimit,
318
371
  applicableProductLimit = _ref3$applicableProdu === void 0 ? 0 : _ref3$applicableProdu,
319
372
  _ref3$deductTaxAndFee = _ref3.deductTaxAndFee,
320
- deductTaxAndFee = _ref3$deductTaxAndFee === void 0 ? true : _ref3$deductTaxAndFee;
373
+ deductTaxAndFee = _ref3$deductTaxAndFee === void 0 ? true : _ref3$deductTaxAndFee,
374
+ _ref3$maxPassesPerIte = _ref3.maxPassesPerItem,
375
+ maxPassesPerItem = _ref3$maxPassesPerIte === void 0 ? 0 : _ref3$maxPassesPerIte;
321
376
 
322
377
  // 根据券的配置选择使用哪个单价字段和金额字段
323
378
  var unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure';
@@ -327,6 +382,9 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
327
382
  var applicableProducts = getApplicableProducts(voucher, productsForRecommendation).filter(function (p) {
328
383
  return p[amountField].greaterThan(0);
329
384
  });
385
+
386
+ // 按 maxPassesPerItem 过滤:排除已达到单商品可用卡券上限的商品
387
+ applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsageMap, product_id, maxPassesPerItem);
330
388
  if (applicableProducts.length === 0) return false;
331
389
 
332
390
  // ========== 关键修改:在应用券之前,基于当前剩余金额计算 _available_max_amount ==========
@@ -466,6 +524,11 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
466
524
  // 更新券使用次数(按 product_id 统计)
467
525
  usedVoucherCounts.set(product_id, (usedVoucherCounts.get(product_id) || 0) + 1);
468
526
 
527
+ // 更新 maxPassesPerItem 追踪:记录每个被抵扣的商品行
528
+ deductionDetails.forEach(function (detail) {
529
+ incrementItemPassUsage(itemPassUsageMap, product_id, detail.product_id);
530
+ });
531
+
469
532
  // 添加到推荐列表(包含基于当前剩余金额计算的 available_max_amount)
470
533
  recommendedVouchers.push(_objectSpread(_objectSpread({}, voucher), {}, {
471
534
  actualDeduction: totalDeducted.toNumber(),
@@ -547,6 +610,27 @@ export function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmo
547
610
  var remainingOrderAmount = new Decimal(orderTotalAmount);
548
611
  var selectedWithDetails = [];
549
612
 
613
+ // 追踪每个 Wallet Pass 商品对每个订单商品行的已使用卡券次数
614
+ // Map<walletPassProductId, Map<orderItemProductId, usedCount>>
615
+ var itemPassUsageMap = new Map();
616
+ var getItemPassUsage = function getItemPassUsage(walletPassProductId, orderItemProductId) {
617
+ var _itemPassUsageMap$get;
618
+ return ((_itemPassUsageMap$get = itemPassUsageMap.get(walletPassProductId)) === null || _itemPassUsageMap$get === void 0 ? void 0 : _itemPassUsageMap$get.get(orderItemProductId)) || 0;
619
+ };
620
+ var incrementItemPassUsage = function incrementItemPassUsage(walletPassProductId, orderItemProductId) {
621
+ if (!itemPassUsageMap.has(walletPassProductId)) {
622
+ itemPassUsageMap.set(walletPassProductId, new Map());
623
+ }
624
+ var innerMap = itemPassUsageMap.get(walletPassProductId);
625
+ innerMap.set(orderItemProductId, (innerMap.get(orderItemProductId) || 0) + 1);
626
+ };
627
+ var filterByMaxPassesPerItem = function filterByMaxPassesPerItem(products, walletPassProductId, maxPassesPerItem) {
628
+ if (maxPassesPerItem <= 0) return products; // 0 = 不限制
629
+ return products.filter(function (p) {
630
+ return getItemPassUsage(walletPassProductId, p.product_id) < maxPassesPerItem;
631
+ });
632
+ };
633
+
550
634
  // 第一步:按顺序应用已选中的券,计算实际抵扣
551
635
  selectedVouchers.forEach(function (selectedVoucher) {
552
636
  var config = selectedVoucher.config,
@@ -554,8 +638,10 @@ export function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmo
554
638
  var maxDeductionAmount = config.maxDeductionAmount,
555
639
  allowCrossProduct = config.allowCrossProduct,
556
640
  applicableProductLimit = config.applicableProductLimit,
557
- _config$deductTaxAndF3 = config.deductTaxAndFee,
558
- deductTaxAndFee = _config$deductTaxAndF3 === void 0 ? true : _config$deductTaxAndF3;
641
+ _config$deductTaxAndF4 = config.deductTaxAndFee,
642
+ deductTaxAndFee = _config$deductTaxAndF4 === void 0 ? true : _config$deductTaxAndF4,
643
+ _config$maxPassesPerI = config.maxPassesPerItem,
644
+ maxPassesPerItem = _config$maxPassesPerI === void 0 ? 0 : _config$maxPassesPerI;
559
645
 
560
646
  // 根据券的配置选择使用哪个单价字段和金额字段
561
647
  var unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure';
@@ -565,6 +651,9 @@ export function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmo
565
651
  var applicableProducts = getApplicableProducts(selectedVoucher, productsForCalc).filter(function (p) {
566
652
  return p[amountField].greaterThan(0);
567
653
  });
654
+
655
+ // 按 maxPassesPerItem 过滤:排除已达到单商品可用卡券上限的商品
656
+ applicableProducts = filterByMaxPassesPerItem(applicableProducts, selectedVoucher.product_id, maxPassesPerItem);
568
657
  if (applicableProducts.length === 0) {
569
658
  // 无适用商品,跳过
570
659
  selectedWithDetails.push(_objectSpread(_objectSpread({}, selectedVoucher), {}, {
@@ -658,6 +747,11 @@ export function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmo
658
747
 
659
748
  // 更新订单剩余金额
660
749
  remainingOrderAmount = remainingOrderAmount.minus(totalDeducted);
750
+
751
+ // 更新 maxPassesPerItem 追踪:记录每个被抵扣的商品行
752
+ deductionDetails.forEach(function (detail) {
753
+ incrementItemPassUsage(selectedVoucher.product_id, detail.product_id);
754
+ });
661
755
  selectedWithDetails.push(_objectSpread(_objectSpread({}, selectedVoucher), {}, {
662
756
  actualDeduction: totalDeducted.toNumber(),
663
757
  // 转换为数字
@@ -692,8 +786,10 @@ export function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmo
692
786
  var maxDeductionAmount = config.maxDeductionAmount,
693
787
  allowCrossProduct = config.allowCrossProduct,
694
788
  applicableProductLimit = config.applicableProductLimit,
695
- _config$deductTaxAndF4 = config.deductTaxAndFee,
696
- deductTaxAndFee = _config$deductTaxAndF4 === void 0 ? true : _config$deductTaxAndF4;
789
+ _config$deductTaxAndF5 = config.deductTaxAndFee,
790
+ deductTaxAndFee = _config$deductTaxAndF5 === void 0 ? true : _config$deductTaxAndF5,
791
+ _config$maxPassesPerI2 = config.maxPassesPerItem,
792
+ maxPassesPerItem = _config$maxPassesPerI2 === void 0 ? 0 : _config$maxPassesPerI2;
697
793
 
698
794
  // 根据券的配置选择使用哪个单价字段和金额字段
699
795
  var unitPriceField = deductTaxAndFee ? 'unitPriceWithTax' : 'unitPricePure';
@@ -726,6 +822,9 @@ export function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmo
726
822
  var applicableProducts = getApplicableProducts(voucher, productsForCalc).filter(function (p) {
727
823
  return p[amountField].greaterThan(0);
728
824
  });
825
+
826
+ // 按 maxPassesPerItem 过滤:排除已达到单商品可用卡券上限的商品
827
+ applicableProducts = filterByMaxPassesPerItem(applicableProducts, product_id, maxPassesPerItem);
729
828
  if (applicableProducts.length === 0) {
730
829
  isAvailable = false;
731
830
  reasonCode = 'not_meet_the_required_conditions';
@@ -22,6 +22,9 @@ export declare class ProductList extends BaseModule implements Module {
22
22
  schedule_datetime?: string;
23
23
  with_count?: string[];
24
24
  with_schedule?: number;
25
+ }, options?: {
26
+ callback?: (result: any) => void;
27
+ subscriberId?: string;
25
28
  }): Promise<any>;
26
29
  loadProductsPrice({ ids, customer_id, schedule_date, channel, }: {
27
30
  ids?: number[];
@@ -84,7 +84,7 @@ export var ProductList = /*#__PURE__*/function (_BaseModule) {
84
84
  }, {
85
85
  key: "loadProducts",
86
86
  value: function () {
87
- var _loadProducts = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(_ref) {
87
+ var _loadProducts = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(_ref, options) {
88
88
  var _this$otherParams;
89
89
  var _ref$category_ids, category_ids, _ref$product_ids, product_ids, _ref$collection, collection, _ref$menu_list_ids, menu_list_ids, paramsCustomerId, _ref$with_count, with_count, schedule_datetime, schedule_date, cacheId, with_schedule, userPlugin, customer_id, _userPlugin$get, productsData, sortedList;
90
90
  return _regeneratorRuntime().wrap(function _callee3$(_context3) {
@@ -134,7 +134,9 @@ export var ProductList = /*#__PURE__*/function (_BaseModule) {
134
134
  with_schedule: with_schedule,
135
135
  schedule_datetime: schedule_datetime
136
136
  }, {
137
- osServer: true
137
+ osServer: true,
138
+ callback: options === null || options === void 0 ? void 0 : options.callback,
139
+ subscriberId: options === null || options === void 0 ? void 0 : options.subscriberId
138
140
  });
139
141
  case 6:
140
142
  productsData = _context3.sent;
@@ -155,7 +157,7 @@ export var ProductList = /*#__PURE__*/function (_BaseModule) {
155
157
  }
156
158
  }, _callee3, this);
157
159
  }));
158
- function loadProducts(_x5) {
160
+ function loadProducts(_x5, _x6) {
159
161
  return _loadProducts.apply(this, arguments);
160
162
  }
161
163
  return loadProducts;
@@ -187,7 +189,7 @@ export var ProductList = /*#__PURE__*/function (_BaseModule) {
187
189
  }
188
190
  }, _callee4, this);
189
191
  }));
190
- function loadProductsPrice(_x6) {
192
+ function loadProductsPrice(_x7) {
191
193
  return _loadProductsPrice.apply(this, arguments);
192
194
  }
193
195
  return loadProductsPrice;
@@ -235,7 +237,7 @@ export var ProductList = /*#__PURE__*/function (_BaseModule) {
235
237
  }
236
238
  }, _callee6, this);
237
239
  }));
238
- function getProduct(_x7) {
240
+ function getProduct(_x8) {
239
241
  return _getProduct.apply(this, arguments);
240
242
  }
241
243
  return getProduct;
@@ -273,7 +275,7 @@ export var ProductList = /*#__PURE__*/function (_BaseModule) {
273
275
  }
274
276
  }, _callee7, this);
275
277
  }));
276
- function addProduct(_x8) {
278
+ function addProduct(_x9) {
277
279
  return _addProduct.apply(this, arguments);
278
280
  }
279
281
  return addProduct;
@@ -292,7 +294,7 @@ export var ProductList = /*#__PURE__*/function (_BaseModule) {
292
294
  }
293
295
  }, _callee8, this);
294
296
  }));
295
- function selectProducts(_x9) {
297
+ function selectProducts(_x10) {
296
298
  return _selectProducts.apply(this, arguments);
297
299
  }
298
300
  return selectProducts;
@@ -69,6 +69,8 @@ export interface RequestOptions {
69
69
  customToast?: () => void;
70
70
  cache?: CacheProps;
71
71
  osServer?: boolean;
72
+ callback?: (res: any) => void;
73
+ subscriberId?: string;
72
74
  }
73
75
  /**
74
76
  * 响应接口
@@ -18,6 +18,7 @@ declare class Server {
18
18
  quotation?: QuotationModule;
19
19
  schedule?: ScheduleModuleEx;
20
20
  router: Router;
21
+ private productQuerySubscribers;
21
22
  private moduleRegistry;
22
23
  constructor(core: PisellCore);
23
24
  /**
@@ -85,6 +86,12 @@ declare class Server {
85
86
  * 获取所有已注册的模块列表
86
87
  */
87
88
  getRegisteredModules(): string[];
89
+ /**
90
+ * 后台静默刷新商品数据
91
+ * 重新拉取全量 SSE 接口,更新本地数据后触发 onProductsSyncCompleted
92
+ * 不影响当前界面展示,适用于切回前台、定时刷新等场景
93
+ */
94
+ refreshProductsInBackground(): Promise<void>;
88
95
  /**
89
96
  * 清空所有server模块的IndexedDB缓存
90
97
  * @returns Promise<void>
@@ -132,10 +139,28 @@ declare class Server {
132
139
  */
133
140
  private registerServerRoutes;
134
141
  /**
135
- * 处理商品查询请求(编排 Products、Menu、Schedule 模块)
136
- * 这是一个业务编排方法,协调多个模块完成复杂的业务需求
142
+ * 根据 subscriberId 移除商品查询订阅者
143
+ */
144
+ removeProductQuerySubscriber(subscriberId?: string): void;
145
+ /**
146
+ * 处理商品查询请求
147
+ * 存储订阅者信息,便于数据变更时推送最新结果
137
148
  */
138
149
  private handleProductQuery;
150
+ /**
151
+ * 取消商品查询订阅(HTTP 路由入口)
152
+ */
153
+ private handleUnsubscribeProductQuery;
154
+ /**
155
+ * 商品查询的核心计算逻辑(编排 Products、Menu、Schedule 模块)
156
+ * 供 handleProductQuery 首次返回及 pubsub 变更推送复用
157
+ */
158
+ private computeProductQueryResult;
159
+ /**
160
+ * 数据变更后,遍历所有订阅者重新计算查询结果并通过 callback 推送
161
+ * 由 ProductsModule 的 onProductsSyncCompleted 事件触发
162
+ */
163
+ private recomputeAndNotifyProductQuery;
139
164
  /**
140
165
  * 根据餐牌配置过滤商品
141
166
  * @param products 所有商品列表