@pisell/pisellos 0.0.479 → 0.0.481
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.js +7 -0
- package/dist/effects/index.d.ts +2 -2
- package/dist/effects/index.js +34 -81
- package/dist/model/strategy/adapter/promotion/evaluator.js +99 -26
- package/dist/model/strategy/adapter/walletPass/type.d.ts +9 -2
- package/dist/model/strategy/adapter/walletPass/utils.d.ts +6 -6
- package/dist/model/strategy/adapter/walletPass/utils.js +111 -72
- package/dist/modules/Customer/index.js +1 -1
- package/dist/modules/Discount/index.d.ts +6 -2
- package/dist/modules/Discount/index.js +14 -8
- package/dist/modules/Order/index.d.ts +1 -1
- package/dist/modules/Order/index.js +18 -13
- package/dist/modules/Payment/index.d.ts +4 -0
- package/dist/modules/Payment/index.js +774 -649
- package/dist/modules/Payment/walletpass.js +44 -17
- package/dist/modules/Product/index.d.ts +1 -1
- package/dist/modules/Product/types.d.ts +2 -0
- package/dist/modules/ProductList/index.d.ts +3 -0
- package/dist/modules/ProductList/index.js +9 -7
- package/dist/modules/Rules/index.d.ts +2 -2
- package/dist/modules/Rules/index.js +37 -31
- package/dist/modules/Rules/types.d.ts +2 -2
- package/dist/modules/Schedule/index.d.ts +9 -0
- package/dist/modules/Schedule/index.js +15 -2
- package/dist/plugins/app-types/app/app.d.ts +1 -0
- package/dist/plugins/request.d.ts +2 -0
- package/dist/server/index.d.ts +107 -2
- package/dist/server/index.js +1507 -279
- package/dist/server/modules/index.d.ts +6 -0
- package/dist/server/modules/index.js +7 -0
- package/dist/server/modules/menu/index.d.ts +19 -0
- package/dist/server/modules/menu/index.js +221 -71
- package/dist/server/modules/order/index.d.ts +87 -0
- package/dist/server/modules/order/index.js +916 -0
- package/dist/server/modules/order/types.d.ts +530 -0
- package/dist/server/modules/order/types.js +141 -0
- package/dist/server/modules/order/utils/filterBookings.d.ts +6 -0
- package/dist/server/modules/order/utils/filterBookings.js +350 -0
- package/dist/server/modules/order/utils/filterOrders.d.ts +15 -0
- package/dist/server/modules/order/utils/filterOrders.js +226 -0
- package/dist/server/modules/products/index.d.ts +117 -5
- package/dist/server/modules/products/index.js +1450 -240
- package/dist/server/modules/products/types.d.ts +25 -1
- package/dist/server/modules/products/types.js +3 -0
- package/dist/server/modules/resource/index.d.ts +86 -0
- package/dist/server/modules/resource/index.js +1128 -0
- package/dist/server/modules/resource/types.d.ts +121 -0
- package/dist/server/modules/resource/types.js +47 -0
- package/dist/server/modules/schedule/index.d.ts +19 -0
- package/dist/server/modules/schedule/index.js +229 -68
- package/dist/server/utils/product.d.ts +5 -0
- package/dist/server/utils/product.js +71 -31
- package/dist/solution/BookingTicket/index.d.ts +10 -2
- package/dist/solution/BookingTicket/index.js +41 -28
- package/dist/solution/BookingTicket/utils/scan/index.js +1 -1
- package/dist/solution/Checkout/index.d.ts +1 -0
- package/dist/solution/Checkout/index.js +286 -188
- package/dist/solution/Checkout/utils/index.d.ts +2 -1
- package/dist/solution/Checkout/utils/index.js +6 -4
- package/dist/solution/RegisterAndLogin/config.js +340 -1
- package/dist/solution/Sales/index.d.ts +96 -0
- package/dist/solution/Sales/index.js +566 -0
- package/dist/solution/Sales/types.d.ts +67 -0
- package/dist/solution/Sales/types.js +26 -0
- package/dist/solution/ShopDiscount/index.d.ts +1 -0
- package/dist/solution/ShopDiscount/index.js +35 -22
- package/dist/solution/ShopDiscount/types.d.ts +6 -0
- package/dist/solution/ShopDiscount/utils.d.ts +9 -0
- package/dist/solution/ShopDiscount/utils.js +21 -27
- package/dist/solution/index.d.ts +2 -1
- package/dist/solution/index.js +2 -1
- package/dist/types/index.d.ts +5 -0
- package/lib/core/index.d.ts +3 -2
- package/lib/core/index.js +4 -0
- package/lib/effects/index.d.ts +2 -2
- package/lib/effects/index.js +22 -31
- package/lib/model/strategy/adapter/promotion/evaluator.js +57 -8
- package/lib/model/strategy/adapter/walletPass/type.d.ts +9 -2
- package/lib/model/strategy/adapter/walletPass/utils.d.ts +6 -6
- package/lib/model/strategy/adapter/walletPass/utils.js +115 -48
- package/lib/modules/Customer/index.js +1 -1
- package/lib/modules/Discount/index.d.ts +6 -2
- package/lib/modules/Discount/index.js +3 -1
- package/lib/modules/Order/index.d.ts +1 -1
- package/lib/modules/Order/index.js +20 -18
- package/lib/modules/Payment/index.d.ts +4 -0
- package/lib/modules/Payment/index.js +134 -66
- package/lib/modules/Payment/walletpass.js +23 -4
- package/lib/modules/Product/index.d.ts +1 -1
- package/lib/modules/Product/types.d.ts +2 -0
- package/lib/modules/ProductList/index.d.ts +3 -0
- package/lib/modules/ProductList/index.js +2 -2
- package/lib/modules/Rules/index.d.ts +2 -2
- package/lib/modules/Rules/index.js +69 -73
- package/lib/modules/Rules/types.d.ts +2 -2
- package/lib/modules/Schedule/index.d.ts +9 -0
- package/lib/modules/Schedule/index.js +11 -0
- package/lib/plugins/app-types/app/app.d.ts +1 -0
- package/lib/plugins/request.d.ts +2 -0
- package/lib/server/index.d.ts +107 -2
- package/lib/server/index.js +773 -51
- package/lib/server/modules/index.d.ts +6 -0
- package/lib/server/modules/index.js +16 -2
- package/lib/server/modules/menu/index.d.ts +19 -0
- package/lib/server/modules/menu/index.js +121 -2
- package/lib/server/modules/order/index.d.ts +87 -0
- package/lib/server/modules/order/index.js +543 -0
- package/lib/server/modules/order/types.d.ts +530 -0
- package/lib/server/modules/order/types.js +34 -0
- package/lib/server/modules/order/utils/filterBookings.d.ts +6 -0
- package/lib/server/modules/order/utils/filterBookings.js +320 -0
- package/lib/server/modules/order/utils/filterOrders.d.ts +15 -0
- package/lib/server/modules/order/utils/filterOrders.js +197 -0
- package/lib/server/modules/products/index.d.ts +117 -5
- package/lib/server/modules/products/index.js +799 -62
- package/lib/server/modules/products/types.d.ts +25 -1
- package/lib/server/modules/products/types.js +1 -0
- package/lib/server/modules/resource/index.d.ts +86 -0
- package/lib/server/modules/resource/index.js +557 -0
- package/lib/server/modules/resource/types.d.ts +121 -0
- package/lib/server/modules/resource/types.js +35 -0
- package/lib/server/modules/schedule/index.d.ts +19 -0
- package/lib/server/modules/schedule/index.js +141 -12
- package/lib/server/utils/product.d.ts +5 -0
- package/lib/server/utils/product.js +56 -27
- package/lib/solution/BookingTicket/index.d.ts +10 -2
- package/lib/solution/BookingTicket/index.js +10 -2
- package/lib/solution/BookingTicket/utils/scan/index.js +0 -1
- package/lib/solution/Checkout/index.d.ts +1 -0
- package/lib/solution/Checkout/index.js +399 -331
- package/lib/solution/Checkout/utils/index.d.ts +2 -1
- package/lib/solution/Checkout/utils/index.js +6 -4
- package/lib/solution/RegisterAndLogin/config.js +266 -1
- package/lib/solution/Sales/index.d.ts +96 -0
- package/lib/solution/Sales/index.js +416 -0
- package/lib/solution/Sales/types.d.ts +67 -0
- package/lib/solution/Sales/types.js +35 -0
- package/lib/solution/ShopDiscount/index.d.ts +1 -0
- package/lib/solution/ShopDiscount/index.js +14 -6
- package/lib/solution/ShopDiscount/types.d.ts +6 -0
- package/lib/solution/ShopDiscount/utils.d.ts +9 -0
- package/lib/solution/ShopDiscount/utils.js +6 -10
- package/lib/solution/index.d.ts +2 -1
- package/lib/solution/index.js +4 -2
- package/lib/types/index.d.ts +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/solution/Sales/index.ts
|
|
31
|
+
var Sales_exports = {};
|
|
32
|
+
__export(Sales_exports, {
|
|
33
|
+
Sales: () => SalesImpl,
|
|
34
|
+
SalesImpl: () => SalesImpl,
|
|
35
|
+
default: () => Sales_default
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(Sales_exports);
|
|
38
|
+
var import_dayjs = __toESM(require("dayjs"));
|
|
39
|
+
var import_BaseModule = require("../../modules/BaseModule");
|
|
40
|
+
var import_types = require("./types");
|
|
41
|
+
__reExport(Sales_exports, require("./types"), module.exports);
|
|
42
|
+
var SalesImpl = class extends import_BaseModule.BaseModule {
|
|
43
|
+
constructor(name, version) {
|
|
44
|
+
super(name, version);
|
|
45
|
+
this.defaultName = "sales";
|
|
46
|
+
this.defaultVersion = "1.0.0";
|
|
47
|
+
this.defaultTimelineBucketMinutes = 15;
|
|
48
|
+
this.isSolution = true;
|
|
49
|
+
this.options = {};
|
|
50
|
+
this.otherParams = {};
|
|
51
|
+
}
|
|
52
|
+
async initialize(core, options = {}) {
|
|
53
|
+
this.core = core;
|
|
54
|
+
this.options = options;
|
|
55
|
+
this.otherParams = options.otherParams || {};
|
|
56
|
+
const appPlugin = this.core.getPlugin("app");
|
|
57
|
+
this.request = appPlugin == null ? void 0 : appPlugin.getApp().request;
|
|
58
|
+
if (!this.request) {
|
|
59
|
+
throw new Error("Sales 解决方案需要 request 插件支持");
|
|
60
|
+
}
|
|
61
|
+
this.store = {
|
|
62
|
+
currentDay: (0, import_dayjs.default)().startOf("day"),
|
|
63
|
+
reservationList: []
|
|
64
|
+
};
|
|
65
|
+
await this.core.effects.emit(`${this.name}:onInited`, {});
|
|
66
|
+
}
|
|
67
|
+
// -------------------------------------------------------------------------
|
|
68
|
+
// SalesModuleAPI 实现
|
|
69
|
+
// -------------------------------------------------------------------------
|
|
70
|
+
/** 获取当前 store 快照 */
|
|
71
|
+
getState() {
|
|
72
|
+
return { ...this.store };
|
|
73
|
+
}
|
|
74
|
+
/** 获取当前选择日期 */
|
|
75
|
+
getCurrentDay() {
|
|
76
|
+
return this.store.currentDay;
|
|
77
|
+
}
|
|
78
|
+
/** 设置当前选择日期,会自动归一到当天 00:00:00 */
|
|
79
|
+
setCurrentDay(currentDay) {
|
|
80
|
+
const normalized = (0, import_dayjs.default)(currentDay).startOf("day");
|
|
81
|
+
this.store.currentDay = normalized;
|
|
82
|
+
this.core.effects.emit(import_types.SalesHooks.onCurrentDayChanged, { currentDay: normalized });
|
|
83
|
+
return normalized;
|
|
84
|
+
}
|
|
85
|
+
/** 获取当前预约列表 */
|
|
86
|
+
getReservationList() {
|
|
87
|
+
return [...this.store.reservationList];
|
|
88
|
+
}
|
|
89
|
+
/** 覆盖设置当前预约列表 */
|
|
90
|
+
setReservationList(reservationList) {
|
|
91
|
+
this.store.reservationList = reservationList;
|
|
92
|
+
this.core.effects.emit(import_types.SalesHooks.onReservationListChanged, { reservationList });
|
|
93
|
+
return reservationList;
|
|
94
|
+
}
|
|
95
|
+
/** 重置预约列表为空 */
|
|
96
|
+
resetReservationList() {
|
|
97
|
+
this.store.reservationList = [];
|
|
98
|
+
this.core.effects.emit(import_types.SalesHooks.onReservationListChanged, { reservationList: [] });
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
// -------------------------------------------------------------------------
|
|
102
|
+
// 生命周期
|
|
103
|
+
// -------------------------------------------------------------------------
|
|
104
|
+
async destroy() {
|
|
105
|
+
await this.core.effects.emit(`${this.name}:onDestroy`, {});
|
|
106
|
+
super.destroy();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* 时间轴粒度(分钟)
|
|
110
|
+
* - 默认 15 分钟
|
|
111
|
+
* - 可通过 registerModule 时的 options.otherParams.timelineBucketMinutes 覆盖
|
|
112
|
+
*/
|
|
113
|
+
getTimelineBucketMinutes() {
|
|
114
|
+
var _a;
|
|
115
|
+
const dynamicBucket = Number((_a = this.otherParams) == null ? void 0 : _a.timelineBucketMinutes);
|
|
116
|
+
if (!Number.isFinite(dynamicBucket) || dynamicBucket <= 0)
|
|
117
|
+
return this.defaultTimelineBucketMinutes;
|
|
118
|
+
return Math.floor(dynamicBucket);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 解析营业日统计窗口:
|
|
122
|
+
* - 当 operating_day_boundary.type === 'start_time'
|
|
123
|
+
* 使用「今天 + boundary.time」到「明天 + boundary.time」
|
|
124
|
+
* - 否则回退自然日(00:00 到次日 00:00)
|
|
125
|
+
*/
|
|
126
|
+
getTimelineRangeByOperatingBoundary() {
|
|
127
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
128
|
+
const today = (0, import_dayjs.default)();
|
|
129
|
+
const defaultStart = today.startOf("day");
|
|
130
|
+
const defaultEndExclusive = defaultStart.add(1, "day");
|
|
131
|
+
const appPlugin = this.core.getPlugin("app");
|
|
132
|
+
const coreData = (_f = (_d = (_c = (_b = (_a = appPlugin == null ? void 0 : appPlugin.getApp()) == null ? void 0 : _a.data) == null ? void 0 : _b.store) == null ? void 0 : _c.getStore) == null ? void 0 : (_e = _d.call(_c)).getDataByModel) == null ? void 0 : _f.call(_e, "core");
|
|
133
|
+
const operatingDayBoundary = (_g = coreData == null ? void 0 : coreData.core) == null ? void 0 : _g.operating_day_boundary;
|
|
134
|
+
if ((operatingDayBoundary == null ? void 0 : operatingDayBoundary.type) !== "start_time") {
|
|
135
|
+
return { startAt: defaultStart, endExclusiveAt: defaultEndExclusive };
|
|
136
|
+
}
|
|
137
|
+
const boundaryTime = String(operatingDayBoundary.time || "").trim();
|
|
138
|
+
const startAt = (0, import_dayjs.default)(`${today.format("YYYY-MM-DD")} ${boundaryTime}`);
|
|
139
|
+
if (!startAt.isValid()) {
|
|
140
|
+
return { startAt: defaultStart, endExclusiveAt: defaultEndExclusive };
|
|
141
|
+
}
|
|
142
|
+
return { startAt, endExclusiveAt: startAt.add(1, "day") };
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* 统计时间轴每个时间片的预约数量。
|
|
146
|
+
* 算法使用差分数组,复杂度 O(n + s):
|
|
147
|
+
* - n = booking 数量
|
|
148
|
+
* - s = 时间片数量
|
|
149
|
+
*/
|
|
150
|
+
getTimelineHighlights(bookingList = [], startDateTime, endDateTime) {
|
|
151
|
+
const bucketMinutes = this.getTimelineBucketMinutes();
|
|
152
|
+
const bucketMs = bucketMinutes * 60 * 1e3;
|
|
153
|
+
const customStartAt = startDateTime ? (0, import_dayjs.default)(startDateTime) : (0, import_dayjs.default)("");
|
|
154
|
+
const customEndExclusiveAt = endDateTime ? (0, import_dayjs.default)(endDateTime) : (0, import_dayjs.default)("");
|
|
155
|
+
const hasValidCustomRange = customStartAt.isValid() && customEndExclusiveAt.isValid();
|
|
156
|
+
const { startAt, endExclusiveAt } = hasValidCustomRange ? { startAt: customStartAt, endExclusiveAt: customEndExclusiveAt } : this.getTimelineRangeByOperatingBoundary();
|
|
157
|
+
const startAtMs = startAt.valueOf();
|
|
158
|
+
const endExclusiveAtMs = endExclusiveAt.valueOf();
|
|
159
|
+
if (!startAt.isValid() || !endExclusiveAt.isValid() || endExclusiveAtMs <= startAtMs)
|
|
160
|
+
return [];
|
|
161
|
+
const slotCount = Math.ceil((endExclusiveAtMs - startAtMs) / bucketMs);
|
|
162
|
+
if (slotCount <= 0)
|
|
163
|
+
return [];
|
|
164
|
+
const diff = new Int32Array(slotCount + 1);
|
|
165
|
+
for (let i = 0; i < bookingList.length; i++) {
|
|
166
|
+
const booking = bookingList[i];
|
|
167
|
+
const bookingStartAt = this.toBookingDateTime(booking.start_date, booking.start_time);
|
|
168
|
+
const bookingEndAt = this.toBookingDateTime(booking.end_date, booking.end_time);
|
|
169
|
+
if (!bookingStartAt.isValid() || !bookingEndAt.isValid())
|
|
170
|
+
continue;
|
|
171
|
+
const overlapStartMs = Math.max(bookingStartAt.valueOf(), startAtMs);
|
|
172
|
+
const overlapEndExclusiveMs = Math.min(bookingEndAt.valueOf() + 1, endExclusiveAtMs);
|
|
173
|
+
if (overlapStartMs >= overlapEndExclusiveMs)
|
|
174
|
+
continue;
|
|
175
|
+
const startIdx = Math.max(0, Math.ceil((overlapStartMs - startAtMs) / bucketMs));
|
|
176
|
+
const endIdx = Math.min(
|
|
177
|
+
slotCount - 1,
|
|
178
|
+
Math.floor((overlapEndExclusiveMs - 1 - startAtMs) / bucketMs)
|
|
179
|
+
);
|
|
180
|
+
if (startIdx > endIdx)
|
|
181
|
+
continue;
|
|
182
|
+
diff[startIdx] += 1;
|
|
183
|
+
diff[endIdx + 1] -= 1;
|
|
184
|
+
}
|
|
185
|
+
const timeline = [];
|
|
186
|
+
let runningCount = 0;
|
|
187
|
+
for (let i = 0; i < slotCount; i++) {
|
|
188
|
+
runningCount += diff[i];
|
|
189
|
+
timeline.push(runningCount);
|
|
190
|
+
}
|
|
191
|
+
return timeline;
|
|
192
|
+
}
|
|
193
|
+
/** dayjs 未启用插件时,手动封装 >= 判断 */
|
|
194
|
+
isSameOrAfter(left, right) {
|
|
195
|
+
return left.isAfter(right) || left.isSame(right);
|
|
196
|
+
}
|
|
197
|
+
/** dayjs 未启用插件时,手动封装 <= 判断 */
|
|
198
|
+
isSameOrBefore(left, right) {
|
|
199
|
+
return left.isBefore(right) || left.isSame(right);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* 将 booking 的日期/时间字段统一组装为 dayjs
|
|
203
|
+
* - date + time 都有:按完整时间解析
|
|
204
|
+
* - 只有一个字段:按单字段解析(兼容历史数据)
|
|
205
|
+
* - 都没有:返回 invalid
|
|
206
|
+
*/
|
|
207
|
+
toBookingDateTime(date, time) {
|
|
208
|
+
if (!date && !time)
|
|
209
|
+
return (0, import_dayjs.default)("");
|
|
210
|
+
if (date && time)
|
|
211
|
+
return (0, import_dayjs.default)(`${date} ${time}`);
|
|
212
|
+
return (0, import_dayjs.default)(date || time);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* 预约状态映射(面向 UI 的统一状态)
|
|
216
|
+
* 说明:locked 逻辑后续会补业务规则,这里先保留分支占位。
|
|
217
|
+
*/
|
|
218
|
+
getBookingStatus(appointmentStatus) {
|
|
219
|
+
if (appointmentStatus === "started")
|
|
220
|
+
return "occupied";
|
|
221
|
+
if (appointmentStatus === "new" || appointmentStatus === "confirmed" || appointmentStatus === "arrived") {
|
|
222
|
+
return "reserved";
|
|
223
|
+
}
|
|
224
|
+
if (appointmentStatus === "locked")
|
|
225
|
+
return "locked";
|
|
226
|
+
return void 0;
|
|
227
|
+
}
|
|
228
|
+
getResourceId(resource) {
|
|
229
|
+
return resource.id ?? resource.form_record_id ?? "";
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* 资源下 bookings 的返回裁剪策略:
|
|
233
|
+
* 1) 优先返回当前时刻正在进行中的预约(允许并发返回多条)
|
|
234
|
+
* 2) 若无 active,返回已超时且仍占用中的预约(允许并发多条)
|
|
235
|
+
* 3) 若仍无,返回最近一组未来预约(同 start_time 的并发预约全部返回)
|
|
236
|
+
* 4) 最后兜底返回一条(避免资源有历史预约时完全无反馈)
|
|
237
|
+
*/
|
|
238
|
+
pickBookingsForCurrentPoint(current, bookings) {
|
|
239
|
+
if (bookings.length === 0)
|
|
240
|
+
return [];
|
|
241
|
+
const currentDayStart = current.startOf("day");
|
|
242
|
+
const currentDayEnd = current.endOf("day");
|
|
243
|
+
const dayScopedBookings = bookings.filter((booking) => {
|
|
244
|
+
const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
|
|
245
|
+
const endAt = this.toBookingDateTime(booking.end_date, booking.end_time);
|
|
246
|
+
if (!startAt.isValid() || !endAt.isValid())
|
|
247
|
+
return false;
|
|
248
|
+
return this.isSameOrBefore(startAt, currentDayEnd) && this.isSameOrAfter(endAt, currentDayStart);
|
|
249
|
+
});
|
|
250
|
+
if (dayScopedBookings.length === 0)
|
|
251
|
+
return [];
|
|
252
|
+
const appendNextStartGroupIfNeeded = (selectedBookings) => {
|
|
253
|
+
if (selectedBookings.length === 0)
|
|
254
|
+
return selectedBookings;
|
|
255
|
+
const shouldAppendNextGroup = selectedBookings.some(
|
|
256
|
+
(booking) => booking.status === "reserved" || booking.status === "occupied"
|
|
257
|
+
);
|
|
258
|
+
if (!shouldAppendNextGroup)
|
|
259
|
+
return selectedBookings;
|
|
260
|
+
const selectedStartValues = new Set(
|
|
261
|
+
selectedBookings.map((booking) => this.toBookingDateTime(booking.start_date, booking.start_time)).filter((startAt) => startAt.isValid()).map((startAt) => startAt.valueOf())
|
|
262
|
+
);
|
|
263
|
+
const futureCandidates = dayScopedBookings.filter((booking) => {
|
|
264
|
+
const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
|
|
265
|
+
if (!startAt.isValid())
|
|
266
|
+
return false;
|
|
267
|
+
return startAt.isAfter(current) && !selectedStartValues.has(startAt.valueOf());
|
|
268
|
+
});
|
|
269
|
+
if (futureCandidates.length === 0)
|
|
270
|
+
return selectedBookings;
|
|
271
|
+
const nextStartAt = this.toBookingDateTime(
|
|
272
|
+
futureCandidates[0].start_date,
|
|
273
|
+
futureCandidates[0].start_time
|
|
274
|
+
).valueOf();
|
|
275
|
+
const nextStartGroup = futureCandidates.filter((booking) => {
|
|
276
|
+
const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
|
|
277
|
+
return startAt.isValid() && startAt.valueOf() === nextStartAt;
|
|
278
|
+
});
|
|
279
|
+
if (nextStartGroup.length === 0)
|
|
280
|
+
return selectedBookings;
|
|
281
|
+
return [...selectedBookings, ...nextStartGroup];
|
|
282
|
+
};
|
|
283
|
+
const activeBookings = dayScopedBookings.filter((booking) => {
|
|
284
|
+
const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
|
|
285
|
+
const endAt = this.toBookingDateTime(booking.end_date, booking.end_time);
|
|
286
|
+
if (!startAt.isValid() || !endAt.isValid())
|
|
287
|
+
return false;
|
|
288
|
+
return this.isSameOrAfter(current, startAt) && this.isSameOrBefore(current, endAt);
|
|
289
|
+
});
|
|
290
|
+
if (activeBookings.length > 0)
|
|
291
|
+
return appendNextStartGroupIfNeeded(activeBookings);
|
|
292
|
+
const timeoutOccupied = dayScopedBookings.filter(
|
|
293
|
+
(booking) => booking.status === "occupied" && booking.isTimeout
|
|
294
|
+
);
|
|
295
|
+
if (timeoutOccupied.length > 0)
|
|
296
|
+
return appendNextStartGroupIfNeeded(timeoutOccupied);
|
|
297
|
+
const upcoming = dayScopedBookings.filter((booking) => {
|
|
298
|
+
const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
|
|
299
|
+
return startAt.isValid() && startAt.isAfter(current) && startAt.isSame(current, "day");
|
|
300
|
+
});
|
|
301
|
+
if (upcoming.length > 0) {
|
|
302
|
+
const firstStartAt = this.toBookingDateTime(upcoming[0].start_date, upcoming[0].start_time).valueOf();
|
|
303
|
+
const upcomingStartGroup = upcoming.filter((booking) => {
|
|
304
|
+
const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
|
|
305
|
+
return startAt.valueOf() === firstStartAt;
|
|
306
|
+
});
|
|
307
|
+
return appendNextStartGroupIfNeeded(upcomingStartGroup);
|
|
308
|
+
}
|
|
309
|
+
const fallback = dayScopedBookings[dayScopedBookings.length - 1];
|
|
310
|
+
return fallback ? [fallback] : [];
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* 标准化单条 booking:
|
|
314
|
+
* - 过滤终态(rejected/cancelled/completed)
|
|
315
|
+
* - 注入 status / isTimeout / reserved_status
|
|
316
|
+
*/
|
|
317
|
+
normalizeMatchedBooking(current, booking) {
|
|
318
|
+
const appointmentStatus = String(booking.appointment_status ?? booking.status ?? "");
|
|
319
|
+
if (appointmentStatus === "rejected" || appointmentStatus === "cancelled" || appointmentStatus === "completed") {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
const bookingStatus = this.getBookingStatus(appointmentStatus);
|
|
323
|
+
const endAt = this.toBookingDateTime(booking.end_date, booking.end_time);
|
|
324
|
+
const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
|
|
325
|
+
const isTimeout = bookingStatus === "occupied" && endAt.isValid() && current.isAfter(endAt);
|
|
326
|
+
const timeoutTime = isTimeout ? current.diff(endAt, "minute") : void 0;
|
|
327
|
+
const progressPercent = (() => {
|
|
328
|
+
if (bookingStatus !== "occupied")
|
|
329
|
+
return 0;
|
|
330
|
+
if (!startAt.isValid() || !endAt.isValid())
|
|
331
|
+
return 0;
|
|
332
|
+
const totalMinutes = endAt.diff(startAt, "minute");
|
|
333
|
+
if (totalMinutes <= 0)
|
|
334
|
+
return 0;
|
|
335
|
+
const elapsedMinutes = current.diff(startAt, "minute");
|
|
336
|
+
if (elapsedMinutes <= 0)
|
|
337
|
+
return 0;
|
|
338
|
+
if (elapsedMinutes >= totalMinutes)
|
|
339
|
+
return 100;
|
|
340
|
+
return Math.floor(elapsedMinutes / totalMinutes * 100);
|
|
341
|
+
})();
|
|
342
|
+
let reservedStatus;
|
|
343
|
+
let lateTime;
|
|
344
|
+
let remainingReserveTime;
|
|
345
|
+
if (bookingStatus === "reserved" && startAt.isValid()) {
|
|
346
|
+
if (current.isBefore(startAt)) {
|
|
347
|
+
reservedStatus = "not_arrived";
|
|
348
|
+
remainingReserveTime = startAt.diff(current, "minute");
|
|
349
|
+
} else {
|
|
350
|
+
reservedStatus = "late";
|
|
351
|
+
lateTime = Math.max(current.diff(startAt, "minute"), 0);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return {
|
|
355
|
+
...booking,
|
|
356
|
+
status: bookingStatus,
|
|
357
|
+
isTimeout,
|
|
358
|
+
timeoutTime,
|
|
359
|
+
progressPercent,
|
|
360
|
+
lateTime,
|
|
361
|
+
reserved_status: reservedStatus,
|
|
362
|
+
remainingReserveTime
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
async getResourceBookingList(currentTime, bookingList = []) {
|
|
366
|
+
var _a;
|
|
367
|
+
const current = (0, import_dayjs.default)(currentTime);
|
|
368
|
+
if (!current.isValid())
|
|
369
|
+
return [];
|
|
370
|
+
const resourceResponse = await this.request.get(
|
|
371
|
+
"/shop/form/resource/page",
|
|
372
|
+
{ skip: 1, num: 999 },
|
|
373
|
+
// @ts-ignore
|
|
374
|
+
{ osServer: true, isShopApi: true }
|
|
375
|
+
);
|
|
376
|
+
const resourceList = ((_a = resourceResponse == null ? void 0 : resourceResponse.data) == null ? void 0 : _a.list) ?? [];
|
|
377
|
+
if (!Array.isArray(resourceList) || resourceList.length === 0)
|
|
378
|
+
return [];
|
|
379
|
+
const normalizedBookings = bookingList.map((booking) => this.normalizeMatchedBooking(current, booking)).filter((booking) => Boolean(booking)).sort((left, right) => {
|
|
380
|
+
const leftStartAt = this.toBookingDateTime(left.start_date, left.start_time).valueOf();
|
|
381
|
+
const rightStartAt = this.toBookingDateTime(right.start_date, right.start_time).valueOf();
|
|
382
|
+
return leftStartAt - rightStartAt;
|
|
383
|
+
});
|
|
384
|
+
const bookingMap = /* @__PURE__ */ new Map();
|
|
385
|
+
normalizedBookings.forEach((booking) => {
|
|
386
|
+
if (!Array.isArray(booking.resources))
|
|
387
|
+
return;
|
|
388
|
+
booking.resources.forEach((resource) => {
|
|
389
|
+
const relationId = resource == null ? void 0 : resource.relation_id;
|
|
390
|
+
if (relationId === void 0 || relationId === null)
|
|
391
|
+
return;
|
|
392
|
+
const key = String(relationId);
|
|
393
|
+
const list = bookingMap.get(key) || [];
|
|
394
|
+
list.push(booking);
|
|
395
|
+
bookingMap.set(key, list);
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
return resourceList.map((resource) => {
|
|
399
|
+
const resourceId = this.getResourceId(resource);
|
|
400
|
+
const matchedBookings = bookingMap.get(String(resourceId)) || [];
|
|
401
|
+
const bookings = this.pickBookingsForCurrentPoint(current, matchedBookings);
|
|
402
|
+
return {
|
|
403
|
+
...resource,
|
|
404
|
+
resource_id: resourceId,
|
|
405
|
+
bookings
|
|
406
|
+
};
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
var Sales_default = SalesImpl;
|
|
411
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
412
|
+
0 && (module.exports = {
|
|
413
|
+
Sales,
|
|
414
|
+
SalesImpl,
|
|
415
|
+
...require("./types")
|
|
416
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import type { OrderData } from '../../server/modules/order/types';
|
|
3
|
+
import type { BookingData } from '../../server/modules/order/types';
|
|
4
|
+
import type { ResourceData, ResourceId } from '../../server/modules/resource/types';
|
|
5
|
+
export declare enum SalesHooks {
|
|
6
|
+
onInited = "sales:onInited",
|
|
7
|
+
onDestroy = "sales:onDestroy",
|
|
8
|
+
onCurrentDayChanged = "sales:onCurrentDayChanged",
|
|
9
|
+
onReservationListChanged = "sales:onReservationListChanged"
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 预订记录类型(暂用 OrderData 占位)
|
|
13
|
+
*
|
|
14
|
+
* TODO(Rolo): 等领导提供 reservationList 的目标结构后,
|
|
15
|
+
* 将 Server/Order 原始数据转换为真正的 Reservation DTO,
|
|
16
|
+
* 当前不要直接把 OrderData 当作最终 UI 数据结构。
|
|
17
|
+
*/
|
|
18
|
+
export type Reservation = OrderData;
|
|
19
|
+
export type SalesBookingStatus = 'reserved' | 'occupied' | 'locked' | undefined;
|
|
20
|
+
export type SalesReservedStatus = 'not_arrived' | 'late' | undefined;
|
|
21
|
+
export interface SalesResourceMatchedBooking extends Omit<BookingData, 'status'> {
|
|
22
|
+
status: SalesBookingStatus;
|
|
23
|
+
isTimeout: boolean;
|
|
24
|
+
timeoutTime?: number;
|
|
25
|
+
progressPercent?: number;
|
|
26
|
+
lateTime?: number;
|
|
27
|
+
remainingReserveTime?: number;
|
|
28
|
+
reserved_status: SalesReservedStatus;
|
|
29
|
+
}
|
|
30
|
+
export interface SalesResourceBookingItem extends Omit<ResourceData, 'bookings'> {
|
|
31
|
+
resource_id: ResourceId;
|
|
32
|
+
bookings: SalesResourceMatchedBooking[];
|
|
33
|
+
}
|
|
34
|
+
export type SalesTimelineHighlights = number[];
|
|
35
|
+
/**
|
|
36
|
+
* Sales 解决方案状态
|
|
37
|
+
*
|
|
38
|
+
* - currentDay: 当前选择的日期,默认当天 00:00:00
|
|
39
|
+
* - reservationList: currentDay 对应的预约列表(数据来源于 Server/Order,转换逻辑待补)
|
|
40
|
+
*/
|
|
41
|
+
export interface SalesState {
|
|
42
|
+
/** 当前选择的日期,默认当天 00:00:00 */
|
|
43
|
+
currentDay: dayjs.Dayjs;
|
|
44
|
+
/** 当前日期对应的预约列表 */
|
|
45
|
+
reservationList: Reservation[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Sales 解决方案最小 API 面
|
|
49
|
+
*/
|
|
50
|
+
export interface SalesModuleAPI {
|
|
51
|
+
/** 获取当前 store 快照 */
|
|
52
|
+
getState: () => SalesState;
|
|
53
|
+
/** 获取当前选择日期 */
|
|
54
|
+
getCurrentDay: () => dayjs.Dayjs;
|
|
55
|
+
/** 设置当前选择日期,会自动归一到当天 00:00:00 */
|
|
56
|
+
setCurrentDay: (currentDay: dayjs.ConfigType) => dayjs.Dayjs;
|
|
57
|
+
/** 获取当前预约列表 */
|
|
58
|
+
getReservationList: () => Reservation[];
|
|
59
|
+
/** 覆盖设置当前预约列表 */
|
|
60
|
+
setReservationList: (reservationList: Reservation[]) => Reservation[];
|
|
61
|
+
/** 重置预约列表为空 */
|
|
62
|
+
resetReservationList: () => Reservation[];
|
|
63
|
+
/** 获取资源维度的预约占用列表 */
|
|
64
|
+
getResourceBookingList: (currentTime: string, bookingList: BookingData[]) => Promise<SalesResourceBookingItem[]>;
|
|
65
|
+
/** 获取时间轴每个时间片的预约数量 */
|
|
66
|
+
getTimelineHighlights: (bookingList: BookingData[], startDateTime?: string, endDateTime?: string) => SalesTimelineHighlights;
|
|
67
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/solution/Sales/types.ts
|
|
20
|
+
var types_exports = {};
|
|
21
|
+
__export(types_exports, {
|
|
22
|
+
SalesHooks: () => SalesHooks
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(types_exports);
|
|
25
|
+
var SalesHooks = /* @__PURE__ */ ((SalesHooks2) => {
|
|
26
|
+
SalesHooks2["onInited"] = "sales:onInited";
|
|
27
|
+
SalesHooks2["onDestroy"] = "sales:onDestroy";
|
|
28
|
+
SalesHooks2["onCurrentDayChanged"] = "sales:onCurrentDayChanged";
|
|
29
|
+
SalesHooks2["onReservationListChanged"] = "sales:onReservationListChanged";
|
|
30
|
+
return SalesHooks2;
|
|
31
|
+
})(SalesHooks || {});
|
|
32
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
33
|
+
0 && (module.exports = {
|
|
34
|
+
SalesHooks
|
|
35
|
+
});
|
|
@@ -30,6 +30,7 @@ export declare class ShopDiscountImpl extends BaseModule implements Module {
|
|
|
30
30
|
type?: 'form' | 'customer';
|
|
31
31
|
[key: string]: any;
|
|
32
32
|
}): void;
|
|
33
|
+
setOrderId(id?: number): void;
|
|
33
34
|
calcDiscount(productList: Record<string, any>[], options?: SetDiscountSelectedParams): {
|
|
34
35
|
productList: Record<string, any>[];
|
|
35
36
|
discountList: Discount[];
|
|
@@ -57,7 +57,8 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
|
|
|
57
57
|
filteredDiscountList: [],
|
|
58
58
|
orderTotalAmount: 0,
|
|
59
59
|
holders: [],
|
|
60
|
-
bookingSubject: void 0
|
|
60
|
+
bookingSubject: void 0,
|
|
61
|
+
orderId: void 0
|
|
61
62
|
};
|
|
62
63
|
}
|
|
63
64
|
// =========== 生命周期方法 ===========
|
|
@@ -205,6 +206,9 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
|
|
|
205
206
|
setBookingSubject(bookingSubject) {
|
|
206
207
|
this.store.bookingSubject = bookingSubject;
|
|
207
208
|
}
|
|
209
|
+
setOrderId(id) {
|
|
210
|
+
this.store.orderId = id;
|
|
211
|
+
}
|
|
208
212
|
// 计算优惠券
|
|
209
213
|
calcDiscount(productList, options) {
|
|
210
214
|
var _a;
|
|
@@ -247,6 +251,8 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
|
|
|
247
251
|
selectionMap.set(operation.discountId, operation.isSelected);
|
|
248
252
|
});
|
|
249
253
|
const newDiscountList = discountList.map((discount) => {
|
|
254
|
+
if (discount.isEditMode)
|
|
255
|
+
return discount;
|
|
250
256
|
if (selectionMap.has(discount.id)) {
|
|
251
257
|
const targetIsSelected = selectionMap.get(discount.id);
|
|
252
258
|
return {
|
|
@@ -282,7 +288,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
|
|
|
282
288
|
async scanCode(code, customerId) {
|
|
283
289
|
var _a, _b, _c;
|
|
284
290
|
try {
|
|
285
|
-
const resultDiscountList = await ((_a = this.store.discount) == null ? void 0 : _a.batchSearch(code, customerId)) || [];
|
|
291
|
+
const resultDiscountList = await ((_a = this.store.discount) == null ? void 0 : _a.batchSearch(code, { customerId, orderId: this.store.orderId })) || [];
|
|
286
292
|
const rulesModule = this.store.rules;
|
|
287
293
|
if (!rulesModule) {
|
|
288
294
|
return {
|
|
@@ -325,9 +331,9 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
|
|
|
325
331
|
productList: this.store.productList || [],
|
|
326
332
|
oldDiscountList: this.getDiscountList(),
|
|
327
333
|
newDiscountList: withScanList,
|
|
328
|
-
orderTotalAmount: this.store.orderTotalAmount || 0,
|
|
329
334
|
holders: this.store.holders || [],
|
|
330
|
-
isFormSubject: ((_b = this.store.bookingSubject) == null ? void 0 : _b.type) === "form"
|
|
335
|
+
isFormSubject: ((_b = this.store.bookingSubject) == null ? void 0 : _b.type) === "form",
|
|
336
|
+
orderTotalAmount: this.store.orderTotalAmount || 0
|
|
331
337
|
}) || {
|
|
332
338
|
isAvailable: false,
|
|
333
339
|
productList: this.store.productList || [],
|
|
@@ -517,14 +523,16 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
|
|
|
517
523
|
async loadPrepareConfig(params) {
|
|
518
524
|
var _a, _b, _c, _d, _e;
|
|
519
525
|
try {
|
|
526
|
+
const orderId = this.store.orderId;
|
|
520
527
|
const customerId = params.customerId || ((_a = this.getCustomer()) == null ? void 0 : _a.id);
|
|
521
528
|
const goodPassList = await ((_b = this.store.discount) == null ? void 0 : _b.loadPrepareConfig({
|
|
522
529
|
customer_id: customerId,
|
|
523
|
-
action: "create",
|
|
530
|
+
action: orderId ? "update" : "create",
|
|
524
531
|
with_good_pass: 1,
|
|
525
532
|
with_discount_card: 1,
|
|
526
533
|
with_wallet_pass_holder: 1,
|
|
527
|
-
request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
534
|
+
request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
535
|
+
...orderId ? { order_id: orderId } : {}
|
|
528
536
|
}));
|
|
529
537
|
const scanDiscount = (_c = this.getDiscountList()) == null ? void 0 : _c.filter(
|
|
530
538
|
(item) => item.isScan
|
|
@@ -36,6 +36,7 @@ export interface ShopDiscountState {
|
|
|
36
36
|
type?: 'form' | 'customer';
|
|
37
37
|
[key: string]: any;
|
|
38
38
|
};
|
|
39
|
+
orderId?: number;
|
|
39
40
|
}
|
|
40
41
|
export interface SetDiscountSelectedParams {
|
|
41
42
|
discountId: number;
|
|
@@ -44,4 +45,9 @@ export interface SetDiscountSelectedParams {
|
|
|
44
45
|
discountId: number;
|
|
45
46
|
isSelected: boolean;
|
|
46
47
|
}[];
|
|
48
|
+
bookingSubject?: {
|
|
49
|
+
type?: 'form' | 'customer';
|
|
50
|
+
[key: string]: any;
|
|
51
|
+
};
|
|
52
|
+
orderId?: number;
|
|
47
53
|
}
|
|
@@ -2,6 +2,15 @@ import { Discount } from "../../modules/Discount/types";
|
|
|
2
2
|
export declare const uniqueById: <T>(arr: T[], key?: string) => T[];
|
|
3
3
|
export declare const isNormalProductByDurationSchedule: (item: any) => boolean;
|
|
4
4
|
export declare const isAllNormalProduct: (items: any[]) => boolean;
|
|
5
|
+
/**
|
|
6
|
+
* 获取折扣金额 基于折扣卡类型计算
|
|
7
|
+
* 商品券:直接返回商品价格
|
|
8
|
+
* 折扣卡:根据折扣卡类型计算 固定金额:直接返回折扣卡金额 百分比:根据折扣卡金额计算
|
|
9
|
+
* @param discount
|
|
10
|
+
* @param total
|
|
11
|
+
* @param price
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
5
14
|
/**
|
|
6
15
|
* 获取折扣金额 基于折扣卡类型计算
|
|
7
16
|
* 商品券:直接返回商品价格
|
|
@@ -56,18 +56,14 @@ var isAllNormalProduct = (items) => {
|
|
|
56
56
|
};
|
|
57
57
|
var getDiscountAmount = (discount, total, price) => {
|
|
58
58
|
var _a;
|
|
59
|
-
let discountedPrice = 0;
|
|
60
59
|
if (discount.tag === "good_pass") {
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
} else {
|
|
67
|
-
discountedPrice = new import_decimal.default(100).minus(discount.par_value || 0).div(100).mul(new import_decimal.default(price)).toNumber();
|
|
68
|
-
}
|
|
60
|
+
return new import_decimal.default(price).minus(new import_decimal.default(price || 0)).toNumber();
|
|
61
|
+
}
|
|
62
|
+
const isFixedAmount = ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.discount_card_type) === "fixed_amount";
|
|
63
|
+
if (isFixedAmount) {
|
|
64
|
+
return Math.max(new import_decimal.default(price).minus(new import_decimal.default((discount.amount ?? discount.par_value) || 0)).toNumber(), 0);
|
|
69
65
|
}
|
|
70
|
-
return
|
|
66
|
+
return new import_decimal.default(100).minus(discount.par_value || 0).div(100).mul(new import_decimal.default(price)).toNumber();
|
|
71
67
|
};
|
|
72
68
|
var getDiscountListAmountTotal = (discount) => {
|
|
73
69
|
return discount.reduce((acc, cur) => {
|
package/lib/solution/index.d.ts
CHANGED