@pisell/pisellos 0.10.21 → 0.10.23
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/modules/BookingContext/index.d.ts +3 -0
- package/dist/modules/BookingContext/index.js +42 -13
- package/dist/modules/BookingContext/types.d.ts +4 -4
- package/dist/modules/BookingContext/types.js +3 -3
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +10 -7
- package/dist/modules/OpenData/index.d.ts +1 -0
- package/dist/modules/OpenData/index.js +28 -9
- package/dist/modules/Order/index.d.ts +5 -0
- package/dist/modules/Order/index.js +148 -84
- package/dist/modules/ProductList/clientDataVariants.d.ts +50 -0
- package/dist/modules/ProductList/clientDataVariants.js +216 -0
- package/dist/modules/ProductList/index.d.ts +14 -13
- package/dist/modules/ProductList/index.js +105 -77
- package/dist/modules/Quotation/index.d.ts +16 -0
- package/dist/modules/Quotation/index.js +240 -27
- package/dist/modules/ResourcePlanner/planner.d.ts +2 -2
- package/dist/modules/ResourcePlanner/planner.js +88 -21
- package/dist/modules/ResourcePlanner/types.d.ts +12 -0
- package/dist/modules/Rules/index.d.ts +5 -0
- package/dist/modules/Rules/index.js +27 -12
- package/dist/solution/BaseSales/index.d.ts +16 -1
- package/dist/solution/BaseSales/index.js +667 -349
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/Sales/index.js +5 -3
- package/dist/solution/UnifiedBookingSales/index.d.ts +1 -1
- package/dist/solution/UnifiedBookingSales/index.js +290 -81
- package/dist/solution/UnifiedBookingSales/types.d.ts +4 -0
- package/dist/solution/VenueBooking/index.d.ts +2 -0
- package/dist/solution/VenueBooking/index.js +542 -494
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.js +3 -1
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +2 -0
- package/dist/solution/VenueBooking/utils/slotMerge.js +3 -1
- package/dist/utils/platform.d.ts +8 -0
- package/dist/utils/platform.js +15 -0
- package/lib/modules/BookingContext/index.d.ts +3 -0
- package/lib/modules/BookingContext/index.js +35 -8
- package/lib/modules/BookingContext/types.d.ts +4 -4
- package/lib/modules/BookingContext/types.js +3 -3
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +4 -0
- package/lib/modules/OpenData/index.d.ts +1 -0
- package/lib/modules/OpenData/index.js +13 -0
- package/lib/modules/Order/index.d.ts +5 -0
- package/lib/modules/Order/index.js +65 -8
- package/lib/modules/ProductList/clientDataVariants.d.ts +50 -0
- package/lib/modules/ProductList/clientDataVariants.js +204 -0
- package/lib/modules/ProductList/index.d.ts +14 -13
- package/lib/modules/ProductList/index.js +77 -58
- package/lib/modules/Quotation/index.d.ts +16 -0
- package/lib/modules/Quotation/index.js +112 -9
- package/lib/modules/ResourcePlanner/planner.d.ts +2 -2
- package/lib/modules/ResourcePlanner/planner.js +80 -20
- package/lib/modules/ResourcePlanner/types.d.ts +12 -0
- package/lib/modules/Rules/index.d.ts +5 -0
- package/lib/modules/Rules/index.js +20 -11
- package/lib/solution/BaseSales/index.d.ts +16 -1
- package/lib/solution/BaseSales/index.js +293 -66
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/Sales/index.js +2 -1
- package/lib/solution/UnifiedBookingSales/index.d.ts +1 -1
- package/lib/solution/UnifiedBookingSales/index.js +225 -20
- package/lib/solution/UnifiedBookingSales/types.d.ts +4 -0
- package/lib/solution/VenueBooking/index.d.ts +2 -0
- package/lib/solution/VenueBooking/index.js +28 -8
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.js +3 -1
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +2 -0
- package/lib/solution/VenueBooking/utils/slotMerge.js +3 -1
- package/lib/utils/platform.d.ts +8 -0
- package/lib/utils/platform.js +22 -0
- package/package.json +1 -1
|
@@ -7,5 +7,6 @@ export declare function buildDateRangeSummary(params: {
|
|
|
7
7
|
rawResources: VenueResourceRawData[];
|
|
8
8
|
resourceProductMap: Map<number | string, ResourceProductMapping[]>;
|
|
9
9
|
quotationModule?: QuotationModule;
|
|
10
|
+
channel?: string;
|
|
10
11
|
resolveConfig?: (date: string) => VenueBookingSlotConfig;
|
|
11
12
|
}): VenueDateSummaryItem[];
|
|
@@ -14,6 +14,7 @@ export function buildDateRangeSummary(params) {
|
|
|
14
14
|
rawResources = params.rawResources,
|
|
15
15
|
resourceProductMap = params.resourceProductMap,
|
|
16
16
|
quotationModule = params.quotationModule,
|
|
17
|
+
channel = params.channel,
|
|
17
18
|
resolveConfig = params.resolveConfig;
|
|
18
19
|
var result = [];
|
|
19
20
|
var productIds = quotationModule ? _toConsumableArray(new Set(_toConsumableArray(resourceProductMap.values()).flat().map(function (m) {
|
|
@@ -32,7 +33,8 @@ export function buildDateRangeSummary(params) {
|
|
|
32
33
|
});
|
|
33
34
|
quotationPriceMap = quotationModule.buildProductPriceMap({
|
|
34
35
|
productIds: productIds,
|
|
35
|
-
timePoints: timePoints
|
|
36
|
+
timePoints: timePoints,
|
|
37
|
+
channel: channel
|
|
36
38
|
});
|
|
37
39
|
}
|
|
38
40
|
var grid = buildTimeSlotGrid({
|
|
@@ -5,10 +5,12 @@ export declare function mergeConsecutiveSlots(slots: VenueSlotSelection[]): Merg
|
|
|
5
5
|
export declare function buildPriceBreakdown(params: {
|
|
6
6
|
group: MergedSlotGroup;
|
|
7
7
|
productId: number;
|
|
8
|
+
channel?: string;
|
|
8
9
|
quotation?: {
|
|
9
10
|
getQuotationShelfId: (p: {
|
|
10
11
|
productId: number;
|
|
11
12
|
datetime: string;
|
|
13
|
+
channel?: string;
|
|
12
14
|
}) => number;
|
|
13
15
|
};
|
|
14
16
|
}): PriceBreakdownEntry[];
|
|
@@ -53,6 +53,7 @@ export function mergeConsecutiveSlots(slots) {
|
|
|
53
53
|
export function buildPriceBreakdown(params) {
|
|
54
54
|
var group = params.group,
|
|
55
55
|
productId = params.productId,
|
|
56
|
+
channel = params.channel,
|
|
56
57
|
quotation = params.quotation;
|
|
57
58
|
if (!group.slots.length) return [];
|
|
58
59
|
var entries = [];
|
|
@@ -64,7 +65,8 @@ export function buildPriceBreakdown(params) {
|
|
|
64
65
|
var unitPrice = Number(slot.price || '0');
|
|
65
66
|
var shelfId = quotation ? quotation.getQuotationShelfId({
|
|
66
67
|
productId: productId,
|
|
67
|
-
datetime: slot.startTime
|
|
68
|
+
datetime: slot.startTime,
|
|
69
|
+
channel: channel
|
|
68
70
|
}) : 0;
|
|
69
71
|
var startHm = dayjs(slot.startTime, 'YYYY-MM-DD HH:mm').format('YYYY-MM-DD HH:mm');
|
|
70
72
|
var endHm = dayjs(slot.endTime, 'YYYY-MM-DD HH:mm').format('YYYY-MM-DD HH:mm');
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize the runtime platform passed through solution/module otherParams.
|
|
3
|
+
*/
|
|
4
|
+
export declare function normalizeRuntimePlatform(platform: unknown): string;
|
|
5
|
+
/**
|
|
6
|
+
* PC and H5 are authenticated-customer clients rather than staff terminals.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isCustomerUserPlatform(platform: unknown): boolean;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
var CUSTOMER_USER_PLATFORMS = new Set(['pc', 'h5']);
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Normalize the runtime platform passed through solution/module otherParams.
|
|
5
|
+
*/
|
|
6
|
+
export function normalizeRuntimePlatform(platform) {
|
|
7
|
+
return String(platform !== null && platform !== void 0 ? platform : '').trim().toLowerCase();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* PC and H5 are authenticated-customer clients rather than staff terminals.
|
|
12
|
+
*/
|
|
13
|
+
export function isCustomerUserPlatform(platform) {
|
|
14
|
+
return CUSTOMER_USER_PLATFORMS.has(normalizeRuntimePlatform(platform));
|
|
15
|
+
}
|
|
@@ -19,12 +19,15 @@ export declare class BookingContextModule extends BaseModule implements Module,
|
|
|
19
19
|
protected defaultVersion: string;
|
|
20
20
|
private request;
|
|
21
21
|
private store;
|
|
22
|
+
private otherParams;
|
|
22
23
|
/** 上次成功 loadBookingConfig 的 query key;命中则不再请求。 */
|
|
23
24
|
private lastConfigQueryKey;
|
|
24
25
|
/** 上次成功 loadResources 的 query key(date|bookingIds);命中则不再请求。 */
|
|
25
26
|
private lastResourcesQueryKey;
|
|
26
27
|
constructor(name?: string, version?: string);
|
|
27
28
|
initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
|
|
29
|
+
/** 同步父级解决方案的运行态参数;platform 变化后会自然切换 config endpoint/cache key。 */
|
|
30
|
+
updateOtherParams(params: Record<string, any>): void;
|
|
28
31
|
loadBookingConfig(params?: LoadBookingConfigParams, options?: {
|
|
29
32
|
forceRefresh?: boolean;
|
|
30
33
|
}): Promise<BookingContextConfig | null>;
|
|
@@ -16,6 +16,7 @@ exports.buildBookingResourcesQueryKey = buildBookingResourcesQueryKey;
|
|
|
16
16
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
17
17
|
var _BaseModule = require("../BaseModule");
|
|
18
18
|
var _request = require("../../plugins/request");
|
|
19
|
+
var _platform = require("../../utils/platform");
|
|
19
20
|
var _types = require("./types");
|
|
20
21
|
Object.keys(_types).forEach(function (key) {
|
|
21
22
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -52,6 +53,8 @@ const DEFAULT_BOOKING_CONFIG_PARAMS = {
|
|
|
52
53
|
item_type: 'appointment_booking',
|
|
53
54
|
sub_type: 'ticket'
|
|
54
55
|
};
|
|
56
|
+
const BOOKING_CONFIG_ENDPOINT = '/core/board/management/config';
|
|
57
|
+
const H5_BOOKING_CONFIG_ENDPOINT = '/core/board/config';
|
|
55
58
|
const BOARD_CONFIG_CACHE = {
|
|
56
59
|
useCache: true,
|
|
57
60
|
cache: {
|
|
@@ -167,6 +170,26 @@ function buildBookingConfigQueryKey(params = {}) {
|
|
|
167
170
|
});
|
|
168
171
|
return JSON.stringify(sorted);
|
|
169
172
|
}
|
|
173
|
+
function resolveBookingConfigRequest(platform, params = {}) {
|
|
174
|
+
const isH5 = (0, _platform.normalizeRuntimePlatform)(platform) === 'h5';
|
|
175
|
+
const endpoint = isH5 ? H5_BOOKING_CONFIG_ENDPOINT : BOOKING_CONFIG_ENDPOINT;
|
|
176
|
+
const query = isH5 ? {
|
|
177
|
+
item_type: params.item_type || DEFAULT_BOOKING_CONFIG_PARAMS.item_type
|
|
178
|
+
} : {
|
|
179
|
+
...DEFAULT_BOOKING_CONFIG_PARAMS,
|
|
180
|
+
...params
|
|
181
|
+
};
|
|
182
|
+
const keys = Object.keys(query).sort();
|
|
183
|
+
const sortedQuery = {};
|
|
184
|
+
keys.forEach(key => {
|
|
185
|
+
sortedQuery[key] = query[key];
|
|
186
|
+
});
|
|
187
|
+
return {
|
|
188
|
+
endpoint,
|
|
189
|
+
query,
|
|
190
|
+
key: `${endpoint}:${JSON.stringify(sortedQuery)}`
|
|
191
|
+
};
|
|
192
|
+
}
|
|
170
193
|
|
|
171
194
|
/** 稳定序列化资源列表查询(date + bookingIds),用于跳过重复 loadResources。 */
|
|
172
195
|
function buildBookingResourcesQueryKey(params = {}) {
|
|
@@ -181,6 +204,7 @@ class BookingContextModule extends _BaseModule.BaseModule {
|
|
|
181
204
|
store = {
|
|
182
205
|
...EMPTY_STATE
|
|
183
206
|
};
|
|
207
|
+
otherParams = {};
|
|
184
208
|
/** 上次成功 loadBookingConfig 的 query key;命中则不再请求。 */
|
|
185
209
|
lastConfigQueryKey = null;
|
|
186
210
|
/** 上次成功 loadResources 的 query key(date|bookingIds);命中则不再请求。 */
|
|
@@ -194,6 +218,7 @@ class BookingContextModule extends _BaseModule.BaseModule {
|
|
|
194
218
|
if (!this.request) {
|
|
195
219
|
throw new Error('BookingContextModule 需要 request 插件支持');
|
|
196
220
|
}
|
|
221
|
+
this.otherParams = options.otherParams || {};
|
|
197
222
|
this.store = {
|
|
198
223
|
bookingConfig: null,
|
|
199
224
|
resourcesOrigin: [],
|
|
@@ -212,15 +237,17 @@ class BookingContextModule extends _BaseModule.BaseModule {
|
|
|
212
237
|
this.store.date = initialState.date;
|
|
213
238
|
}
|
|
214
239
|
}
|
|
240
|
+
|
|
241
|
+
/** 同步父级解决方案的运行态参数;platform 变化后会自然切换 config endpoint/cache key。 */
|
|
242
|
+
updateOtherParams(params) {
|
|
243
|
+
this.otherParams = params || {};
|
|
244
|
+
}
|
|
215
245
|
async loadBookingConfig(params = {}, options = {}) {
|
|
216
|
-
const
|
|
246
|
+
const requestConfig = resolveBookingConfigRequest(this.otherParams?.platform, params);
|
|
247
|
+
const configKey = requestConfig.key;
|
|
217
248
|
if (!options.forceRefresh && this.store.bookingConfig != null && this.lastConfigQueryKey === configKey) {
|
|
218
249
|
return this.store.bookingConfig;
|
|
219
250
|
}
|
|
220
|
-
const query = {
|
|
221
|
-
...DEFAULT_BOOKING_CONFIG_PARAMS,
|
|
222
|
-
...params
|
|
223
|
-
};
|
|
224
251
|
const sharedKey = buildSharedCacheKey(this.request, configKey);
|
|
225
252
|
if (!options.forceRefresh && sharedBookingConfigCache.has(sharedKey)) {
|
|
226
253
|
const cached = sharedBookingConfigCache.get(sharedKey) ?? null;
|
|
@@ -232,7 +259,7 @@ class BookingContextModule extends _BaseModule.BaseModule {
|
|
|
232
259
|
if (!pending) {
|
|
233
260
|
const requestPromise = (async () => {
|
|
234
261
|
try {
|
|
235
|
-
const res = await this.request.get(
|
|
262
|
+
const res = await this.request.get(requestConfig.endpoint, requestConfig.query, BOARD_CONFIG_CACHE);
|
|
236
263
|
const config = res?.data ?? null;
|
|
237
264
|
sharedBookingConfigCache.set(sharedKey, config);
|
|
238
265
|
return config;
|
|
@@ -293,7 +320,7 @@ class BookingContextModule extends _BaseModule.BaseModule {
|
|
|
293
320
|
* store 内是否已具备与本次 init 入参等价的 config / resources(不再打接口)。
|
|
294
321
|
*/
|
|
295
322
|
isBookingContextReady(params = {}) {
|
|
296
|
-
const configKey =
|
|
323
|
+
const configKey = resolveBookingConfigRequest(this.otherParams?.platform, params.bookingConfigParams).key;
|
|
297
324
|
const dateInput = params.date ?? this.store.date ?? (0, _dayjs.default)();
|
|
298
325
|
const queryDate = toScheduleQueryDate(dateInput);
|
|
299
326
|
const resourcesKey = buildBookingResourcesQueryKey({
|
|
@@ -311,7 +338,7 @@ class BookingContextModule extends _BaseModule.BaseModule {
|
|
|
311
338
|
if (!params.forceRefresh && this.isBookingContextReady(params)) {
|
|
312
339
|
return this.getState();
|
|
313
340
|
}
|
|
314
|
-
const configKey =
|
|
341
|
+
const configKey = resolveBookingConfigRequest(this.otherParams?.platform, params.bookingConfigParams).key;
|
|
315
342
|
const resourcesKey = buildBookingResourcesQueryKey({
|
|
316
343
|
date: queryDate,
|
|
317
344
|
bookingIds: params.bookingIds
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* BookingContext 子模块:承载「预约 UI 上下文」三件套。
|
|
3
3
|
*
|
|
4
|
-
* - bookingConfig:来自 `/core/board/management/config` 的整套预约配置(service_time / resource_tab /
|
|
4
|
+
* - bookingConfig:来自 staff `/core/board/management/config` 或 H5 `/core/board/config` 的整套预约配置(service_time / resource_tab /
|
|
5
5
|
* appointment_subject / subject_require / stock_setting / basic / capacity 等)。
|
|
6
6
|
* - resourcesOrigin / resourcesOriginMap:来自 `/schedule/resource/list` 的资源全集,含 times / event_list /
|
|
7
7
|
* combined_resource 等运行态信息,是 getResourceByIds / getResourceTimeIsUsable 的输入。
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* - 默认由 `loadBookingConfig` / `loadResources` 拉取并写入 store;也支持消费方 `set*` 直接灌入(复用 ticketBooking 已拉到的数据)。
|
|
12
12
|
* - 所有读 API 返回浅克隆(数组)或原引用(map / config),避免 UI 写穿。
|
|
13
13
|
*/
|
|
14
|
-
/** `loadBookingConfig`
|
|
14
|
+
/** `loadBookingConfig` 入参;H5 公共接口只消费 `item_type`。 */
|
|
15
15
|
export interface LoadBookingConfigParams {
|
|
16
16
|
item_type?: string;
|
|
17
17
|
sub_type?: string;
|
|
@@ -42,7 +42,7 @@ export interface InitBookingContextParams {
|
|
|
42
42
|
export type BookingContextResource = Record<string, any>;
|
|
43
43
|
export type BookingContextResourceMap = Record<string, BookingContextResource>;
|
|
44
44
|
/**
|
|
45
|
-
* 形参 booking_config(结构来自
|
|
45
|
+
* 形参 booking_config(结构来自 staff management 或 H5 board config 接口的 `data`)。
|
|
46
46
|
* OS 不强制 schema,保留 `Record<string, any>` 兼容现网;常用路径文档化在 SDK docs。
|
|
47
47
|
*/
|
|
48
48
|
export type BookingContextConfig = Record<string, any>;
|
|
@@ -80,7 +80,7 @@ export interface BookingContextModuleAPI {
|
|
|
80
80
|
getState(): BookingContextState;
|
|
81
81
|
/** 一键清空,destroy / 切租户场景用。 */
|
|
82
82
|
clear(): void;
|
|
83
|
-
/**
|
|
83
|
+
/** 按运行平台拉取 board config 并写入 store。 */
|
|
84
84
|
loadBookingConfig(params?: LoadBookingConfigParams): Promise<BookingContextConfig | null>;
|
|
85
85
|
/** 拉取资源全集并写入 store(`/schedule/resource/list`)。 */
|
|
86
86
|
loadResources(params?: LoadBookingResourcesParams): Promise<BookingContextResource[]>;
|
|
@@ -7,7 +7,7 @@ exports.BookingContextEvent = void 0;
|
|
|
7
7
|
/**
|
|
8
8
|
* BookingContext 子模块:承载「预约 UI 上下文」三件套。
|
|
9
9
|
*
|
|
10
|
-
* - bookingConfig:来自 `/core/board/management/config` 的整套预约配置(service_time / resource_tab /
|
|
10
|
+
* - bookingConfig:来自 staff `/core/board/management/config` 或 H5 `/core/board/config` 的整套预约配置(service_time / resource_tab /
|
|
11
11
|
* appointment_subject / subject_require / stock_setting / basic / capacity 等)。
|
|
12
12
|
* - resourcesOrigin / resourcesOriginMap:来自 `/schedule/resource/list` 的资源全集,含 times / event_list /
|
|
13
13
|
* combined_resource 等运行态信息,是 getResourceByIds / getResourceTimeIsUsable 的输入。
|
|
@@ -17,7 +17,7 @@ exports.BookingContextEvent = void 0;
|
|
|
17
17
|
* - 默认由 `loadBookingConfig` / `loadResources` 拉取并写入 store;也支持消费方 `set*` 直接灌入(复用 ticketBooking 已拉到的数据)。
|
|
18
18
|
* - 所有读 API 返回浅克隆(数组)或原引用(map / config),避免 UI 写穿。
|
|
19
19
|
*/
|
|
20
|
-
/** `loadBookingConfig`
|
|
20
|
+
/** `loadBookingConfig` 入参;H5 公共接口只消费 `item_type`。 */
|
|
21
21
|
/** `loadResources` 入参,与 info2 `getResourceList` 一致。 */
|
|
22
22
|
/** `initBookingContext` 入参(BookingTicket 聚合入口)。 */
|
|
23
23
|
/**
|
|
@@ -25,7 +25,7 @@ exports.BookingContextEvent = void 0;
|
|
|
25
25
|
* 这里只声明 Record 形态;具体字段保留 `any`,与 ticketBooking 现网传入的数据形状兼容。
|
|
26
26
|
*/
|
|
27
27
|
/**
|
|
28
|
-
* 形参 booking_config(结构来自
|
|
28
|
+
* 形参 booking_config(结构来自 staff management 或 H5 board config 接口的 `data`)。
|
|
29
29
|
* OS 不强制 schema,保留 `Record<string, any>` 兼容现网;常用路径文档化在 SDK docs。
|
|
30
30
|
*/
|
|
31
31
|
/**
|
|
@@ -181,6 +181,7 @@ function buildCacheItemFromOrderLine(input) {
|
|
|
181
181
|
booking,
|
|
182
182
|
sourceProduct
|
|
183
183
|
} = input;
|
|
184
|
+
const holderConfig = sourceProduct?.holder_config ?? sourceProduct?.origin?.holder_config ?? product.metadata?.holder_config;
|
|
184
185
|
const resolvedId = product.product_id ?? sourceProduct?.id;
|
|
185
186
|
const selling = Number(product.selling_price ?? 0);
|
|
186
187
|
const original = Number(product.original_price ?? selling);
|
|
@@ -249,6 +250,9 @@ function buildCacheItemFromOrderLine(input) {
|
|
|
249
250
|
}
|
|
250
251
|
const base = {
|
|
251
252
|
...(sourceProduct || {}),
|
|
253
|
+
...(holderConfig !== undefined && holderConfig !== null ? {
|
|
254
|
+
holder_config: holderConfig
|
|
255
|
+
} : {}),
|
|
252
256
|
id: resolvedId,
|
|
253
257
|
product_id: resolvedId,
|
|
254
258
|
extension_type: sourceProduct?.extension_type ?? booking?.product?.extension_type ?? sourceProduct?.extension_type,
|
|
@@ -28,6 +28,7 @@ export declare class OpenDataModule extends BaseModule implements Module {
|
|
|
28
28
|
* openDataModule.updateOtherParams({ openCache: true, cacheId: 'cache-2' })
|
|
29
29
|
*/
|
|
30
30
|
updateOtherParams(params: Record<string, any>): void;
|
|
31
|
+
private shouldSkipInvoiceTemplateDocument;
|
|
31
32
|
fetchOpenData(params: OpenDataFetchParams): Promise<OpenDataConfig>;
|
|
32
33
|
getOpenData(): OpenDataConfig | null;
|
|
33
34
|
getInvoiceLayoutConfig(): InvoiceLayoutConfig;
|
|
@@ -152,6 +152,9 @@ class OpenDataModule extends _BaseModule.BaseModule {
|
|
|
152
152
|
this.cacheId = this.otherParams.cacheId;
|
|
153
153
|
this.fatherModule = this.otherParams.fatherModule;
|
|
154
154
|
}
|
|
155
|
+
shouldSkipInvoiceTemplateDocument() {
|
|
156
|
+
return String(this.otherParams?.platform || '').trim().toLowerCase() === 'h5';
|
|
157
|
+
}
|
|
155
158
|
async fetchOpenData(params) {
|
|
156
159
|
const fetchRevision = ++this.fetchRevision;
|
|
157
160
|
const getData = this.appPlugin?.getData?.();
|
|
@@ -190,6 +193,9 @@ class OpenDataModule extends _BaseModule.BaseModule {
|
|
|
190
193
|
return (0, _utils.normalizeInvoiceLayoutFromTemplateSettings)(this.getInvoiceTemplateSettings());
|
|
191
194
|
}
|
|
192
195
|
getInvoiceTemplateSettings() {
|
|
196
|
+
if (this.shouldSkipInvoiceTemplateDocument()) {
|
|
197
|
+
return (0, _utils.getDefaultInvoiceTemplateSettings)();
|
|
198
|
+
}
|
|
193
199
|
if (isRecord(this.store.invoiceTemplateSettings)) {
|
|
194
200
|
const documentId = resolveInvoiceDocumentId(this.store.data?.['documents.invoice_template']);
|
|
195
201
|
if (documentId) {
|
|
@@ -226,6 +232,13 @@ class OpenDataModule extends _BaseModule.BaseModule {
|
|
|
226
232
|
this.store.invoiceTemplateCacheKey = resolved.cacheKey;
|
|
227
233
|
}
|
|
228
234
|
async resolveInvoiceTemplateSettings(config, target) {
|
|
235
|
+
if (this.shouldSkipInvoiceTemplateDocument()) {
|
|
236
|
+
return {
|
|
237
|
+
settings: (0, _utils.getDefaultInvoiceTemplateSettings)(),
|
|
238
|
+
documentId: null,
|
|
239
|
+
cacheKey: null
|
|
240
|
+
};
|
|
241
|
+
}
|
|
229
242
|
const rawTemplate = config['documents.invoice_template'];
|
|
230
243
|
const documentId = resolveInvoiceDocumentId(rawTemplate);
|
|
231
244
|
if (!documentId) {
|
|
@@ -415,6 +415,11 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
415
415
|
* if (pending) await pending;
|
|
416
416
|
*/
|
|
417
417
|
private appendProductLineToTempOrder;
|
|
418
|
+
/**
|
|
419
|
+
* booking 数量拆行时,若 Holder 数量与拆行数严格一致,则按下标分配。
|
|
420
|
+
* 数量不一致时保持旧数据,避免猜测 Holder 与商品份数的对应关系。
|
|
421
|
+
*/
|
|
422
|
+
private createSplitBookingLine;
|
|
418
423
|
/**
|
|
419
424
|
* 添加商品行。带 booking 时强制独立行;num>1 时拆成多条 num=1 的 product+booking(对齐 BookingByStep / ticketBooking addService)。
|
|
420
425
|
*
|
|
@@ -3060,6 +3060,67 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3060
3060
|
commitProductLine(shouldMerge);
|
|
3061
3061
|
}
|
|
3062
3062
|
|
|
3063
|
+
/**
|
|
3064
|
+
* booking 数量拆行时,若 Holder 数量与拆行数严格一致,则按下标分配。
|
|
3065
|
+
* 数量不一致时保持旧数据,避免猜测 Holder 与商品份数的对应关系。
|
|
3066
|
+
*/
|
|
3067
|
+
createSplitBookingLine(product, booking, index, splitCount) {
|
|
3068
|
+
const singleLine = (0, _lodashEs.cloneDeep)(product);
|
|
3069
|
+
singleLine.num = 1;
|
|
3070
|
+
delete singleLine.product_quantity;
|
|
3071
|
+
const singleBooking = (0, _lodashEs.cloneDeep)(booking);
|
|
3072
|
+
const bookingHolder = booking?.holder && typeof booking.holder === 'object' ? booking.holder : null;
|
|
3073
|
+
const metadataHolder = booking?.metadata?.holder && typeof booking.metadata.holder === 'object' ? booking.metadata.holder : null;
|
|
3074
|
+
const rawHolderIds = bookingHolder?.form_record ?? booking?.metadata?.holder_id ?? metadataHolder?.form_record ?? product?.metadata?.holder_id;
|
|
3075
|
+
const holderIds = (Array.isArray(rawHolderIds) ? rawHolderIds : [rawHolderIds]).map(holderId => holderId && typeof holderId === 'object' ? holderId.form_record_id : holderId).filter(holderId => holderId !== undefined && holderId !== null && holderId !== '');
|
|
3076
|
+
if (holderIds.length !== splitCount) {
|
|
3077
|
+
return {
|
|
3078
|
+
product: singleLine,
|
|
3079
|
+
booking: singleBooking
|
|
3080
|
+
};
|
|
3081
|
+
}
|
|
3082
|
+
const holderId = holderIds[index];
|
|
3083
|
+
const rawHolderName = bookingHolder?.name ?? metadataHolder?.name;
|
|
3084
|
+
const holderNames = Array.isArray(rawHolderName) ? rawHolderName.map(name => String(name || '').trim()) : typeof rawHolderName === 'string' ? rawHolderName.split(',').map(name => name.trim()) : [];
|
|
3085
|
+
const holderName = holderNames.length === splitCount ? holderNames[index] : undefined;
|
|
3086
|
+
const splitHolder = holder => ({
|
|
3087
|
+
...holder,
|
|
3088
|
+
form_record: [holderId],
|
|
3089
|
+
...(holderName ? {
|
|
3090
|
+
name: holderName
|
|
3091
|
+
} : Object.prototype.hasOwnProperty.call(holder, 'name') ? {
|
|
3092
|
+
name: undefined
|
|
3093
|
+
} : {})
|
|
3094
|
+
});
|
|
3095
|
+
singleLine.metadata = {
|
|
3096
|
+
...(singleLine.metadata || {}),
|
|
3097
|
+
holder_id: [holderId]
|
|
3098
|
+
};
|
|
3099
|
+
if (singleLine._extend && typeof singleLine._extend === 'object') {
|
|
3100
|
+
singleLine._extend = {
|
|
3101
|
+
...singleLine._extend,
|
|
3102
|
+
holder_id: [holderId]
|
|
3103
|
+
};
|
|
3104
|
+
}
|
|
3105
|
+
if (singleBooking.holder && typeof singleBooking.holder === 'object') {
|
|
3106
|
+
singleBooking.holder = splitHolder(singleBooking.holder);
|
|
3107
|
+
}
|
|
3108
|
+
singleBooking.metadata = {
|
|
3109
|
+
...(singleBooking.metadata || {}),
|
|
3110
|
+
holder_id: [holderId],
|
|
3111
|
+
...(singleBooking.metadata?.holder && typeof singleBooking.metadata.holder === 'object' ? {
|
|
3112
|
+
holder: splitHolder(singleBooking.metadata.holder)
|
|
3113
|
+
} : {})
|
|
3114
|
+
};
|
|
3115
|
+
if (Object.prototype.hasOwnProperty.call(singleBooking, 'holder_id')) {
|
|
3116
|
+
singleBooking.holder_id = [holderId];
|
|
3117
|
+
}
|
|
3118
|
+
return {
|
|
3119
|
+
product: singleLine,
|
|
3120
|
+
booking: singleBooking
|
|
3121
|
+
};
|
|
3122
|
+
}
|
|
3123
|
+
|
|
3063
3124
|
/**
|
|
3064
3125
|
* 添加商品行。带 booking 时强制独立行;num>1 时拆成多条 num=1 的 product+booking(对齐 BookingByStep / ticketBooking addService)。
|
|
3065
3126
|
*
|
|
@@ -3080,10 +3141,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3080
3141
|
const splitCount = (0, _utils3.getSafeProductNum)(productRecord.num ?? productRecord.product_quantity ?? 1);
|
|
3081
3142
|
if (splitCount > 1) {
|
|
3082
3143
|
for (let i = 0; i < splitCount; i += 1) {
|
|
3083
|
-
const
|
|
3084
|
-
|
|
3085
|
-
delete singleLine.product_quantity;
|
|
3086
|
-
const appendResult = this.appendProductLineToTempOrder(tempOrder, singleLine, (0, _lodashEs.cloneDeep)(booking), {
|
|
3144
|
+
const splitLine = this.createSplitBookingLine(productRecord, booking, i, splitCount);
|
|
3145
|
+
const appendResult = this.appendProductLineToTempOrder(tempOrder, splitLine.product, splitLine.booking, {
|
|
3087
3146
|
insertAtIndex,
|
|
3088
3147
|
disableMerge: options?.disableMerge
|
|
3089
3148
|
});
|
|
@@ -3130,10 +3189,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3130
3189
|
const splitCount = (0, _utils3.getSafeProductNum)(productRecord.num ?? productRecord.product_quantity ?? 1);
|
|
3131
3190
|
if (splitCount > 1) {
|
|
3132
3191
|
for (let i = 0; i < splitCount; i += 1) {
|
|
3133
|
-
const
|
|
3134
|
-
|
|
3135
|
-
delete singleLine.product_quantity;
|
|
3136
|
-
const appendResult = this.appendProductLineToTempOrder(tempOrder, singleLine, (0, _lodashEs.cloneDeep)(booking));
|
|
3192
|
+
const splitLine = this.createSplitBookingLine(productRecord, booking, i, splitCount);
|
|
3193
|
+
const appendResult = this.appendProductLineToTempOrder(tempOrder, splitLine.product, splitLine.booking);
|
|
3137
3194
|
if (appendResult) await appendResult;
|
|
3138
3195
|
}
|
|
3139
3196
|
continue;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { PisellCore } from '../../types';
|
|
2
|
+
import type { RequestPlugin } from '../../plugins';
|
|
3
|
+
import type { ProductData } from '../Product/types';
|
|
4
|
+
export declare const PRODUCT_QUERY_DATA_VARIANT_RELATIONS: readonly ["category", "collection", "resourceRelation", "bundleGroup.bundleItem", "optionGroup.optionItem", "variantGroup.variantItem", "dataVariants"];
|
|
5
|
+
/**
|
|
6
|
+
* 判断当前商品查询是否会被本地 OS Server 接管。
|
|
7
|
+
*
|
|
8
|
+
* H5 RequestPlugin 即使收到 osServer=true 仍会直接请求远端接口,因此必须按
|
|
9
|
+
* RequestPlugin 实际 baseUrl 对应的已注册路由判断,不能只看请求选项。
|
|
10
|
+
*/
|
|
11
|
+
export declare function isProductQueryHandledByOsServer(core: PisellCore | undefined, request: RequestPlugin | undefined): boolean;
|
|
12
|
+
export interface ResolveClientDataVariantsParams {
|
|
13
|
+
core: PisellCore | undefined;
|
|
14
|
+
otherParams?: Record<string, any>;
|
|
15
|
+
products: ProductData[];
|
|
16
|
+
queryPayload: Record<string, any>;
|
|
17
|
+
handledByOsServer: boolean;
|
|
18
|
+
scheduleList?: unknown;
|
|
19
|
+
menuList?: unknown;
|
|
20
|
+
/** Quote fast paths require hydrated relations; legacy list resolution does not. */
|
|
21
|
+
requireCompleteDataVariantRelations?: boolean;
|
|
22
|
+
/** Quote fast paths require every referenced rule; legacy list resolution is best-effort. */
|
|
23
|
+
requireEvaluatorReady?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export type ResolveClientDataVariantsResult = {
|
|
26
|
+
status: 'handled-by-os-server' | 'empty' | 'data-variants-unavailable' | 'evaluator-unavailable' | 'evaluator-not-ready';
|
|
27
|
+
products: ProductData[];
|
|
28
|
+
} | {
|
|
29
|
+
status: 'resolved';
|
|
30
|
+
products: ProductData[];
|
|
31
|
+
} | {
|
|
32
|
+
status: 'error';
|
|
33
|
+
products: ProductData[];
|
|
34
|
+
error: unknown;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Strict client-side Data Variant resolution for quote fast paths.
|
|
38
|
+
*
|
|
39
|
+
* Unlike resolveClientDataVariants, callers can distinguish a complete local
|
|
40
|
+
* result from a capability/readiness/error fallback and decide to query the
|
|
41
|
+
* remote product endpoint instead.
|
|
42
|
+
*/
|
|
43
|
+
export declare function tryResolveClientDataVariants({ core, otherParams, products, queryPayload, handledByOsServer, scheduleList: explicitScheduleList, menuList: explicitMenuList, requireCompleteDataVariantRelations, requireEvaluatorReady, }: ResolveClientDataVariantsParams): ResolveClientDataVariantsResult;
|
|
44
|
+
/**
|
|
45
|
+
* 未启用商品 OS 路由时,在客户端补做 Data Variant 解析。
|
|
46
|
+
*
|
|
47
|
+
* 商品列表和预约报价必须共用这个边界,避免 H5 的弹窗报价绕过客户端智能定价。
|
|
48
|
+
* OS Server 已接管时直接信任服务端结果,确保同一批商品只评估一次。
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveClientDataVariants({ core, otherParams, products, queryPayload, handledByOsServer, scheduleList: explicitScheduleList, menuList: explicitMenuList, }: ResolveClientDataVariantsParams): ProductData[];
|