@pisell/pisellos 2.3.30 → 2.3.32

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 (73) hide show
  1. package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
  2. package/dist/model/strategy/adapter/dataVariant/adapter.js +167 -0
  3. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
  4. package/dist/model/strategy/adapter/dataVariant/evaluator.js +780 -0
  5. package/dist/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  6. package/dist/model/strategy/adapter/dataVariant/examples.js +277 -0
  7. package/dist/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  8. package/dist/model/strategy/adapter/dataVariant/index.js +4 -0
  9. package/dist/model/strategy/adapter/dataVariant/type.d.ts +148 -0
  10. package/dist/model/strategy/adapter/dataVariant/type.js +54 -0
  11. package/dist/model/strategy/adapter/index.d.ts +4 -0
  12. package/dist/model/strategy/adapter/index.js +5 -1
  13. package/dist/model/strategy/adapter/promotion/index.js +0 -9
  14. package/dist/modules/Discount/index.d.ts +5 -2
  15. package/dist/modules/Discount/index.js +30 -7
  16. package/dist/modules/Discount/types.d.ts +4 -0
  17. package/dist/modules/Order/index.d.ts +2 -1
  18. package/dist/modules/Order/index.js +25 -11
  19. package/dist/modules/Order/types.d.ts +2 -0
  20. package/dist/modules/Product/index.d.ts +1 -1
  21. package/dist/modules/Product/types.d.ts +22 -0
  22. package/dist/modules/ProductList/index.d.ts +1 -1
  23. package/dist/modules/ProductList/index.js +4 -2
  24. package/dist/modules/ProductList/types.d.ts +2 -0
  25. package/dist/server/index.d.ts +50 -0
  26. package/dist/server/index.js +1095 -849
  27. package/dist/server/modules/order/index.d.ts +8 -3
  28. package/dist/server/modules/order/index.js +765 -675
  29. package/dist/server/modules/products/index.d.ts +26 -7
  30. package/dist/server/modules/products/index.js +167 -76
  31. package/dist/server/modules/products/types.d.ts +14 -0
  32. package/dist/solution/BaseSales/index.d.ts +2 -0
  33. package/dist/solution/BaseSales/index.js +23 -13
  34. package/dist/solution/BookingByStep/index.d.ts +1 -1
  35. package/dist/solution/BookingTicket/types.d.ts +2 -0
  36. package/dist/solution/ShopDiscount/index.js +15 -14
  37. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
  38. package/lib/model/strategy/adapter/dataVariant/adapter.js +149 -0
  39. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
  40. package/lib/model/strategy/adapter/dataVariant/evaluator.js +583 -0
  41. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  42. package/lib/model/strategy/adapter/dataVariant/examples.js +293 -0
  43. package/lib/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  44. package/lib/model/strategy/adapter/dataVariant/index.js +38 -0
  45. package/lib/model/strategy/adapter/dataVariant/type.d.ts +148 -0
  46. package/lib/model/strategy/adapter/dataVariant/type.js +31 -0
  47. package/lib/model/strategy/adapter/index.d.ts +4 -0
  48. package/lib/model/strategy/adapter/index.js +13 -2
  49. package/lib/model/strategy/adapter/promotion/index.js +0 -49
  50. package/lib/modules/Discount/index.d.ts +5 -2
  51. package/lib/modules/Discount/index.js +23 -3
  52. package/lib/modules/Discount/types.d.ts +4 -0
  53. package/lib/modules/Order/index.d.ts +2 -1
  54. package/lib/modules/Order/index.js +13 -1
  55. package/lib/modules/Order/types.d.ts +2 -0
  56. package/lib/modules/Product/index.d.ts +1 -1
  57. package/lib/modules/Product/types.d.ts +22 -0
  58. package/lib/modules/ProductList/index.d.ts +1 -1
  59. package/lib/modules/ProductList/index.js +4 -2
  60. package/lib/modules/ProductList/types.d.ts +2 -0
  61. package/lib/server/index.d.ts +50 -0
  62. package/lib/server/index.js +206 -29
  63. package/lib/server/modules/order/index.d.ts +8 -3
  64. package/lib/server/modules/order/index.js +152 -43
  65. package/lib/server/modules/products/index.d.ts +26 -7
  66. package/lib/server/modules/products/index.js +114 -35
  67. package/lib/server/modules/products/types.d.ts +14 -0
  68. package/lib/solution/BaseSales/index.d.ts +2 -0
  69. package/lib/solution/BaseSales/index.js +12 -3
  70. package/lib/solution/BookingByStep/index.d.ts +1 -1
  71. package/lib/solution/BookingTicket/types.d.ts +2 -0
  72. package/lib/solution/ShopDiscount/index.js +2 -1
  73. package/package.json +1 -1
@@ -103,7 +103,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
103
103
  this.updateCreateStore();
104
104
  }
105
105
  if (Array.isArray((_a = options == null ? void 0 : options.initialState) == null ? void 0 : _a.list)) {
106
- this.store.list = options.initialState.list.map((order) => this.normalizeOrderForMemoryList(order));
106
+ this.store.list = this.normalizeOrdersForMemoryList(
107
+ options.initialState.list,
108
+ "initialState"
109
+ );
107
110
  this.syncOrdersMap();
108
111
  this.emitOrdersChanged([], "initialState");
109
112
  } else {
@@ -463,17 +466,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
463
466
  return DEFAULT_ORDER_SYNC_THROTTLE_MS;
464
467
  }
465
468
  async preload() {
466
- const getData = async () => {
467
- const orders = await this.loadOrdersByServer();
468
- if (orders.length === 0) {
469
- return;
470
- }
471
- this.store.list = (0, import_lodash_es.cloneDeep)(orders);
472
- this.syncOrdersMap();
473
- this.emitOrdersChanged([], "preload");
474
- this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
475
- };
476
- getData();
469
+ const orders = await this.loadOrdersByServer();
470
+ this.store.list = (0, import_lodash_es.cloneDeep)(orders);
471
+ this.syncOrdersMap();
472
+ await this.emitOrdersChanged([], "preload");
473
+ await this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
477
474
  }
478
475
  getOrders() {
479
476
  return this.store.list;
@@ -558,7 +555,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
558
555
  }
559
556
  return null;
560
557
  }
561
- this.store.list = orders.map((order) => this.normalizeOrderForMemoryList(order));
558
+ this.store.list = this.normalizeOrdersForMemoryList(
559
+ orders,
560
+ "getLocalOrderByLookup.sqliteMemory"
561
+ );
562
562
  this.syncOrdersMap();
563
563
  const normalizedOrder = this.normalizeOrderForMemoryList(localOrder);
564
564
  if (options.operationId) {
@@ -653,12 +653,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
653
653
  };
654
654
  this.logInfo("updateLocalPayment-支付项合并完成", paymentContext);
655
655
  const targetIndex = this.findOrderIndexByIdentity(this.store.list, found.order);
656
- if (targetIndex < 0) {
656
+ const shouldKeepInMemory = this.shouldKeepOrderInMemory(nextOrder);
657
+ if (targetIndex < 0 && shouldKeepInMemory) {
657
658
  this.logError("updateLocalPayment-订单Store索引未命中", paymentContext);
658
659
  return null;
659
660
  }
660
661
  const previousList = this.store.list;
661
- this.store.list = this.store.list.map((order, index) => index === targetIndex ? nextOrder : order);
662
+ this.store.list = shouldKeepInMemory ? this.store.list.map((order, index) => index === targetIndex ? nextOrder : order) : this.store.list.filter((_, index) => index !== targetIndex);
662
663
  this.syncOrdersMap();
663
664
  const storageOrder = this.withoutSyntheticDraftOrderId(nextOrder);
664
665
  try {
@@ -681,16 +682,25 @@ var OrderModule = class extends import_BaseModule.BaseModule {
681
682
  });
682
683
  throw error;
683
684
  }
684
- await this.emitOrdersChanged([nextOrder], "updateLocalPayment");
685
+ if (shouldKeepInMemory || targetIndex >= 0) {
686
+ await this.emitOrdersChanged(
687
+ shouldKeepInMemory ? [nextOrder] : [],
688
+ shouldKeepInMemory ? "updateLocalPayment" : "updateLocalPayment.sqliteOnlyDraft"
689
+ );
690
+ }
685
691
  this.logInfo("updateLocalPayment-变更事件完成", paymentContext);
686
692
  return { order: nextOrder, payment: nextPayment, previousPayment };
687
693
  }
688
694
  async loadOrdersByServer() {
689
695
  var _a;
690
696
  let orderList = [];
697
+ const protectedOrdersBeforeRemoteFetch = (await this.loadOrdersFromSQLite()).filter(
698
+ (order) => this.isPendingSyncOrder(order) || this.isDraftOrder(order)
699
+ );
691
700
  this.logInfo("loadOrdersByServer-开始", {
692
701
  hasOrderDataSource: !!this.orderDataSource,
693
- query: ((_a = this.store) == null ? void 0 : _a.createdAtQuery) || null
702
+ query: ((_a = this.store) == null ? void 0 : _a.createdAtQuery) || null,
703
+ protectedLocalOrderCount: protectedOrdersBeforeRemoteFetch.length
694
704
  });
695
705
  if (this.orderDataSource) {
696
706
  try {
@@ -710,10 +720,19 @@ var OrderModule = class extends import_BaseModule.BaseModule {
710
720
  return this.store.list;
711
721
  }
712
722
  }
713
- const mergedOrders = await this.replaceOrdersSnapshotInSQLite(orderList, "loadOrdersByServer");
714
- const memoryOrders = mergedOrders.map((order) => this.normalizeOrderForMemoryList(order));
723
+ const mergedOrders = await this.replaceOrdersSnapshotInSQLite(
724
+ orderList,
725
+ "loadOrdersByServer",
726
+ protectedOrdersBeforeRemoteFetch
727
+ );
728
+ const memoryOrders = this.normalizeOrdersForMemoryList(
729
+ mergedOrders,
730
+ "loadOrdersByServer.memory"
731
+ );
715
732
  this.logInfo("loadOrdersByServer-结束", {
716
- count: memoryOrders.length
733
+ count: memoryOrders.length,
734
+ persistedCount: mergedOrders.length,
735
+ sqliteOnlyDraftCount: mergedOrders.length - memoryOrders.length
717
736
  });
718
737
  await this.core.effects.emit(import_types.OrderHooks.onOrdersLoaded, memoryOrders);
719
738
  return memoryOrders;
@@ -733,18 +752,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
733
752
  try {
734
753
  this.updateCreateStore();
735
754
  const orders = await this.loadOrdersByServer();
736
- if (orders.length > 0) {
737
- this.store.list = (0, import_lodash_es.cloneDeep)(orders);
738
- this.syncOrdersMap();
739
- this.emitOrdersChanged([], "silentRefresh");
740
- await this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
741
- this.logInfo("silentRefresh 完成", {
742
- orderCount: orders.length,
743
- duration: `${Date.now() - startTime}ms`
744
- });
745
- } else {
746
- this.logInfo("silentRefresh: 服务器未返回数据");
747
- }
755
+ this.store.list = (0, import_lodash_es.cloneDeep)(orders);
756
+ this.syncOrdersMap();
757
+ await this.emitOrdersChanged([], "silentRefresh");
758
+ await this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
759
+ this.logInfo("silentRefresh 完成", {
760
+ orderCount: orders.length,
761
+ duration: `${Date.now() - startTime}ms`
762
+ });
748
763
  return this.store.list;
749
764
  } catch (error) {
750
765
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -758,6 +773,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
758
773
  normalizeOrderForMemoryList(order, source = "normalizeOrderForMemoryList") {
759
774
  const normalizedOrder = this.normalizeOrderCollectionsForIngress(order, source);
760
775
  const externalSaleNumber = normalizedOrder == null ? void 0 : normalizedOrder.external_sale_number;
776
+ if (this.isDraftOrder(normalizedOrder) && !this.hasRealOrderId(normalizedOrder)) {
777
+ return normalizedOrder;
778
+ }
761
779
  if ((normalizedOrder == null ? void 0 : normalizedOrder.order_id) !== void 0 && (normalizedOrder == null ? void 0 : normalizedOrder.order_id) !== null && (normalizedOrder == null ? void 0 : normalizedOrder.order_id) !== "") {
762
780
  return normalizedOrder;
763
781
  }
@@ -769,6 +787,18 @@ var OrderModule = class extends import_BaseModule.BaseModule {
769
787
  order_id: externalSaleNumber
770
788
  };
771
789
  }
790
+ normalizeOrdersForMemoryList(orders, source) {
791
+ return orders.map((order) => this.normalizeOrderForMemoryList(order, source)).filter((order) => this.shouldKeepOrderInMemory(order));
792
+ }
793
+ hasRealOrderId(order) {
794
+ if (!order || this.isBlankIdentityValue(order.order_id))
795
+ return false;
796
+ const externalSaleNumber = order.external_sale_number;
797
+ return !(this.isDraftOrder(order) && !this.isBlankIdentityValue(externalSaleNumber) && String(order.order_id) === String(externalSaleNumber));
798
+ }
799
+ shouldKeepOrderInMemory(order) {
800
+ return !this.isDraftOrder(order) || this.hasRealOrderId(order);
801
+ }
772
802
  withoutSyntheticDraftOrderId(order) {
773
803
  const externalSaleNumber = order.external_sale_number;
774
804
  if (Number(order.is_draft_order || 0) !== 1 || order.order_id === void 0 || externalSaleNumber === void 0 || String(order.order_id) !== String(externalSaleNumber)) {
@@ -984,8 +1014,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
984
1014
  await this.emitOrdersChanged(patchedOrders, "upsertPendingSyncOrders");
985
1015
  }
986
1016
  /**
987
- * 将 POS 草稿订单按 SQLite storage key 合并进 store 并落库。
988
- * 草稿只表示本地可恢复快照,不进入同步队列。
1017
+ * 将 POS 草稿订单按 SQLite storage key 落库。
1018
+ * 只有具备真实 order_id 的草稿进入 store;其余草稿仅供本地恢复查询。
989
1019
  */
990
1020
  async upsertLocalDraftOrders(draftOrders) {
991
1021
  if (!(draftOrders == null ? void 0 : draftOrders.length)) {
@@ -1004,7 +1034,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1004
1034
  if (!storageKey)
1005
1035
  continue;
1006
1036
  draftMap.set(storageKey, draftOrder);
1007
- memoryDraftMap.set(storageKey, this.normalizeOrderForMemoryList(draftOrder));
1037
+ const memoryDraftOrder = this.normalizeOrderForMemoryList(draftOrder);
1038
+ if (this.shouldKeepOrderInMemory(memoryDraftOrder)) {
1039
+ memoryDraftMap.set(storageKey, memoryDraftOrder);
1040
+ }
1008
1041
  }
1009
1042
  if (draftMap.size === 0) {
1010
1043
  this.logError("upsertLocalDraftOrders-订单缺少可落库标识", {
@@ -1012,10 +1045,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1012
1045
  });
1013
1046
  return;
1014
1047
  }
1015
- this.logInfo("upsertLocalDraftOrders-开始", { count: draftMap.size });
1048
+ this.logInfo("upsertLocalDraftOrders-开始", {
1049
+ count: draftMap.size,
1050
+ memoryDraftCount: memoryDraftMap.size,
1051
+ sqliteOnlyDraftCount: draftMap.size - memoryDraftMap.size
1052
+ });
1016
1053
  const patchedOrders = [...draftMap.values()];
1017
1054
  const mergeActions = {};
1018
- const updatedList = [...this.store.list];
1055
+ const updatedList = this.store.list.filter((order) => this.shouldKeepOrderInMemory(order));
1019
1056
  const identityKeyToIndex = /* @__PURE__ */ new Map();
1020
1057
  for (let index = 0; index < updatedList.length; index += 1) {
1021
1058
  for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
@@ -1045,14 +1082,34 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1045
1082
  this.registerOrderIdentityKeys(identityKeyToIndex, draftOrder, insertIndex);
1046
1083
  mergeActions[storageKey] = "insert";
1047
1084
  }
1085
+ const previousList = this.store.list;
1048
1086
  this.store.list = this.runOrderStoreSelfCheck(updatedList, "upsertLocalDraftOrders.store");
1049
1087
  this.syncOrdersMap();
1050
- await this.patchOrdersInSQLite(patchedOrders, "upsertLocalDraftOrders", mergeActions);
1088
+ try {
1089
+ await this.patchOrdersInSQLite(
1090
+ patchedOrders,
1091
+ "upsertLocalDraftOrders",
1092
+ mergeActions,
1093
+ { throwOnError: true }
1094
+ );
1095
+ } catch (error) {
1096
+ this.store.list = previousList;
1097
+ this.syncOrdersMap();
1098
+ throw error;
1099
+ }
1051
1100
  this.logInfo("upsertLocalDraftOrders-结束", {
1052
1101
  count: patchedOrders.length,
1053
1102
  storeOrderCountAfter: this.store.list.length
1054
1103
  });
1055
- await this.emitOrdersChanged(patchedOrders, "upsertLocalDraftOrders");
1104
+ const removedLegacyMemoryDraft = previousList.some(
1105
+ (order) => !this.shouldKeepOrderInMemory(order)
1106
+ );
1107
+ if (memoryDraftMap.size > 0 || removedLegacyMemoryDraft) {
1108
+ await this.emitOrdersChanged(
1109
+ patchedOrders.filter((order) => this.shouldKeepOrderInMemory(order)),
1110
+ "upsertLocalDraftOrders"
1111
+ );
1112
+ }
1056
1113
  }
1057
1114
  /**
1058
1115
  * 通过 SSE 按自定义 query 拉取订单(支持 select/with 精简字段)
@@ -1086,6 +1143,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1086
1143
  super.destroy();
1087
1144
  }
1088
1145
  syncOrdersMap() {
1146
+ this.store.list = this.store.list.filter((order) => this.shouldKeepOrderInMemory(order));
1089
1147
  this.store.map.clear();
1090
1148
  for (const order of this.store.list) {
1091
1149
  const primaryIdentity = this.getOrderMapKey(order);
@@ -1924,6 +1982,26 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1924
1982
  is_draft_order: 0
1925
1983
  };
1926
1984
  }
1985
+ mergeRemoteIdentityIntoDraftOrder(draftOrder, remoteOrder) {
1986
+ const merged = {
1987
+ ...this.withoutSyntheticDraftOrderId(draftOrder)
1988
+ };
1989
+ const remote = remoteOrder;
1990
+ for (const field of [
1991
+ "order_id",
1992
+ "order_number",
1993
+ "shop_order_number",
1994
+ "shop_full_order_number"
1995
+ ]) {
1996
+ if (this.isBlankIdentityValue(merged[field]) && !this.isBlankIdentityValue(remote[field])) {
1997
+ merged[field] = remote[field];
1998
+ }
1999
+ }
2000
+ return this.normalizeOrderCollectionsForIngress(
2001
+ merged,
2002
+ "mergeRemoteIdentityIntoDraftOrder"
2003
+ );
2004
+ }
1927
2005
  mergeRemoteSnapshotWithPendingOrders(remoteOrders, existingOrders) {
1928
2006
  const merged = remoteOrders.map((order) => this.normalizeRemoteSyncedOrder(order));
1929
2007
  for (const rawOrder of existingOrders) {
@@ -1936,7 +2014,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1936
2014
  const matchIndex = this.findOrderIndexByIdentity(merged, order);
1937
2015
  if (matchIndex >= 0) {
1938
2016
  if (this.isDraftOrder(order)) {
1939
- merged[matchIndex] = order;
2017
+ merged[matchIndex] = this.mergeRemoteIdentityIntoDraftOrder(
2018
+ order,
2019
+ merged[matchIndex]
2020
+ );
1940
2021
  } else {
1941
2022
  merged[matchIndex] = this.mergeOrderRecords(order, merged[matchIndex]);
1942
2023
  }
@@ -2089,12 +2170,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2089
2170
  }
2090
2171
  }
2091
2172
  /**
2092
- * 全量快照替换 orders 表(clear + bulkAdd),用于 SSE 全量拉取与营业日窗口裁剪。
2173
+ * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync 订单。
2174
+ * 用于 SSE 全量拉取与营业日窗口裁剪。
2093
2175
  *
2094
2176
  * @example
2095
2177
  * await this.replaceOrdersSnapshotInSQLite(orderList)
2096
2178
  */
2097
- async replaceOrdersSnapshotInSQLite(orderList, source) {
2179
+ async replaceOrdersSnapshotInSQLite(orderList, source, protectedOrdersBeforeRemoteFetch = []) {
2098
2180
  if (!this.dbManager) {
2099
2181
  return this.compactOrderListByIdentity(
2100
2182
  orderList.map((order) => this.normalizeRemoteSyncedOrder(order)),
@@ -2111,15 +2193,42 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2111
2193
  try {
2112
2194
  await this.runInOrderSQLiteSaveQueue(async () => {
2113
2195
  const existingOrders = typeof this.dbManager.getAll === "function" ? await this.dbManager.getAll(INDEXDB_STORE_NAME) : [];
2196
+ const protectedLocalOrders = protectedOrdersBeforeRemoteFetch.map((order) => this.normalizeOrderCollectionsForIngress(
2197
+ order,
2198
+ `${source}.protectedBeforeRemoteFetch`
2199
+ )).filter((order) => this.isPendingSyncOrder(order) || this.isDraftOrder(order));
2200
+ for (const rawCurrentOrder of existingOrders || []) {
2201
+ const currentOrder = this.normalizeOrderCollectionsForIngress(
2202
+ rawCurrentOrder,
2203
+ `${source}.currentSQLite`
2204
+ );
2205
+ const protectedIndex = this.findOrderIndexByIdentity(
2206
+ protectedLocalOrders,
2207
+ currentOrder
2208
+ );
2209
+ const currentNeedsProtection = this.isPendingSyncOrder(currentOrder) || this.isDraftOrder(currentOrder);
2210
+ if (protectedIndex >= 0) {
2211
+ if (currentNeedsProtection) {
2212
+ protectedLocalOrders[protectedIndex] = currentOrder;
2213
+ } else {
2214
+ protectedLocalOrders.splice(protectedIndex, 1);
2215
+ }
2216
+ continue;
2217
+ }
2218
+ if (currentNeedsProtection)
2219
+ protectedLocalOrders.push(currentOrder);
2220
+ }
2114
2221
  const orderListSnapshot = this.mergeRemoteSnapshotWithPendingOrders(
2115
2222
  remoteSnapshot,
2116
- existingOrders || []
2223
+ protectedLocalOrders
2117
2224
  );
2118
2225
  mergedSnapshot = this.compactOrderListByIdentity(orderListSnapshot, `${source}.sqliteSnapshot`).list;
2119
2226
  this.logInfo("replaceOrdersSnapshotInSQLite-开始", {
2120
2227
  source,
2121
2228
  count: mergedSnapshot.length,
2122
2229
  remoteCount: remoteSnapshot.length,
2230
+ protectedBeforeRemoteFetchCount: protectedOrdersBeforeRemoteFetch.length,
2231
+ protectedLocalOrderCount: protectedLocalOrders.length,
2123
2232
  preservedLocalUnsyncedCount: mergedSnapshot.length - remoteSnapshot.length
2124
2233
  });
2125
2234
  await this.dbManager.clear(INDEXDB_STORE_NAME);
@@ -18,7 +18,8 @@ export declare class ProductsModule extends BaseModule implements Module {
18
18
  private productsPriceCache;
19
19
  private readonly CACHE_MAX_DAYS;
20
20
  private formatters;
21
- private isPriceFormatterRegistered;
21
+ private isBuiltinFormatterRegistered;
22
+ private isLegacyPriceFormatterEnabled;
22
23
  private quotationPriceBridge?;
23
24
  private quotationBridgeChannel?;
24
25
  private quotationBridgeLoadedKey?;
@@ -36,6 +37,8 @@ export declare class ProductsModule extends BaseModule implements Module {
36
37
  private lastPreloadCompletedAtMs;
37
38
  /** IndexDB 写入串行队列,避免快照与 patch 并发交错 */
38
39
  private productIndexDBSaveQueue;
40
+ /** 最近一次智能定价评估提取的 schedule 变价时间点(HH:mm),供 Server 订阅定时刷新使用 */
41
+ private lastScheduleTimePoints;
39
42
  constructor(name?: string, version?: string);
40
43
  initialize(core: PisellCore, options: any): Promise<void>;
41
44
  /**
@@ -108,6 +111,10 @@ export declare class ProductsModule extends BaseModule implements Module {
108
111
  */
109
112
  private prepareProductsWithPrice;
110
113
  private getProductsPriceCacheKey;
114
+ /**
115
+ * 稳定序列化策略上下文,避免对象 key 顺序不同导致缓存 key 抖动。
116
+ */
117
+ private stringifyStable;
111
118
  private normalizeProductIds;
112
119
  /**
113
120
  * 按轻量范围返回商品 ID,不做 structuredClone。
@@ -122,14 +129,26 @@ export declare class ProductsModule extends BaseModule implements Module {
122
129
  */
123
130
  private applyFormatters;
124
131
  /**
125
- * 注册内置的价格格式化器
126
- * 这个格式化器负责将价格数据应用到商品上
132
+ * 注册内置商品格式化器。
133
+ *
134
+ * 智能定价默认替代报价单逻辑;报价单 formatter 仅在 enableLegacyPriceFormatter=true 时启用。
127
135
  * @private
128
136
  */
129
- private registerBuiltinPriceFormatter;
137
+ private registerBuiltinProductFormatters;
138
+ /**
139
+ * 是否启用旧报价单价格 formatter。
140
+ *
141
+ * 默认关闭,避免报价单逻辑覆盖智能定价结果。
142
+ */
143
+ private shouldEnableLegacyPriceFormatter;
144
+ /**
145
+ * 返回最近一次 prepareProductsWithPrice / DataVariant 评估提取的变价时间点(HH:mm)。
146
+ * 供 OS Server 商品 query 订阅定时刷新使用。
147
+ */
148
+ getLastScheduleTimePoints(): string[];
130
149
  /**
131
150
  * 注册商品格式化器
132
- * 格式化器会按注册顺序依次执行(内置价格格式化器始终是第一个)
151
+ * 格式化器会按注册顺序依次执行;legacy 启用时先兜底报价,再由智能定价覆盖。
133
152
  * @param formatter 格式化函数
134
153
  * @param prepend 是否插入到队列开头(默认 false,追加到末尾)
135
154
  * @example
@@ -144,8 +163,8 @@ export declare class ProductsModule extends BaseModule implements Module {
144
163
  */
145
164
  registerFormatter(formatter: ProductFormatter, prepend?: boolean): void;
146
165
  /**
147
- * 清空所有格式化器(包括内置价格格式化器)
148
- * @param keepBuiltin 是否保留内置价格格式化器(默认 true)
166
+ * 清空所有格式化器(包括内置智能定价格式化器)
167
+ * @param keepBuiltin 是否保留内置智能定价格式化器(默认 true)
149
168
  */
150
169
  clearFormatters(keepBuiltin?: boolean): void;
151
170
  /**