@pisell/pisellos 2.1.1 → 2.1.3

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 (31) hide show
  1. package/dist/modules/Cart/utils/changePrice.d.ts +2 -2
  2. package/dist/modules/Cart/utils/changePrice.js +1 -1
  3. package/dist/modules/Discount/index.d.ts +2 -1
  4. package/dist/modules/Discount/index.js +67 -4
  5. package/dist/modules/Discount/types.d.ts +25 -0
  6. package/dist/modules/ProductList/index.d.ts +1 -2
  7. package/dist/modules/ProductList/index.js +26 -40
  8. package/dist/modules/ProductList/types.d.ts +0 -1
  9. package/dist/solution/BookingByStep/index.js +51 -35
  10. package/dist/solution/BookingByStep/types.d.ts +3 -2
  11. package/dist/solution/BookingByStep/utils/timeslots.js +161 -69
  12. package/dist/solution/BuyTickets/index.d.ts +2 -2
  13. package/dist/solution/BuyTickets/index.js +1 -1
  14. package/dist/solution/ShopDiscount/index.d.ts +1 -1
  15. package/dist/solution/ShopDiscount/index.js +6 -6
  16. package/lib/modules/Cart/utils/changePrice.d.ts +2 -2
  17. package/lib/modules/Cart/utils/changePrice.js +1 -1
  18. package/lib/modules/Discount/index.d.ts +2 -1
  19. package/lib/modules/Discount/index.js +45 -3
  20. package/lib/modules/Discount/types.d.ts +25 -0
  21. package/lib/modules/ProductList/index.d.ts +1 -2
  22. package/lib/modules/ProductList/index.js +8 -24
  23. package/lib/modules/ProductList/types.d.ts +0 -1
  24. package/lib/solution/BookingByStep/index.js +40 -28
  25. package/lib/solution/BookingByStep/types.d.ts +3 -2
  26. package/lib/solution/BookingByStep/utils/timeslots.js +103 -49
  27. package/lib/solution/BuyTickets/index.d.ts +2 -2
  28. package/lib/solution/BuyTickets/index.js +1 -1
  29. package/lib/solution/ShopDiscount/index.d.ts +1 -1
  30. package/lib/solution/ShopDiscount/index.js +2 -2
  31. package/package.json +1 -1
@@ -95,6 +95,12 @@ export function findFastestAvailableResource(_ref2) {
95
95
  var currentTime = dayjs();
96
96
  var fastestTime = null;
97
97
  var fastestResources = [];
98
+ console.log('[TimeslotUtils] 查找最快可用资源:', {
99
+ currentTime: currentTime.format('YYYY-MM-DD HH:mm:ss'),
100
+ resourceCount: resources.length,
101
+ currentCapacity: currentCapacity,
102
+ countMap: countMap
103
+ });
98
104
 
99
105
  // 遍历所有资源,找到最快可用的时间点
100
106
  var _iterator2 = _createForOfIteratorHelper(resources),
@@ -102,75 +108,120 @@ export function findFastestAvailableResource(_ref2) {
102
108
  try {
103
109
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
104
110
  var _resource = _step2.value;
105
- // 获取资源当天的时间段
111
+ // 获取资源当天且还在工作时间内的时间段
106
112
  var todayTimes = _resource.times.filter(function (time) {
107
- return dayjs(time.start_at).isSame(currentTime, 'day');
108
- });
109
- if (todayTimes.length === 0) continue;
110
-
111
- // 按开始时间排序
112
- todayTimes.sort(function (a, b) {
113
- return dayjs(a.start_at).diff(dayjs(b.start_at));
113
+ var isToday = dayjs(time.start_at).isSame(currentTime, 'day');
114
+ var isStillWorking = dayjs(time.end_at).isAfter(currentTime);
115
+ return isToday && isStillWorking;
114
116
  });
115
-
116
- // 找到第一个可用的时间段
117
- var _iterator3 = _createForOfIteratorHelper(todayTimes),
118
- _step3;
117
+ if (todayTimes.length === 0) {
118
+ console.log("[TimeslotUtils] \u8D44\u6E90 ".concat(_resource.id, "(").concat(_resource.main_field, ") \u4ECA\u65E5\u65E0\u53EF\u7528\u65F6\u95F4\u6BB5"));
119
+ continue;
120
+ }
121
+ var _iterator4 = _createForOfIteratorHelper(todayTimes),
122
+ _step4;
119
123
  try {
120
124
  var _loop = function _loop() {
121
- var time = _step3.value;
122
- var startTime = dayjs(time.start_at);
123
-
124
- // 如果开始时间在当前时间之前,跳过
125
- if (startTime.isBefore(currentTime)) return 0; // continue
126
-
127
- // 检查这个时间段是否可用
128
- if (_resource.resourceType === 'single') {
129
- var _time$event_list;
130
- // 单个预约类型:检查是否有预约
131
- var hasBooking = (_time$event_list = time.event_list) === null || _time$event_list === void 0 ? void 0 : _time$event_list.some(function (event) {
132
- return dayjs(event.start_at).isSame(startTime);
133
- });
134
- if (!hasBooking) {
135
- if (!fastestTime || startTime.isSame(fastestTime)) {
136
- fastestTime = startTime;
137
- fastestResources.push(_resource);
138
- } else if (startTime.isBefore(fastestTime)) {
139
- fastestTime = startTime;
140
- fastestResources = [_resource];
141
- }
142
- return 1; // break
143
- }
144
- } else {
145
- var _time$event_list2;
146
- // 多个预约类型:检查容量
147
- var totalCapacity = _resource.capacity || 0;
148
- var usedCapacity = ((_time$event_list2 = time.event_list) === null || _time$event_list2 === void 0 ? void 0 : _time$event_list2.reduce(function (sum, event) {
149
- return dayjs(event.start_at).isSame(startTime) ? sum + (event.pax || 0) : sum;
150
- }, 0)) || 0;
151
- var remainingCapacity = totalCapacity - usedCapacity;
152
- if (remainingCapacity >= (countMap[_resource.id] || 0) + currentCapacity) {
153
- if (!fastestTime || startTime.isSame(fastestTime)) {
154
- fastestTime = startTime;
155
- fastestResources.push(_resource);
156
- } else if (startTime.isBefore(fastestTime)) {
157
- fastestTime = startTime;
158
- fastestResources = [_resource];
125
+ var _time$event_list, _time$event_list2;
126
+ var time = _step4.value;
127
+ var workStartTime = dayjs(time.start_at);
128
+ var workEndTime = dayjs(time.end_at);
129
+
130
+ // 确定检查的起始时间(当前时间 vs 工作开始时间)
131
+ var nextAvailableTime = currentTime.isBefore(workStartTime) ? workStartTime : currentTime;
132
+ console.log("[TimeslotUtils] \u68C0\u67E5\u8D44\u6E90 ".concat(_resource.id, "(").concat(_resource.main_field, "):"), {
133
+ workTime: "".concat(workStartTime.format('HH:mm'), "-").concat(workEndTime.format('HH:mm')),
134
+ checkStartTime: nextAvailableTime.format('HH:mm:ss'),
135
+ eventCount: ((_time$event_list = time.event_list) === null || _time$event_list === void 0 ? void 0 : _time$event_list.length) || 0
136
+ });
137
+
138
+ // 获取所有影响的预约事件(当前时间之后的)
139
+ var relevantEvents = ((_time$event_list2 = time.event_list) === null || _time$event_list2 === void 0 ? void 0 : _time$event_list2.filter(function (event) {
140
+ var eventEnd = dayjs(event.end_at);
141
+ return eventEnd.isAfter(nextAvailableTime);
142
+ })) || [];
143
+
144
+ // 按开始时间排序
145
+ relevantEvents.sort(function (a, b) {
146
+ return dayjs(a.start_at).diff(dayjs(b.start_at));
147
+ });
148
+
149
+ // 检查从 nextAvailableTime 开始的可用性
150
+ var finalAvailableTime = nextAvailableTime;
151
+ var _iterator5 = _createForOfIteratorHelper(relevantEvents),
152
+ _step5;
153
+ try {
154
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
155
+ var _event = _step5.value;
156
+ var _eventStart = dayjs(_event.start_at);
157
+ var _eventEnd = dayjs(_event.end_at);
158
+ console.log("[TimeslotUtils] \u68C0\u67E5\u4E8B\u4EF6\u51B2\u7A81:", {
159
+ resourceId: _resource.id,
160
+ eventTime: "".concat(_eventStart.format('HH:mm'), "-").concat(_eventEnd.format('HH:mm')),
161
+ checkTime: finalAvailableTime.format('HH:mm:ss'),
162
+ pax: _event.pax || 1
163
+ });
164
+
165
+ // 检查资源类型和容量
166
+ if (_resource.resourceType === 'single' || (_resource.capacity || 1) === 1) {
167
+ // 单人预约资源:检查时间冲突
168
+ if (finalAvailableTime.isBefore(_eventEnd) && _eventStart.isBefore(finalAvailableTime.add(30, 'minute'))) {
169
+ // 有冲突,使用事件结束时间
170
+ finalAvailableTime = _eventEnd;
171
+ console.log("[TimeslotUtils] \u53D1\u73B0\u65F6\u95F4\u51B2\u7A81\uFF0C\u8C03\u6574\u5230: ".concat(finalAvailableTime.format('HH:mm:ss')));
172
+ }
173
+ } else {
174
+ // 多人预约资源:检查容量
175
+ var totalCapacity = _resource.capacity || 0;
176
+ var currentUsedCapacity = countMap[_resource.id] || 0;
177
+ var eventUsedCapacity = _event.pax || 1;
178
+
179
+ // 如果在事件时间范围内,检查容量是否足够
180
+ if (finalAvailableTime.isBefore(_eventEnd) && _eventStart.isBefore(finalAvailableTime.add(30, 'minute'))) {
181
+ var totalRequiredCapacity = currentUsedCapacity + currentCapacity + eventUsedCapacity;
182
+ if (totalRequiredCapacity > totalCapacity) {
183
+ // 容量不足,使用事件结束时间
184
+ finalAvailableTime = _eventEnd;
185
+ console.log("[TimeslotUtils] \u5BB9\u91CF\u4E0D\u8DB3\uFF0C\u8C03\u6574\u5230: ".concat(finalAvailableTime.format('HH:mm:ss')));
186
+ }
187
+ }
159
188
  }
160
- return 1; // break
161
189
  }
190
+
191
+ // 确保可用时间在工作时间内
192
+ } catch (err) {
193
+ _iterator5.e(err);
194
+ } finally {
195
+ _iterator5.f();
196
+ }
197
+ if (finalAvailableTime.isAfter(workEndTime)) {
198
+ console.log("[TimeslotUtils] \u8D44\u6E90 ".concat(_resource.id, " \u53EF\u7528\u65F6\u95F4\u8D85\u51FA\u5DE5\u4F5C\u65F6\u95F4\uFF0C\u8DF3\u8FC7"));
199
+ return 0; // continue
162
200
  }
201
+ console.log("[TimeslotUtils] \u8D44\u6E90 ".concat(_resource.id, "(").concat(_resource.main_field, ") \u6700\u5FEB\u53EF\u7528\u65F6\u95F4: ").concat(finalAvailableTime.format('HH:mm:ss')));
202
+
203
+ // 更新最快可用时间和资源
204
+ if (!fastestTime || finalAvailableTime.isBefore(fastestTime)) {
205
+ fastestTime = finalAvailableTime;
206
+ fastestResources = [_resource];
207
+ console.log("[TimeslotUtils] \u66F4\u65B0\u6700\u5FEB\u65F6\u95F4: ".concat(fastestTime.format('HH:mm:ss'), ", \u8D44\u6E90: ").concat(_resource.main_field));
208
+ } else if (finalAvailableTime.isSame(fastestTime)) {
209
+ fastestResources.push(_resource);
210
+ console.log("[TimeslotUtils] \u6DFB\u52A0\u76F8\u540C\u65F6\u95F4\u8D44\u6E90: ".concat(_resource.main_field));
211
+ }
212
+ return 1; // break
213
+ // 每个资源只需要计算一次
163
214
  },
164
215
  _ret;
165
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
216
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
166
217
  _ret = _loop();
167
218
  if (_ret === 0) continue;
168
219
  if (_ret === 1) break;
169
220
  }
170
221
  } catch (err) {
171
- _iterator3.e(err);
222
+ _iterator4.e(err);
172
223
  } finally {
173
- _iterator3.f();
224
+ _iterator4.f();
174
225
  }
175
226
  }
176
227
 
@@ -180,31 +231,72 @@ export function findFastestAvailableResource(_ref2) {
180
231
  } finally {
181
232
  _iterator2.f();
182
233
  }
183
- if (!fastestTime || fastestResources.length === 0) return null;
234
+ if (!fastestTime || fastestResources.length === 0) {
235
+ console.log('[TimeslotUtils] 未找到可用资源');
236
+ return null;
237
+ }
238
+ console.log("[TimeslotUtils] \u627E\u5230 ".concat(fastestResources.length, " \u4E2A\u6700\u5FEB\u53EF\u7528\u8D44\u6E90\uFF0C\u65F6\u95F4: ").concat(fastestTime.format('HH:mm:ss')));
184
239
 
185
240
  // 如果只有一个最快可用的资源,直接返回
186
- if (fastestResources.length === 1) return fastestResources[0];
241
+ if (fastestResources.length === 1) {
242
+ console.log("[TimeslotUtils] \u8FD4\u56DE\u552F\u4E00\u6700\u5FEB\u8D44\u6E90: ".concat(fastestResources[0].main_field));
243
+ return fastestResources[0];
244
+ }
187
245
 
188
- // 如果有多个最快可用的资源,比较它们的空闲时间
246
+ // 如果有多个最快可用的资源,选择空闲时间最长的资源
247
+ var selectedResource = fastestResources[0];
189
248
  var maxIdleTime = 0;
190
- var selectedResource = null;
249
+ console.log("[TimeslotUtils] \u6BD4\u8F83 ".concat(fastestResources.length, " \u4E2A\u8D44\u6E90\u7684\u7A7A\u95F2\u65F6\u95F4:"));
191
250
  for (var _i2 = 0, _fastestResources = fastestResources; _i2 < _fastestResources.length; _i2++) {
251
+ var _workingTime$event_li;
192
252
  var resource = _fastestResources[_i2];
193
- var idleTime = calculateResourceAvailableTime({
194
- resource: resource,
195
- timeSlots: {
196
- start_time: fastestTime.format('HH:mm'),
197
- end_time: fastestTime.format('HH:mm'),
198
- start_at: fastestTime,
199
- end_at: fastestTime
200
- },
201
- currentCapacity: (countMap[resource.id] || 0) + currentCapacity
253
+ // 找到该资源当天且还在工作的时间段
254
+ var workingTime = resource.times.find(function (time) {
255
+ var isToday = dayjs(time.start_at).isSame(fastestTime, 'day');
256
+ var isStillWorking = dayjs(time.end_at).isAfter(fastestTime);
257
+ return isToday && isStillWorking;
258
+ });
259
+ if (!workingTime) continue;
260
+ var workEndTime = dayjs(workingTime.end_at);
261
+
262
+ // 计算从最快可用时间到工作结束时间的空闲时长(分钟)
263
+ var totalIdleTime = workEndTime.diff(fastestTime, 'minute');
264
+
265
+ // 减去已有预约占用的时间
266
+ var relevantEvents = ((_workingTime$event_li = workingTime.event_list) === null || _workingTime$event_li === void 0 ? void 0 : _workingTime$event_li.filter(function (event) {
267
+ var eventStart = dayjs(event.start_at);
268
+ var eventEnd = dayjs(event.end_at);
269
+ // 只计算在最快可用时间之后的预约
270
+ return eventEnd.isAfter(fastestTime) && eventStart.isAfter(fastestTime);
271
+ })) || [];
272
+ var _iterator3 = _createForOfIteratorHelper(relevantEvents),
273
+ _step3;
274
+ try {
275
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
276
+ var event = _step3.value;
277
+ var eventStart = dayjs(event.start_at);
278
+ var eventEnd = dayjs(event.end_at);
279
+ var eventDuration = eventEnd.diff(eventStart, 'minute');
280
+ totalIdleTime -= eventDuration;
281
+ }
282
+ } catch (err) {
283
+ _iterator3.e(err);
284
+ } finally {
285
+ _iterator3.f();
286
+ }
287
+ console.log("[TimeslotUtils] \u8D44\u6E90 ".concat(resource.id, "(").concat(resource.main_field, "):"), {
288
+ 工作结束时间: workEndTime.format('HH:mm'),
289
+ 总工作时长: workEndTime.diff(fastestTime, 'minute') + '分钟',
290
+ 预约占用时长: workEndTime.diff(fastestTime, 'minute') - totalIdleTime + '分钟',
291
+ 实际空闲时长: totalIdleTime + '分钟'
202
292
  });
203
- if (idleTime > maxIdleTime) {
204
- maxIdleTime = idleTime;
293
+ if (totalIdleTime > maxIdleTime) {
294
+ maxIdleTime = totalIdleTime;
205
295
  selectedResource = resource;
296
+ console.log("[TimeslotUtils] \u66F4\u65B0\u6700\u4F73\u9009\u62E9: ".concat(resource.main_field, " (\u7A7A\u95F2").concat(totalIdleTime, "\u5206\u949F)"));
206
297
  }
207
298
  }
299
+ console.log("[TimeslotUtils] \u6700\u7EC8\u9009\u62E9\u8D44\u6E90: ".concat(selectedResource.main_field, " (\u6700\u957F\u7A7A\u95F2").concat(maxIdleTime, "\u5206\u949F)"));
208
300
  return selectedResource;
209
301
  }
210
302
 
@@ -1,5 +1,5 @@
1
1
  import { Module, PisellCore } from '../../types';
2
- import { Product, ProductData } from '../../modules/';
2
+ import { ProductData } from '../../modules/';
3
3
  import { BaseModule } from '../../modules/BaseModule';
4
4
  export * from './types';
5
5
  export declare class BuyTicketsImpl extends BaseModule implements Module {
@@ -16,7 +16,7 @@ export declare class BuyTicketsImpl extends BaseModule implements Module {
16
16
  loadProductsByCategory(categoryId: number): Promise<void>;
17
17
  destroy(): Promise<void>;
18
18
  getProducts(): Promise<ProductData[]>;
19
- getProduct(id: number): Promise<Product>;
19
+ getProduct(id: number): Promise<ProductData>;
20
20
  listSubmit(data: Record<string, any>): Promise<{
21
21
  status: boolean;
22
22
  data: any;
@@ -238,7 +238,7 @@ export var BuyTicketsImpl = /*#__PURE__*/function (_BaseModule) {
238
238
  }
239
239
  return _context6.abrupt("return", otherProduct);
240
240
  case 10:
241
- return _context6.abrupt("return", Promise.reject('Not fund product for id: ' + id));
241
+ throw new Error("Product not found: ".concat(id));
242
242
  case 11:
243
243
  case "end":
244
244
  return _context6.stop();
@@ -34,7 +34,7 @@ export declare class ShopDiscountImpl extends BaseModule implements Module {
34
34
  discountList: Discount[];
35
35
  };
36
36
  setProductList(productList: Record<string, any>[]): void;
37
- scanCode(code: string): Promise<{
37
+ scanCode(code: string, customerId?: number): Promise<{
38
38
  isAvailable: boolean;
39
39
  productList: Record<string, any>[];
40
40
  discountList: Discount[];
@@ -304,14 +304,14 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
304
304
  }, {
305
305
  key: "scanCode",
306
306
  value: function () {
307
- var _scanCode = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(code) {
307
+ var _scanCode = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(code, customerId) {
308
308
  var _this$store$discount3, resultDiscountList, rulesModule, withScanList, _ref3, newProductList, newDiscountList, isAvailable, _this$options$otherPa6;
309
309
  return _regeneratorRuntime().wrap(function _callee5$(_context5) {
310
310
  while (1) switch (_context5.prev = _context5.next) {
311
311
  case 0:
312
312
  _context5.prev = 0;
313
313
  _context5.next = 3;
314
- return (_this$store$discount3 = this.store.discount) === null || _this$store$discount3 === void 0 ? void 0 : _this$store$discount3.batchSearch(code);
314
+ return (_this$store$discount3 = this.store.discount) === null || _this$store$discount3 === void 0 ? void 0 : _this$store$discount3.batchSearch(code, customerId);
315
315
  case 3:
316
316
  _context5.t0 = _context5.sent;
317
317
  if (_context5.t0) {
@@ -393,7 +393,7 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
393
393
  }
394
394
  }, _callee5, this, [[0, 23]]);
395
395
  }));
396
- function scanCode(_x4) {
396
+ function scanCode(_x4, _x5) {
397
397
  return _scanCode.apply(this, arguments);
398
398
  }
399
399
  return scanCode;
@@ -438,7 +438,7 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
438
438
  }
439
439
  }, _callee6, this);
440
440
  }));
441
- function emitDiscountListChange(_x5) {
441
+ function emitDiscountListChange(_x6) {
442
442
  return _emitDiscountListChange.apply(this, arguments);
443
443
  }
444
444
  return emitDiscountListChange;
@@ -574,7 +574,7 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
574
574
  }
575
575
  }, _callee7, this, [[0, 11]]);
576
576
  }));
577
- function getCustomerWallet(_x6) {
577
+ function getCustomerWallet(_x7) {
578
578
  return _getCustomerWallet.apply(this, arguments);
579
579
  }
580
580
  return getCustomerWallet;
@@ -634,7 +634,7 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
634
634
  }
635
635
  }, _callee8, this, [[0, 18]]);
636
636
  }));
637
- function loadPrepareConfig(_x7) {
637
+ function loadPrepareConfig(_x8) {
638
638
  return _loadPrepareConfig.apply(this, arguments);
639
639
  }
640
640
  return loadPrepareConfig;
@@ -1,3 +1,3 @@
1
- import { Product } from "../../Product";
1
+ import { ProductData } from "../../Product";
2
2
  import { CartItem, IUpdateItemParams } from "../types";
3
- export declare function updateAllCartItemPrice(cartItems: CartItem[], priceData: any, getProduct: (id: number) => Promise<Product | undefined>, updateCart: (item: IUpdateItemParams) => void, updateItemInitInfo: (item: IUpdateItemParams) => void): Promise<void>;
3
+ export declare function updateAllCartItemPrice(cartItems: CartItem[], priceData: any, getProduct: (id: number) => Promise<ProductData | undefined>, updateCart: (item: IUpdateItemParams) => void, updateItemInitInfo: (item: IUpdateItemParams) => void): Promise<void>;
@@ -40,7 +40,7 @@ async function updateAllCartItemPrice(cartItems, priceData, getProduct, updateCa
40
40
  const cartProduct = await getProduct(
41
41
  item.id
42
42
  );
43
- let productInfo = cartProduct == null ? void 0 : cartProduct.getData();
43
+ let productInfo = cartProduct;
44
44
  if (!productInfo) {
45
45
  productInfo = item._productOrigin;
46
46
  }
@@ -20,8 +20,9 @@ export declare class DiscountModule extends BaseModule implements Module, Discou
20
20
  with_discount_card: 0 | 1;
21
21
  customer_id: number;
22
22
  }): Promise<Discount[]>;
23
- batchSearch(code: string): Promise<Discount[]>;
23
+ batchSearch(code: string, customerId?: number): Promise<Discount[]>;
24
24
  filterEnabledDiscountList(discountList: Discount[]): Discount[];
25
+ private checkUsageCreditsLimit;
25
26
  uniqueByProductId(discountList: Discount[]): Discount[];
26
27
  filterDiscountListByProductIds(discountList: Discount[], productIds: number[]): Discount[];
27
28
  calcDiscountApplicableProductTotalPrice(discount: Discount): number | undefined;
@@ -89,22 +89,64 @@ var DiscountModule = class extends import_BaseModule.BaseModule {
89
89
  ) || [];
90
90
  return goodPassList;
91
91
  }
92
- async batchSearch(code) {
92
+ async batchSearch(code, customerId) {
93
93
  const result = await this.request.get(`/machinecode/batch-search`, {
94
94
  code,
95
95
  translate_flag: 1,
96
96
  tags: ["good_pass", "product_discount_card"],
97
97
  available: 1,
98
- relation_product: 1
98
+ relation_product: 1,
99
+ with: ["extensionData"],
100
+ order_behavior_count: 1,
101
+ order_behavior_count_customer_id: customerId || 1
99
102
  });
100
103
  const resultDiscountList = this.filterEnabledDiscountList((result == null ? void 0 : result.data) || []) || [];
101
104
  return resultDiscountList;
102
105
  }
103
106
  filterEnabledDiscountList(discountList) {
104
107
  return discountList.filter(
105
- (discount) => discount.limit_status === "enable" && new import_decimal.default((discount == null ? void 0 : discount.par_value) || 0).minus(new import_decimal.default((discount == null ? void 0 : discount.used_par_value) || 0)).greaterThan(0)
108
+ (discount) => discount.limit_status === "enable" && new import_decimal.default((discount == null ? void 0 : discount.par_value) || 0).minus(new import_decimal.default((discount == null ? void 0 : discount.used_par_value) || 0)).greaterThan(0) && this.checkUsageCreditsLimit(discount)
106
109
  );
107
110
  }
111
+ // 检查使用次数限制
112
+ checkUsageCreditsLimit(discount) {
113
+ if (!discount.extension_data || discount.extension_data.length === 0) {
114
+ return true;
115
+ }
116
+ const usageCreditsData = discount.extension_data.find(
117
+ (data) => data.field_key === "usage_credits"
118
+ );
119
+ if (!usageCreditsData) {
120
+ return true;
121
+ }
122
+ const value = usageCreditsData.value;
123
+ if (value.total_credits && value.total_credits > 0) {
124
+ if ((discount.total_order_behavior_count || 0) >= value.total_credits) {
125
+ return false;
126
+ }
127
+ }
128
+ if (value.per_user_limit && value.per_user_limit > 0) {
129
+ if ((discount.customer_order_behavior_count || 0) >= value.per_user_limit) {
130
+ return false;
131
+ }
132
+ }
133
+ if (value.max_per_day && value.max_per_day > 0) {
134
+ if ((discount.today_order_behavior_count || 0) >= value.max_per_day) {
135
+ return false;
136
+ }
137
+ }
138
+ if (value.max_per_week && value.max_per_week > 0) {
139
+ if ((discount.week_order_behavior_count || 0) >= value.max_per_week) {
140
+ return false;
141
+ }
142
+ }
143
+ if (value.max_per_month && value.max_per_month > 0) {
144
+ if ((discount.month_order_behavior_count || 0) >= value.max_per_month) {
145
+ return false;
146
+ }
147
+ }
148
+ return true;
149
+ }
108
150
  // 根据productIds去重
109
151
  uniqueByProductId(discountList) {
110
152
  return (0, import_utils.uniqueById)(discountList, "product_id");
@@ -36,6 +36,25 @@ interface ApplicableProductDetails {
36
36
  title?: string;
37
37
  };
38
38
  }
39
+ interface UsageCreditsValue {
40
+ total_credits: number;
41
+ per_user_limit: number;
42
+ max_per_day: number;
43
+ max_per_week: number;
44
+ max_per_month: number;
45
+ }
46
+ interface ExtensionData {
47
+ id: number;
48
+ shop_id: number;
49
+ product_id: number;
50
+ field_id: number;
51
+ field_key: string;
52
+ type: string;
53
+ value: UsageCreditsValue | Record<string, any> | string | number | boolean | any[];
54
+ created_at: string | null;
55
+ updated_at: string | null;
56
+ deleted_at: string | null;
57
+ }
39
58
  export interface Discount {
40
59
  id: number;
41
60
  product_name: string;
@@ -70,6 +89,12 @@ export interface Discount {
70
89
  appliedProductDetails: ApplicableProductDetails[];
71
90
  isDisabledForProductUsed?: boolean;
72
91
  amount?: number;
92
+ extension_data?: ExtensionData[];
93
+ total_order_behavior_count?: number;
94
+ today_order_behavior_count?: number;
95
+ week_order_behavior_count?: number;
96
+ month_order_behavior_count?: number;
97
+ customer_order_behavior_count?: number;
73
98
  }
74
99
  export interface DiscountState {
75
100
  discountList: Discount[];
@@ -1,6 +1,5 @@
1
1
  import { Module, PisellCore } from '../../types';
2
2
  import { BaseModule } from '../BaseModule';
3
- import { Product } from '../Product';
4
3
  import { ProductData } from '../Product/types';
5
4
  export * from './types';
6
5
  export declare class ProductList extends BaseModule implements Module {
@@ -26,7 +25,7 @@ export declare class ProductList extends BaseModule implements Module {
26
25
  channel?: string;
27
26
  }): Promise<any>;
28
27
  getProducts(): Promise<ProductData[]>;
29
- getProduct(id: number): Promise<Product | undefined>;
28
+ getProduct(id: number): Promise<ProductData | undefined>;
30
29
  addProduct(products: ProductData[]): Promise<void>;
31
30
  selectProducts(products: ProductData[]): Promise<void>;
32
31
  }
@@ -24,7 +24,6 @@ __export(ProductList_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(ProductList_exports);
26
26
  var import_BaseModule = require("../BaseModule");
27
- var import_Product = require("../Product");
28
27
  var import_types = require("./types");
29
28
  var import_lodash_es = require("lodash-es");
30
29
  __reExport(ProductList_exports, require("./types"), module.exports);
@@ -41,30 +40,15 @@ var ProductList = class extends import_BaseModule.BaseModule {
41
40
  this.store = options.store;
42
41
  this.otherParams = options.otherParams || {};
43
42
  if (Array.isArray((_a = options.initialState) == null ? void 0 : _a.list)) {
44
- this.store.list = options.initialState.list;
43
+ this.store.list = options.initialState.list.slice().sort((a, b) => Number(b.sort) - Number(a.sort));
45
44
  this.core.effects.emit(`${this.name}:changed`, this.store.list);
46
- this.storeChange();
47
45
  } else {
48
46
  this.store.list = [];
49
- this.store.productMap = /* @__PURE__ */ new Map();
50
47
  this.store.selectProducts = [];
51
48
  }
52
49
  this.request = core.getPlugin("request");
53
50
  }
54
51
  async storeChange(path, value) {
55
- var _a;
56
- (_a = this.store.list) == null ? void 0 : _a.forEach((product) => {
57
- const productModule = this.store.productMap.get(`product-${product.id}`);
58
- if (!productModule) {
59
- const newProductModule = new import_Product.Product(
60
- `product_${product.id.toString()}`
61
- );
62
- this.core.registerModule(newProductModule, { initialState: product });
63
- this.store.productMap.set(product.id.toString(), newProductModule);
64
- } else {
65
- productModule.updateData(product);
66
- }
67
- });
68
52
  }
69
53
  async loadProducts({
70
54
  category_ids = [],
@@ -109,8 +93,9 @@ var ProductList = class extends import_BaseModule.BaseModule {
109
93
  },
110
94
  { useCache: true }
111
95
  );
112
- this.addProduct(productsData.data.list);
113
- return productsData.data.list;
96
+ const sortedList = (productsData.data.list || []).slice().sort((a, b) => Number(b.sort) - Number(a.sort));
97
+ this.addProduct(sortedList);
98
+ return sortedList;
114
99
  }
115
100
  async loadProductsPrice({
116
101
  ids = [],
@@ -142,10 +127,8 @@ var ProductList = class extends import_BaseModule.BaseModule {
142
127
  import_types.ProductListHooks.onGetProduct,
143
128
  this.store.list
144
129
  );
145
- const product = this.store.productMap.get(`${id}`);
146
- if (product)
147
- return product;
148
- return void 0;
130
+ const product = this.store.list.find((product2) => product2.id === id);
131
+ return product ? (0, import_lodash_es.cloneDeep)(product) : void 0;
149
132
  }
150
133
  async addProduct(products) {
151
134
  if (!this.store.list) {
@@ -159,7 +142,8 @@ var ProductList = class extends import_BaseModule.BaseModule {
159
142
  this.store.list[index] = n;
160
143
  }
161
144
  });
162
- this.storeChange();
145
+ this.store.list.sort((a, b) => Number(b.sort) - Number(a.sort));
146
+ this.core.effects.emit(`${this.name}:changed`, this.store.list);
163
147
  }
164
148
  async selectProducts(products) {
165
149
  this.store.selectProducts = products;
@@ -1,7 +1,6 @@
1
1
  import { ProductData } from '../Product/types';
2
2
  export interface ProductListData {
3
3
  list: ProductData[];
4
- productMap: Map<string, any>;
5
4
  selectProducts: ProductData[];
6
5
  }
7
6
  export declare enum ProductListHooks {