@pisell/pisellos 0.10.54 → 0.10.55
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 +9 -0
- package/dist/modules/BusinessAvailability/index.d.ts +30 -0
- package/dist/modules/BusinessAvailability/index.js +204 -0
- package/dist/modules/OpenData/types.d.ts +2 -0
- package/dist/modules/Order/index.d.ts +5 -2
- package/dist/modules/Order/index.js +315 -241
- package/dist/modules/Order/types.d.ts +8 -0
- package/dist/solution/BaseSales/index.d.ts +4 -15
- package/dist/solution/BaseSales/index.js +131 -86
- package/dist/solution/BaseSales/types.d.ts +11 -0
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +41 -13
- package/dist/solution/UnifiedBookingSales/businessAvailability.d.ts +27 -0
- package/dist/solution/UnifiedBookingSales/businessAvailability.js +292 -0
- package/dist/solution/UnifiedBookingSales/index.d.ts +11 -0
- package/dist/solution/UnifiedBookingSales/index.js +154 -75
- package/dist/solution/UnifiedBookingSales/types.d.ts +2 -0
- package/lib/model/strategy/adapter/promotion/index.js +1 -46
- package/lib/modules/BusinessAvailability/index.d.ts +30 -0
- package/lib/modules/BusinessAvailability/index.js +146 -0
- package/lib/modules/OpenData/types.d.ts +2 -0
- package/lib/modules/Order/index.d.ts +5 -2
- package/lib/modules/Order/index.js +62 -6
- package/lib/modules/Order/types.d.ts +8 -0
- package/lib/solution/BaseSales/index.d.ts +4 -15
- package/lib/solution/BaseSales/index.js +45 -24
- package/lib/solution/BaseSales/types.d.ts +11 -0
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +37 -4
- package/lib/solution/UnifiedBookingSales/businessAvailability.d.ts +27 -0
- package/lib/solution/UnifiedBookingSales/businessAvailability.js +138 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +11 -0
- package/lib/solution/UnifiedBookingSales/index.js +54 -0
- package/lib/solution/UnifiedBookingSales/types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -4,6 +4,8 @@ import type { ScanOrderLogInput as BaseSalesLogInput, ScanOrderLoggerProviderCon
|
|
|
4
4
|
import type { QuantityCheckResult, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
|
|
5
5
|
import type { QuotationCustomerScopeInfo } from '../../modules/Quotation/types';
|
|
6
6
|
import type { PaymentMethod } from '../../modules/Payment/types';
|
|
7
|
+
import type { OrderPaymentSource } from '../../modules/Order/types';
|
|
8
|
+
import type { SubmitPayloadEnhancer } from '../../modules/Order/utils';
|
|
7
9
|
/**
|
|
8
10
|
* BaseSales 流程 hook 后缀。
|
|
9
11
|
* 完整事件名应由当前模块名动态拼接,避免多个实例共享固定事件 key。
|
|
@@ -23,6 +25,15 @@ export type BaseSalesHookName = typeof BaseSalesHookNames[keyof typeof BaseSales
|
|
|
23
25
|
export declare function createBaseSalesHook(moduleName: string, hookName: BaseSalesHookName): string;
|
|
24
26
|
export type BaseSalesStatus = 'idle' | 'initializing' | 'ready' | 'error';
|
|
25
27
|
export type BaseSalesPaymentStatus = 'paid' | 'partially_paid' | 'unpaid' | 'payment_processing' | string;
|
|
28
|
+
export interface BaseSalesSubmitSalesOrderParams {
|
|
29
|
+
payments?: OrderPaymentSource[];
|
|
30
|
+
paymentStatus?: BaseSalesPaymentStatus;
|
|
31
|
+
smallTicketDataFlag?: number;
|
|
32
|
+
confirmPendingVoucherPayments?: boolean;
|
|
33
|
+
enhancePayload?: SubmitPayloadEnhancer;
|
|
34
|
+
/** Create the order without executing payment; payment status comes from the server. */
|
|
35
|
+
paymentExecution?: 'deferred';
|
|
36
|
+
}
|
|
26
37
|
export interface BaseSalesCashPaymentConfig {
|
|
27
38
|
available: boolean;
|
|
28
39
|
paymentMethod?: PaymentMethod;
|
|
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
326
326
|
date: string;
|
|
327
327
|
status: string;
|
|
328
328
|
week: string;
|
|
329
|
-
weekNum: 0 |
|
|
329
|
+
weekNum: 0 | 2 | 1 | 6 | 4 | 5 | 3;
|
|
330
330
|
}[]>;
|
|
331
331
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
332
332
|
private getScheduleDataByIds;
|
|
@@ -345,7 +345,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
345
345
|
* 获取当前的客户搜索条件
|
|
346
346
|
* @returns 当前搜索条件
|
|
347
347
|
*/
|
|
348
|
-
getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "
|
|
348
|
+
getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
|
|
349
349
|
/**
|
|
350
350
|
* 获取客户列表状态(包含滚动加载相关状态)
|
|
351
351
|
* @returns 客户状态
|
|
@@ -1672,6 +1672,30 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1672
1672
|
};
|
|
1673
1673
|
}
|
|
1674
1674
|
try {
|
|
1675
|
+
// Capture before lookup/UI awaits, so a result cannot land in a new cart.
|
|
1676
|
+
// Unscoped POS Order modules return a no-op guard.
|
|
1677
|
+
const beforeScanCommit = this.store.order.createCartIntentCommitGuard('add_product');
|
|
1678
|
+
const beforeScanDialog = this.store.order.createCartIntentCommitGuard('add_product');
|
|
1679
|
+
const guardCallback = callback => callback ? (...args) => {
|
|
1680
|
+
beforeScanCommit();
|
|
1681
|
+
return callback(...args);
|
|
1682
|
+
} : undefined;
|
|
1683
|
+
const guardedBridge = bridge ? {
|
|
1684
|
+
...bridge,
|
|
1685
|
+
confirmDetail: guardCallback(bridge.confirmDetail),
|
|
1686
|
+
confirmBookingEdit: guardCallback(bridge.confirmBookingEdit),
|
|
1687
|
+
applyPromotionCode: guardCallback(bridge.applyPromotionCode),
|
|
1688
|
+
requestCustomerSwitch: guardCallback(bridge.requestCustomerSwitch),
|
|
1689
|
+
openOrder: guardCallback(bridge.openOrder),
|
|
1690
|
+
openProductDetail: bridge.openProductDetail ? payload => {
|
|
1691
|
+
beforeScanDialog();
|
|
1692
|
+
return bridge.openProductDetail(payload);
|
|
1693
|
+
} : undefined,
|
|
1694
|
+
openBookingEdit: bridge.openBookingEdit ? payload => {
|
|
1695
|
+
beforeScanDialog();
|
|
1696
|
+
return bridge.openBookingEdit(payload);
|
|
1697
|
+
} : undefined
|
|
1698
|
+
} : undefined;
|
|
1675
1699
|
const localSearch = v => this.store.products.findProductsByCodeOrBarcode(v);
|
|
1676
1700
|
const scanCallback = (0, _handleScan.handleGlobalScan)(this.request, localSearch, this.getSubmitOrderSalesChannel());
|
|
1677
1701
|
const raw = await scanCallback({
|
|
@@ -1687,7 +1711,10 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1687
1711
|
};
|
|
1688
1712
|
}
|
|
1689
1713
|
const result = await (0, _applyGlobalScan.applyGlobalScan)({
|
|
1690
|
-
setOrderCustomer: customer =>
|
|
1714
|
+
setOrderCustomer: customer => {
|
|
1715
|
+
beforeScanCommit();
|
|
1716
|
+
this.setOrderCustomer(customer);
|
|
1717
|
+
},
|
|
1691
1718
|
getOrderCustomerSnapshot: () => this.getOrderCustomerSnapshot(),
|
|
1692
1719
|
resolveCustomerById: customerId => this.resolveCustomerById(customerId),
|
|
1693
1720
|
getBusinessCode: () => this.otherParams?.businessCode,
|
|
@@ -1695,10 +1722,16 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1695
1722
|
decideAddProduct: (item, options) => this.decideAddProduct(item, options),
|
|
1696
1723
|
decideAfterDetail: (cacheItem, options) => this.decideAfterDetail(cacheItem, options),
|
|
1697
1724
|
transformDetailToProductAndBooking: input => this.transformDetailToProductAndBooking(input),
|
|
1698
|
-
addProductToOrder: (product, booking) =>
|
|
1725
|
+
addProductToOrder: (product, booking) => {
|
|
1726
|
+
beforeScanCommit();
|
|
1727
|
+
return this.addProductToOrder(product, booking);
|
|
1728
|
+
},
|
|
1699
1729
|
refreshWalletAssets: params => this.refreshWalletAssets(params),
|
|
1700
|
-
scanWalletAsset: scanCode =>
|
|
1701
|
-
|
|
1730
|
+
scanWalletAsset: scanCode => {
|
|
1731
|
+
beforeScanCommit();
|
|
1732
|
+
return this.scanWalletAsset(scanCode);
|
|
1733
|
+
}
|
|
1734
|
+
}, formatted, guardedBridge);
|
|
1702
1735
|
bridge?.refresh?.();
|
|
1703
1736
|
return result;
|
|
1704
1737
|
} catch (error) {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type BusinessAvailability } from '../../modules/BusinessAvailability';
|
|
2
|
+
import type { ScheduleModule } from '../../modules/Schedule';
|
|
3
|
+
interface BusinessAvailabilityHost {
|
|
4
|
+
loadOpenData: () => Promise<Record<string, unknown> | null>;
|
|
5
|
+
getSchedule: () => ScheduleModule | undefined;
|
|
6
|
+
getTimezone: () => string;
|
|
7
|
+
getScope: () => string;
|
|
8
|
+
now?: () => Date;
|
|
9
|
+
}
|
|
10
|
+
/** Read successful configuration once per business runtime; evaluate the clock on demand. */
|
|
11
|
+
export declare class BusinessAvailabilityController {
|
|
12
|
+
private readonly host;
|
|
13
|
+
private runtime?;
|
|
14
|
+
constructor(host: BusinessAvailabilityHost);
|
|
15
|
+
invalidate(): void;
|
|
16
|
+
private now;
|
|
17
|
+
private getRuntime;
|
|
18
|
+
private assertCurrent;
|
|
19
|
+
private loadConfig;
|
|
20
|
+
private loadSchedules;
|
|
21
|
+
private error;
|
|
22
|
+
/** Synchronous final cart-commit check; deliberately never starts a load. */
|
|
23
|
+
getCachedAvailability(): BusinessAvailability;
|
|
24
|
+
getAvailability(): Promise<BusinessAvailability>;
|
|
25
|
+
assertAvailable(): void;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.BusinessAvailabilityController = void 0;
|
|
7
|
+
var _lodashEs = require("lodash-es");
|
|
8
|
+
var _BusinessAvailability = require("../../modules/BusinessAvailability");
|
|
9
|
+
async function withTimeout(request) {
|
|
10
|
+
let timer;
|
|
11
|
+
try {
|
|
12
|
+
return await Promise.race([request, new Promise((_, reject) => {
|
|
13
|
+
timer = setTimeout(() => reject(new Error('Unable to load business settings. Please try again.')), 30_000);
|
|
14
|
+
})]);
|
|
15
|
+
} finally {
|
|
16
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Read successful configuration once per business runtime; evaluate the clock on demand. */
|
|
21
|
+
class BusinessAvailabilityController {
|
|
22
|
+
runtime;
|
|
23
|
+
constructor(host) {
|
|
24
|
+
this.host = host;
|
|
25
|
+
}
|
|
26
|
+
invalidate() {
|
|
27
|
+
this.runtime = undefined;
|
|
28
|
+
}
|
|
29
|
+
now() {
|
|
30
|
+
return this.host.now?.() ?? new Date();
|
|
31
|
+
}
|
|
32
|
+
getRuntime() {
|
|
33
|
+
const scope = this.host.getScope();
|
|
34
|
+
if (this.runtime?.scope !== scope) this.runtime = {
|
|
35
|
+
scope
|
|
36
|
+
};
|
|
37
|
+
return this.runtime;
|
|
38
|
+
}
|
|
39
|
+
assertCurrent(runtime) {
|
|
40
|
+
if (this.runtime !== runtime || runtime.scope !== this.host.getScope()) {
|
|
41
|
+
throw new Error('Store settings changed. Please try again.');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async loadConfig(runtime) {
|
|
45
|
+
if (runtime.config) return runtime.config;
|
|
46
|
+
if (!runtime.configRequest) {
|
|
47
|
+
runtime.configRequest = (async () => {
|
|
48
|
+
const data = await withTimeout(this.host.loadOpenData());
|
|
49
|
+
this.assertCurrent(runtime);
|
|
50
|
+
if (!data) throw new Error('Business settings are unavailable. Please try again.');
|
|
51
|
+
const config = (0, _lodashEs.cloneDeep)((0, _BusinessAvailability.normalizeBusinessAvailabilityConfig)(data));
|
|
52
|
+
runtime.config = config;
|
|
53
|
+
return config;
|
|
54
|
+
})();
|
|
55
|
+
}
|
|
56
|
+
const request = runtime.configRequest;
|
|
57
|
+
try {
|
|
58
|
+
return await request;
|
|
59
|
+
} finally {
|
|
60
|
+
if (runtime.configRequest === request) runtime.configRequest = undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async loadSchedules(runtime) {
|
|
64
|
+
if (runtime.schedules) return runtime.schedules;
|
|
65
|
+
if (!runtime.scheduleRequest) {
|
|
66
|
+
runtime.scheduleRequest = (async () => {
|
|
67
|
+
const schedule = this.host.getSchedule();
|
|
68
|
+
if (!schedule) throw new Error('Business operating-hours schedule is unavailable. Please try again.');
|
|
69
|
+
await withTimeout(schedule.loadAllSchedule({
|
|
70
|
+
useCache: true
|
|
71
|
+
}));
|
|
72
|
+
this.assertCurrent(runtime);
|
|
73
|
+
const schedules = (0, _lodashEs.cloneDeep)(schedule.getScheduleListByIds(runtime.config.scheduleIds) || []);
|
|
74
|
+
runtime.schedules = schedules;
|
|
75
|
+
return schedules;
|
|
76
|
+
})();
|
|
77
|
+
}
|
|
78
|
+
const request = runtime.scheduleRequest;
|
|
79
|
+
try {
|
|
80
|
+
return await request;
|
|
81
|
+
} finally {
|
|
82
|
+
if (runtime.scheduleRequest === request) runtime.scheduleRequest = undefined;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
error(reason, runtime) {
|
|
86
|
+
return {
|
|
87
|
+
status: 'error',
|
|
88
|
+
behavior: 'hide_all',
|
|
89
|
+
message: null,
|
|
90
|
+
nextChangeAt: this.now().getTime() + 60_000,
|
|
91
|
+
requirePaymentOnSubmit: runtime?.config?.requirePaymentOnSubmit ?? true,
|
|
92
|
+
error: reason instanceof Error ? reason.message : 'Business settings are unavailable. Please try again.'
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Synchronous final cart-commit check; deliberately never starts a load. */
|
|
97
|
+
getCachedAvailability() {
|
|
98
|
+
const runtime = this.getRuntime();
|
|
99
|
+
try {
|
|
100
|
+
this.assertCurrent(runtime);
|
|
101
|
+
if (!runtime.config) throw new Error('Business settings are still loading. Please try again.');
|
|
102
|
+
return (0, _BusinessAvailability.computeBusinessAvailability)({
|
|
103
|
+
config: runtime.config,
|
|
104
|
+
schedules: runtime.schedules || [],
|
|
105
|
+
timezone: this.host.getTimezone(),
|
|
106
|
+
now: this.now()
|
|
107
|
+
});
|
|
108
|
+
} catch (reason) {
|
|
109
|
+
return this.error(reason, runtime);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async getAvailability() {
|
|
113
|
+
const runtime = this.getRuntime();
|
|
114
|
+
try {
|
|
115
|
+
const config = await this.loadConfig(runtime);
|
|
116
|
+
this.assertCurrent(runtime);
|
|
117
|
+
if (!config.paused && !config.invalidScheduleIds && config.scheduleIds.length) {
|
|
118
|
+
await this.loadSchedules(runtime);
|
|
119
|
+
}
|
|
120
|
+
this.assertCurrent(runtime);
|
|
121
|
+
return this.getCachedAvailability();
|
|
122
|
+
} catch (reason) {
|
|
123
|
+
return this.error(reason, runtime);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
assertAvailable() {
|
|
127
|
+
const availability = this.getCachedAvailability();
|
|
128
|
+
if (availability.status !== 'open') {
|
|
129
|
+
const error = new Error(availability.error || (availability.status === 'paused' ? 'Ordering is temporarily paused.' : 'Ordering is currently closed.'));
|
|
130
|
+
Object.assign(error, {
|
|
131
|
+
code: 'BUSINESS_UNAVAILABLE',
|
|
132
|
+
businessAvailability: availability
|
|
133
|
+
});
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.BusinessAvailabilityController = BusinessAvailabilityController;
|
|
@@ -5,9 +5,11 @@ import type { LoadScheduleAvailableDateParams, ScheduleItem } from '../../module
|
|
|
5
5
|
import type { ProductListLoadProductsParams, ProductListStoreQueryParams } from '../../modules/ProductList';
|
|
6
6
|
import type { AvailabilityDateRange, AvailabilityOccupancy, AvailabilityProduct, AvailabilityResource, GetProductTimeRangesRequest } from '../../modules/ResourcePlanner';
|
|
7
7
|
import type { AvailabilityContextRef, ContextualAvailabilityQuery, ContextualAvailabilityQueryResult, ContextualCommitAvailabilitySelectionParams, ContextualProductTimeRangeGroup, UnifiedBookingSalesAddRetailProductParams, UnifiedBookingSalesApplyPlannerDiscountsParams, UnifiedBookingSalesCommitAvailabilitySelectionResult, UnifiedBookingSalesDiscountResult, UnifiedBookingSalesLoadProductsByScheduleDateParams, UnifiedBookingSalesLoadOpenDataParams, UnifiedBookingSalesPrepareAvailabilityProjectionParams, UnifiedBookingSalesPolicyResponse, UnifiedBookingSalesResolveProductAllergyRequirementParams, UnifiedBookingSalesStageRetailProductsParams, UnifiedBookingSalesState } from './types';
|
|
8
|
+
import type { BusinessAvailability } from '../../modules/BusinessAvailability';
|
|
8
9
|
import { BookingTicket } from '../BookingTicket';
|
|
9
10
|
import type { AllergyRequirement } from '../../model/strategy/adapter/itemRule';
|
|
10
11
|
export * from './types';
|
|
12
|
+
export type { BusinessAvailability, BusinessClosedBehavior } from '../../modules/BusinessAvailability';
|
|
11
13
|
export { AvailabilityError } from '../../modules/ResourcePlanner';
|
|
12
14
|
/**
|
|
13
15
|
* Converts Rules/Order discount internals into a small UI-facing diagnostic. The result keeps
|
|
@@ -60,6 +62,7 @@ export declare class UnifiedBookingSalesImpl extends BookingTicket {
|
|
|
60
62
|
protected defaultVersion: string;
|
|
61
63
|
protected store: UnifiedBookingSalesState;
|
|
62
64
|
protected pickupTimingEnabled: boolean;
|
|
65
|
+
private businessAvailabilityController?;
|
|
63
66
|
private runtimeOpenDataScope;
|
|
64
67
|
private runtimeOpenDataSnapshot;
|
|
65
68
|
private runtimeOpenDataModule;
|
|
@@ -86,6 +89,14 @@ export declare class UnifiedBookingSalesImpl extends BookingTicket {
|
|
|
86
89
|
private allergyItemRuleConfigsPromise;
|
|
87
90
|
initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
|
|
88
91
|
protected getSubmitOrderSalesChannel(): string;
|
|
92
|
+
/** Only the explicit Kiosk Sales consumer entry enables this policy; POS stays unchanged. */
|
|
93
|
+
protected isBusinessAvailabilityEnabled(): boolean;
|
|
94
|
+
protected getBusinessAvailabilityScope(): string;
|
|
95
|
+
private getBusinessAvailabilityController;
|
|
96
|
+
getBusinessAvailability(): Promise<BusinessAvailability>;
|
|
97
|
+
/** Internal final-write assertion; does not fetch OpenData or Schedule. */
|
|
98
|
+
assertBusinessAvailability(): void;
|
|
99
|
+
protected getSubModuleHooks(moduleName: string): any;
|
|
89
100
|
private createAvailabilityFacadeError;
|
|
90
101
|
private getAvailabilityScopeDescriptor;
|
|
91
102
|
private normalizeAvailabilityIdList;
|
|
@@ -49,6 +49,7 @@ Object.keys(_types).forEach(function (key) {
|
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
51
|
var _remoteOccupancyCache = require("./remoteOccupancyCache");
|
|
52
|
+
var _businessAvailability = require("./businessAvailability");
|
|
52
53
|
var _BookingTicket = require("../BookingTicket");
|
|
53
54
|
var _localClock = require("../../modules/ResourcePlanner/localClock");
|
|
54
55
|
var _platform = require("../../utils/platform");
|
|
@@ -1199,6 +1200,7 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
|
|
|
1199
1200
|
defaultVersion = '1.0.0';
|
|
1200
1201
|
store = {};
|
|
1201
1202
|
pickupTimingEnabled = true;
|
|
1203
|
+
businessAvailabilityController;
|
|
1202
1204
|
runtimeOpenDataScope = null;
|
|
1203
1205
|
runtimeOpenDataSnapshot = null;
|
|
1204
1206
|
runtimeOpenDataModule = null;
|
|
@@ -1241,6 +1243,57 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
|
|
|
1241
1243
|
const channel = String(this.otherParams?.channel ?? '').trim();
|
|
1242
1244
|
return channel || super.getSubmitOrderSalesChannel();
|
|
1243
1245
|
}
|
|
1246
|
+
|
|
1247
|
+
/** Only the explicit Kiosk Sales consumer entry enables this policy; POS stays unchanged. */
|
|
1248
|
+
isBusinessAvailabilityEnabled() {
|
|
1249
|
+
return this.otherParams?.enableBusinessAvailability === true && ['pc', 'h5', 'kiosk'].includes((0, _platform.normalizeRuntimePlatform)(this.otherParams?.platform));
|
|
1250
|
+
}
|
|
1251
|
+
getBusinessAvailabilityScope() {
|
|
1252
|
+
return `${this.getRuntimeOpenDataScope()}:${this.runtimeOpenDataGeneration}`;
|
|
1253
|
+
}
|
|
1254
|
+
getBusinessAvailabilityController() {
|
|
1255
|
+
if (!this.businessAvailabilityController) {
|
|
1256
|
+
this.businessAvailabilityController = new _businessAvailability.BusinessAvailabilityController({
|
|
1257
|
+
loadOpenData: () => this.loadOpenDataConfig(),
|
|
1258
|
+
getSchedule: () => this.store.schedule,
|
|
1259
|
+
getTimezone: () => String(this.otherParams?.businessTimezone || this.getPickupTimingContextData('timezone') || ''),
|
|
1260
|
+
getScope: () => this.getBusinessAvailabilityScope()
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
return this.businessAvailabilityController;
|
|
1264
|
+
}
|
|
1265
|
+
getBusinessAvailability() {
|
|
1266
|
+
return this.getBusinessAvailabilityController().getAvailability();
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
/** Internal final-write assertion; does not fetch OpenData or Schedule. */
|
|
1270
|
+
assertBusinessAvailability() {
|
|
1271
|
+
if (this.isBusinessAvailabilityEnabled()) this.getBusinessAvailabilityController().assertAvailable();
|
|
1272
|
+
}
|
|
1273
|
+
getSubModuleHooks(moduleName) {
|
|
1274
|
+
const hooks = super.getSubModuleHooks(moduleName);
|
|
1275
|
+
if (moduleName !== 'order' || !this.isBusinessAvailabilityEnabled()) return hooks;
|
|
1276
|
+
let lastScope;
|
|
1277
|
+
let lastExistingScope;
|
|
1278
|
+
let scopeToken = {};
|
|
1279
|
+
return {
|
|
1280
|
+
...hooks,
|
|
1281
|
+
getCartIntentScope: () => {
|
|
1282
|
+
const scope = this.getBusinessAvailabilityScope();
|
|
1283
|
+
const existingScope = hooks?.getCartIntentScope?.();
|
|
1284
|
+
if (scope !== lastScope || !Object.is(existingScope, lastExistingScope)) {
|
|
1285
|
+
lastScope = scope;
|
|
1286
|
+
lastExistingScope = existingScope;
|
|
1287
|
+
scopeToken = {};
|
|
1288
|
+
}
|
|
1289
|
+
return scopeToken;
|
|
1290
|
+
},
|
|
1291
|
+
beforeCartIntentCommit: context => {
|
|
1292
|
+
this.assertBusinessAvailability();
|
|
1293
|
+
hooks?.beforeCartIntentCommit?.(context);
|
|
1294
|
+
}
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1244
1297
|
createAvailabilityFacadeError(code, message, details) {
|
|
1245
1298
|
return new _ResourcePlanner.AvailabilityError(code, message, details);
|
|
1246
1299
|
}
|
|
@@ -1714,6 +1767,7 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
|
|
|
1714
1767
|
});
|
|
1715
1768
|
}
|
|
1716
1769
|
resetRuntimeOpenData() {
|
|
1770
|
+
this.businessAvailabilityController?.invalidate();
|
|
1717
1771
|
this.runtimeOpenDataGeneration += 1;
|
|
1718
1772
|
this.runtimeOpenDataScope = null;
|
|
1719
1773
|
this.runtimeOpenDataSnapshot = null;
|
|
@@ -216,6 +216,8 @@ export interface UnifiedBookingSalesDiscountResult {
|
|
|
216
216
|
summaryAfter?: unknown;
|
|
217
217
|
}
|
|
218
218
|
export interface UnifiedBookingSalesApi {
|
|
219
|
+
/** Uses cached business settings and evaluates the current store-local clock. */
|
|
220
|
+
getBusinessAvailability: () => Promise<import('../../modules/BusinessAvailability').BusinessAvailability>;
|
|
219
221
|
loadOpenData: (params: UnifiedBookingSalesLoadOpenDataParams) => Promise<OpenDataConfig>;
|
|
220
222
|
/** Returns the latest OpenData payload cached by this solution instance. */
|
|
221
223
|
getOpenData: () => Promise<OpenDataConfig | null>;
|