@pisell/pisellos 2.3.31 → 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.
@@ -123,6 +123,9 @@ export declare class OrderModule extends BaseModule implements Module {
123
123
  */
124
124
  silentRefresh(): Promise<OrderData[]>;
125
125
  private normalizeOrderForMemoryList;
126
+ private normalizeOrdersForMemoryList;
127
+ private hasRealOrderId;
128
+ private shouldKeepOrderInMemory;
126
129
  private withoutSyntheticDraftOrderId;
127
130
  /**
128
131
  * 仅覆盖本地已存在的订单;不存在则直接跳过,不落库、不 emit。
@@ -151,8 +154,8 @@ export declare class OrderModule extends BaseModule implements Module {
151
154
  throwOnError?: boolean;
152
155
  }): Promise<void>;
153
156
  /**
154
- * 将 POS 草稿订单按 SQLite storage key 合并进 store 并落库。
155
- * 草稿只表示本地可恢复快照,不进入同步队列。
157
+ * 将 POS 草稿订单按 SQLite storage key 落库。
158
+ * 只有具备真实 order_id 的草稿进入 store;其余草稿仅供本地恢复查询。
156
159
  */
157
160
  upsertLocalDraftOrders(draftOrders: OrderData[]): Promise<void>;
158
161
  /**
@@ -276,6 +279,7 @@ export declare class OrderModule extends BaseModule implements Module {
276
279
  private isDraftOrder;
277
280
  private shouldProtectDraftOrderFromIncoming;
278
281
  private normalizeRemoteSyncedOrder;
282
+ private mergeRemoteIdentityIntoDraftOrder;
279
283
  private mergeRemoteSnapshotWithPendingOrders;
280
284
  /**
281
285
  * 串行执行订单 SQLite 写入任务,避免快照替换与增量 upsert 并发交错。
@@ -301,7 +305,8 @@ export declare class OrderModule extends BaseModule implements Module {
301
305
  */
302
306
  private updateOrderInSQLite;
303
307
  /**
304
- * 全量快照替换 orders 表(clear + bulkAdd),用于 SSE 全量拉取与营业日窗口裁剪。
308
+ * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync 订单。
309
+ * 用于 SSE 全量拉取与营业日窗口裁剪。
305
310
  *
306
311
  * @example
307
312
  * await this.replaceOrdersSnapshotInSQLite(orderList)
@@ -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);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.3.31",
4
+ "version": "2.3.32",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",