@pisell/pisellos 0.10.57 → 0.10.59
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/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/inventory/index.d.ts +92 -0
- package/dist/inventory/index.js +500 -0
- package/dist/modules/Order/index.d.ts +20 -3
- package/dist/modules/Order/index.js +1369 -1021
- package/dist/modules/Order/types.d.ts +5 -0
- package/dist/modules/Order/utils.d.ts +5 -3
- package/dist/modules/Order/utils.js +32 -11
- package/dist/modules/ProductList/index.js +40 -17
- package/dist/solution/BaseSales/index.d.ts +8 -0
- package/dist/solution/BaseSales/index.js +1382 -1207
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/UnifiedBookingSales/index.js +58 -38
- package/lib/index.d.ts +1 -0
- package/lib/index.js +12 -0
- package/lib/inventory/index.d.ts +92 -0
- package/lib/inventory/index.js +280 -0
- package/lib/modules/Order/index.d.ts +20 -3
- package/lib/modules/Order/index.js +111 -19
- package/lib/modules/Order/types.d.ts +5 -0
- package/lib/modules/Order/utils.d.ts +5 -3
- package/lib/modules/Order/utils.js +29 -10
- package/lib/modules/ProductList/index.js +21 -4
- package/lib/solution/BaseSales/index.d.ts +8 -0
- package/lib/solution/BaseSales/index.js +82 -7
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/UnifiedBookingSales/index.js +11 -0
- package/package.json +1 -1
|
@@ -633,8 +633,9 @@ function getBundleSellingMagnitude(bundle) {
|
|
|
633
633
|
* = `metadata.main_product_original_price` + Σ(bundle 原价 × num)。
|
|
634
634
|
* - `metadata.source_product_price`:主商品/variant 基础价(已应用报价单),不含 option、
|
|
635
635
|
* 不含折扣。**权威源**。
|
|
636
|
-
* - `
|
|
637
|
-
* - `metadata.
|
|
636
|
+
* - `product_sku.option[].add_price` 保留单规格折前单价;Rules 的 option.price 只用于本次计算。
|
|
637
|
+
* - `metadata.main_product_original_price` = source + Σ(option.add_price × option.num)(含 option、不含折扣)。
|
|
638
|
+
* - `metadata.main_product_selling_price` = main_original − 行内 per-unit amount(含主商品及 option 优惠)。
|
|
638
639
|
* - `payment_price`:出站 payload 中为行 composite 已减整单折扣均摊价(无折扣时与 `selling_price` 同义)。
|
|
639
640
|
*
|
|
640
641
|
* Rules 钩子契约(hook_adapt 方案,Rules 内部保持不变):
|
|
@@ -643,8 +644,9 @@ function getBundleSellingMagnitude(bundle) {
|
|
|
643
644
|
* `getProductOriginTotalPrice` 会自行叠加 option + bundle,喂 source 可避免 option 双加。
|
|
644
645
|
* - `getProduct.total` = `selling_price × num`(行 composite × num),与 Rules 内部产出的
|
|
645
646
|
* total(source + option + bundle)对齐。
|
|
647
|
+
* - `getProduct.options` 用单规格原价参与重算;主商品折后价从 main_selling 减去 option 折后合计反推。
|
|
646
648
|
* - `setProduct` 反向流程:把 Rules 返回的 source-level `main_product_selling_price` / `price`
|
|
647
|
-
*
|
|
649
|
+
* 加回单规格原价合计,再减去 optionDiscountAmount;保留订单单规格原价供取消折扣及后续重算。
|
|
648
650
|
* 优先级:
|
|
649
651
|
* 1. `values.main_product_selling_price`(券应用分支,per-unit 券后 source-level 主价)
|
|
650
652
|
* 2. `values.price`(还原分支 `restoredPrice`、good_pass 归零)
|
|
@@ -843,6 +845,14 @@ function createDefaultOrderRulesHooks(getBookings) {
|
|
|
843
845
|
const effectiveNum = Number(num) > 0 ? Number(num) : 1;
|
|
844
846
|
return new _decimal.default(Number(totalLike) || 0).dividedBy(effectiveNum).toDecimalPlaces(2).toString();
|
|
845
847
|
};
|
|
848
|
+
|
|
849
|
+
// optionDiscountAmount 已是每件主商品内的单规格优惠合计,不再乘商品数量。
|
|
850
|
+
const getOptionDiscountAmount = discountList => {
|
|
851
|
+
return (discountList || []).reduce((total, discount) => {
|
|
852
|
+
if (discount?.metadata?.custom_product_bundle_map_id) return total;
|
|
853
|
+
return total.plus(Number(discount?.metadata?.optionDiscountAmount) || 0);
|
|
854
|
+
}, new _decimal.default(0));
|
|
855
|
+
};
|
|
846
856
|
const getBundleIdentity = bundle => {
|
|
847
857
|
return [bundle.bundle_id ?? bundle.id ?? '', bundle.bundle_product_id ?? bundle._bundle_product_id ?? bundle.product_id ?? '', bundle.bundle_variant_id ?? bundle.variant_id ?? bundle.product_variant_id ?? 0, bundle.bundle_group_id ?? bundle.group_id ?? ''].join('|');
|
|
848
858
|
};
|
|
@@ -885,12 +895,14 @@ function createDefaultOrderRulesHooks(getBookings) {
|
|
|
885
895
|
getProduct: product => {
|
|
886
896
|
// source_product_price 是权威源;兜底链:source → mainSelling − options(反推)→ 行 selling_price
|
|
887
897
|
const metadataAny = product.metadata || {};
|
|
888
|
-
const
|
|
898
|
+
const productOptions = getProductSkuOptions(product);
|
|
899
|
+
const optionSum = sumOptionUnitPrice(productOptions);
|
|
900
|
+
const optionSellingSum = optionSum.minus(getOptionDiscountAmount(product.discount_list));
|
|
889
901
|
let sourcePrice;
|
|
890
902
|
if (metadataAny.source_product_price !== undefined) {
|
|
891
903
|
sourcePrice = String(metadataAny.source_product_price);
|
|
892
904
|
} else if (metadataAny.main_product_selling_price !== undefined) {
|
|
893
|
-
sourcePrice = new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(
|
|
905
|
+
sourcePrice = new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSellingSum).toDecimalPlaces(2).toString();
|
|
894
906
|
} else {
|
|
895
907
|
sourcePrice = String(product.selling_price ?? 0);
|
|
896
908
|
}
|
|
@@ -920,6 +932,11 @@ function createDefaultOrderRulesHooks(getBookings) {
|
|
|
920
932
|
num: product.num || 1,
|
|
921
933
|
discount_list: product.discount_list || [],
|
|
922
934
|
bundle: product.product_bundle || [],
|
|
935
|
+
// 仅在 Rules 入参中映射 price,避免折后价污染订单的 add_price。
|
|
936
|
+
options: productOptions.map(option => ({
|
|
937
|
+
...option,
|
|
938
|
+
price: option.add_price
|
|
939
|
+
})),
|
|
923
940
|
booking_id: product.metadata?.booking_id || null,
|
|
924
941
|
isClient: false,
|
|
925
942
|
// 勿写死 false:否则 Rules 不会走 total≠origin_total 的手动价推断,
|
|
@@ -927,7 +944,7 @@ function createDefaultOrderRulesHooks(getBookings) {
|
|
|
927
944
|
isManualDiscount: resolveRulesManualDiscountFlag(metadataAny),
|
|
928
945
|
holder_id: product.metadata?.holder_id,
|
|
929
946
|
startDate: getProductStartDate(product),
|
|
930
|
-
main_product_selling_price: metadataAny.main_product_selling_price !== undefined ? new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(
|
|
947
|
+
main_product_selling_price: metadataAny.main_product_selling_price !== undefined ? new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSellingSum).toDecimalPlaces(2).toString() : undefined,
|
|
931
948
|
inPromotion: metadataAny._promotion?.inPromotion === true,
|
|
932
949
|
_promotion: metadataAny._promotion
|
|
933
950
|
};
|
|
@@ -938,8 +955,10 @@ function createDefaultOrderRulesHooks(getBookings) {
|
|
|
938
955
|
const existedSource = metadataAny.source_product_price ?? product.selling_price ?? '0';
|
|
939
956
|
const nextOptions = getProductSkuOptions(product);
|
|
940
957
|
const optionSum = sumOptionUnitPrice(nextOptions);
|
|
958
|
+
const nextDiscountList = values.discount_list ?? product.discount_list;
|
|
959
|
+
const optionSellingSum = optionSum.minus(getOptionDiscountAmount(nextDiscountList));
|
|
941
960
|
|
|
942
|
-
// Rules 返回的 main_product_selling_price / price
|
|
961
|
+
// Rules 返回的 main_product_selling_price / price 为不含 option 的主商品价。
|
|
943
962
|
// 优先级:main_product_selling_price(per-unit 券后 source)> price(还原/good_pass 分支)>
|
|
944
963
|
// total/num(仅当 Rules 只给 total 时的兜底)> 保留当前 source。
|
|
945
964
|
const nextSourceSellingPrice = values.main_product_selling_price !== undefined ? String(values.main_product_selling_price) : values.price !== undefined ? String(values.price) : values.total !== undefined ? toUnitPriceString(values.total, nextNum) : String(existedSource);
|
|
@@ -948,8 +967,8 @@ function createDefaultOrderRulesHooks(getBookings) {
|
|
|
948
967
|
// 缺省时保留现有 source(券前 = 当前 source)。
|
|
949
968
|
const nextSourceOriginalPrice = values.original_price !== undefined ? String(values.original_price) : String(existedSource);
|
|
950
969
|
|
|
951
|
-
//
|
|
952
|
-
const nextMainSellingPrice = new _decimal.default(Number(nextSourceSellingPrice) || 0).plus(
|
|
970
|
+
// 成交价只加回 option 折后合计;原价仍使用订单中保存的 option 原价。
|
|
971
|
+
const nextMainSellingPrice = new _decimal.default(Number(nextSourceSellingPrice) || 0).plus(optionSellingSum).toDecimalPlaces(2).toFixed(2);
|
|
953
972
|
const nextMainOriginalPrice = new _decimal.default(Number(nextSourceOriginalPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
954
973
|
const nextBundle = values.bundle !== undefined ? mergeRulesBundlePrices(product.product_bundle, values.bundle) : product.product_bundle;
|
|
955
974
|
const composedSellingPrice = composeLinePrice({
|
|
@@ -970,7 +989,7 @@ function createDefaultOrderRulesHooks(getBookings) {
|
|
|
970
989
|
...product,
|
|
971
990
|
selling_price: composedSellingPrice,
|
|
972
991
|
original_price: finalOriginalPrice,
|
|
973
|
-
discount_list:
|
|
992
|
+
discount_list: nextDiscountList,
|
|
974
993
|
num: values.quantity ?? product.num,
|
|
975
994
|
product_bundle: nextBundle,
|
|
976
995
|
metadata: {
|
|
@@ -66,7 +66,13 @@ class ProductList extends _BaseModule.BaseModule {
|
|
|
66
66
|
* productList.updateOtherParams({ channel: 'pos' });
|
|
67
67
|
*/
|
|
68
68
|
updateOtherParams(params) {
|
|
69
|
+
const previousScope = this.otherParams.catalogScopeKey;
|
|
69
70
|
this.otherParams = params || {};
|
|
71
|
+
if (previousScope !== this.otherParams.catalogScopeKey && (previousScope || this.otherParams.catalogScopeKey)) {
|
|
72
|
+
this.store.list = [];
|
|
73
|
+
this.rawProductPriceSources.clear();
|
|
74
|
+
this.core.effects.emit(`${this.name}:changed`, this.store.list);
|
|
75
|
+
}
|
|
70
76
|
}
|
|
71
77
|
async storeChange(path, value) {
|
|
72
78
|
// No longer needed - products are stored as plain objects instead of Product instances
|
|
@@ -101,6 +107,14 @@ class ProductList extends _BaseModule.BaseModule {
|
|
|
101
107
|
status = 'published',
|
|
102
108
|
strategy_context
|
|
103
109
|
} = {}, options) {
|
|
110
|
+
const scope = this.otherParams.catalogScopeKey;
|
|
111
|
+
const assertScope = () => {
|
|
112
|
+
if (scope !== this.otherParams.catalogScopeKey) {
|
|
113
|
+
throw Object.assign(new Error('Product catalog context changed'), {
|
|
114
|
+
name: 'AbortError'
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
};
|
|
104
118
|
// // 如果 schedule_ids 为空,则需要尝试从 schedule 模块里获取
|
|
105
119
|
// if (!schedule_ids?.length) {
|
|
106
120
|
// const schedule_ids_data = this.store.schedule
|
|
@@ -180,6 +194,7 @@ class ProductList extends _BaseModule.BaseModule {
|
|
|
180
194
|
const handledByOsServer = (0, _clientDataVariants.isProductQueryHandledByOsServer)(this.core, this.request);
|
|
181
195
|
const originalCallback = typeof options?.callback === 'function' ? options.callback : undefined;
|
|
182
196
|
const subscriptionCallback = originalCallback ? async result => {
|
|
197
|
+
if (scope !== this.otherParams.catalogScopeKey) return;
|
|
183
198
|
const callbackList = result?.data?.list;
|
|
184
199
|
if (!Array.isArray(callbackList)) {
|
|
185
200
|
originalCallback(result);
|
|
@@ -190,19 +205,20 @@ class ProductList extends _BaseModule.BaseModule {
|
|
|
190
205
|
// the existing raw catalog scope and upsert the changed records.
|
|
191
206
|
this.rememberRawProductQueryResult(callbackList);
|
|
192
207
|
}
|
|
193
|
-
const
|
|
208
|
+
const products = (0, _clientDataVariants.resolveClientDataVariants)({
|
|
194
209
|
core: this.core,
|
|
195
210
|
otherParams: this.otherParams,
|
|
196
211
|
products: callbackList,
|
|
197
212
|
queryPayload,
|
|
198
213
|
handledByOsServer
|
|
199
214
|
});
|
|
200
|
-
|
|
201
|
-
|
|
215
|
+
assertScope();
|
|
216
|
+
await this.addProduct(products);
|
|
217
|
+
originalCallback(handledByOsServer ? result : {
|
|
202
218
|
...result,
|
|
203
219
|
data: {
|
|
204
220
|
...result.data,
|
|
205
|
-
list:
|
|
221
|
+
list: products
|
|
206
222
|
}
|
|
207
223
|
});
|
|
208
224
|
} : undefined;
|
|
@@ -212,6 +228,7 @@ class ProductList extends _BaseModule.BaseModule {
|
|
|
212
228
|
subscriberId: options?.subscriberId,
|
|
213
229
|
customToast: () => {}
|
|
214
230
|
});
|
|
231
|
+
assertScope();
|
|
215
232
|
if (!handledByOsServer && Array.isArray(productsData.data.list)) {
|
|
216
233
|
this.replaceRawProductQueryResult(productsData.data.list, product_ids);
|
|
217
234
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { InventoryController, type CheckoutRuntimeSnapshot } from '../../inventory';
|
|
1
2
|
import { Module, ModuleOptions, PisellCore } from '../../types';
|
|
2
3
|
import { BaseModule } from '../../modules/BaseModule';
|
|
3
4
|
import { BaseSalesOrderProduct, BaseSalesOrderProductIdentity, BaseSalesPaymentStatus, BaseSalesSubmitSalesOrderParams, BaseSalesUpdateOrderProductQuantityParams, BaseSalesCalculateProductBookingPriceParams, BaseSalesPriceRecalculationContextChange, BaseSalesProductBookingPriceResult, BaseSalesQuotationCustomerScopeInfo, BaseSalesScanCodeResult, BaseSalesCashPaymentOptions, BaseSalesCashPaymentConfig, BaseSalesPayCashParams, BaseSalesPayCashResult, BaseSalesCommitPaymentMethodParams, BaseSalesCommitPaymentMethodResult, BaseSalesConfirmWalletPaymentResult } from './types';
|
|
@@ -49,6 +50,8 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
49
50
|
protected appPlugin: AppPlugin;
|
|
50
51
|
protected store: BaseSalesState;
|
|
51
52
|
protected otherParams: Record<string, any>;
|
|
53
|
+
getInventory(): InventoryController | undefined;
|
|
54
|
+
prepareCheckout(signal?: AbortSignal): Promise<CheckoutRuntimeSnapshot | undefined>;
|
|
52
55
|
protected cacheId: string | undefined;
|
|
53
56
|
/**
|
|
54
57
|
* 由已在初始化阶段解析过设备短号的业务解决方案写入。
|
|
@@ -187,6 +190,7 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
187
190
|
* 可覆盖此方法并把未识别的 name 委托给 `super.createSubModule(name)`。
|
|
188
191
|
*/
|
|
189
192
|
protected createSubModule(moduleName: string): Module | null;
|
|
193
|
+
private inventoryOrderHooks?;
|
|
190
194
|
protected getSubModuleHooks(moduleName: string): any;
|
|
191
195
|
/**
|
|
192
196
|
* 构造传给 BaseSales 子模块的完整运行态参数,保证初始化和后续同步语义一致。
|
|
@@ -224,7 +228,11 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
224
228
|
private isActiveVirtualSettlementOrder;
|
|
225
229
|
private isHistoricalVirtualSettlementOrder;
|
|
226
230
|
private syncAppDataToTempOrder;
|
|
231
|
+
private initialization?;
|
|
232
|
+
/** Hosts can await readiness without changing Core's synchronous registration API. */
|
|
233
|
+
whenInitialized(): Promise<void>;
|
|
227
234
|
initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
|
|
235
|
+
private initializeSalesRuntime;
|
|
228
236
|
destroy(): Promise<void>;
|
|
229
237
|
/**
|
|
230
238
|
* 加载销售订单到统一 tempOrder 工作区。
|
|
@@ -7,6 +7,7 @@ var _exportNames = {
|
|
|
7
7
|
BaseSalesImpl: true
|
|
8
8
|
};
|
|
9
9
|
exports.BaseSalesImpl = void 0;
|
|
10
|
+
var _inventory = require("../../inventory");
|
|
10
11
|
var _BaseModule = require("../../modules/BaseModule");
|
|
11
12
|
var _types = require("./types");
|
|
12
13
|
Object.keys(_types).forEach(function (key) {
|
|
@@ -470,6 +471,40 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
470
471
|
order: undefined
|
|
471
472
|
};
|
|
472
473
|
otherParams = {};
|
|
474
|
+
getInventory() {
|
|
475
|
+
return this.otherParams.inventory;
|
|
476
|
+
}
|
|
477
|
+
async prepareCheckout(signal) {
|
|
478
|
+
const inventory = this.getInventory();
|
|
479
|
+
const hooks = this.otherParams.checkoutHooks;
|
|
480
|
+
if (!inventory && !hooks?.beforeCheckout) return undefined;
|
|
481
|
+
if (!this.store.order) throw new Error('Order module is not ready');
|
|
482
|
+
return this.store.order.prepareCheckout(async items => {
|
|
483
|
+
const assertCurrent = () => {
|
|
484
|
+
if (signal?.aborted) throw Object.assign(new Error('Checkout cancelled'), {
|
|
485
|
+
name: 'AbortError'
|
|
486
|
+
});
|
|
487
|
+
if (inventory !== this.getInventory() || hooks !== this.otherParams.checkoutHooks) throw (0, _inventory.salesGuardError)('The sales context changed. Please try again.');
|
|
488
|
+
};
|
|
489
|
+
assertCurrent();
|
|
490
|
+
try {
|
|
491
|
+
await hooks?.beforeCheckout?.({
|
|
492
|
+
items,
|
|
493
|
+
signal
|
|
494
|
+
});
|
|
495
|
+
if (inventory) await inventory.refresh({
|
|
496
|
+
reason: 'checkout',
|
|
497
|
+
force: true,
|
|
498
|
+
signal
|
|
499
|
+
});
|
|
500
|
+
assertCurrent();
|
|
501
|
+
return inventory?.freezeCheckout(items);
|
|
502
|
+
} catch (error) {
|
|
503
|
+
if (error?.name === 'AbortError') throw error;
|
|
504
|
+
throw (0, _inventory.salesGuardError)(error instanceof Error ? error.message : String(error));
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
}
|
|
473
508
|
cacheId;
|
|
474
509
|
/**
|
|
475
510
|
* 由已在初始化阶段解析过设备短号的业务解决方案写入。
|
|
@@ -1302,12 +1337,37 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1302
1337
|
}
|
|
1303
1338
|
return (0, _types2.createModule)(moduleName, this.name);
|
|
1304
1339
|
}
|
|
1340
|
+
inventoryOrderHooks;
|
|
1305
1341
|
getSubModuleHooks(moduleName) {
|
|
1306
1342
|
const optionHooks = this.initializeOptions.hooks || {};
|
|
1307
1343
|
const otherHooks = this.otherParams.hooks || {};
|
|
1308
1344
|
if (moduleName === 'order') {
|
|
1309
1345
|
const directOrderHooks = optionHooks;
|
|
1310
|
-
|
|
1346
|
+
const hooks = optionHooks.order || this.otherParams.order?.hooks || otherHooks.order || (directOrderHooks.onBeforeMergeProductToOrder || directOrderHooks.onBeforeCartCommit || directOrderHooks.beforeCartIntentCommit || directOrderHooks.getCartIntentScope ? directOrderHooks : undefined);
|
|
1347
|
+
const inventory = this.getInventory();
|
|
1348
|
+
if (!inventory) {
|
|
1349
|
+
this.inventoryOrderHooks = undefined;
|
|
1350
|
+
return hooks;
|
|
1351
|
+
}
|
|
1352
|
+
if (this.inventoryOrderHooks?.inventory === inventory && this.inventoryOrderHooks.base === hooks) {
|
|
1353
|
+
return this.inventoryOrderHooks.hooks;
|
|
1354
|
+
}
|
|
1355
|
+
const combined = {
|
|
1356
|
+
...hooks,
|
|
1357
|
+
onBeforeCartCommit: async context => {
|
|
1358
|
+
await hooks?.onBeforeCartCommit?.(context);
|
|
1359
|
+
if (inventory !== this.getInventory()) {
|
|
1360
|
+
throw (0, _inventory.salesGuardError)('The sales context changed. Please try again.');
|
|
1361
|
+
}
|
|
1362
|
+
inventory.validate(context.proposedItems, context.currentItems);
|
|
1363
|
+
}
|
|
1364
|
+
};
|
|
1365
|
+
this.inventoryOrderHooks = {
|
|
1366
|
+
inventory,
|
|
1367
|
+
base: hooks,
|
|
1368
|
+
hooks: combined
|
|
1369
|
+
};
|
|
1370
|
+
return combined;
|
|
1311
1371
|
}
|
|
1312
1372
|
return optionHooks[moduleName] || this.otherParams[moduleName]?.hooks || otherHooks[moduleName];
|
|
1313
1373
|
}
|
|
@@ -1355,7 +1415,10 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1355
1415
|
const nextSubModuleOtherParams = this.buildSubModuleOtherParams(moduleName);
|
|
1356
1416
|
await targetModule.updateOtherParams(nextSubModuleOtherParams, {
|
|
1357
1417
|
changedParams,
|
|
1358
|
-
cover
|
|
1418
|
+
cover,
|
|
1419
|
+
...(moduleName === 'order' ? {
|
|
1420
|
+
hooks: this.getSubModuleHooks(moduleName)
|
|
1421
|
+
} : {})
|
|
1359
1422
|
});
|
|
1360
1423
|
}));
|
|
1361
1424
|
}
|
|
@@ -1504,7 +1567,17 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1504
1567
|
}
|
|
1505
1568
|
return isChanged;
|
|
1506
1569
|
}
|
|
1507
|
-
|
|
1570
|
+
initialization;
|
|
1571
|
+
|
|
1572
|
+
/** Hosts can await readiness without changing Core's synchronous registration API. */
|
|
1573
|
+
whenInitialized() {
|
|
1574
|
+
return this.initialization || Promise.reject(new Error('Sales module is not registered'));
|
|
1575
|
+
}
|
|
1576
|
+
initialize(core, options = {}) {
|
|
1577
|
+
this.initialization = this.initializeSalesRuntime(core, options);
|
|
1578
|
+
return this.initialization;
|
|
1579
|
+
}
|
|
1580
|
+
async initializeSalesRuntime(core, options = {}) {
|
|
1508
1581
|
this.resetPickupTimingCache();
|
|
1509
1582
|
this.core = core;
|
|
1510
1583
|
this.initializeOptions = options || {};
|
|
@@ -1563,17 +1636,19 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1563
1636
|
this.serverOrderChangeUnsubscribe = null;
|
|
1564
1637
|
this.paymentMethodsChangedUnsubscribe?.();
|
|
1565
1638
|
this.paymentMethodsChangedUnsubscribe = null;
|
|
1566
|
-
Object.keys(this.store)
|
|
1567
|
-
if (this.reusedSharedSubModuleNames.has(key))
|
|
1639
|
+
for (const key of Object.keys(this.store)) {
|
|
1640
|
+
if (this.reusedSharedSubModuleNames.has(key)) continue;
|
|
1568
1641
|
const sub = this.store[key];
|
|
1569
1642
|
if (sub && typeof sub.destroy === 'function') {
|
|
1570
1643
|
try {
|
|
1571
|
-
|
|
1644
|
+
// A host may register a replacement after destroy resolves. Wait for
|
|
1645
|
+
// nested modules so their cleanup cannot unregister the replacement.
|
|
1646
|
+
await sub.destroy();
|
|
1572
1647
|
} catch (error) {
|
|
1573
1648
|
console.warn(`[BaseSales] 子模块 ${key} 销毁失败`, error);
|
|
1574
1649
|
}
|
|
1575
1650
|
}
|
|
1576
|
-
}
|
|
1651
|
+
}
|
|
1577
1652
|
this.currentSalesDetail = null;
|
|
1578
1653
|
this.paymentNumberDevicePrefix = null;
|
|
1579
1654
|
this.queuedServerOrderChanges = [];
|
|
@@ -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 | 2 | 1 | 3 |
|
|
329
|
+
weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
|
|
330
330
|
}[]>;
|
|
331
331
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
332
332
|
private getScheduleDataByIds;
|
|
@@ -1425,6 +1425,7 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
|
|
|
1425
1425
|
cover = false
|
|
1426
1426
|
} = {}) {
|
|
1427
1427
|
const previousScope = this.getAvailabilityScopeDescriptor(this.otherParams || {});
|
|
1428
|
+
const previousCatalogScope = this.otherParams?.catalogScopeKey;
|
|
1428
1429
|
const previousItemRuleConfig = this.otherParams?.itemRule;
|
|
1429
1430
|
const explicitlySetsOpenData = Object.prototype.hasOwnProperty.call(params, 'openData');
|
|
1430
1431
|
const nextParams = cover ? params : {
|
|
@@ -1437,6 +1438,10 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
|
|
|
1437
1438
|
await super.setOtherParams(params, {
|
|
1438
1439
|
cover
|
|
1439
1440
|
});
|
|
1441
|
+
if (previousCatalogScope !== this.otherParams?.catalogScopeKey && (previousCatalogScope || this.otherParams?.catalogScopeKey)) {
|
|
1442
|
+
this.unifiedProductCatalog = [];
|
|
1443
|
+
await this.core.effects.emit(`${this.name}:onProductsLoaded`, []);
|
|
1444
|
+
}
|
|
1440
1445
|
const nextScope = this.getAvailabilityScopeDescriptor(this.otherParams || {});
|
|
1441
1446
|
if (explicitlySetsOpenData) {
|
|
1442
1447
|
this.openDataTarget = this.otherParams?.openData && nextScope.businessCode && nextScope.channel ? `${nextScope.businessCode}+${nextScope.channel}` : null;
|
|
@@ -2024,6 +2029,7 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
|
|
|
2024
2029
|
*/
|
|
2025
2030
|
async loadProducts(params = {}, options) {
|
|
2026
2031
|
if (!this.store.products) throw new Error('[UnifiedBookingSales] products 模块未初始化');
|
|
2032
|
+
const catalogScope = this.otherParams.catalogScopeKey;
|
|
2027
2033
|
const schedule_date = params.schedule_date || (0, _dayjs.default)().format('YYYY-MM-DD');
|
|
2028
2034
|
const schedule_datetime = params.schedule_datetime || `${schedule_date} ${(0, _dayjs.default)().format('HH:mm:ss')}`;
|
|
2029
2035
|
const result = await this.store.products.loadProducts({
|
|
@@ -2034,6 +2040,11 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
|
|
|
2034
2040
|
schedule_datetime,
|
|
2035
2041
|
cacheId: this.cacheId
|
|
2036
2042
|
}, options);
|
|
2043
|
+
if (catalogScope !== this.otherParams.catalogScopeKey) {
|
|
2044
|
+
throw Object.assign(new Error('Product scope changed'), {
|
|
2045
|
+
name: 'AbortError'
|
|
2046
|
+
});
|
|
2047
|
+
}
|
|
2037
2048
|
this.unifiedProductCatalog = Array.isArray(result) ? [...result] : [];
|
|
2038
2049
|
await this.core.effects.emit(`${this.name}:onProductsLoaded`, result);
|
|
2039
2050
|
return result;
|