@pisell/pisellos 3.0.65 → 3.0.67

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.
@@ -15,8 +15,9 @@ export declare const formatDefaultCapacitys: ({ capacity, product_bundle, }: any
15
15
  * @return {*}
16
16
  * @Author: zhiwei.Wang
17
17
  */
18
- export declare const getSumCapacity: ({ capacity }: {
18
+ export declare const getSumCapacity: ({ capacity, num }: {
19
19
  capacity: CapacityItem[];
20
+ num: number;
20
21
  }) => number;
21
22
  /**
22
23
  * 给定购物车数据,返回对应的 capacity 信息和套餐 capacity
@@ -45,3 +46,30 @@ export declare const checkSubResourcesCapacity: (resource: ResourceItem) => void
45
46
  * @returns 如果资源可以容纳额外的容量则返回 true
46
47
  */
47
48
  export declare const checkResourceCanUseByCapacity: (currentCapacity: number, requiredCapacity: number, maxCapacity: number) => boolean;
49
+ /**
50
+ * 计算按资源类型分组的容量占用情况
51
+ *
52
+ * @param {CartItem[]} cartItems 购物车商品列表
53
+ * @param {string} timeSlotStart 时间段开始时间
54
+ * @param {string} timeSlotEnd 时间段结束时间
55
+ * @param {ResourceItem[]} allProductResources 当前商品的所有资源列表
56
+ * @return {Record<string, number>} 返回每种资源类型(form_id)的容量占用
57
+ */
58
+ export declare function calculateCartItemsCapacityUsageByResourceType({ cartItems, timeSlotStart, timeSlotEnd, allProductResources }: {
59
+ cartItems: CartItem[];
60
+ timeSlotStart: string;
61
+ timeSlotEnd: string;
62
+ allProductResources: ResourceItem[];
63
+ }): Record<string, number>;
64
+ /**
65
+ * 获取商品的资源ID列表
66
+ */
67
+ export declare function getResourcesIdsByProduct(product: any): number[];
68
+ /**
69
+ * 检查特定时间段的容量是否足够
70
+ */
71
+ export declare function checkTimeSlotCapacity(timeSlotStart: string, timeSlotEnd: string, cartItems: CartItem[], allResources: ResourceItem[]): {
72
+ success: boolean;
73
+ required: number;
74
+ available: number;
75
+ };
@@ -1,6 +1,16 @@
1
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
4
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
5
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
6
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
7
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
8
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
1
9
  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
2
10
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
3
11
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
12
+ import dayjs from 'dayjs';
13
+
4
14
  /**
5
15
  * @title: 基于选择的商品格式化容量
6
16
  * @description:
@@ -50,7 +60,9 @@ export var formatDefaultCapacitys = function formatDefaultCapacitys(_ref) {
50
60
  * @Author: zhiwei.Wang
51
61
  */
52
62
  export var getSumCapacity = function getSumCapacity(_ref2) {
53
- var capacity = _ref2.capacity;
63
+ var capacity = _ref2.capacity,
64
+ _ref2$num = _ref2.num,
65
+ num = _ref2$num === void 0 ? 1 : _ref2$num;
54
66
  var sum = 0;
55
67
  var _iterator = _createForOfIteratorHelper(capacity || []),
56
68
  _step;
@@ -64,7 +76,7 @@ export var getSumCapacity = function getSumCapacity(_ref2) {
64
76
  } finally {
65
77
  _iterator.f();
66
78
  }
67
- return sum;
79
+ return sum * num;
68
80
  };
69
81
 
70
82
  /**
@@ -81,7 +93,8 @@ export function getCapacityInfoByCartItem(targetCartItem) {
81
93
  product_bundle: targetCartItem._origin.product.product_bundle
82
94
  });
83
95
  var currentCapacity = getSumCapacity({
84
- capacity: formatCapacity
96
+ capacity: formatCapacity,
97
+ num: (targetCartItem === null || targetCartItem === void 0 ? void 0 : targetCartItem.num) || 1
85
98
  });
86
99
  return {
87
100
  formatCapacity: formatCapacity,
@@ -129,4 +142,236 @@ export var checkResourceCanUseByCapacity = function checkResourceCanUseByCapacit
129
142
  return false;
130
143
  }
131
144
  return currentCapacity + requiredCapacity <= maxCapacity;
132
- };
145
+ };
146
+
147
+ /**
148
+ * 计算按资源类型分组的容量占用情况
149
+ *
150
+ * @param {CartItem[]} cartItems 购物车商品列表
151
+ * @param {string} timeSlotStart 时间段开始时间
152
+ * @param {string} timeSlotEnd 时间段结束时间
153
+ * @param {ResourceItem[]} allProductResources 当前商品的所有资源列表
154
+ * @return {Record<string, number>} 返回每种资源类型(form_id)的容量占用
155
+ */
156
+ export function calculateCartItemsCapacityUsageByResourceType(_ref3) {
157
+ var cartItems = _ref3.cartItems,
158
+ timeSlotStart = _ref3.timeSlotStart,
159
+ timeSlotEnd = _ref3.timeSlotEnd,
160
+ allProductResources = _ref3.allProductResources;
161
+ // 按 form_id 分组当前商品的资源
162
+ var resourceTypeMap = {};
163
+ allProductResources.forEach(function (resource) {
164
+ var _resource$form_id;
165
+ var formId = ((_resource$form_id = resource.form_id) === null || _resource$form_id === void 0 ? void 0 : _resource$form_id.toString()) || 'default';
166
+ if (!resourceTypeMap[formId]) {
167
+ resourceTypeMap[formId] = [];
168
+ }
169
+ resourceTypeMap[formId].push(resource);
170
+ });
171
+
172
+ // 计算每种资源类型的容量占用
173
+ var capacityUsageByType = {};
174
+ Object.keys(resourceTypeMap).forEach(function (formId) {
175
+ var totalUsage = 0;
176
+ var resourcesInThisType = resourceTypeMap[formId];
177
+ var resourceIdsInThisType = resourcesInThisType.map(function (r) {
178
+ return r.id;
179
+ });
180
+ cartItems.forEach(function (cartItem) {
181
+ // 检查该商品是否已经选定了时间
182
+ if (!cartItem.start_time || !cartItem.end_time) return;
183
+
184
+ // 构建该商品的时间段
185
+ var itemStart = "".concat(cartItem.start_date, " ").concat(cartItem.start_time);
186
+ var itemEnd = "".concat(cartItem.end_date || cartItem.start_date, " ").concat(cartItem.end_time);
187
+
188
+ // 检查时间段是否有重叠
189
+ var hasTimeOverlap = !(dayjs(itemEnd).isBefore(dayjs(timeSlotStart)) || dayjs(itemStart).isAfter(dayjs(timeSlotEnd)));
190
+ if (!hasTimeOverlap) return;
191
+
192
+ // 检查该商品的资源配置中是否需要这种类型的资源
193
+ // 由于购物车商品只选定了时间,没有选定具体资源,我们需要看商品的资源配置
194
+ var productResourceIds = getResourcesIdsByProduct(cartItem._productOrigin);
195
+ var hasResourceTypeOverlap = productResourceIds.some(function (id) {
196
+ return resourceIdsInThisType.includes(id);
197
+ });
198
+ if (!hasResourceTypeOverlap) return;
199
+
200
+ // 计算该商品的容量占用
201
+ var _getCapacityInfoByCar = getCapacityInfoByCartItem(cartItem),
202
+ currentCapacity = _getCapacityInfoByCar.currentCapacity;
203
+ totalUsage += currentCapacity;
204
+ });
205
+ capacityUsageByType[formId] = totalUsage;
206
+ });
207
+ return capacityUsageByType;
208
+ }
209
+
210
+ /**
211
+ * 获取商品的资源ID列表
212
+ */
213
+ export function getResourcesIdsByProduct(product) {
214
+ var _product$product_reso, _product$product_reso2;
215
+ var tempResourceIds = [];
216
+ product === null || product === void 0 || (_product$product_reso = product.product_resource) === null || _product$product_reso === void 0 || (_product$product_reso = _product$product_reso.resources) === null || _product$product_reso === void 0 || (_product$product_reso2 = _product$product_reso.forEach) === null || _product$product_reso2 === void 0 || _product$product_reso2.call(_product$product_reso, function (resource) {
217
+ if ((resource === null || resource === void 0 ? void 0 : resource.status) == 1) {
218
+ var _resource$default_res, _resource$optional_re;
219
+ if (resource !== null && resource !== void 0 && (_resource$default_res = resource.default_resource) !== null && _resource$default_res !== void 0 && _resource$default_res.length) {
220
+ tempResourceIds.push.apply(tempResourceIds, _toConsumableArray(resource === null || resource === void 0 ? void 0 : resource.default_resource));
221
+ } else if (resource !== null && resource !== void 0 && (_resource$optional_re = resource.optional_resource) !== null && _resource$optional_re !== void 0 && _resource$optional_re.length) {
222
+ tempResourceIds.push.apply(tempResourceIds, _toConsumableArray(resource === null || resource === void 0 ? void 0 : resource.optional_resource));
223
+ }
224
+ }
225
+ });
226
+ return tempResourceIds;
227
+ }
228
+
229
+ /**
230
+ * 检查特定时间段的容量是否足够
231
+ */
232
+ export function checkTimeSlotCapacity(timeSlotStart, timeSlotEnd, cartItems, allResources) {
233
+ // 按资源类型分组
234
+ var resourceTypeMap = {};
235
+ allResources.forEach(function (resource) {
236
+ var _resource$form_id2;
237
+ var formId = ((_resource$form_id2 = resource.form_id) === null || _resource$form_id2 === void 0 ? void 0 : _resource$form_id2.toString()) || 'default';
238
+ if (!resourceTypeMap[formId]) {
239
+ resourceTypeMap[formId] = [];
240
+ }
241
+ resourceTypeMap[formId].push(resource);
242
+ });
243
+
244
+ // 计算每种资源类型需要的总容量
245
+ var requiredCapacityByType = {};
246
+ cartItems.forEach(function (cartItem) {
247
+ var productResourceIds = getResourcesIdsByProduct(cartItem._productOrigin);
248
+ var _getCapacityInfoByCar2 = getCapacityInfoByCartItem(cartItem),
249
+ currentCapacity = _getCapacityInfoByCar2.currentCapacity;
250
+ Object.keys(resourceTypeMap).forEach(function (formId) {
251
+ var _cartItem$_productOri;
252
+ var resourcesInType = resourceTypeMap[formId];
253
+ var resourceIdsInType = resourcesInType.map(function (r) {
254
+ return r.id;
255
+ });
256
+ var selectType = (_cartItem$_productOri = cartItem._productOrigin) === null || _cartItem$_productOri === void 0 || (_cartItem$_productOri = _cartItem$_productOri.product_resource) === null || _cartItem$_productOri === void 0 || (_cartItem$_productOri = _cartItem$_productOri.resources) === null || _cartItem$_productOri === void 0 || (_cartItem$_productOri = _cartItem$_productOri.find(function (r) {
257
+ var _r$id;
258
+ return ((_r$id = r.id) === null || _r$id === void 0 ? void 0 : _r$id.toString()) === formId;
259
+ })) === null || _cartItem$_productOri === void 0 ? void 0 : _cartItem$_productOri.type;
260
+
261
+ // 检查该商品是否需要这种类型的资源
262
+ var needsThisResourceType = productResourceIds.some(function (id) {
263
+ return resourceIdsInType.includes(id);
264
+ });
265
+ if (needsThisResourceType) {
266
+ // 需要判断是单个预约还是多个预约,如果是单个预约,不用加 capacity,只用+1
267
+ if (selectType === 'single') {
268
+ requiredCapacityByType[formId] = (requiredCapacityByType[formId] || 0) + ((cartItem === null || cartItem === void 0 ? void 0 : cartItem.num) || 1);
269
+ } else {
270
+ requiredCapacityByType[formId] = (requiredCapacityByType[formId] || 0) + currentCapacity;
271
+ }
272
+ // requiredCapacityByType[formId] = (requiredCapacityByType[formId] || 0) + currentCapacity;
273
+ }
274
+ });
275
+ });
276
+
277
+ // 检查每种资源类型是否有足够的容量
278
+ var _loop = function _loop() {
279
+ var _resourceTypeConfig, _resourceTypeConfig2;
280
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
281
+ formId = _Object$entries$_i[0],
282
+ requiredCapacity = _Object$entries$_i[1];
283
+ var resourcesInType = resourceTypeMap[formId];
284
+ if (resourcesInType.length === 0) return 0; // continue
285
+
286
+ // 从购物车商品中获取正确的资源类型配置
287
+ var resourceTypeConfig = null;
288
+ var _iterator2 = _createForOfIteratorHelper(cartItems),
289
+ _step2;
290
+ try {
291
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
292
+ var _cartItem$_productOri2;
293
+ var cartItem = _step2.value;
294
+ if ((_cartItem$_productOri2 = cartItem._productOrigin) !== null && _cartItem$_productOri2 !== void 0 && (_cartItem$_productOri2 = _cartItem$_productOri2.product_resource) !== null && _cartItem$_productOri2 !== void 0 && _cartItem$_productOri2.resources) {
295
+ resourceTypeConfig = cartItem._productOrigin.product_resource.resources.find(function (r) {
296
+ var _r$id2;
297
+ return ((_r$id2 = r.id) === null || _r$id2 === void 0 ? void 0 : _r$id2.toString()) === formId && r.status === 1;
298
+ });
299
+ if (resourceTypeConfig) break;
300
+ }
301
+ }
302
+
303
+ // 确定这种资源类型的预约类型
304
+ } catch (err) {
305
+ _iterator2.e(err);
306
+ } finally {
307
+ _iterator2.f();
308
+ }
309
+ var isMultipleBooking = ((_resourceTypeConfig = resourceTypeConfig) === null || _resourceTypeConfig === void 0 ? void 0 : _resourceTypeConfig.type) === 'multiple';
310
+ console.log("capacity.ts - \u8D44\u6E90\u7C7B\u578B ".concat(formId, " \u914D\u7F6E:"), {
311
+ resourceTypeConfig: resourceTypeConfig,
312
+ type: (_resourceTypeConfig2 = resourceTypeConfig) === null || _resourceTypeConfig2 === void 0 ? void 0 : _resourceTypeConfig2.type,
313
+ isMultipleBooking: isMultipleBooking,
314
+ requiredCapacity: requiredCapacity
315
+ });
316
+ if (isMultipleBooking) {
317
+ // 多个预约:计算总可用容量
318
+ var totalAvailableCapacity = 0;
319
+ resourcesInType.forEach(function (resource) {
320
+ // 过滤出在时间段内的资源时间片
321
+ var availableTimes = resource.times.filter(function (time) {
322
+ return !dayjs(time.start_at).isAfter(dayjs(timeSlotStart), 'minute') && !dayjs(time.end_at).isBefore(dayjs(timeSlotEnd), 'minute') || dayjs(time.start_at).isBefore(dayjs(timeSlotEnd), 'minute') && dayjs(time.end_at).isAfter(dayjs(timeSlotStart), 'minute');
323
+ });
324
+ if (availableTimes.length > 0) {
325
+ // 简化逻辑:如果资源在时间段内有可用时间,就计算其容量
326
+ totalAvailableCapacity += resource.capacity || 0;
327
+ }
328
+ });
329
+ console.log("capacity.ts - \u8D44\u6E90\u7C7B\u578B ".concat(formId, " \u591A\u4E2A\u9884\u7EA6\u68C0\u67E5: \u603B\u5BB9\u91CF ").concat(totalAvailableCapacity, ", \u9700\u6C42 ").concat(requiredCapacity));
330
+ if (totalAvailableCapacity < requiredCapacity) {
331
+ console.log("\u8D44\u6E90\u7C7B\u578B ".concat(formId, " \u5BB9\u91CF\u4E0D\u8DB3: \u9700\u8981 ").concat(requiredCapacity, ", \u53EF\u7528 ").concat(totalAvailableCapacity));
332
+ return {
333
+ v: {
334
+ success: false,
335
+ required: requiredCapacity,
336
+ available: totalAvailableCapacity
337
+ }
338
+ };
339
+ }
340
+ } else {
341
+ // 单个预约:计算可用资源数量
342
+ var availableResourceCount = 0;
343
+ resourcesInType.forEach(function (resource) {
344
+ // 过滤出在时间段内的资源时间片
345
+ var availableTimes = resource.times.filter(function (time) {
346
+ var _time$event_list;
347
+ return !dayjs(time.start_at).isAfter(dayjs(timeSlotStart), 'minute') && !dayjs(time.end_at).isBefore(dayjs(timeSlotEnd), 'minute') || dayjs(time.start_at).isBefore(dayjs(timeSlotEnd), 'minute') && dayjs(time.end_at).isAfter(dayjs(timeSlotStart), 'minute') && ((_time$event_list = time.event_list) === null || _time$event_list === void 0 ? void 0 : _time$event_list.length) === 0;
348
+ });
349
+ if (availableTimes.length > 0) {
350
+ availableResourceCount++;
351
+ }
352
+ });
353
+ console.log("capacity.ts - \u8D44\u6E90\u7C7B\u578B ".concat(formId, " \u5355\u4E2A\u9884\u7EA6\u68C0\u67E5: \u53EF\u7528\u8D44\u6E90\u6570 ").concat(availableResourceCount, ", \u9700\u6C42 ").concat(requiredCapacity));
354
+ if (availableResourceCount < requiredCapacity) {
355
+ console.log("\u8D44\u6E90\u7C7B\u578B ".concat(formId, " \u6570\u91CF\u4E0D\u8DB3: \u9700\u8981 ").concat(requiredCapacity, ", \u53EF\u7528 ").concat(availableResourceCount));
356
+ return {
357
+ v: {
358
+ success: false,
359
+ required: requiredCapacity,
360
+ available: availableResourceCount
361
+ }
362
+ };
363
+ }
364
+ }
365
+ },
366
+ _ret;
367
+ for (var _i = 0, _Object$entries = Object.entries(requiredCapacityByType); _i < _Object$entries.length; _i++) {
368
+ _ret = _loop();
369
+ if (_ret === 0) continue;
370
+ if (_ret) return _ret.v;
371
+ }
372
+ return {
373
+ success: true,
374
+ required: 0,
375
+ available: 0
376
+ };
377
+ }
@@ -20,6 +20,21 @@ export interface ResourceItem {
20
20
  interface BookingItem {
21
21
  [key: string]: any;
22
22
  }
23
+ /**
24
+ * @title: 判断两个时间段是否有重叠
25
+ * @description:
26
+ * @param {object} event
27
+ * @param {object} current
28
+ * @return {*}
29
+ * @Author: zhiwei.Wang
30
+ */
31
+ export declare const isConflict: (event: {
32
+ start_at: DateType;
33
+ end_at: DateType;
34
+ }, current: {
35
+ start_at: DateType;
36
+ end_at?: DateType;
37
+ }) => boolean;
23
38
  /**
24
39
  * @title: 获取时间切片是否可用
25
40
  * @description: 根据时间切片、资源、当前预约量判断时间切片是否可用
@@ -42,7 +42,7 @@ var getUseableEventCount = function getUseableEventCount(eventList, current) {
42
42
  * @return {*}
43
43
  * @Author: zhiwei.Wang
44
44
  */
45
- var isConflict = function isConflict(event, current) {
45
+ export var isConflict = function isConflict(event, current) {
46
46
  var eventStart = dayjs(event.start_at);
47
47
  var eventEnd = dayjs(event.end_at);
48
48
  var currentStart = dayjs(current.start_at);
@@ -0,0 +1,29 @@
1
+ import { CartItem } from '../../../modules';
2
+ /**
3
+ * 检测商品库存是否足够
4
+ *
5
+ * 只有同时满足以下条件时才会进行库存检测:
6
+ * - is_track 开启(值为 1 或 true)
7
+ * - over_sold 为 0(不允许超卖)
8
+ *
9
+ * 对于多规格商品:
10
+ * - 如果有 product_variant_id,则从 productData.variant 数组中查找对应规格
11
+ * - 使用规格的 is_track, over_sold, stock_quantity 而不是主商品的
12
+ *
13
+ * @param productData 商品数据(需包含 is_track, over_sold, stock_quantity 字段,多规格商品需包含 variant 数组)
14
+ * @param product_variant_id 商品变体ID,如果存在则为多规格商品
15
+ * @param quantity 需要添加的数量
16
+ * @param bundle 套餐配置(子商品需包含 is_track, over_sold, stock_quantity 字段)
17
+ * @param currentCartItems 当前购物车商品列表
18
+ * @returns 库存检测结果
19
+ */
20
+ export declare function checkProductStock({ productData, product_variant_id, quantity, bundle, currentCartItems }: {
21
+ productData: any;
22
+ product_variant_id?: any;
23
+ quantity: number;
24
+ bundle?: any[];
25
+ currentCartItems: CartItem[];
26
+ }): {
27
+ success: boolean;
28
+ errorCode?: string;
29
+ };
@@ -0,0 +1,126 @@
1
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
2
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
3
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
4
+ /**
5
+ * 检测商品库存是否足够
6
+ *
7
+ * 只有同时满足以下条件时才会进行库存检测:
8
+ * - is_track 开启(值为 1 或 true)
9
+ * - over_sold 为 0(不允许超卖)
10
+ *
11
+ * 对于多规格商品:
12
+ * - 如果有 product_variant_id,则从 productData.variant 数组中查找对应规格
13
+ * - 使用规格的 is_track, over_sold, stock_quantity 而不是主商品的
14
+ *
15
+ * @param productData 商品数据(需包含 is_track, over_sold, stock_quantity 字段,多规格商品需包含 variant 数组)
16
+ * @param product_variant_id 商品变体ID,如果存在则为多规格商品
17
+ * @param quantity 需要添加的数量
18
+ * @param bundle 套餐配置(子商品需包含 is_track, over_sold, stock_quantity 字段)
19
+ * @param currentCartItems 当前购物车商品列表
20
+ * @returns 库存检测结果
21
+ */
22
+ export function checkProductStock(_ref) {
23
+ var productData = _ref.productData,
24
+ product_variant_id = _ref.product_variant_id,
25
+ quantity = _ref.quantity,
26
+ bundle = _ref.bundle,
27
+ currentCartItems = _ref.currentCartItems;
28
+ // 1. 检测主商品库存
29
+ // 处理多规格商品:如果有product_variant_id,则从variant数组中查找对应的规格配置
30
+ var mainProductConfig = productData;
31
+ if (product_variant_id && productData.variant && Array.isArray(productData.variant)) {
32
+ var variant = productData.variant.find(function (v) {
33
+ return v.id === product_variant_id;
34
+ });
35
+ if (variant) {
36
+ mainProductConfig = variant; // 使用规格的配置替换主商品配置
37
+ }
38
+ }
39
+
40
+ // 只有开启库存控制且不允许超卖时才需要检测主商品库存
41
+ var isMainProductTrackingEnabled = mainProductConfig.is_track === 1 || mainProductConfig.is_track === true;
42
+ var isMainProductOverSoldDisabled = mainProductConfig.over_sold === 0;
43
+ if (isMainProductTrackingEnabled && isMainProductOverSoldDisabled) {
44
+ var existingQuantity = currentCartItems.reduce(function (total, cartItem) {
45
+ var _cartItem$_productOri, _cartItem$_productOri2, _cartItem$_productOri3;
46
+ // 检查是否为相同商品(比较商品ID和变体ID)
47
+ var isSameProduct = ((_cartItem$_productOri = cartItem._productOrigin) === null || _cartItem$_productOri === void 0 ? void 0 : _cartItem$_productOri.id) === productData.id;
48
+ var isSameVariant = !product_variant_id && !((_cartItem$_productOri2 = cartItem._productOrigin) !== null && _cartItem$_productOri2 !== void 0 && _cartItem$_productOri2.product_variant_id) || ((_cartItem$_productOri3 = cartItem._productOrigin) === null || _cartItem$_productOri3 === void 0 ? void 0 : _cartItem$_productOri3.product_variant_id) === product_variant_id;
49
+ if (isSameProduct && isSameVariant) {
50
+ return total + (cartItem.num || 0);
51
+ }
52
+ return total;
53
+ }, 0);
54
+ var totalQuantity = existingQuantity + quantity;
55
+ var stockQuantity = mainProductConfig.stock_quantity;
56
+
57
+ // 检查主商品库存是否足够
58
+ if (stockQuantity !== undefined && stockQuantity !== null && totalQuantity > stockQuantity) {
59
+ return {
60
+ success: false,
61
+ errorCode: 'not_enough_stock'
62
+ };
63
+ }
64
+ }
65
+
66
+ // 2. 检测套餐商品库存
67
+ if (bundle && Array.isArray(bundle)) {
68
+ // 直接遍历套餐商品数组
69
+ var _iterator = _createForOfIteratorHelper(bundle),
70
+ _step;
71
+ try {
72
+ var _loop = function _loop() {
73
+ var bundleItem = _step.value;
74
+ var bundleProductId = bundleItem.bundle_product_id;
75
+ var bundleStockQuantity = bundleItem.stock_quantity;
76
+ var bundleRequiredQuantity = (bundleItem.num || 1) * quantity; // 子商品需求数量 = 子商品配置数量 * 主商品购买数量
77
+
78
+ // 检查套餐子商品是否需要进行库存控制
79
+ var isBundleTrackingEnabled = bundleItem.is_track === 1 || bundleItem.is_track === true;
80
+ var isBundleOverSoldDisabled = bundleItem.over_sold === 0;
81
+
82
+ // 跳过没有开启库存控制或允许超卖的子商品
83
+ if (!isBundleTrackingEnabled || !isBundleOverSoldDisabled) return 0; // continue
84
+
85
+ // 跳过没有库存配置的子商品
86
+ if (bundleStockQuantity === undefined || bundleStockQuantity === null) return 0; // continue
87
+
88
+ // 计算购物车中已有的相同子商品数量
89
+ var existingBundleQuantity = currentCartItems.reduce(function (total, cartItem) {
90
+ // 检查购物车中商品的套餐配置
91
+ if (!cartItem._bundleOrigin || !Array.isArray(cartItem._bundleOrigin)) return total;
92
+ cartItem._bundleOrigin.forEach(function (cartBundleItem) {
93
+ if (cartBundleItem.bundle_product_id === bundleProductId) {
94
+ total += (cartBundleItem.num || 1) * (cartItem.num || 1);
95
+ }
96
+ });
97
+ return total;
98
+ }, 0);
99
+ var totalBundleQuantity = existingBundleQuantity + bundleRequiredQuantity;
100
+
101
+ // 检查子商品库存是否足够
102
+ if (totalBundleQuantity > bundleStockQuantity) {
103
+ return {
104
+ v: {
105
+ success: false,
106
+ errorCode: 'not_enough_stock'
107
+ }
108
+ };
109
+ }
110
+ },
111
+ _ret;
112
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
113
+ _ret = _loop();
114
+ if (_ret === 0) continue;
115
+ if (_ret) return _ret.v;
116
+ }
117
+ } catch (err) {
118
+ _iterator.e(err);
119
+ } finally {
120
+ _iterator.f();
121
+ }
122
+ }
123
+ return {
124
+ success: true
125
+ };
126
+ }
@@ -305,7 +305,7 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
305
305
  key: "scanCode",
306
306
  value: function () {
307
307
  var _scanCode = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(code, customerId) {
308
- var _this$store$discount3, resultDiscountList, rulesModule, withScanList, _ref3, newProductList, newDiscountList, isAvailable, _this$options$otherPa6;
308
+ var _this$store$discount3, resultDiscountList, rulesModule, withScanList, currentSelectedDiscountList, _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:
@@ -348,7 +348,25 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
348
348
  return _objectSpread(_objectSpread({}, item), {}, {
349
349
  isScan: true
350
350
  });
351
+ }); // 如果扫回来的券当前有选中的,则不进行计算
352
+ currentSelectedDiscountList = this.getDiscountList().filter(function (n) {
353
+ return n.isSelected;
351
354
  });
355
+ if (!(currentSelectedDiscountList.length && currentSelectedDiscountList.some(function (n) {
356
+ return withScanList.some(function (m) {
357
+ return m.id === n.id;
358
+ });
359
+ }))) {
360
+ _context5.next = 16;
361
+ break;
362
+ }
363
+ return _context5.abrupt("return", {
364
+ type: "clientCalc",
365
+ isAvailable: true,
366
+ productList: this.store.productList || [],
367
+ discountList: this.getDiscountList()
368
+ });
369
+ case 16:
352
370
  _ref3 = rulesModule.isDiscountListAvailable({
353
371
  productList: this.store.productList || [],
354
372
  oldDiscountList: this.getDiscountList(),
@@ -359,26 +377,26 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
359
377
  discountList: this.getDiscountList()
360
378
  }, newProductList = _ref3.productList, newDiscountList = _ref3.discountList, isAvailable = _ref3.isAvailable;
361
379
  if (!isAvailable) {
362
- _context5.next = 20;
380
+ _context5.next = 23;
363
381
  break;
364
382
  }
365
383
  this.setDiscountList(newDiscountList || []);
366
384
  this.setProductList(newProductList || []);
367
385
  if (!(this.isWalkIn() && resultDiscountList.length && ((_this$options$otherPa6 = this.options.otherParams) === null || _this$options$otherPa6 === void 0 ? void 0 : _this$options$otherPa6.platform) === 'shop')) {
368
- _context5.next = 20;
386
+ _context5.next = 23;
369
387
  break;
370
388
  }
371
- _context5.next = 20;
389
+ _context5.next = 23;
372
390
  return this.getCustomerWallet(resultDiscountList[0].customer_id);
373
- case 20:
391
+ case 23:
374
392
  return _context5.abrupt("return", {
375
393
  type: "clientCalc",
376
394
  isAvailable: isAvailable || false,
377
395
  productList: newProductList || this.store.productList || [],
378
396
  discountList: newDiscountList || this.getDiscountList()
379
397
  });
380
- case 23:
381
- _context5.prev = 23;
398
+ case 26:
399
+ _context5.prev = 26;
382
400
  _context5.t1 = _context5["catch"](0);
383
401
  console.error('[ShopDiscount] 扫码出错:', _context5.t1);
384
402
  return _context5.abrupt("return", {
@@ -387,11 +405,11 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
387
405
  productList: this.store.productList || [],
388
406
  discountList: this.getDiscountList()
389
407
  });
390
- case 27:
408
+ case 30:
391
409
  case "end":
392
410
  return _context5.stop();
393
411
  }
394
- }, _callee5, this, [[0, 23]]);
412
+ }, _callee5, this, [[0, 26]]);
395
413
  }));
396
414
  function scanCode(_x4, _x5) {
397
415
  return _scanCode.apply(this, arguments);
@@ -89,11 +89,19 @@ var ProductList = class extends import_BaseModule.BaseModule {
89
89
  front_end_cache_id: cacheId,
90
90
  // client_schedule_ids: schedule_ids,
91
91
  schedule_date,
92
- application_code: (_b = this.otherParams) == null ? void 0 : _b.channel
92
+ application_code: (_b = this.otherParams) == null ? void 0 : _b.channel,
93
+ is_eject: 1
93
94
  },
94
95
  { useCache: true }
95
96
  );
96
97
  const sortedList = (productsData.data.list || []).slice().sort((a, b) => Number(b.sort) - Number(a.sort));
98
+ if (sortedList.length) {
99
+ sortedList.forEach((n) => {
100
+ if (n.is_eject !== 1 && n["schedule.ids"] && n["schedule.ids"].length) {
101
+ n.is_eject = 1;
102
+ }
103
+ });
104
+ }
97
105
  this.addProduct(sortedList);
98
106
  return sortedList;
99
107
  }