@pisell/pisellos 2.3.67 → 2.3.68

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.
Files changed (85) hide show
  1. package/dist/core/index.d.ts +0 -7
  2. package/dist/core/index.js +65 -109
  3. package/dist/model/strategy/adapter/walletPass/evaluator.js +0 -1
  4. package/dist/model/strategy/adapter/walletPass/utils.js +0 -2
  5. package/dist/modules/BaseModule.d.ts +1 -0
  6. package/dist/modules/BaseModule.js +24 -28
  7. package/dist/modules/Customer/index.d.ts +4 -0
  8. package/dist/modules/Customer/index.js +91 -59
  9. package/dist/modules/Customer/types.d.ts +2 -0
  10. package/dist/modules/Order/index.d.ts +22 -2
  11. package/dist/modules/Order/index.js +313 -142
  12. package/dist/modules/Order/types.d.ts +13 -1
  13. package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +15 -0
  14. package/dist/modules/Order/utils/orderCollectionIdentity.js +75 -0
  15. package/dist/modules/Order/utils.js +0 -1
  16. package/dist/modules/Payment/index.d.ts +4 -0
  17. package/dist/modules/Payment/index.js +14 -4
  18. package/dist/modules/Payment/walletpass.js +52 -18
  19. package/dist/modules/Quotation/index.d.ts +0 -6
  20. package/dist/modules/Quotation/index.js +19 -75
  21. package/dist/modules/Rules/index.js +46 -31
  22. package/dist/plugins/request.d.ts +0 -1
  23. package/dist/server/index.d.ts +2 -8
  24. package/dist/server/index.js +143 -212
  25. package/dist/server/modules/floor-plan/index.d.ts +0 -4
  26. package/dist/server/modules/floor-plan/index.js +98 -240
  27. package/dist/server/modules/menu/index.js +23 -48
  28. package/dist/server/modules/order/index.d.ts +8 -17
  29. package/dist/server/modules/order/index.js +453 -506
  30. package/dist/server/modules/products/index.d.ts +2 -8
  31. package/dist/server/modules/products/index.js +75 -167
  32. package/dist/server/modules/resource/index.js +13 -21
  33. package/dist/server/utils/small-ticket.js +2 -1
  34. package/dist/solution/BaseSales/index.d.ts +3 -1
  35. package/dist/solution/BaseSales/index.js +99 -82
  36. package/dist/solution/BaseSales/utils.js +31 -20
  37. package/dist/solution/BookingTicket/index.d.ts +6 -2
  38. package/dist/solution/BookingTicket/index.js +123 -75
  39. package/dist/solution/ScanOrder/utils.js +31 -20
  40. package/dist/solution/UnifiedBookingSales/index.d.ts +25 -0
  41. package/dist/solution/UnifiedBookingSales/index.js +640 -321
  42. package/dist/solution/UnifiedBookingSales/types.d.ts +7 -0
  43. package/lib/core/index.d.ts +0 -7
  44. package/lib/core/index.js +2 -20
  45. package/lib/model/strategy/adapter/walletPass/evaluator.js +0 -1
  46. package/lib/model/strategy/adapter/walletPass/utils.js +0 -1
  47. package/lib/modules/BaseModule.d.ts +1 -0
  48. package/lib/modules/BaseModule.js +24 -37
  49. package/lib/modules/Customer/index.d.ts +4 -0
  50. package/lib/modules/Customer/index.js +11 -0
  51. package/lib/modules/Customer/types.d.ts +2 -0
  52. package/lib/modules/Order/index.d.ts +22 -2
  53. package/lib/modules/Order/index.js +212 -54
  54. package/lib/modules/Order/types.d.ts +13 -1
  55. package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +15 -0
  56. package/lib/modules/Order/utils/orderCollectionIdentity.js +70 -0
  57. package/lib/modules/Order/utils.js +0 -1
  58. package/lib/modules/Payment/index.d.ts +4 -0
  59. package/lib/modules/Payment/index.js +7 -0
  60. package/lib/modules/Payment/walletpass.js +27 -2
  61. package/lib/modules/Quotation/index.d.ts +0 -6
  62. package/lib/modules/Quotation/index.js +5 -49
  63. package/lib/modules/Rules/index.js +17 -1
  64. package/lib/plugins/request.d.ts +0 -1
  65. package/lib/server/index.d.ts +2 -8
  66. package/lib/server/index.js +20 -58
  67. package/lib/server/modules/floor-plan/index.d.ts +0 -4
  68. package/lib/server/modules/floor-plan/index.js +6 -54
  69. package/lib/server/modules/menu/index.js +5 -31
  70. package/lib/server/modules/order/index.d.ts +8 -17
  71. package/lib/server/modules/order/index.js +106 -199
  72. package/lib/server/modules/products/index.d.ts +2 -8
  73. package/lib/server/modules/products/index.js +24 -97
  74. package/lib/server/modules/resource/index.js +2 -7
  75. package/lib/server/utils/small-ticket.js +1 -1
  76. package/lib/solution/BaseSales/index.d.ts +3 -1
  77. package/lib/solution/BaseSales/index.js +29 -16
  78. package/lib/solution/BaseSales/utils.js +29 -18
  79. package/lib/solution/BookingTicket/index.d.ts +6 -2
  80. package/lib/solution/BookingTicket/index.js +53 -14
  81. package/lib/solution/ScanOrder/utils.js +29 -18
  82. package/lib/solution/UnifiedBookingSales/index.d.ts +25 -0
  83. package/lib/solution/UnifiedBookingSales/index.js +188 -0
  84. package/lib/solution/UnifiedBookingSales/types.d.ts +7 -0
  85. package/package.json +1 -1
@@ -192,7 +192,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
192
192
  * Server 层负责传入完整 schedule 模块,Products 只负责把报价单计算结果转成价格响应形状。
193
193
  */
194
194
  async setupQuotationPriceBridge(params) {
195
- var _a, _b, _c;
195
+ var _a;
196
196
  if (!this.core) {
197
197
  this.logWarning("setupQuotationPriceBridge: core 尚未初始化");
198
198
  return;
@@ -211,13 +211,13 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
211
211
  this.quotationScheduleCacheSource = params.scheduleModule;
212
212
  }
213
213
  this.quotationPriceBridge.setScheduleResolver((id) => {
214
- var _a2, _b2, _c2, _d, _e, _f;
214
+ var _a2, _b, _c, _d, _e, _f;
215
215
  const scheduleId = String(id);
216
216
  if (this.quotationScheduleCache.has(scheduleId)) {
217
217
  return this.quotationScheduleCache.get(scheduleId);
218
218
  }
219
219
  if (!this.quotationScheduleCacheLoaded) {
220
- const scheduleList = ((_b2 = (_a2 = params.scheduleModule).getScheduleList) == null ? void 0 : _b2.call(_a2)) || [];
220
+ const scheduleList = ((_b = (_a2 = params.scheduleModule).getScheduleList) == null ? void 0 : _b.call(_a2)) || [];
221
221
  for (const schedule of scheduleList) {
222
222
  this.quotationScheduleCache.set(String(schedule.id), schedule);
223
223
  }
@@ -226,21 +226,12 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
226
226
  if (this.quotationScheduleCache.has(scheduleId)) {
227
227
  return this.quotationScheduleCache.get(scheduleId);
228
228
  }
229
- const schedules = ((_d = (_c2 = params.scheduleModule).getScheduleListByIds) == null ? void 0 : _d.call(_c2, [id])) || ((_f = (_e = params.scheduleModule).getScheduleByIds) == null ? void 0 : _f.call(_e, [id])) || [];
229
+ const schedules = ((_d = (_c = params.scheduleModule).getScheduleListByIds) == null ? void 0 : _d.call(_c, [id])) || ((_f = (_e = params.scheduleModule).getScheduleByIds) == null ? void 0 : _f.call(_e, [id])) || [];
230
230
  if (schedules[0])
231
231
  this.quotationScheduleCache.set(scheduleId, schedules[0]);
232
232
  return schedules[0];
233
233
  });
234
234
  }
235
- if (params.onQuotationUpdated) {
236
- this.quotationBridgeUpdatedCallback = params.onQuotationUpdated;
237
- }
238
- (_c = (_b = this.quotationPriceBridge).setQuotationListUpdatedListener) == null ? void 0 : _c.call(_b, () => {
239
- var _a2;
240
- this.quotationBridgeLoadedKey = this.getQuotationBridgeScopeKey();
241
- this.clearPriceCache();
242
- (_a2 = this.quotationBridgeUpdatedCallback) == null ? void 0 : _a2.call(this);
243
- });
244
235
  await this.refreshQuotationPriceBridge({ customer_id: params.customer_id });
245
236
  }
246
237
  /**
@@ -807,20 +798,17 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
807
798
  */
808
799
  clearPriceCache() {
809
800
  this.productsPriceCache.clear();
810
- this.quotationScheduleCache.clear();
811
- this.quotationScheduleCacheLoaded = false;
812
801
  console.log("[ProductsModule] 🗑️ 商品价格缓存已清空");
813
802
  }
814
803
  /**
815
804
  * 通过 ProductDataSource SSE 加载完整商品列表
816
805
  */
817
- async loadProductsByServer(options = {}) {
806
+ async loadProductsByServer() {
818
807
  if (!this.productDataSource) {
819
808
  this.logWarning("loadProductsByServer: ProductDataSource 不可用");
820
809
  return [];
821
810
  }
822
- const trigger = options.trigger || "unknown";
823
- this.logInfo("开始通过 DataSource SSE 加载商品列表", { trigger });
811
+ this.logInfo("开始通过 DataSource SSE 加载商品列表");
824
812
  const t0 = performance.now();
825
813
  try {
826
814
  const tSSE = performance.now();
@@ -828,7 +816,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
828
816
  const list = productList || [];
829
817
  (0, import_product.perfMark)("loadProductsByServer.SSE", performance.now() - tSSE, { count: list.length });
830
818
  this.logInfo("通过 DataSource SSE 加载商品列表成功", {
831
- trigger,
832
819
  productCount: list.length,
833
820
  duration: `${Math.round(performance.now() - t0)}ms`
834
821
  });
@@ -842,7 +829,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
842
829
  const errorMessage = error instanceof Error ? error.message : String(error);
843
830
  console.error("[Products] 加载商品数据失败:", error);
844
831
  this.logError("通过 DataSource SSE 加载商品列表失败", {
845
- trigger,
846
832
  duration: `${duration}ms`,
847
833
  error: errorMessage
848
834
  });
@@ -1033,9 +1019,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1033
1019
  async refreshProducts() {
1034
1020
  const tTotal = performance.now();
1035
1021
  this.logInfo("refreshProducts 开始");
1036
- const products = await this.loadProductsByServer({
1037
- trigger: "product_sync"
1038
- });
1022
+ const products = await this.loadProductsByServer();
1039
1023
  if (products && products.length > 0) {
1040
1024
  this.store.list = products;
1041
1025
  this.syncProductsMap();
@@ -1080,23 +1064,18 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1080
1064
  this.logWarning("loadProductsFromIndexDB: dbManager 不可用");
1081
1065
  return [];
1082
1066
  }
1083
- const startedAt = performance.now();
1084
1067
  try {
1068
+ const t0 = performance.now();
1085
1069
  const products = await this.dbManager.getAll(INDEXDB_STORE_NAME);
1086
- const durationMs = +(performance.now() - startedAt).toFixed(2);
1087
- (0, import_product.perfMark)("loadProductsFromIndexDB", durationMs, { count: (products == null ? void 0 : products.length) ?? 0 });
1070
+ (0, import_product.perfMark)("loadProductsFromIndexDB", performance.now() - t0, { count: (products == null ? void 0 : products.length) ?? 0 });
1088
1071
  this.logInfo("从 IndexDB 加载商品数据", {
1089
- productCount: (products == null ? void 0 : products.length) ?? 0,
1090
- durationMs
1072
+ productCount: (products == null ? void 0 : products.length) ?? 0
1091
1073
  });
1092
1074
  return products || [];
1093
1075
  } catch (error) {
1094
1076
  const errorMessage = error instanceof Error ? error.message : String(error);
1095
1077
  console.error("[Products] 从 IndexDB 读取数据失败:", error);
1096
- this.logError("从 IndexDB 读取数据失败", {
1097
- durationMs: +(performance.now() - startedAt).toFixed(2),
1098
- error: errorMessage
1099
- });
1078
+ this.logError("从 IndexDB 读取数据失败", { error: errorMessage });
1100
1079
  return [];
1101
1080
  }
1102
1081
  }
@@ -1124,54 +1103,22 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1124
1103
  this.logWarning("replaceProductsSnapshotInIndexDB: dbManager 不可用");
1125
1104
  return;
1126
1105
  }
1127
- const enqueuedAt = performance.now();
1128
- let queueWaitMs = 0;
1129
- let clearDurationMs = 0;
1130
- let writeDurationMs = 0;
1131
1106
  try {
1132
1107
  await this.runInProductIndexDBSaveQueue(async () => {
1133
- const operationStartedAt = performance.now();
1134
- queueWaitMs = +(operationStartedAt - enqueuedAt).toFixed(2);
1135
- this.logInfo("replaceProductsSnapshotInIndexDB 开始", {
1136
- source,
1137
- productCount: products.length,
1138
- queueWaitMs
1139
- });
1140
- const clearStartedAt = performance.now();
1141
- try {
1142
- await this.dbManager.clear(INDEXDB_STORE_NAME);
1143
- } finally {
1144
- clearDurationMs = +(performance.now() - clearStartedAt).toFixed(2);
1145
- }
1108
+ this.logInfo("replaceProductsSnapshotInIndexDB 开始", { source, productCount: products.length });
1109
+ const t0 = performance.now();
1110
+ await this.dbManager.clear(INDEXDB_STORE_NAME);
1146
1111
  if (products.length > 0) {
1147
- const writeStartedAt = performance.now();
1148
- try {
1149
- await this.dbManager.bulkUpdate(INDEXDB_STORE_NAME, products);
1150
- } finally {
1151
- writeDurationMs = +(performance.now() - writeStartedAt).toFixed(2);
1152
- }
1112
+ await this.dbManager.bulkUpdate(INDEXDB_STORE_NAME, products);
1153
1113
  }
1154
- const executeDurationMs = +(performance.now() - operationStartedAt).toFixed(2);
1155
- (0, import_product.perfMark)("replaceProductsSnapshotInIndexDB", executeDurationMs, { count: products.length });
1156
- this.logInfo("replaceProductsSnapshotInIndexDB 完成", {
1157
- source,
1158
- productCount: products.length,
1159
- queueWaitMs,
1160
- clearDurationMs,
1161
- writeDurationMs,
1162
- executeDurationMs,
1163
- totalDurationMs: +(performance.now() - enqueuedAt).toFixed(2)
1164
- });
1114
+ (0, import_product.perfMark)("replaceProductsSnapshotInIndexDB", performance.now() - t0, { count: products.length });
1115
+ this.logInfo("replaceProductsSnapshotInIndexDB 完成", { source, productCount: products.length });
1165
1116
  });
1166
1117
  } catch (error) {
1167
1118
  const errorMessage = error instanceof Error ? error.message : String(error);
1168
1119
  this.logError("全量保存商品到 IndexDB 失败", {
1169
1120
  source,
1170
1121
  productCount: products.length,
1171
- queueWaitMs,
1172
- clearDurationMs,
1173
- writeDurationMs,
1174
- totalDurationMs: +(performance.now() - enqueuedAt).toFixed(2),
1175
1122
  error: errorMessage
1176
1123
  });
1177
1124
  }
@@ -1253,7 +1200,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1253
1200
  source: "IndexDB"
1254
1201
  });
1255
1202
  this.logInfo("预加载完成(从 IndexDB)", {
1256
- trigger: "preload",
1257
1203
  productCount: cachedData.length,
1258
1204
  duration: `${Math.round(performance.now() - tTotal)}ms`,
1259
1205
  source: "IndexDB"
@@ -1269,9 +1215,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1269
1215
  this.logWarning("从 IndexDB 加载数据失败,准备从服务器加载", { error: errorMessage });
1270
1216
  }
1271
1217
  const tServer = performance.now();
1272
- const products = await this.loadProductsByServer({
1273
- trigger: "preload"
1274
- });
1218
+ const products = await this.loadProductsByServer();
1275
1219
  (0, import_product.perfMark)("preload.loadFromServer", performance.now() - tServer, { count: (products == null ? void 0 : products.length) ?? 0 });
1276
1220
  if (products && products.length > 0) {
1277
1221
  this.store.list = products;
@@ -1284,7 +1228,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1284
1228
  source: "Server"
1285
1229
  });
1286
1230
  this.logInfo("预加载完成(从服务器)", {
1287
- trigger: "preload",
1288
1231
  productCount: products.length,
1289
1232
  duration: `${Math.round(performance.now() - tTotal)}ms`,
1290
1233
  source: "Server"
@@ -1649,31 +1592,17 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1649
1592
  * 拿到完整数据后一次性替换 store,清除价格缓存,触发 onProductsSyncCompleted
1650
1593
  * @returns 刷新后的商品列表
1651
1594
  */
1652
- async silentRefresh(options = {}) {
1595
+ async silentRefresh() {
1653
1596
  const t0 = performance.now();
1654
1597
  const now = Date.now();
1655
- const trigger = options.trigger || "background";
1656
- const elapsedSincePreloadMs = now - this.lastPreloadCompletedAtMs;
1657
- const elapsedSinceFullFetchMs = now - this.lastServerFullFetchAtMs;
1658
- if (this.lastPreloadCompletedAtMs > 0 && elapsedSincePreloadMs < PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS || this.lastServerFullFetchAtMs > 0 && elapsedSinceFullFetchMs < PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS) {
1659
- this.logInfo("silentRefresh 跳过全量 SSE", {
1660
- trigger,
1661
- reason: "within_min_interval",
1662
- minIntervalMs: PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS,
1663
- elapsedSincePreloadMs,
1664
- elapsedSinceFullFetchMs,
1665
- productCount: this.store.list.length
1666
- });
1598
+ const elapsedSincePreload = now - this.lastPreloadCompletedAtMs;
1599
+ const elapsedSinceFullFetch = now - this.lastServerFullFetchAtMs;
1600
+ if (this.lastPreloadCompletedAtMs > 0 && elapsedSincePreload < PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS || this.lastServerFullFetchAtMs > 0 && elapsedSinceFullFetch < PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS) {
1667
1601
  return this.store.list;
1668
1602
  }
1669
- this.logInfo("silentRefresh 开始", {
1670
- trigger,
1671
- elapsedSincePreloadMs,
1672
- elapsedSinceFullFetchMs,
1673
- productCount: this.store.list.length
1674
- });
1603
+ this.logInfo("silentRefresh 开始");
1675
1604
  try {
1676
- const products = await this.loadProductsByServer({ trigger });
1605
+ const products = await this.loadProductsByServer();
1677
1606
  if (products && products.length > 0) {
1678
1607
  this.store.list = products;
1679
1608
  this.syncProductsMap();
@@ -1681,7 +1610,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1681
1610
  this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
1682
1611
  await this.core.effects.emit(import_types.ProductsHooks.onProductsSyncCompleted, null);
1683
1612
  this.logInfo("silentRefresh 完成", {
1684
- trigger,
1685
1613
  productCount: products.length,
1686
1614
  duration: `${Math.round(performance.now() - t0)}ms`
1687
1615
  });
@@ -1693,7 +1621,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1693
1621
  } catch (error) {
1694
1622
  const errorMessage = error instanceof Error ? error.message : String(error);
1695
1623
  this.logError("silentRefresh 失败", {
1696
- trigger,
1697
1624
  duration: `${Math.round(performance.now() - t0)}ms`,
1698
1625
  error: errorMessage
1699
1626
  });
@@ -88,18 +88,13 @@ var ResourceModule = class extends import_BaseModule.BaseModule {
88
88
  }
89
89
  }
90
90
  async preload() {
91
+ await this.setupResourceSync();
91
92
  const cachedResources = await this.loadResourcesFromSQLite();
92
93
  if (cachedResources.length > 0) {
93
94
  this.store.list = (0, import_lodash_es.cloneDeep)(cachedResources).map((item) => this.normalizeResource(item));
94
95
  this.syncResourcesMap();
95
96
  await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
96
- void this.setupResourceSync().catch((error) => {
97
- this.logError("后台初始化资源同步失败", error);
98
- });
99
- return;
100
- }
101
- await this.setupResourceSync();
102
- if (this.store.list.length === 0) {
97
+ } else {
103
98
  const resources = await this.loadResourcesByServer();
104
99
  if (resources.length > 0) {
105
100
  this.store.list = (0, import_lodash_es.cloneDeep)(resources).map((item) => this.normalizeResource(item));
@@ -562,7 +562,7 @@ function buildOptionTitleSuffix(options) {
562
562
  function formatBundlePrice(bundle, currencySymbol) {
563
563
  const value = bundle.bundle_selling_price ?? bundle.bundle_sum_price ?? bundle.price ?? 0;
564
564
  const amount = new import_decimal.default(toMoneyNumber(value));
565
- const isNegative = bundle.price_type === "markdown" || bundle.price_type === "markup" && bundle.price_type_ext === "product_price";
565
+ const isNegative = bundle.price_type === "markdown";
566
566
  if (isNegative)
567
567
  return `-${currencySymbol}${amount.abs().toFixed(2)}`;
568
568
  return formatMoney(amount, currencySymbol);
@@ -141,7 +141,9 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
141
141
  * const params = this.buildSubModuleOtherParams();
142
142
  * this.core.registerModule(orderModule, { otherParams: params });
143
143
  */
144
- protected buildSubModuleOtherParams(): Record<string, any>;
144
+ protected isSessionStoragePersistEnabled(): boolean;
145
+ protected shouldUseSessionStorageForSubModule(_moduleName?: string): boolean;
146
+ protected buildSubModuleOtherParams(moduleName?: string): Record<string, any>;
145
147
  /**
146
148
  * 将父级 otherParams 的变更显式同步给已注册的子模块。
147
149
  *
@@ -591,7 +591,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
591
591
  });
592
592
  });
593
593
  }
594
- async hydrateLatestLoadedSalesDetail(record, loadSequence) {
594
+ async hydrateLatestLoadedSalesDetail(record, loadSequence, hydrateSource) {
595
595
  let hydratedSales = null;
596
596
  let skippedBeforeHydrate = false;
597
597
  const hydrateTask = async () => {
@@ -601,9 +601,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
601
601
  }
602
602
  if (!this.store.order)
603
603
  throw new Error("order 模块未初始化");
604
- const sales = await this.store.order.hydrateTempOrderFromRecord(record, {
605
- recalcOnHydrate: false
606
- });
604
+ const sales = await this.store.order.hydrateTempOrderFromRecord(
605
+ record,
606
+ hydrateSource === "sessionStorage" ? { recalcOnHydrate: true, source: "sessionStorage" } : { recalcOnHydrate: false }
607
+ );
607
608
  hydratedSales = sales;
608
609
  if (loadSequence !== this.salesDetailLoadSequence)
609
610
  return;
@@ -927,12 +928,18 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
927
928
  * const params = this.buildSubModuleOtherParams();
928
929
  * this.core.registerModule(orderModule, { otherParams: params });
929
930
  */
930
- buildSubModuleOtherParams() {
931
+ isSessionStoragePersistEnabled() {
932
+ return Boolean(this.cacheId);
933
+ }
934
+ shouldUseSessionStorageForSubModule(_moduleName) {
935
+ return this.isSessionStoragePersistEnabled();
936
+ }
937
+ buildSubModuleOtherParams(moduleName) {
931
938
  return {
932
939
  ...this.otherParams,
933
940
  salesSummaryModuleName: `${this.name}_salesSummary`,
934
941
  fatherModule: this.name,
935
- openCache: this.cacheId ? true : false,
942
+ openCache: this.shouldUseSessionStorageForSubModule(moduleName),
936
943
  cacheId: this.cacheId
937
944
  };
938
945
  }
@@ -943,7 +950,6 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
943
950
  * await this.syncOtherParamsToSubModules({ channel: 'pos' });
944
951
  */
945
952
  async syncOtherParamsToSubModules(changedParams, { cover = false } = {}) {
946
- const nextSubModuleOtherParams = this.buildSubModuleOtherParams();
947
953
  await Promise.all(
948
954
  Object.entries(this.store).map(async ([moduleName, subModule]) => {
949
955
  if (this.reusedSharedSubModuleNames.has(moduleName)) {
@@ -953,6 +959,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
953
959
  if (!targetModule || typeof targetModule.updateOtherParams !== "function") {
954
960
  return;
955
961
  }
962
+ const nextSubModuleOtherParams = this.buildSubModuleOtherParams(moduleName);
956
963
  await targetModule.updateOtherParams(nextSubModuleOtherParams, {
957
964
  changedParams,
958
965
  cover
@@ -965,14 +972,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
965
972
  * sessionStorage 损坏时静默忽略,按空状态注册。
966
973
  */
967
974
  readSessionCacheData() {
968
- if (!this.cacheId || !this.window)
975
+ const cacheId = this.cacheId;
976
+ if (!cacheId || !this.isSessionStoragePersistEnabled() || !this.window) {
969
977
  return {};
978
+ }
970
979
  try {
971
980
  const sessionData = this.window.sessionStorage.getItem(this.name);
972
981
  if (!sessionData)
973
982
  return {};
974
983
  const data = JSON.parse(sessionData);
975
- return data && data[this.cacheId] || {};
984
+ return data && data[cacheId] || {};
976
985
  } catch {
977
986
  return {};
978
987
  }
@@ -1074,9 +1083,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1074
1083
  const hooks = this.getSubModuleHooks(step);
1075
1084
  this.store[step] = targetModule;
1076
1085
  this.core.registerModule(targetModule, {
1077
- initialState: (targetCacheData == null ? void 0 : targetCacheData[targetModule.name]) || {},
1086
+ initialState: this.shouldUseSessionStorageForSubModule(step) ? (targetCacheData == null ? void 0 : targetCacheData[targetModule.name]) || {} : {},
1078
1087
  ...hooks ? { hooks } : {},
1079
- otherParams: this.buildSubModuleOtherParams()
1088
+ otherParams: this.buildSubModuleOtherParams(step)
1080
1089
  });
1081
1090
  });
1082
1091
  if (this.store.schedule && !this.isScheduleListLoaded(this.store.schedule)) {
@@ -1143,17 +1152,21 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1143
1152
  const message = loadedRecord && (loadedRecord.message || loadedRecord.msg) || `加载销售详情失败: ${lookup}`;
1144
1153
  throw new Error(message);
1145
1154
  }
1146
- const remoteRecord = filterPendingPaymentsFromLoadedSalesDetail(
1147
- preloadedSalesDetail ?? loadedRecord.data
1148
- );
1155
+ const loadedSalesDetail = preloadedSalesDetail ?? loadedRecord.data;
1156
+ const shouldFilterPendingPayments = params.hydrateSource !== "sessionStorage";
1157
+ const remoteRecord = shouldFilterPendingPayments ? filterPendingPaymentsFromLoadedSalesDetail(loadedSalesDetail) : loadedSalesDetail;
1149
1158
  const currentTempOrder = params.merge ? this.store.order.getTempOrder() : null;
1150
1159
  const mergedRecord = params.merge ? mergeSalesDetailRecordWithTempOrder(
1151
1160
  currentTempOrder,
1152
1161
  remoteRecord,
1153
1162
  "preserve-local"
1154
1163
  ) : remoteRecord;
1155
- const record = filterPendingPaymentsFromLoadedSalesDetail(mergedRecord);
1156
- return await this.hydrateLatestLoadedSalesDetail(record, loadSequence);
1164
+ const record = shouldFilterPendingPayments ? filterPendingPaymentsFromLoadedSalesDetail(mergedRecord) : mergedRecord;
1165
+ return await this.hydrateLatestLoadedSalesDetail(
1166
+ record,
1167
+ loadSequence,
1168
+ params.hydrateSource
1169
+ );
1157
1170
  } finally {
1158
1171
  this.salesDetailLoadInFlightCount = Math.max(
1159
1172
  0,
@@ -60,33 +60,44 @@ function createEmptySummary() {
60
60
  };
61
61
  }
62
62
  function buildProductLineFingerprint(productOptionItem, productBundle) {
63
- const optArr = Array.isArray(productOptionItem) ? productOptionItem : [];
64
- const normalizedOpts = optArr.map((item) => ({
65
- option_group_item_id: Number(item == null ? void 0 : item.option_group_item_id) || 0,
66
- option_group_id: Number(item == null ? void 0 : item.option_group_id) || 0,
67
- num: typeof (item == null ? void 0 : item.num) === "number" && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1,
68
- price: String((item == null ? void 0 : item.add_price) ?? (item == null ? void 0 : item.price) ?? "")
69
- })).sort((p, q) => {
70
- if (p.option_group_item_id !== q.option_group_item_id) {
71
- return p.option_group_item_id - q.option_group_item_id;
72
- }
73
- if (p.option_group_id !== q.option_group_id)
74
- return p.option_group_id - q.option_group_id;
75
- if (p.num !== q.num)
76
- return p.num - q.num;
77
- return p.price.localeCompare(q.price);
78
- });
63
+ const normalizeOptions = (options) => {
64
+ const optionArr = Array.isArray(options) ? options : [];
65
+ return optionArr.map((item) => ({
66
+ option_group_item_id: Number(item == null ? void 0 : item.option_group_item_id) || 0,
67
+ option_group_id: Number(item == null ? void 0 : item.option_group_id) || 0,
68
+ num: typeof (item == null ? void 0 : item.num) === "number" && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1,
69
+ price: String((item == null ? void 0 : item.add_price) ?? (item == null ? void 0 : item.price) ?? "")
70
+ })).sort((p, q) => {
71
+ if (p.option_group_item_id !== q.option_group_item_id) {
72
+ return p.option_group_item_id - q.option_group_item_id;
73
+ }
74
+ if (p.option_group_id !== q.option_group_id) {
75
+ return p.option_group_id - q.option_group_id;
76
+ }
77
+ if (p.num !== q.num)
78
+ return p.num - q.num;
79
+ return p.price.localeCompare(q.price);
80
+ });
81
+ };
82
+ const normalizedOpts = normalizeOptions(productOptionItem);
79
83
  const bundleArr = Array.isArray(productBundle) ? productBundle : [];
80
84
  const normalizedBundles = bundleArr.map((item) => ({
81
85
  bundle_id: Number((item == null ? void 0 : item.bundle_id) ?? (item == null ? void 0 : item.id) ?? 0) || 0,
82
86
  product_id: Number(item == null ? void 0 : item.product_id) || 0,
83
- num: typeof (item == null ? void 0 : item.num) === "number" && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1
87
+ product_variant_id: Number((item == null ? void 0 : item.bundle_variant_id) ?? (item == null ? void 0 : item.product_variant_id)) || 0,
88
+ num: typeof (item == null ? void 0 : item.num) === "number" && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1,
89
+ option: normalizeOptions(item == null ? void 0 : item.option)
84
90
  })).sort((p, q) => {
85
91
  if (p.bundle_id !== q.bundle_id)
86
92
  return p.bundle_id - q.bundle_id;
87
93
  if (p.product_id !== q.product_id)
88
94
  return p.product_id - q.product_id;
89
- return p.num - q.num;
95
+ if (p.product_variant_id !== q.product_variant_id) {
96
+ return p.product_variant_id - q.product_variant_id;
97
+ }
98
+ if (p.num !== q.num)
99
+ return p.num - q.num;
100
+ return JSON.stringify(p.option).localeCompare(JSON.stringify(q.option));
90
101
  });
91
102
  return JSON.stringify([normalizedOpts, normalizedBundles]);
92
103
  }
@@ -29,6 +29,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
29
29
  private addTimeProductsCatalog;
30
30
  private orderCustomerDiscountRefreshInFlight;
31
31
  private orderCustomerDiscountRefreshCustomerId;
32
+ private orderCustomerPromotionRefreshInFlight;
32
33
  private loadOpenDataConfigInFlight;
33
34
  /**
34
35
  * 在 BaseSales 默认模块清单(products/order/salesSummary/schedule)基础上追加 customer + bookingContext。
@@ -63,6 +64,8 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
63
64
  scanPromotionCode(code: string, customerId?: number): Promise<BaseSalesScanCodeResult>;
64
65
  private hydrateOrderCustomerFromScanDiscounts;
65
66
  private getDiscountCustomerId;
67
+ resolveCustomerById(customerId: string | number): Promise<ICustomer | null>;
68
+ /** 兼容既有优惠码扫码逻辑。 */
66
69
  private resolveCustomerByDiscountCustomerId;
67
70
  private findCustomerById;
68
71
  private normalizeCustomer;
@@ -282,7 +285,8 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
282
285
  restoreOrder(): Promise<import("../../modules/Order/types").OrderTempOrder>;
283
286
  /** 内部:基于 OrderModule 当前状态构造一份 OrderCustomerChangePayload。 */
284
287
  private buildOrderCustomerPayload;
285
- private refreshDiscountConfigAfterOrderCustomerChange;
288
+ protected refreshDiscountConfigAfterOrderCustomerChange(customerId: number | null): Promise<void>;
289
+ protected waitForOrderCustomerPromotionRefresh(): Promise<void>;
286
290
  /**
287
291
  * 获取客户分页信息
288
292
  * @returns 分页信息
@@ -326,7 +330,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
326
330
  * 获取当前的客户搜索条件
327
331
  * @returns 当前搜索条件
328
332
  */
329
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
333
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
330
334
  /**
331
335
  * 获取客户列表状态(包含滚动加载相关状态)
332
336
  * @returns 客户状态