@pisell/pisellos 1.0.85 → 1.0.87

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.
@@ -36,6 +36,7 @@ module.exports = __toCommonJS(ShopDiscount_exports);
36
36
  var import_BaseModule = require("../../modules/BaseModule");
37
37
  var import_Discount = require("../../modules/Discount");
38
38
  var import_Rules = require("../../modules/Rules");
39
+ var import_utils = require("./utils");
39
40
  var import_decimal = __toESM(require("decimal.js"));
40
41
  var import_lodash_es = require("lodash-es");
41
42
  var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
@@ -50,7 +51,9 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
50
51
  productList: [],
51
52
  discount: null,
52
53
  rules: null,
53
- originalDiscountList: []
54
+ originalDiscountList: [],
55
+ currentBookingTime: "",
56
+ filteredDiscountList: []
54
57
  };
55
58
  }
56
59
  // =========== 生命周期方法 ===========
@@ -139,6 +142,44 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
139
142
  );
140
143
  }
141
144
  // =========== 公共 API ===========
145
+ // 设置预约时间
146
+ // public async setBookingTime(bookingTime: string | null): Promise<void> {
147
+ // if (this.store.currentBookingTime !== bookingTime) {
148
+ // this.store.currentBookingTime = bookingTime;
149
+ //
150
+ // // 更新过滤后的优惠券列表
151
+ // await this.updateFilteredDiscountList();
152
+ // }
153
+ // }
154
+ // 获取当前预约时间
155
+ getCurrentBookingTime() {
156
+ return this.store.currentBookingTime;
157
+ }
158
+ // 根据预约时间过滤优惠券列表
159
+ filterDiscountListByBookingTime(discountList, bookingTime) {
160
+ if ((0, import_utils.isAllNormalProduct)(this.store.productList || [])) {
161
+ return discountList;
162
+ }
163
+ return (0, import_utils.filterDiscountListByBookingTime)(discountList, bookingTime);
164
+ }
165
+ // 更新过滤后的优惠券列表
166
+ // private async updateFilteredDiscountList(): Promise<void> {
167
+ // const originalList = this.store.originalDiscountList;
168
+ // const filteredList = this.filterDiscountListByBookingTime(originalList, this.store.currentBookingTime);
169
+ //
170
+ // this.store.filteredDiscountList = filteredList;
171
+ //
172
+ // // 更新 DiscountModule 中的优惠券列表
173
+ // this.setDiscountList(filteredList);
174
+ //
175
+ // if (this.store.productList?.length) {
176
+ // const result = this.calcDiscount(this.store.productList);
177
+ // await this.core.effects.emit(
178
+ // ShopDiscountHooks.onLoadPrepareCalcResult,
179
+ // result,
180
+ // );
181
+ // }
182
+ // }
142
183
  // 设置客户
143
184
  async setCustomer(customer) {
144
185
  var _a;
@@ -427,7 +468,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
427
468
  }
428
469
  // 加载准备配置
429
470
  async loadPrepareConfig(params) {
430
- var _a, _b, _c, _d;
471
+ var _a, _b, _c, _d, _e;
431
472
  try {
432
473
  const customerId = params.customerId || ((_a = this.getCustomer()) == null ? void 0 : _a.id);
433
474
  const goodPassList = await ((_b = this.store.discount) == null ? void 0 : _b.loadPrepareConfig({
@@ -443,8 +484,11 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
443
484
  const newGoodPassList = goodPassList == null ? void 0 : goodPassList.filter((n) => !scanDiscountIds.includes(n.id));
444
485
  const newDiscountList = [...scanDiscount, ...newGoodPassList || []];
445
486
  this.store.originalDiscountList = newDiscountList;
446
- this.setDiscountList(newDiscountList || []);
447
- if ((_d = this.store.productList) == null ? void 0 : _d.length) {
487
+ await ((_d = this.store.discount) == null ? void 0 : _d.setOriginalDiscountList(newDiscountList));
488
+ const filteredDiscountList = this.filterDiscountListByBookingTime(newDiscountList, this.store.currentBookingTime);
489
+ this.store.filteredDiscountList = filteredDiscountList;
490
+ this.setDiscountList(filteredDiscountList || []);
491
+ if ((_e = this.store.productList) == null ? void 0 : _e.length) {
448
492
  const result = this.calcDiscount(this.store.productList);
449
493
  await this.core.effects.emit(
450
494
  `${this.name}:onLoadPrepareCalcResult`,
@@ -453,7 +497,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
453
497
  }
454
498
  await this.core.effects.emit(
455
499
  `${this.name}:onLoadDiscountList`,
456
- newDiscountList
500
+ filteredDiscountList
457
501
  );
458
502
  } catch (error) {
459
503
  console.error("[ShopDiscount] 加载准备配置出错:", error);
@@ -1,5 +1,6 @@
1
- import { DiscountModule, Discount } from '../../modules/Discount';
1
+ import { DiscountModule } from '../../modules/Discount';
2
2
  import { RulesModule } from '../../modules/Rules';
3
+ import { Discount } from "../../modules/Discount/types";
3
4
  export declare enum ShopDiscountHooks {
4
5
  onInited = "shopDiscount:onInited",
5
6
  onDestroy = "shopDiscount:onDestroy",
@@ -23,6 +24,8 @@ export interface ShopDiscountState {
23
24
  rules: RulesModule | null;
24
25
  productList: Record<string, any>[];
25
26
  originalDiscountList: Discount[];
27
+ currentBookingTime: string | null;
28
+ filteredDiscountList: Discount[];
26
29
  }
27
30
  export interface SetDiscountSelectedParams {
28
31
  discountId: number;
@@ -1,5 +1,7 @@
1
1
  import { Discount } from "../../modules/Discount/types";
2
2
  export declare const uniqueById: <T>(arr: T[], key?: string) => T[];
3
+ export declare const isNormalProductByDurationSchedule: (item: any) => boolean;
4
+ export declare const isAllNormalProduct: (items: any[]) => boolean;
3
5
  /**
4
6
  * 获取折扣金额 基于折扣卡类型计算
5
7
  * 商品券:直接返回商品价格
@@ -17,3 +19,49 @@ export declare const getDiscountListAmountTotal: (discount: Discount[]) => any;
17
19
  * @returns
18
20
  */
19
21
  export declare const getDiscountListAmount: (discount: Discount[]) => any;
22
+ export interface ScheduleItem {
23
+ id: number;
24
+ name: string | {
25
+ [key: string]: string;
26
+ };
27
+ type: 'standard' | 'time-slots' | 'designation';
28
+ start_time: string | null;
29
+ end_time: string | null;
30
+ repeat_type: 'none' | 'daily' | 'weekly';
31
+ repeat_rule: {
32
+ end: {
33
+ type: 'never' | 'date' | 'occurrence';
34
+ end_date: string | null;
35
+ occurrence: number | null;
36
+ };
37
+ frequency: number;
38
+ excluded_date: Array<{
39
+ start: string;
40
+ end: string;
41
+ }>;
42
+ included_date: Array<{
43
+ start: string;
44
+ end: string;
45
+ }>;
46
+ frequency_date: number[];
47
+ } | null;
48
+ designation: Array<{
49
+ start_date: string;
50
+ start_time: string;
51
+ end_date: string;
52
+ end_time: string;
53
+ }> | null;
54
+ is_all: number;
55
+ time_slot: Array<{
56
+ start_time: string;
57
+ end_time: string;
58
+ }>;
59
+ }
60
+ export declare const getDateIsInSchedule: (dateTime: string, scheduleList: ScheduleItem[]) => boolean;
61
+ /**
62
+ * 根据预约时间过滤优惠券列表
63
+ * @param discountList 优惠券列表
64
+ * @param bookingTime 预约时间 (格式: YYYY-MM-DD HH:mm:ss)
65
+ * @returns 过滤后的优惠券列表
66
+ */
67
+ export declare const filterDiscountListByBookingTime: (discountList: Discount[], bookingTime: string | null) => Discount[];
@@ -29,17 +29,29 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/solution/ShopDiscount/utils.ts
30
30
  var utils_exports = {};
31
31
  __export(utils_exports, {
32
+ filterDiscountListByBookingTime: () => filterDiscountListByBookingTime,
33
+ getDateIsInSchedule: () => getDateIsInSchedule,
32
34
  getDiscountAmount: () => getDiscountAmount,
33
35
  getDiscountListAmount: () => getDiscountListAmount,
34
36
  getDiscountListAmountTotal: () => getDiscountListAmountTotal,
37
+ isAllNormalProduct: () => isAllNormalProduct,
38
+ isNormalProductByDurationSchedule: () => isNormalProductByDurationSchedule,
35
39
  uniqueById: () => uniqueById
36
40
  });
37
41
  module.exports = __toCommonJS(utils_exports);
38
42
  var import_decimal = __toESM(require("decimal.js"));
43
+ var import_dayjs = __toESM(require("dayjs"));
39
44
  var uniqueById = (arr, key = "id") => {
40
45
  const seen = /* @__PURE__ */ new Set();
41
46
  return arr.filter((item) => !seen.has(item[key]) && seen.add(item[key]));
42
47
  };
48
+ var isNormalProductByDurationSchedule = (item) => {
49
+ var _a, _b;
50
+ return !(item == null ? void 0 : item.duration) && !((_a = item == null ? void 0 : item.schedules) == null ? void 0 : _a.length) && !((_b = item == null ? void 0 : item["schedule.ids"]) == null ? void 0 : _b.length);
51
+ };
52
+ var isAllNormalProduct = (items) => {
53
+ return items.every((item) => isNormalProductByDurationSchedule(item));
54
+ };
43
55
  var getDiscountAmount = (discount, total, price) => {
44
56
  var _a;
45
57
  if (discount.tag === "good_pass") {
@@ -61,10 +73,238 @@ var getDiscountListAmount = (discount) => {
61
73
  return new import_decimal.default(acc).plus(new import_decimal.default(cur.amount || 0)).toNumber();
62
74
  }, new import_decimal.default(0));
63
75
  };
76
+ var getDateIsInSchedule = (dateTime, scheduleList) => {
77
+ if (!dateTime || !scheduleList || scheduleList.length === 0) {
78
+ return false;
79
+ }
80
+ const targetDate = (0, import_dayjs.default)(dateTime);
81
+ if (!targetDate.isValid()) {
82
+ return false;
83
+ }
84
+ for (const schedule of scheduleList) {
85
+ if (isTimeInScheduleItem(dateTime, schedule)) {
86
+ return true;
87
+ }
88
+ }
89
+ return false;
90
+ };
91
+ var isTimeInScheduleItem = (dateTime, schedule) => {
92
+ const targetDate = (0, import_dayjs.default)(dateTime);
93
+ const targetDateString = dateTime.split(" ")[0];
94
+ const targetTimeString = dateTime.split(" ")[1] || "00:00:00";
95
+ switch (schedule.type) {
96
+ case "standard":
97
+ return isInStandardSchedule(targetDate, targetDateString, targetTimeString, schedule);
98
+ case "time-slots":
99
+ return isInTimeSlotsSchedule(targetDate, targetDateString, targetTimeString, schedule);
100
+ case "designation":
101
+ return isInDesignationSchedule(targetDate, targetDateString, targetTimeString, schedule);
102
+ default:
103
+ return false;
104
+ }
105
+ };
106
+ var isInStandardSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
107
+ if (!schedule.start_time || !schedule.end_time) {
108
+ return false;
109
+ }
110
+ const startDate = (0, import_dayjs.default)(schedule.start_time);
111
+ const endDate = (0, import_dayjs.default)(schedule.end_time);
112
+ const isInBasicRange = targetDate.isSameOrAfter(startDate) && targetDate.isSameOrBefore(endDate);
113
+ if (schedule.repeat_type === "none") {
114
+ return isInBasicRange;
115
+ }
116
+ return isInRepeatingSchedule(targetDate, targetDateString, targetTimeString, schedule, startDate, endDate);
117
+ };
118
+ var isInTimeSlotsSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
119
+ if (!schedule.start_time) {
120
+ return false;
121
+ }
122
+ if (schedule.repeat_type === "none") {
123
+ const scheduleDate = schedule.start_time.split(" ")[0];
124
+ if (targetDateString !== scheduleDate) {
125
+ return false;
126
+ }
127
+ return checkTimeSlotsForDate(targetDate, targetDateString, schedule.time_slot);
128
+ }
129
+ return isInTimeSlotsRepeatingSchedule(targetDate, targetDateString, targetTimeString, schedule);
130
+ };
131
+ var isInDesignationSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
132
+ if (!schedule.designation) {
133
+ return false;
134
+ }
135
+ for (const designation of schedule.designation) {
136
+ const startDateTime = `${designation.start_date} ${designation.start_time}:00`;
137
+ const endDateTime = `${designation.end_date} ${designation.end_time}:00`;
138
+ const startDate = (0, import_dayjs.default)(startDateTime);
139
+ const endDate = (0, import_dayjs.default)(endDateTime);
140
+ if (targetDate.isSameOrAfter(startDate) && targetDate.isSameOrBefore(endDate)) {
141
+ return true;
142
+ }
143
+ }
144
+ return false;
145
+ };
146
+ var isInRepeatingSchedule = (targetDate, targetDateString, targetTimeString, schedule, startDate, endDate) => {
147
+ if (!schedule.repeat_rule) {
148
+ return false;
149
+ }
150
+ const { repeat_rule, repeat_type } = schedule;
151
+ const targetDateOnly = (0, import_dayjs.default)(targetDateString);
152
+ if (repeat_rule.included_date && repeat_rule.included_date.length > 0) {
153
+ for (const includedDate of repeat_rule.included_date) {
154
+ const includeStartDate = (0, import_dayjs.default)(includedDate.start);
155
+ const includeEndDate = (0, import_dayjs.default)(includedDate.end);
156
+ if (targetDateOnly.isSameOrAfter(includeStartDate, "day") && targetDateOnly.isSameOrBefore(includeEndDate, "day")) {
157
+ return true;
158
+ }
159
+ }
160
+ }
161
+ for (const excludedDate of repeat_rule.excluded_date) {
162
+ const excludeStartDate = (0, import_dayjs.default)(excludedDate.start);
163
+ const excludeEndDate = (0, import_dayjs.default)(excludedDate.end);
164
+ if (targetDateOnly.isSameOrAfter(excludeStartDate, "day") && targetDateOnly.isSameOrBefore(excludeEndDate, "day")) {
165
+ return false;
166
+ }
167
+ }
168
+ if (repeat_rule.end.type === "date" && repeat_rule.end.end_date) {
169
+ const ruleEndDate = (0, import_dayjs.default)(repeat_rule.end.end_date);
170
+ if (targetDate.isAfter(ruleEndDate)) {
171
+ return false;
172
+ }
173
+ }
174
+ switch (repeat_type) {
175
+ case "daily":
176
+ return isInDailyRepeat(targetDate, startDate, endDate, repeat_rule);
177
+ case "weekly":
178
+ return isInWeeklyRepeat(targetDate, startDate, endDate, repeat_rule);
179
+ default:
180
+ return false;
181
+ }
182
+ };
183
+ var isInDailyRepeat = (targetDate, startDate, endDate, repeatRule) => {
184
+ const daysDiff = targetDate.diff(startDate, "day");
185
+ if (daysDiff < 0) {
186
+ return false;
187
+ }
188
+ if (daysDiff % repeatRule.frequency !== 0) {
189
+ return false;
190
+ }
191
+ const targetTimeOfDay = targetDate.hour() * 3600 + targetDate.minute() * 60 + targetDate.second();
192
+ const startTimeOfDay = startDate.hour() * 3600 + startDate.minute() * 60 + startDate.second();
193
+ const endTimeOfDay = endDate.hour() * 3600 + endDate.minute() * 60 + endDate.second();
194
+ return targetTimeOfDay >= startTimeOfDay && targetTimeOfDay <= endTimeOfDay;
195
+ };
196
+ var isInWeeklyRepeat = (targetDate, startDate, endDate, repeatRule) => {
197
+ const targetDayOfWeek = targetDate.day();
198
+ if (!repeatRule.frequency_date.includes(targetDayOfWeek)) {
199
+ return false;
200
+ }
201
+ const weeksDiff = targetDate.diff(startDate, "week");
202
+ if (weeksDiff < 0) {
203
+ return false;
204
+ }
205
+ if (weeksDiff % repeatRule.frequency !== 0) {
206
+ return false;
207
+ }
208
+ const targetTimeOfDay = targetDate.hour() * 3600 + targetDate.minute() * 60 + targetDate.second();
209
+ const startTimeOfDay = startDate.hour() * 3600 + startDate.minute() * 60 + startDate.second();
210
+ const endTimeOfDay = endDate.hour() * 3600 + endDate.minute() * 60 + endDate.second();
211
+ return targetTimeOfDay >= startTimeOfDay && targetTimeOfDay <= endTimeOfDay;
212
+ };
213
+ var isInTimeSlotsRepeatingSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
214
+ if (!schedule.repeat_rule || !schedule.start_time) {
215
+ return false;
216
+ }
217
+ const { repeat_rule, repeat_type } = schedule;
218
+ const startDate = (0, import_dayjs.default)(schedule.start_time);
219
+ const targetDateOnly = (0, import_dayjs.default)(targetDateString);
220
+ if (repeat_rule.included_date && repeat_rule.included_date.length > 0) {
221
+ for (const includedDate of repeat_rule.included_date) {
222
+ const includeStartDate = (0, import_dayjs.default)(includedDate.start);
223
+ const includeEndDate = (0, import_dayjs.default)(includedDate.end);
224
+ if (targetDateOnly.isSameOrAfter(includeStartDate, "day") && targetDateOnly.isSameOrBefore(includeEndDate, "day")) {
225
+ return checkTimeSlotsForDate(targetDate, targetDateString, schedule.time_slot);
226
+ }
227
+ }
228
+ }
229
+ for (const excludedDate of repeat_rule.excluded_date) {
230
+ const excludeStartDate = (0, import_dayjs.default)(excludedDate.start);
231
+ const excludeEndDate = (0, import_dayjs.default)(excludedDate.end);
232
+ if (targetDateOnly.isSameOrAfter(excludeStartDate, "day") && targetDateOnly.isSameOrBefore(excludeEndDate, "day")) {
233
+ return false;
234
+ }
235
+ }
236
+ if (repeat_rule.end.type === "date" && repeat_rule.end.end_date) {
237
+ const ruleEndDate = (0, import_dayjs.default)(repeat_rule.end.end_date);
238
+ if (targetDateOnly.isAfter(ruleEndDate, "day")) {
239
+ return false;
240
+ }
241
+ }
242
+ let isDateValid = false;
243
+ switch (repeat_type) {
244
+ case "daily":
245
+ isDateValid = isInDailyRepeatForDate(targetDateOnly, startDate, repeat_rule);
246
+ break;
247
+ case "weekly":
248
+ isDateValid = isInWeeklyRepeatForDate(targetDateOnly, startDate, repeat_rule);
249
+ break;
250
+ default:
251
+ return false;
252
+ }
253
+ if (isDateValid) {
254
+ return checkTimeSlotsForDate(targetDate, targetDateString, schedule.time_slot);
255
+ }
256
+ return false;
257
+ };
258
+ var checkTimeSlotsForDate = (targetDate, targetDateString, timeSlots) => {
259
+ for (const timeSlot of timeSlots) {
260
+ const slotStart = `${targetDateString} ${timeSlot.start_time}:00`;
261
+ const slotEnd = `${targetDateString} ${timeSlot.end_time}:00`;
262
+ const slotStartDate = (0, import_dayjs.default)(slotStart);
263
+ const slotEndDate = (0, import_dayjs.default)(slotEnd);
264
+ if (targetDate.isSameOrAfter(slotStartDate) && targetDate.isSameOrBefore(slotEndDate)) {
265
+ return true;
266
+ }
267
+ }
268
+ return false;
269
+ };
270
+ var isInDailyRepeatForDate = (targetDate, startDate, repeatRule) => {
271
+ const daysDiff = targetDate.diff(startDate, "day");
272
+ if (daysDiff < 0) {
273
+ return false;
274
+ }
275
+ return daysDiff % repeatRule.frequency === 0;
276
+ };
277
+ var isInWeeklyRepeatForDate = (targetDate, startDate, repeatRule) => {
278
+ const targetDayOfWeek = targetDate.day();
279
+ if (!repeatRule.frequency_date.includes(targetDayOfWeek)) {
280
+ return false;
281
+ }
282
+ const weeksDiff = targetDate.diff(startDate, "week");
283
+ if (weeksDiff < 0) {
284
+ return false;
285
+ }
286
+ return weeksDiff % repeatRule.frequency === 0;
287
+ };
288
+ var filterDiscountListByBookingTime = (discountList, bookingTime) => {
289
+ if (!bookingTime) {
290
+ return discountList;
291
+ }
292
+ return discountList.filter((discount) => {
293
+ var _a, _b, _c;
294
+ if (!((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.validity_type) || ((_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.validity_type) === "fixed_validity") {
295
+ return true;
296
+ }
297
+ return getDateIsInSchedule(bookingTime, ((_c = discount.custom_schedule_snapshot) == null ? void 0 : _c.data) || []);
298
+ });
299
+ };
64
300
  // Annotate the CommonJS export names for ESM import in node:
65
301
  0 && (module.exports = {
302
+ filterDiscountListByBookingTime,
303
+ getDateIsInSchedule,
66
304
  getDiscountAmount,
67
305
  getDiscountListAmount,
68
306
  getDiscountListAmountTotal,
307
+ isAllNormalProduct,
308
+ isNormalProductByDurationSchedule,
69
309
  uniqueById
70
310
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "1.0.85",
4
+ "version": "1.0.87",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",