@pisell/pisellos 0.10.20 → 0.10.22
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/model/strategy/adapter/promotion/index.js +0 -9
- 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 +10 -1
- package/dist/modules/OpenData/index.js +268 -14
- package/dist/modules/OpenData/types.d.ts +14 -1
- package/dist/modules/OpenData/utils.d.ts +1 -0
- package/dist/modules/OpenData/utils.js +8 -5
- package/dist/modules/Order/index.d.ts +6 -1
- 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/plugins/request.d.ts +2 -1
- package/dist/plugins/request.js +4 -2
- package/dist/server/index.js +33 -16
- package/dist/solution/BaseSales/index.d.ts +16 -1
- package/dist/solution/BaseSales/index.js +690 -349
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +14 -2
- package/dist/solution/BookingTicket/index.js +25 -18
- package/dist/solution/Sales/index.js +29 -22
- package/dist/solution/UnifiedBookingSales/index.d.ts +1 -1
- package/dist/solution/UnifiedBookingSales/index.js +315 -99
- 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 +10 -1
- package/lib/modules/OpenData/index.js +162 -2
- package/lib/modules/OpenData/types.d.ts +14 -1
- package/lib/modules/OpenData/utils.d.ts +1 -0
- package/lib/modules/OpenData/utils.js +9 -5
- package/lib/modules/Order/index.d.ts +6 -1
- 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/plugins/request.d.ts +2 -1
- package/lib/plugins/request.js +3 -2
- package/lib/server/index.js +16 -1
- package/lib/solution/BaseSales/index.d.ts +16 -1
- package/lib/solution/BaseSales/index.js +314 -66
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +14 -2
- package/lib/solution/BookingTicket/index.js +3 -0
- package/lib/solution/Sales/index.js +3 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +1 -1
- package/lib/solution/UnifiedBookingSales/index.js +228 -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,
|
|
@@ -3,7 +3,7 @@ import { BaseModule } from '../BaseModule';
|
|
|
3
3
|
import type { ScheduleModule } from '../Schedule';
|
|
4
4
|
import type { OpenDataConfig, OpenDataFetchParams, OpenDataAvailabilityResult, InvoiceLayoutConfig, InvoiceTemplateSettings } from './types';
|
|
5
5
|
export * from './types';
|
|
6
|
-
export { computeAvailability, getDefaultInvoiceLayoutConfig, getDefaultInvoiceTemplateSettings, normalizeInvoiceLayoutConfig, normalizeInvoiceTemplateSettings, normalizeRawInvoiceTemplateSettings, resolveInvoiceReceiptLocales, } from './utils';
|
|
6
|
+
export { computeAvailability, getDefaultInvoiceLayoutConfig, getDefaultInvoiceTemplateSettings, normalizeInvoiceLayoutConfig, normalizeInvoiceLayoutFromTemplateSettings, normalizeInvoiceTemplateSettings, normalizeRawInvoiceTemplateSettings, resolveInvoiceReceiptLocales, } from './utils';
|
|
7
7
|
export declare class OpenDataModule extends BaseModule implements Module {
|
|
8
8
|
protected defaultName: string;
|
|
9
9
|
protected defaultVersion: string;
|
|
@@ -16,6 +16,9 @@ export declare class OpenDataModule extends BaseModule implements Module {
|
|
|
16
16
|
private fatherModule;
|
|
17
17
|
private otherParams;
|
|
18
18
|
private fetchRevision;
|
|
19
|
+
private invoiceTemplateCacheRevision;
|
|
20
|
+
private invoiceTemplateDocumentCache;
|
|
21
|
+
private invoiceTemplateDocumentInFlight;
|
|
19
22
|
constructor(name?: string, version?: string);
|
|
20
23
|
initialize(core: PisellCore, options: ModuleOptions): Promise<void>;
|
|
21
24
|
/**
|
|
@@ -29,6 +32,12 @@ export declare class OpenDataModule extends BaseModule implements Module {
|
|
|
29
32
|
getOpenData(): OpenDataConfig | null;
|
|
30
33
|
getInvoiceLayoutConfig(): InvoiceLayoutConfig;
|
|
31
34
|
getInvoiceTemplateSettings(): InvoiceTemplateSettings;
|
|
35
|
+
ensureInvoiceTemplateSettings(target: string): Promise<InvoiceTemplateSettings>;
|
|
36
|
+
private commitInvoiceTemplateSettings;
|
|
37
|
+
private resolveInvoiceTemplateSettings;
|
|
38
|
+
private buildInvoiceTemplateCacheKey;
|
|
39
|
+
private fetchInvoiceTemplateDocument;
|
|
40
|
+
private logInvoiceTemplateDocumentFallback;
|
|
32
41
|
getLastFetchedAt(): number | null;
|
|
33
42
|
/** 清除内存与 sessionStorage 镜像中的 OpenData,供宿主切店时调用。 */
|
|
34
43
|
clearCache(): void;
|
|
@@ -9,6 +9,7 @@ var _exportNames = {
|
|
|
9
9
|
getDefaultInvoiceLayoutConfig: true,
|
|
10
10
|
getDefaultInvoiceTemplateSettings: true,
|
|
11
11
|
normalizeInvoiceLayoutConfig: true,
|
|
12
|
+
normalizeInvoiceLayoutFromTemplateSettings: true,
|
|
12
13
|
normalizeInvoiceTemplateSettings: true,
|
|
13
14
|
normalizeRawInvoiceTemplateSettings: true,
|
|
14
15
|
resolveInvoiceReceiptLocales: true
|
|
@@ -38,6 +39,12 @@ Object.defineProperty(exports, "normalizeInvoiceLayoutConfig", {
|
|
|
38
39
|
return _utils.normalizeInvoiceLayoutConfig;
|
|
39
40
|
}
|
|
40
41
|
});
|
|
42
|
+
Object.defineProperty(exports, "normalizeInvoiceLayoutFromTemplateSettings", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function () {
|
|
45
|
+
return _utils.normalizeInvoiceLayoutFromTemplateSettings;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
41
48
|
Object.defineProperty(exports, "normalizeInvoiceTemplateSettings", {
|
|
42
49
|
enumerable: true,
|
|
43
50
|
get: function () {
|
|
@@ -70,6 +77,25 @@ Object.keys(_types).forEach(function (key) {
|
|
|
70
77
|
}
|
|
71
78
|
});
|
|
72
79
|
});
|
|
80
|
+
function isRecord(value) {
|
|
81
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
82
|
+
}
|
|
83
|
+
function resolveInvoiceDocumentId(value) {
|
|
84
|
+
if (typeof value === 'number') {
|
|
85
|
+
return Number.isSafeInteger(value) && value > 0 ? String(value) : null;
|
|
86
|
+
}
|
|
87
|
+
if (typeof value !== 'string') return null;
|
|
88
|
+
const normalized = value.trim();
|
|
89
|
+
if (!/^\d+$/.test(normalized)) return null;
|
|
90
|
+
const numericId = Number(normalized);
|
|
91
|
+
return Number.isSafeInteger(numericId) && numericId > 0 ? String(numericId) : null;
|
|
92
|
+
}
|
|
93
|
+
function isLegacyInvoiceTemplate(value) {
|
|
94
|
+
if (typeof value !== 'string' || value.trim().length === 0) return false;
|
|
95
|
+
const normalized = value.trim();
|
|
96
|
+
const numericLike = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i;
|
|
97
|
+
return !numericLike.test(normalized);
|
|
98
|
+
}
|
|
73
99
|
class OpenDataModule extends _BaseModule.BaseModule {
|
|
74
100
|
defaultName = 'openData';
|
|
75
101
|
defaultVersion = '1.0.0';
|
|
@@ -82,6 +108,9 @@ class OpenDataModule extends _BaseModule.BaseModule {
|
|
|
82
108
|
fatherModule;
|
|
83
109
|
otherParams = {};
|
|
84
110
|
fetchRevision = 0;
|
|
111
|
+
invoiceTemplateCacheRevision = 0;
|
|
112
|
+
invoiceTemplateDocumentCache = new Map();
|
|
113
|
+
invoiceTemplateDocumentInFlight = new Map();
|
|
85
114
|
constructor(name, version) {
|
|
86
115
|
super(name, version);
|
|
87
116
|
}
|
|
@@ -90,6 +119,12 @@ class OpenDataModule extends _BaseModule.BaseModule {
|
|
|
90
119
|
this.store = options.store;
|
|
91
120
|
this.store.data = options.initialState?.data ?? null;
|
|
92
121
|
this.store.lastFetchedAt = options.initialState?.lastFetchedAt ?? null;
|
|
122
|
+
// Document 解析结果只在当前模块实例内复用。页面刷新后即使恢复了原始
|
|
123
|
+
// OpenData,也必须重新查询一次 NocoBase,以取得当前模板内容。
|
|
124
|
+
this.store.invoiceTemplateSettings = null;
|
|
125
|
+
this.store.invoiceTemplateTarget = null;
|
|
126
|
+
this.store.invoiceTemplateDocumentId = null;
|
|
127
|
+
this.store.invoiceTemplateCacheKey = null;
|
|
93
128
|
this.otherParams = options.otherParams || {};
|
|
94
129
|
if (this.otherParams.cacheId) {
|
|
95
130
|
this.openCache = this.otherParams.openCache ?? false;
|
|
@@ -139,10 +174,12 @@ class OpenDataModule extends _BaseModule.BaseModule {
|
|
|
139
174
|
throw new Error(response?.message || '获取 OpenData 配置失败');
|
|
140
175
|
}
|
|
141
176
|
const data = response?.data || {};
|
|
177
|
+
const resolvedInvoiceTemplate = await this.resolveInvoiceTemplateSettings(data, params.target);
|
|
142
178
|
// clearCache() 或后续请求发生后,旧响应不得复活已失效的 target 配置。
|
|
143
179
|
if (fetchRevision === this.fetchRevision) {
|
|
144
180
|
this.store.data = data;
|
|
145
181
|
this.store.lastFetchedAt = Date.now();
|
|
182
|
+
this.commitInvoiceTemplateSettings(params.target, resolvedInvoiceTemplate);
|
|
146
183
|
}
|
|
147
184
|
return data;
|
|
148
185
|
}
|
|
@@ -150,10 +187,126 @@ class OpenDataModule extends _BaseModule.BaseModule {
|
|
|
150
187
|
return this.store.data;
|
|
151
188
|
}
|
|
152
189
|
getInvoiceLayoutConfig() {
|
|
153
|
-
return (0, _utils.
|
|
190
|
+
return (0, _utils.normalizeInvoiceLayoutFromTemplateSettings)(this.getInvoiceTemplateSettings());
|
|
154
191
|
}
|
|
155
192
|
getInvoiceTemplateSettings() {
|
|
156
|
-
|
|
193
|
+
if (isRecord(this.store.invoiceTemplateSettings)) {
|
|
194
|
+
const documentId = resolveInvoiceDocumentId(this.store.data?.['documents.invoice_template']);
|
|
195
|
+
if (documentId) {
|
|
196
|
+
const target = this.store.invoiceTemplateTarget;
|
|
197
|
+
if (!target || this.store.invoiceTemplateCacheKey !== this.buildInvoiceTemplateCacheKey(target, documentId)) {
|
|
198
|
+
return (0, _utils.getDefaultInvoiceTemplateSettings)();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return (0, _utils.normalizeRawInvoiceTemplateSettings)(this.store.invoiceTemplateSettings);
|
|
202
|
+
}
|
|
203
|
+
if (isLegacyInvoiceTemplate(this.store.data?.['documents.invoice_template'])) {
|
|
204
|
+
return (0, _utils.normalizeInvoiceTemplateSettings)(this.store.data);
|
|
205
|
+
}
|
|
206
|
+
return (0, _utils.getDefaultInvoiceTemplateSettings)();
|
|
207
|
+
}
|
|
208
|
+
async ensureInvoiceTemplateSettings(target) {
|
|
209
|
+
const normalizedTarget = String(target || '').trim();
|
|
210
|
+
const config = this.store.data;
|
|
211
|
+
if (!normalizedTarget || !config) {
|
|
212
|
+
return (0, _utils.getDefaultInvoiceTemplateSettings)();
|
|
213
|
+
}
|
|
214
|
+
const fetchRevision = this.fetchRevision;
|
|
215
|
+
const resolved = await this.resolveInvoiceTemplateSettings(config, normalizedTarget);
|
|
216
|
+
if (fetchRevision !== this.fetchRevision || this.store.data !== config) {
|
|
217
|
+
return (0, _utils.getDefaultInvoiceTemplateSettings)();
|
|
218
|
+
}
|
|
219
|
+
this.commitInvoiceTemplateSettings(normalizedTarget, resolved);
|
|
220
|
+
return (0, _utils.normalizeRawInvoiceTemplateSettings)(resolved.settings);
|
|
221
|
+
}
|
|
222
|
+
commitInvoiceTemplateSettings(target, resolved) {
|
|
223
|
+
this.store.invoiceTemplateSettings = (0, _utils.normalizeRawInvoiceTemplateSettings)(resolved.settings);
|
|
224
|
+
this.store.invoiceTemplateTarget = target;
|
|
225
|
+
this.store.invoiceTemplateDocumentId = resolved.documentId;
|
|
226
|
+
this.store.invoiceTemplateCacheKey = resolved.cacheKey;
|
|
227
|
+
}
|
|
228
|
+
async resolveInvoiceTemplateSettings(config, target) {
|
|
229
|
+
const rawTemplate = config['documents.invoice_template'];
|
|
230
|
+
const documentId = resolveInvoiceDocumentId(rawTemplate);
|
|
231
|
+
if (!documentId) {
|
|
232
|
+
return {
|
|
233
|
+
settings: isLegacyInvoiceTemplate(rawTemplate) ? (0, _utils.normalizeInvoiceTemplateSettings)(config) : (0, _utils.getDefaultInvoiceTemplateSettings)(),
|
|
234
|
+
documentId: null,
|
|
235
|
+
cacheKey: null
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
const cacheKey = this.buildInvoiceTemplateCacheKey(target, documentId);
|
|
239
|
+
if (this.store.invoiceTemplateTarget === target && this.store.invoiceTemplateDocumentId === documentId && this.store.invoiceTemplateCacheKey === cacheKey && isRecord(this.store.invoiceTemplateSettings)) {
|
|
240
|
+
return {
|
|
241
|
+
settings: (0, _utils.normalizeRawInvoiceTemplateSettings)(this.store.invoiceTemplateSettings),
|
|
242
|
+
documentId,
|
|
243
|
+
cacheKey
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const cachedSettings = this.invoiceTemplateDocumentCache.get(cacheKey);
|
|
247
|
+
if (cachedSettings) {
|
|
248
|
+
return {
|
|
249
|
+
settings: (0, _utils.normalizeRawInvoiceTemplateSettings)(cachedSettings),
|
|
250
|
+
documentId,
|
|
251
|
+
cacheKey
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
let request = this.invoiceTemplateDocumentInFlight.get(cacheKey);
|
|
255
|
+
if (!request) {
|
|
256
|
+
const cacheRevision = this.invoiceTemplateCacheRevision;
|
|
257
|
+
request = this.fetchInvoiceTemplateDocument(documentId).catch(error => {
|
|
258
|
+
this.logInvoiceTemplateDocumentFallback(error, target, documentId);
|
|
259
|
+
return (0, _utils.getDefaultInvoiceTemplateSettings)();
|
|
260
|
+
}).then(settings => {
|
|
261
|
+
const normalized = (0, _utils.normalizeRawInvoiceTemplateSettings)(settings);
|
|
262
|
+
if (cacheRevision === this.invoiceTemplateCacheRevision) {
|
|
263
|
+
this.invoiceTemplateDocumentCache.set(cacheKey, normalized);
|
|
264
|
+
}
|
|
265
|
+
return normalized;
|
|
266
|
+
}).finally(() => {
|
|
267
|
+
if (this.invoiceTemplateDocumentInFlight.get(cacheKey) === request) {
|
|
268
|
+
this.invoiceTemplateDocumentInFlight.delete(cacheKey);
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
this.invoiceTemplateDocumentInFlight.set(cacheKey, request);
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
settings: await request,
|
|
275
|
+
documentId,
|
|
276
|
+
cacheKey
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
buildInvoiceTemplateCacheKey(target, documentId) {
|
|
280
|
+
const getData = this.appPlugin?.getData?.();
|
|
281
|
+
return JSON.stringify([getData?.('tenant_id') ?? null, getData?.('shop_id') ?? null, target, documentId]);
|
|
282
|
+
}
|
|
283
|
+
async fetchInvoiceTemplateDocument(documentId) {
|
|
284
|
+
const response = await this.request.get(`/document:get?filterByTk=${encodeURIComponent(documentId)}`, {}, {
|
|
285
|
+
isNocobase: true,
|
|
286
|
+
prefix: false,
|
|
287
|
+
headers: {
|
|
288
|
+
'x-data-source': 'pisell2'
|
|
289
|
+
},
|
|
290
|
+
customToast: () => {}
|
|
291
|
+
});
|
|
292
|
+
const document = response?.data;
|
|
293
|
+
if (!document || resolveInvoiceDocumentId(document.id) !== documentId) {
|
|
294
|
+
throw new Error(`Invoice Document ${documentId} 返回的 ID 不匹配`);
|
|
295
|
+
}
|
|
296
|
+
if (document.deleted_at !== null && document.deleted_at !== undefined) {
|
|
297
|
+
throw new Error(`Invoice Document ${documentId} 已被删除`);
|
|
298
|
+
}
|
|
299
|
+
if (!isRecord(document.data) || !isRecord(document.data.template_settings)) {
|
|
300
|
+
throw new Error(`Invoice Document ${documentId} 缺少 template_settings`);
|
|
301
|
+
}
|
|
302
|
+
return (0, _utils.normalizeRawInvoiceTemplateSettings)(document.data.template_settings);
|
|
303
|
+
}
|
|
304
|
+
logInvoiceTemplateDocumentFallback(error, target, documentId) {
|
|
305
|
+
console.warn('[OpenDataModule] Invoice Document 加载失败,使用 DEFAULT', {
|
|
306
|
+
target,
|
|
307
|
+
documentId,
|
|
308
|
+
message: error instanceof Error ? error.message : String(error)
|
|
309
|
+
});
|
|
157
310
|
}
|
|
158
311
|
getLastFetchedAt() {
|
|
159
312
|
return this.store.lastFetchedAt ?? null;
|
|
@@ -162,8 +315,15 @@ class OpenDataModule extends _BaseModule.BaseModule {
|
|
|
162
315
|
/** 清除内存与 sessionStorage 镜像中的 OpenData,供宿主切店时调用。 */
|
|
163
316
|
clearCache() {
|
|
164
317
|
this.fetchRevision += 1;
|
|
318
|
+
this.invoiceTemplateCacheRevision += 1;
|
|
319
|
+
this.invoiceTemplateDocumentCache.clear();
|
|
320
|
+
this.invoiceTemplateDocumentInFlight.clear();
|
|
165
321
|
this.store.data = null;
|
|
166
322
|
this.store.lastFetchedAt = null;
|
|
323
|
+
this.store.invoiceTemplateSettings = null;
|
|
324
|
+
this.store.invoiceTemplateTarget = null;
|
|
325
|
+
this.store.invoiceTemplateDocumentId = null;
|
|
326
|
+
this.store.invoiceTemplateCacheKey = null;
|
|
167
327
|
}
|
|
168
328
|
checkAvailability(scheduleModule) {
|
|
169
329
|
const scheduleList = scheduleModule ? scheduleModule?.getScheduleListByIds(this.store.data?.['availability.operating_hours'] || []) : undefined;
|
|
@@ -32,6 +32,15 @@ export interface InvoiceTemplateSettings {
|
|
|
32
32
|
modules: InvoiceTemplateModuleConfig[];
|
|
33
33
|
[key: string]: unknown;
|
|
34
34
|
}
|
|
35
|
+
export interface InvoiceDocumentResponse {
|
|
36
|
+
data?: {
|
|
37
|
+
id?: number | string;
|
|
38
|
+
deleted_at?: string | null;
|
|
39
|
+
data?: {
|
|
40
|
+
template_settings?: unknown;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
}
|
|
35
44
|
export type RawInvoiceEditConfig = string | {
|
|
36
45
|
language?: unknown;
|
|
37
46
|
modules?: unknown;
|
|
@@ -79,7 +88,7 @@ export interface OpenDataConfig {
|
|
|
79
88
|
label: string;
|
|
80
89
|
value: number;
|
|
81
90
|
}>;
|
|
82
|
-
'documents.invoice_template'?: string;
|
|
91
|
+
'documents.invoice_template'?: string | number;
|
|
83
92
|
'documents.invoice_edit'?: RawInvoiceEditConfig;
|
|
84
93
|
/** @deprecated 仅保留旧调用方的类型兼容,Invoice 读取逻辑不再消费该字段。 */
|
|
85
94
|
'documents.invoice'?: RawInvoiceLayoutConfig;
|
|
@@ -92,6 +101,10 @@ export interface OpenDataConfig {
|
|
|
92
101
|
export interface OpenDataState {
|
|
93
102
|
data: OpenDataConfig | null;
|
|
94
103
|
lastFetchedAt: number | null;
|
|
104
|
+
invoiceTemplateSettings?: InvoiceTemplateSettings | null;
|
|
105
|
+
invoiceTemplateTarget?: string | null;
|
|
106
|
+
invoiceTemplateDocumentId?: string | null;
|
|
107
|
+
invoiceTemplateCacheKey?: string | null;
|
|
95
108
|
}
|
|
96
109
|
export interface OpenDataFetchParams {
|
|
97
110
|
scope: string;
|
|
@@ -14,6 +14,7 @@ export declare function normalizeRawInvoiceTemplateSettings(value: unknown): Inv
|
|
|
14
14
|
* 从 OpenData Documents section 的两个扁平字段中构造 Native Invoice 配置。
|
|
15
15
|
*/
|
|
16
16
|
export declare function normalizeInvoiceTemplateSettings(config: OpenDataConfig | null | undefined): InvoiceTemplateSettings;
|
|
17
|
+
export declare function normalizeInvoiceLayoutFromTemplateSettings(settings: InvoiceTemplateSettings | null | undefined): InvoiceLayoutConfig;
|
|
17
18
|
/**
|
|
18
19
|
* 将 invoice_edit.modules 原样投影为 Web Invoice 使用的 module 字段。
|
|
19
20
|
*/
|
|
@@ -7,6 +7,7 @@ exports.computeAvailability = computeAvailability;
|
|
|
7
7
|
exports.getDefaultInvoiceLayoutConfig = getDefaultInvoiceLayoutConfig;
|
|
8
8
|
exports.getDefaultInvoiceTemplateSettings = getDefaultInvoiceTemplateSettings;
|
|
9
9
|
exports.normalizeInvoiceLayoutConfig = normalizeInvoiceLayoutConfig;
|
|
10
|
+
exports.normalizeInvoiceLayoutFromTemplateSettings = normalizeInvoiceLayoutFromTemplateSettings;
|
|
10
11
|
exports.normalizeInvoiceTemplateSettings = normalizeInvoiceTemplateSettings;
|
|
11
12
|
exports.normalizeRawInvoiceTemplateSettings = normalizeRawInvoiceTemplateSettings;
|
|
12
13
|
exports.resolveInvoiceReceiptLocales = resolveInvoiceReceiptLocales;
|
|
@@ -118,16 +119,19 @@ function normalizeInvoiceTemplateSettings(config) {
|
|
|
118
119
|
template: normalizeInvoiceTemplate(config?.['documents.invoice_template'])
|
|
119
120
|
});
|
|
120
121
|
}
|
|
122
|
+
function normalizeInvoiceLayoutFromTemplateSettings(settings) {
|
|
123
|
+
const modules = normalizeRawInvoiceTemplateSettings(settings).modules;
|
|
124
|
+
if (modules.length === 0) return getDefaultInvoiceLayoutConfig();
|
|
125
|
+
return {
|
|
126
|
+
module: modules
|
|
127
|
+
};
|
|
128
|
+
}
|
|
121
129
|
|
|
122
130
|
/**
|
|
123
131
|
* 将 invoice_edit.modules 原样投影为 Web Invoice 使用的 module 字段。
|
|
124
132
|
*/
|
|
125
133
|
function normalizeInvoiceLayoutConfig(config) {
|
|
126
|
-
|
|
127
|
-
if (modules.length === 0) return getDefaultInvoiceLayoutConfig();
|
|
128
|
-
return {
|
|
129
|
-
module: modules
|
|
130
|
-
};
|
|
134
|
+
return normalizeInvoiceLayoutFromTemplateSettings(normalizeInvoiceTemplateSettings(config));
|
|
131
135
|
}
|
|
132
136
|
function toBoolean(value) {
|
|
133
137
|
if (typeof value === 'boolean') return value;
|
|
@@ -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
|
*
|
|
@@ -528,7 +533,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
528
533
|
generateIdempotencyToken(): string;
|
|
529
534
|
syncPaymentsToOrder<T = any>(params: SyncPaymentsToOrderParams): Promise<SyncPaymentsToOrderResult<T>>;
|
|
530
535
|
createOrder(params: CommitOrderParams['query']): {
|
|
531
|
-
type: "
|
|
536
|
+
type: "appointment_booking" | "virtual";
|
|
532
537
|
platform: string;
|
|
533
538
|
sales_channel: string;
|
|
534
539
|
order_sales_channel: string;
|