@pisell/pisellos 2.2.264 → 2.2.266

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 (126) 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/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +16 -10
  14. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -1
  15. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +1 -1
  16. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.js +32 -1
  17. package/dist/modules/Discount/index.d.ts +5 -2
  18. package/dist/modules/Discount/index.js +30 -7
  19. package/dist/modules/Discount/types.d.ts +4 -0
  20. package/dist/modules/Order/index.d.ts +41 -10
  21. package/dist/modules/Order/index.js +1379 -810
  22. package/dist/modules/Order/payment-utils.d.ts +26 -0
  23. package/dist/modules/Order/payment-utils.js +225 -0
  24. package/dist/modules/Order/types.d.ts +49 -1
  25. package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  26. package/dist/modules/Order/utils/orderCollectionIdentity.js +410 -0
  27. package/dist/modules/Order/utils.d.ts +4 -3
  28. package/dist/modules/Order/utils.js +61 -64
  29. package/dist/modules/Payment/index.d.ts +2 -0
  30. package/dist/modules/Payment/index.js +78 -49
  31. package/dist/modules/Payment/types.d.ts +26 -24
  32. package/dist/modules/Payment/types.js +2 -0
  33. package/dist/modules/Product/types.d.ts +22 -0
  34. package/dist/modules/ProductList/index.d.ts +1 -1
  35. package/dist/modules/ProductList/index.js +4 -2
  36. package/dist/modules/ProductList/types.d.ts +2 -0
  37. package/dist/modules/Rules/index.d.ts +2 -8
  38. package/dist/modules/Rules/index.js +55 -9
  39. package/dist/modules/Rules/types.d.ts +10 -1
  40. package/dist/server/index.d.ts +71 -0
  41. package/dist/server/index.js +2504 -1187
  42. package/dist/server/modules/order/index.d.ts +56 -5
  43. package/dist/server/modules/order/index.js +1718 -834
  44. package/dist/server/modules/order/types.d.ts +15 -3
  45. package/dist/server/modules/order/types.js +1 -1
  46. package/dist/server/modules/products/index.d.ts +31 -8
  47. package/dist/server/modules/products/index.js +549 -390
  48. package/dist/server/modules/products/types.d.ts +18 -0
  49. package/dist/solution/BaseSales/index.d.ts +67 -4
  50. package/dist/solution/BaseSales/index.js +1476 -792
  51. package/dist/solution/BaseSales/types.d.ts +6 -1
  52. package/dist/solution/BaseSales/types.js +1 -1
  53. package/dist/solution/BaseSales/utils/cartPromotion.js +19 -7
  54. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +9 -4
  55. package/dist/solution/BaseSales/utils/parseSalesResponse.js +6 -8
  56. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +14 -1
  57. package/dist/solution/BookingByStep/index.d.ts +1 -1
  58. package/dist/solution/BookingTicket/index.js +94 -54
  59. package/dist/solution/BookingTicket/types.d.ts +2 -0
  60. package/dist/solution/Sales/index.d.ts +1 -0
  61. package/dist/solution/Sales/index.js +10 -2
  62. package/dist/solution/ShopDiscount/index.js +15 -14
  63. package/dist/utils/payment-number.d.ts +9 -0
  64. package/dist/utils/payment-number.js +69 -0
  65. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
  66. package/lib/model/strategy/adapter/dataVariant/adapter.js +149 -0
  67. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
  68. package/lib/model/strategy/adapter/dataVariant/evaluator.js +583 -0
  69. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  70. package/lib/model/strategy/adapter/dataVariant/examples.js +293 -0
  71. package/lib/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  72. package/lib/model/strategy/adapter/dataVariant/index.js +38 -0
  73. package/lib/model/strategy/adapter/dataVariant/type.d.ts +148 -0
  74. package/lib/model/strategy/adapter/dataVariant/type.js +31 -0
  75. package/lib/model/strategy/adapter/index.d.ts +4 -0
  76. package/lib/model/strategy/adapter/index.js +13 -2
  77. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +5 -0
  78. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +1 -0
  79. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +1 -1
  80. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +23 -2
  81. package/lib/modules/Discount/index.d.ts +5 -2
  82. package/lib/modules/Discount/index.js +23 -3
  83. package/lib/modules/Discount/types.d.ts +4 -0
  84. package/lib/modules/Order/index.d.ts +41 -10
  85. package/lib/modules/Order/index.js +514 -122
  86. package/lib/modules/Order/payment-utils.d.ts +26 -0
  87. package/lib/modules/Order/payment-utils.js +224 -0
  88. package/lib/modules/Order/types.d.ts +49 -1
  89. package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  90. package/lib/modules/Order/utils/orderCollectionIdentity.js +418 -0
  91. package/lib/modules/Order/utils.d.ts +4 -3
  92. package/lib/modules/Order/utils.js +26 -20
  93. package/lib/modules/Payment/index.d.ts +2 -0
  94. package/lib/modules/Payment/index.js +33 -12
  95. package/lib/modules/Payment/types.d.ts +26 -24
  96. package/lib/modules/Product/types.d.ts +22 -0
  97. package/lib/modules/ProductList/index.d.ts +1 -1
  98. package/lib/modules/ProductList/index.js +4 -2
  99. package/lib/modules/ProductList/types.d.ts +2 -0
  100. package/lib/modules/Rules/index.d.ts +2 -8
  101. package/lib/modules/Rules/index.js +57 -6
  102. package/lib/modules/Rules/types.d.ts +10 -1
  103. package/lib/server/index.d.ts +71 -0
  104. package/lib/server/index.js +1002 -52
  105. package/lib/server/modules/order/index.d.ts +56 -5
  106. package/lib/server/modules/order/index.js +798 -148
  107. package/lib/server/modules/order/types.d.ts +15 -3
  108. package/lib/server/modules/products/index.d.ts +31 -8
  109. package/lib/server/modules/products/index.js +134 -35
  110. package/lib/server/modules/products/types.d.ts +18 -0
  111. package/lib/solution/BaseSales/index.d.ts +67 -4
  112. package/lib/solution/BaseSales/index.js +496 -50
  113. package/lib/solution/BaseSales/types.d.ts +6 -1
  114. package/lib/solution/BaseSales/utils/cartPromotion.js +13 -1
  115. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +9 -4
  116. package/lib/solution/BaseSales/utils/parseSalesResponse.js +4 -5
  117. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +8 -0
  118. package/lib/solution/BookingByStep/index.d.ts +1 -1
  119. package/lib/solution/BookingTicket/index.js +39 -11
  120. package/lib/solution/BookingTicket/types.d.ts +2 -0
  121. package/lib/solution/Sales/index.d.ts +1 -0
  122. package/lib/solution/Sales/index.js +5 -3
  123. package/lib/solution/ShopDiscount/index.js +2 -1
  124. package/lib/utils/payment-number.d.ts +9 -0
  125. package/lib/utils/payment-number.js +64 -0
  126. package/package.json +1 -1
@@ -35,7 +35,9 @@ module.exports = __toCommonJS(order_exports);
35
35
  var import_lodash_es = require("lodash-es");
36
36
  var import_dayjs = __toESM(require("dayjs"));
37
37
  var import_BaseModule = require("../../../modules/BaseModule");
38
+ var import_orderCollectionIdentity = require("../../../modules/Order/utils/orderCollectionIdentity");
38
39
  var import_types = require("./types");
40
+ var import_payment_utils = require("../../../modules/Order/payment-utils");
39
41
  var INDEXDB_STORE_NAME = "orders";
40
42
  var ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY = "server_order_last_full_fetch_at";
41
43
  var ORDER_SYNC_THROTTLE_MS_STORAGE_KEY = "order_sync_throttle_ms";
@@ -45,10 +47,19 @@ var ORDER_SILENT_REFRESH_MIN_INTERVAL_MS = 3e4;
45
47
  var ORDER_BUSINESS_WRITE_SOURCES = /* @__PURE__ */ new Set([
46
48
  "upsertOrdersFromRemote",
47
49
  "upsertPendingSyncOrders",
50
+ "upsertLocalDraftOrders",
48
51
  "overwriteExistingOrder",
49
- "markOrderSyncedByExternalSaleNumber"
52
+ "markOrderSyncedByExternalSaleNumber",
53
+ "updateLocalPayment"
50
54
  ]);
51
55
  var ORDER_MERGE_SELF_CHECK = false;
56
+ var PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER = "__pisell_os_pending_payment_without_unique_number__";
57
+ var ORDER_AUTHORITATIVE_COLLECTION_FIELDS = ["products", "bookings", "payments"];
58
+ var ORDER_COLLECTION_KIND_BY_FIELD = {
59
+ products: "product",
60
+ bookings: "booking",
61
+ payments: "payment"
62
+ };
52
63
  var OrderModule = class extends import_BaseModule.BaseModule {
53
64
  constructor(name, version) {
54
65
  super(name, version);
@@ -93,7 +104,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
93
104
  this.updateCreateStore();
94
105
  }
95
106
  if (Array.isArray((_a = options == null ? void 0 : options.initialState) == null ? void 0 : _a.list)) {
96
- this.store.list = options.initialState.list.map((order) => this.normalizeOrderForMemoryList(order));
107
+ this.store.list = this.normalizeOrdersForMemoryList(
108
+ options.initialState.list,
109
+ "initialState"
110
+ );
97
111
  this.syncOrdersMap();
98
112
  this.emitOrdersChanged([], "initialState");
99
113
  } else {
@@ -154,6 +168,131 @@ var OrderModule = class extends import_BaseModule.BaseModule {
154
168
  } catch {
155
169
  }
156
170
  }
171
+ /**
172
+ * 在订单进入内存或 SQLite 前统一压缩子项强身份重复并补齐协议 UID。
173
+ * 仅记录计数与订单标识,不输出商品、预约、支付或客户明细。
174
+ */
175
+ normalizeOrderCollectionsForIngress(order, source) {
176
+ const sourceOrder = (0, import_lodash_es.cloneDeep)(order);
177
+ const sourceOrderRecord = sourceOrder;
178
+ if (Array.isArray(sourceOrderRecord.payments)) {
179
+ sourceOrderRecord.payments = sourceOrderRecord.payments.map((payment) => {
180
+ if (!(0, import_payment_utils.isPendingOrderPayment)(payment) || (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => key.startsWith("unique_payment_number:"))) {
181
+ return payment;
182
+ }
183
+ return {
184
+ ...payment,
185
+ [PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER]: true
186
+ };
187
+ });
188
+ }
189
+ const result = (0, import_orderCollectionIdentity.normalizeOrderCollections)(sourceOrder);
190
+ const normalizedOrderRecord = result.order;
191
+ if (Array.isArray(normalizedOrderRecord.payments)) {
192
+ normalizedOrderRecord.payments = normalizedOrderRecord.payments.map(
193
+ (payment) => {
194
+ if (!(payment == null ? void 0 : payment[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER]))
195
+ return payment;
196
+ const nextPayment = { ...payment };
197
+ const metadata = { ...nextPayment.metadata || {} };
198
+ delete metadata.unique_payment_number;
199
+ delete nextPayment[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER];
200
+ nextPayment.metadata = metadata;
201
+ return nextPayment;
202
+ }
203
+ );
204
+ }
205
+ const kinds = ["product", "booking", "payment"];
206
+ const hasChanges = kinds.some((kind) => {
207
+ const stats = result.stats[kind];
208
+ return stats.backfilledUidCount > 0 || stats.collapsedDuplicateCount > 0 || stats.uidConflictCount > 0 || stats.anonymousRowCount > 0;
209
+ });
210
+ if (hasChanges) {
211
+ const summarize = (stats) => ({
212
+ backfilled_uid_count: stats.backfilledUidCount,
213
+ collapsed_duplicate_count: stats.collapsedDuplicateCount,
214
+ uid_conflict_count: stats.uidConflictCount,
215
+ anonymous_row_count: stats.anonymousRowCount
216
+ });
217
+ const context = {
218
+ source,
219
+ order_id: (order == null ? void 0 : order.order_id) ?? null,
220
+ external_sale_number: (order == null ? void 0 : order.external_sale_number) ?? null,
221
+ products: summarize(result.stats.product),
222
+ bookings: summarize(result.stats.booking),
223
+ payments: summarize(result.stats.payment)
224
+ };
225
+ const hasUnsafeIdentity = kinds.some((kind) => {
226
+ const stats = result.stats[kind];
227
+ return stats.uidConflictCount > 0 || stats.anonymousRowCount > 0;
228
+ });
229
+ if (hasUnsafeIdentity) {
230
+ this.logWarning("订单子项身份存在冲突或匿名行", context);
231
+ } else {
232
+ this.logInfo("订单子项身份已规范化", context);
233
+ }
234
+ }
235
+ return result.order;
236
+ }
237
+ /**
238
+ * incoming 决定权威成员集合;同一持久化行仍从 existing 补齐 incoming 省略的本地展示字段。
239
+ */
240
+ mergeAuthoritativeOrderCollection(field, existing, incoming, uidRemaps = [], options = {}) {
241
+ const kind = ORDER_COLLECTION_KIND_BY_FIELD[field];
242
+ const existingItems = Array.isArray(existing) ? existing : [];
243
+ if (field === "payments" && options.preserveIdentifiedPendingPayments) {
244
+ return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(
245
+ existingItems,
246
+ incoming,
247
+ { preserveUnmatchedExistingWhen: import_payment_utils.isIdentifiedPendingOrderPayment }
248
+ );
249
+ }
250
+ return incoming.map((incomingItem) => {
251
+ const existingItem = existingItems.find(
252
+ (item) => (0, import_orderCollectionIdentity.isSameOrderCollectionItem)(kind, item, incomingItem)
253
+ );
254
+ if (!existingItem)
255
+ return (0, import_lodash_es.cloneDeep)(incomingItem);
256
+ const mergedItem = (0, import_orderCollectionIdentity.mergeOrderCollectionItems)(kind, existingItem, incomingItem);
257
+ const mergedUid = (0, import_orderCollectionIdentity.getOrderCollectionUid)(kind, mergedItem);
258
+ if (mergedUid) {
259
+ for (const from of /* @__PURE__ */ new Set([
260
+ (0, import_orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, existingItem),
261
+ (0, import_orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, incomingItem)
262
+ ])) {
263
+ if (!from || from === mergedUid)
264
+ continue;
265
+ uidRemaps.push({
266
+ kind,
267
+ from,
268
+ to: mergedUid,
269
+ persistentId: (0, import_orderCollectionIdentity.getOrderCollectionPersistentId)(kind, incomingItem) || (0, import_orderCollectionIdentity.getOrderCollectionPersistentId)(kind, existingItem)
270
+ });
271
+ }
272
+ }
273
+ return mergedItem;
274
+ });
275
+ }
276
+ reconcileOverwriteOrderCollections(existing, incoming) {
277
+ const reconciled = (0, import_lodash_es.cloneDeep)(incoming);
278
+ const existingRecord = existing;
279
+ const incomingRecord = incoming;
280
+ const uidRemaps = [];
281
+ for (const field of ORDER_AUTHORITATIVE_COLLECTION_FIELDS) {
282
+ if (!Array.isArray(incomingRecord[field]))
283
+ continue;
284
+ reconciled[field] = this.mergeAuthoritativeOrderCollection(
285
+ field,
286
+ existingRecord[field],
287
+ incomingRecord[field],
288
+ uidRemaps
289
+ );
290
+ }
291
+ return this.normalizeOrderCollectionsForIngress(
292
+ (0, import_orderCollectionIdentity.applyOrderCollectionUidRemaps)(reconciled, uidRemaps),
293
+ "overwriteExistingOrder.reconciled"
294
+ );
295
+ }
157
296
  /**
158
297
  * 记录订单最近一次 SQLite 写入,供 pubsub 回声去重使用。
159
298
  *
@@ -363,17 +502,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
363
502
  return DEFAULT_ORDER_SYNC_THROTTLE_MS;
364
503
  }
365
504
  async preload() {
366
- const getData = async () => {
367
- const orders = await this.loadOrdersByServer();
368
- if (orders.length === 0) {
369
- return;
370
- }
371
- this.store.list = (0, import_lodash_es.cloneDeep)(orders);
372
- this.syncOrdersMap();
373
- this.emitOrdersChanged([], "preload");
374
- this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
375
- };
376
- getData();
505
+ const orders = await this.loadOrdersByServer();
506
+ this.store.list = (0, import_lodash_es.cloneDeep)(orders);
507
+ this.syncOrdersMap();
508
+ await this.emitOrdersChanged([], "preload");
509
+ await this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
377
510
  }
378
511
  getOrders() {
379
512
  return this.store.list;
@@ -385,6 +518,27 @@ var OrderModule = class extends import_BaseModule.BaseModule {
385
518
  getOrderByOrderId(orderId) {
386
519
  return this.store.map.get(this.getIdKey(orderId));
387
520
  }
521
+ buildLocalPaymentOrderLogContext(order) {
522
+ if (!order)
523
+ return {};
524
+ return {
525
+ order_id: order.order_id ?? null,
526
+ external_sale_number: order.external_sale_number ?? null,
527
+ order_number: order.order_number ?? null,
528
+ shop_order_number: order.shop_order_number ?? null,
529
+ shop_full_order_number: order.shop_full_order_number ?? null,
530
+ order_status: order.status ?? null,
531
+ payment_status: order.payment_status ?? null,
532
+ is_draft_order: Number(order.is_draft_order || 0),
533
+ need_sync: Number(order.need_sync || 0),
534
+ platform: order.platform ?? null,
535
+ business_code: order.business_code ?? null,
536
+ order_sales_channel: order.order_sales_channel ?? null,
537
+ sales_channel: order.sales_channel ?? null,
538
+ order_type: order.type ?? null,
539
+ payments_count: Array.isArray(order.payments) ? order.payments.length : 0
540
+ };
541
+ }
388
542
  getLocalOrderFromMemoryByLookup(lookup) {
389
543
  const key = this.getIdKey(lookup);
390
544
  const memoryOrderById = this.store.map.get(key);
@@ -393,28 +547,200 @@ var OrderModule = class extends import_BaseModule.BaseModule {
393
547
  const memoryOrder = this.store.list.find((order) => this.isOrderLookupMatch(order, key));
394
548
  return memoryOrder || null;
395
549
  }
396
- async getLocalOrderByLookup(lookup) {
550
+ async getLocalOrderByLookup(lookup, options = {}) {
397
551
  const key = this.getIdKey(lookup);
552
+ const logContext = {
553
+ operation_id: options.operationId,
554
+ lookup: key,
555
+ memory_order_count: this.store.list.length
556
+ };
557
+ if (options.operationId) {
558
+ this.logInfo("getLocalOrderByLookup-localPayment-开始", logContext);
559
+ }
398
560
  const memoryOrderById = this.store.map.get(key);
399
- if (memoryOrderById)
561
+ if (memoryOrderById) {
562
+ if (options.operationId) {
563
+ this.logInfo("getLocalOrderByLookup-localPayment-命中内存映射", {
564
+ ...logContext,
565
+ ...this.buildLocalPaymentOrderLogContext(memoryOrderById)
566
+ });
567
+ }
400
568
  return memoryOrderById;
569
+ }
401
570
  const memoryOrder = this.store.list.find((order) => this.isOrderLookupMatch(order, key));
402
- if (memoryOrder)
571
+ if (memoryOrder) {
572
+ if (options.operationId) {
573
+ this.logInfo("getLocalOrderByLookup-localPayment-命中内存列表", {
574
+ ...logContext,
575
+ ...this.buildLocalPaymentOrderLogContext(memoryOrder)
576
+ });
577
+ }
403
578
  return memoryOrder;
579
+ }
580
+ if (options.operationId) {
581
+ this.logInfo("getLocalOrderByLookup-localPayment-开始读取SQLite", logContext);
582
+ }
404
583
  const orders = await this.loadOrdersFromSQLite();
405
584
  const localOrder = orders.find((order) => this.isOrderLookupMatch(order, key));
406
- if (!localOrder)
585
+ if (!localOrder) {
586
+ if (options.operationId) {
587
+ this.logWarning("getLocalOrderByLookup-localPayment-SQLite未命中", {
588
+ ...logContext,
589
+ sqlite_order_count: orders.length
590
+ });
591
+ }
407
592
  return null;
408
- this.store.list = orders.map((order) => this.normalizeOrderForMemoryList(order));
593
+ }
594
+ this.store.list = this.normalizeOrdersForMemoryList(
595
+ orders,
596
+ "getLocalOrderByLookup.sqliteMemory"
597
+ );
409
598
  this.syncOrdersMap();
410
- return this.normalizeOrderForMemoryList(localOrder);
599
+ const normalizedOrder = this.normalizeOrderForMemoryList(localOrder);
600
+ if (options.operationId) {
601
+ this.logInfo("getLocalOrderByLookup-localPayment-SQLite命中", {
602
+ ...logContext,
603
+ sqlite_order_count: orders.length,
604
+ ...this.buildLocalPaymentOrderLogContext(normalizedOrder)
605
+ });
606
+ }
607
+ return normalizedOrder;
608
+ }
609
+ async getLocalPayment(params) {
610
+ const logContext = {
611
+ operation_id: params.operationId,
612
+ sale_id: params.saleId,
613
+ payment_number: params.paymentNumber
614
+ };
615
+ this.logInfo("getLocalPayment-开始", logContext);
616
+ try {
617
+ const order = await this.getLocalOrderByLookup(params.saleId, {
618
+ operationId: params.operationId
619
+ });
620
+ if (!order) {
621
+ this.logWarning("getLocalPayment-订单未命中", logContext);
622
+ return null;
623
+ }
624
+ const payments = order.payments || [];
625
+ const match = (0, import_payment_utils.resolveOrderPaymentIdentity)(
626
+ payments,
627
+ params.paymentNumber,
628
+ "compat"
629
+ );
630
+ if (!match) {
631
+ this.logWarning("getLocalPayment-支付项未命中", {
632
+ ...logContext,
633
+ ...this.buildLocalPaymentOrderLogContext(order),
634
+ payments
635
+ });
636
+ return null;
637
+ }
638
+ this.logInfo("getLocalPayment-支付项命中", {
639
+ ...logContext,
640
+ ...this.buildLocalPaymentOrderLogContext(order),
641
+ matched_by: match.matchedBy,
642
+ payment_index: match.index,
643
+ payment: match.payment
644
+ });
645
+ return {
646
+ order,
647
+ payment: match.payment,
648
+ paymentIndex: match.index,
649
+ matchedBy: match.matchedBy
650
+ };
651
+ } catch (error) {
652
+ this.logError("getLocalPayment-查询失败", {
653
+ ...logContext,
654
+ error: error instanceof Error ? error.message : String(error)
655
+ });
656
+ throw error;
657
+ }
658
+ }
659
+ async updateLocalPayment(params) {
660
+ const logContext = {
661
+ operation_id: params.operationId,
662
+ sale_id: params.saleId,
663
+ payment_number: params.paymentNumber,
664
+ incoming_payment_update: params.updates
665
+ };
666
+ this.logInfo("updateLocalPayment-开始", logContext);
667
+ const found = await this.getLocalPayment(params);
668
+ if (!found) {
669
+ this.logWarning("updateLocalPayment-支付项未命中", logContext);
670
+ return null;
671
+ }
672
+ const previousPayment = (0, import_lodash_es.cloneDeep)(found.payment);
673
+ const nextPayment = (0, import_payment_utils.mergeOrderPaymentRecord)(found.payment, {
674
+ ...params.updates,
675
+ updated_at: params.updates.updated_at || (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
676
+ });
677
+ const nextOrder = {
678
+ ...found.order,
679
+ payments: (found.order.payments || []).map((payment, index) => index === found.paymentIndex ? nextPayment : payment),
680
+ updated_at: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
681
+ };
682
+ const paymentContext = {
683
+ ...logContext,
684
+ matched_by: found.matchedBy,
685
+ payment_index: found.paymentIndex,
686
+ ...this.buildLocalPaymentOrderLogContext(nextOrder),
687
+ previous_payment: previousPayment,
688
+ payment: nextPayment
689
+ };
690
+ this.logInfo("updateLocalPayment-支付项合并完成", paymentContext);
691
+ const targetIndex = this.findOrderIndexByIdentity(this.store.list, found.order);
692
+ const shouldKeepInMemory = this.shouldKeepOrderInMemory(nextOrder);
693
+ if (targetIndex < 0 && shouldKeepInMemory) {
694
+ this.logError("updateLocalPayment-订单Store索引未命中", paymentContext);
695
+ return null;
696
+ }
697
+ const previousList = this.store.list;
698
+ this.store.list = shouldKeepInMemory ? this.store.list.map((order, index) => index === targetIndex ? nextOrder : order) : this.store.list.filter((_, index) => index !== targetIndex);
699
+ this.syncOrdersMap();
700
+ const storageOrder = this.withoutSyntheticDraftOrderId(nextOrder);
701
+ try {
702
+ this.logInfo("updateLocalPayment-SQLite写入开始", {
703
+ ...paymentContext,
704
+ storage_order_id: storageOrder.order_id ?? null
705
+ });
706
+ await this.updateOrderInSQLite(storageOrder, "updateLocalPayment", { throwOnError: true });
707
+ this.logInfo("updateLocalPayment-SQLite写入完成", {
708
+ ...paymentContext,
709
+ storage_order_id: storageOrder.order_id ?? null
710
+ });
711
+ } catch (error) {
712
+ this.store.list = previousList;
713
+ this.syncOrdersMap();
714
+ this.logError("updateLocalPayment-SQLite写入失败并回滚内存", {
715
+ ...paymentContext,
716
+ storage_order_id: storageOrder.order_id ?? null,
717
+ error: error instanceof Error ? error.message : String(error)
718
+ });
719
+ throw error;
720
+ }
721
+ if (shouldKeepInMemory || targetIndex >= 0) {
722
+ await this.emitOrdersChanged(
723
+ shouldKeepInMemory ? [nextOrder] : [],
724
+ shouldKeepInMemory ? "updateLocalPayment" : "updateLocalPayment.sqliteOnlyDraft"
725
+ );
726
+ }
727
+ this.logInfo("updateLocalPayment-变更事件完成", paymentContext);
728
+ return { order: nextOrder, payment: nextPayment, previousPayment };
411
729
  }
412
730
  async loadOrdersByServer() {
413
731
  var _a;
414
732
  let orderList = [];
733
+ const protectedOrdersBeforeRemoteFetch = (await this.loadOrdersFromSQLite()).filter(
734
+ (order) => this.shouldProtectLocalOrderFromRemoteSnapshot(order)
735
+ );
415
736
  this.logInfo("loadOrdersByServer-开始", {
416
737
  hasOrderDataSource: !!this.orderDataSource,
417
- query: ((_a = this.store) == null ? void 0 : _a.createdAtQuery) || null
738
+ query: ((_a = this.store) == null ? void 0 : _a.createdAtQuery) || null,
739
+ protectedLocalOrderCount: protectedOrdersBeforeRemoteFetch.length,
740
+ protectedPendingPaymentCount: protectedOrdersBeforeRemoteFetch.reduce(
741
+ (count, order) => count + this.getIdentifiedPendingPayments(order).length,
742
+ 0
743
+ )
418
744
  });
419
745
  if (this.orderDataSource) {
420
746
  try {
@@ -434,10 +760,19 @@ var OrderModule = class extends import_BaseModule.BaseModule {
434
760
  return this.store.list;
435
761
  }
436
762
  }
437
- const mergedOrders = await this.replaceOrdersSnapshotInSQLite(orderList, "loadOrdersByServer");
438
- const memoryOrders = mergedOrders.map((order) => this.normalizeOrderForMemoryList(order));
763
+ const mergedOrders = await this.replaceOrdersSnapshotInSQLite(
764
+ orderList,
765
+ "loadOrdersByServer",
766
+ protectedOrdersBeforeRemoteFetch
767
+ );
768
+ const memoryOrders = this.normalizeOrdersForMemoryList(
769
+ mergedOrders,
770
+ "loadOrdersByServer.memory"
771
+ );
439
772
  this.logInfo("loadOrdersByServer-结束", {
440
- count: memoryOrders.length
773
+ count: memoryOrders.length,
774
+ persistedCount: mergedOrders.length,
775
+ sqliteOnlyDraftCount: mergedOrders.length - memoryOrders.length
441
776
  });
442
777
  await this.core.effects.emit(import_types.OrderHooks.onOrdersLoaded, memoryOrders);
443
778
  return memoryOrders;
@@ -457,18 +792,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
457
792
  try {
458
793
  this.updateCreateStore();
459
794
  const orders = await this.loadOrdersByServer();
460
- if (orders.length > 0) {
461
- this.store.list = (0, import_lodash_es.cloneDeep)(orders);
462
- this.syncOrdersMap();
463
- this.emitOrdersChanged([], "silentRefresh");
464
- await this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
465
- this.logInfo("silentRefresh 完成", {
466
- orderCount: orders.length,
467
- duration: `${Date.now() - startTime}ms`
468
- });
469
- } else {
470
- this.logInfo("silentRefresh: 服务器未返回数据");
471
- }
795
+ this.store.list = (0, import_lodash_es.cloneDeep)(orders);
796
+ this.syncOrdersMap();
797
+ await this.emitOrdersChanged([], "silentRefresh");
798
+ await this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
799
+ this.logInfo("silentRefresh 完成", {
800
+ orderCount: orders.length,
801
+ duration: `${Date.now() - startTime}ms`
802
+ });
472
803
  return this.store.list;
473
804
  } catch (error) {
474
805
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -479,19 +810,44 @@ var OrderModule = class extends import_BaseModule.BaseModule {
479
810
  return this.store.list;
480
811
  }
481
812
  }
482
- normalizeOrderForMemoryList(order) {
483
- const externalSaleNumber = order == null ? void 0 : order.external_sale_number;
484
- if ((order == null ? void 0 : order.order_id) !== void 0 && (order == null ? void 0 : order.order_id) !== null && (order == null ? void 0 : order.order_id) !== "") {
485
- return order;
813
+ normalizeOrderForMemoryList(order, source = "normalizeOrderForMemoryList") {
814
+ const normalizedOrder = this.normalizeOrderCollectionsForIngress(order, source);
815
+ const externalSaleNumber = normalizedOrder == null ? void 0 : normalizedOrder.external_sale_number;
816
+ if (this.isDraftOrder(normalizedOrder) && !this.hasRealOrderId(normalizedOrder)) {
817
+ return normalizedOrder;
818
+ }
819
+ 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) !== "") {
820
+ return normalizedOrder;
486
821
  }
487
822
  if (externalSaleNumber === void 0 || externalSaleNumber === null || externalSaleNumber === "") {
488
- return order;
823
+ return normalizedOrder;
489
824
  }
490
825
  return {
491
- ...order,
826
+ ...normalizedOrder,
492
827
  order_id: externalSaleNumber
493
828
  };
494
829
  }
830
+ normalizeOrdersForMemoryList(orders, source) {
831
+ return orders.map((order) => this.normalizeOrderForMemoryList(order, source)).filter((order) => this.shouldKeepOrderInMemory(order));
832
+ }
833
+ hasRealOrderId(order) {
834
+ if (!order || this.isBlankIdentityValue(order.order_id))
835
+ return false;
836
+ const externalSaleNumber = order.external_sale_number;
837
+ return !(this.isDraftOrder(order) && !this.isBlankIdentityValue(externalSaleNumber) && String(order.order_id) === String(externalSaleNumber));
838
+ }
839
+ shouldKeepOrderInMemory(order) {
840
+ return !this.isDraftOrder(order) || this.hasRealOrderId(order);
841
+ }
842
+ withoutSyntheticDraftOrderId(order) {
843
+ const externalSaleNumber = order.external_sale_number;
844
+ if (Number(order.is_draft_order || 0) !== 1 || order.order_id === void 0 || externalSaleNumber === void 0 || String(order.order_id) !== String(externalSaleNumber)) {
845
+ return order;
846
+ }
847
+ const next = { ...order };
848
+ delete next.order_id;
849
+ return next;
850
+ }
495
851
  /**
496
852
  * 仅覆盖本地已存在的订单;不存在则直接跳过,不落库、不 emit。
497
853
  * 适用于"按 order_id 主动刷新本地订单详情"的代理场景。
@@ -511,32 +867,42 @@ var OrderModule = class extends import_BaseModule.BaseModule {
511
867
  orderId,
512
868
  storeOrderCountBefore: this.store.list.length
513
869
  });
870
+ const normalizedFresh = this.normalizeOrderForMemoryList(
871
+ fresh,
872
+ "overwriteExistingOrder.incoming"
873
+ );
874
+ const existingOrder = this.store.map.get(key);
875
+ const reconciledFresh = this.reconcileOverwriteOrderCollections(
876
+ existingOrder,
877
+ normalizedFresh
878
+ );
514
879
  this.store.list = this.store.list.map((order) => {
515
880
  const id = order == null ? void 0 : order.order_id;
516
- if (id === void 0 || id === null)
517
- return order;
518
- return this.getIdKey(id) === key ? fresh : order;
881
+ if (id === void 0 || id === null) {
882
+ return this.normalizeOrderForMemoryList(order, "overwriteExistingOrder.existingMemory");
883
+ }
884
+ return this.getIdKey(id) === key ? reconciledFresh : this.normalizeOrderForMemoryList(order, "overwriteExistingOrder.existingMemory");
519
885
  });
520
886
  this.syncOrdersMap();
521
- await this.updateOrderInSQLite(fresh, "overwriteExistingOrder");
887
+ await this.updateOrderInSQLite(reconciledFresh, "overwriteExistingOrder");
522
888
  this.logInfo("overwriteExistingOrder-结束", {
523
889
  orderId,
524
890
  storeOrderCountAfter: this.store.list.length
525
891
  });
526
- await this.emitOrdersChanged([fresh], "overwriteExistingOrder");
892
+ await this.emitOrdersChanged([reconciledFresh], "overwriteExistingOrder");
527
893
  return { overwritten: true };
528
894
  }
529
895
  /**
530
896
  * 将远端拉取的订单合并进本地 store(已存在则更新,不存在则追加),落库并 emit onOrdersChanged。
531
897
  * 供 /update/localOrder 等在「本地尚无该单」时写入新建单。
532
898
  */
533
- async upsertOrdersFromRemote(freshOrders) {
899
+ async upsertOrdersFromRemote(freshOrders, source = "upsertOrdersFromRemote") {
534
900
  if (!(freshOrders == null ? void 0 : freshOrders.length)) {
535
901
  this.logInfo("upsertOrdersFromRemote-订单列表为空", {});
536
902
  return;
537
903
  }
538
- this.logInfo("upsertOrdersFromRemote-开始", { count: freshOrders.length });
539
- await this.mergeOrdersToStore(freshOrders, "upsertOrdersFromRemote");
904
+ this.logInfo("upsertOrdersFromRemote-开始", { count: freshOrders.length, source });
905
+ await this.mergeOrdersToStore(freshOrders, source);
540
906
  }
541
907
  async markOrderSyncedByExternalSaleNumber(params) {
542
908
  const externalSaleNumber = params.externalSaleNumber;
@@ -562,7 +928,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
562
928
  ...existing,
563
929
  ...params.patch || {},
564
930
  external_sale_number: existing.external_sale_number ?? externalSaleNumber,
565
- need_sync: 0
931
+ need_sync: 0,
932
+ is_draft_order: 0
566
933
  });
567
934
  const storageKey = this.getOrderStorageKey(nextOrder) || key;
568
935
  this.store.list = this.store.list.map((order, index) => {
@@ -587,7 +954,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
587
954
  * 将本地待同步订单按 SQLite storage key 合并进 store 并落库。
588
955
  * checkout 离线兜底可能没有 order_id,但通常会有 external_sale_number。
589
956
  */
590
- async upsertPendingSyncOrders(pendingOrders) {
957
+ async upsertPendingSyncOrders(pendingOrders, options = {}) {
591
958
  if (!(pendingOrders == null ? void 0 : pendingOrders.length)) {
592
959
  this.logInfo("upsertPendingSyncOrders-订单列表为空", {});
593
960
  return;
@@ -595,11 +962,26 @@ var OrderModule = class extends import_BaseModule.BaseModule {
595
962
  const pendingMap = /* @__PURE__ */ new Map();
596
963
  const memoryPendingMap = /* @__PURE__ */ new Map();
597
964
  for (const order of pendingOrders) {
598
- const storageKey = this.getOrderStorageKey(order);
965
+ const normalizedOrder = this.normalizeOrderCollectionsForIngress(
966
+ order,
967
+ "upsertPendingSyncOrders.incoming"
968
+ );
969
+ const pendingOrder = {
970
+ ...normalizedOrder,
971
+ need_sync: 1,
972
+ is_draft_order: 0
973
+ };
974
+ const storageKey = this.getOrderStorageKey(pendingOrder);
599
975
  if (!storageKey)
600
976
  continue;
601
- pendingMap.set(storageKey, order);
602
- memoryPendingMap.set(storageKey, this.normalizeOrderForMemoryList(order));
977
+ pendingMap.set(storageKey, pendingOrder);
978
+ memoryPendingMap.set(
979
+ storageKey,
980
+ this.normalizeOrderForMemoryList(
981
+ pendingOrder,
982
+ "upsertPendingSyncOrders.memory"
983
+ )
984
+ );
603
985
  }
604
986
  if (pendingMap.size === 0) {
605
987
  this.logError("upsertPendingSyncOrders-订单缺少可落库标识", {
@@ -608,9 +990,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
608
990
  return;
609
991
  }
610
992
  this.logInfo("upsertPendingSyncOrders-开始", { count: pendingMap.size });
611
- const patchedOrders = [...pendingMap.values()];
612
993
  const mergeActions = {};
613
- const updatedList = [...this.store.list];
994
+ const updatedList = this.store.list.map(
995
+ (order) => this.normalizeOrderForMemoryList(order, "upsertPendingSyncOrders.existingMemory")
996
+ );
614
997
  const identityKeyToIndex = /* @__PURE__ */ new Map();
615
998
  for (let index = 0; index < updatedList.length; index += 1) {
616
999
  for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
@@ -624,11 +1007,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
624
1007
  this.getOrderIdentityMatchKeys(pendingOrder)
625
1008
  );
626
1009
  if (matchIndex >= 0) {
627
- const mergedOrder = this.mergeOrderRecords(updatedList[matchIndex], pendingOrder, {
628
- preferIncomingProducts: true
629
- });
630
- updatedList[matchIndex] = mergedOrder;
631
- this.registerOrderIdentityKeys(identityKeyToIndex, mergedOrder, matchIndex);
1010
+ const existingOrder = updatedList[matchIndex];
1011
+ const mergedOrder = this.mergeOrderRecords(existingOrder, pendingOrder);
1012
+ const nextOrder = {
1013
+ ...mergedOrder,
1014
+ need_sync: 1,
1015
+ is_draft_order: 0
1016
+ };
1017
+ updatedList[matchIndex] = nextOrder;
1018
+ const pendingSnapshot = pendingMap.get(storageKey);
1019
+ if (pendingSnapshot) {
1020
+ pendingMap.set(
1021
+ storageKey,
1022
+ this.reconcileOverwriteOrderCollections(existingOrder, pendingSnapshot)
1023
+ );
1024
+ }
1025
+ this.registerOrderIdentityKeys(identityKeyToIndex, nextOrder, matchIndex);
632
1026
  mergeActions[storageKey] = "update";
633
1027
  continue;
634
1028
  }
@@ -637,15 +1031,126 @@ var OrderModule = class extends import_BaseModule.BaseModule {
637
1031
  this.registerOrderIdentityKeys(identityKeyToIndex, pendingOrder, insertIndex);
638
1032
  mergeActions[storageKey] = "insert";
639
1033
  }
1034
+ const patchedOrders = [...pendingMap.values()];
1035
+ const previousList = this.store.list;
640
1036
  this.store.list = this.runOrderStoreSelfCheck(updatedList, "upsertPendingSyncOrders.store");
641
1037
  this.syncOrdersMap();
642
- await this.patchOrdersInSQLite(patchedOrders, "upsertPendingSyncOrders", mergeActions);
1038
+ try {
1039
+ await this.patchOrdersInSQLite(
1040
+ patchedOrders,
1041
+ "upsertPendingSyncOrders",
1042
+ mergeActions,
1043
+ options
1044
+ );
1045
+ } catch (error) {
1046
+ this.store.list = previousList;
1047
+ this.syncOrdersMap();
1048
+ throw error;
1049
+ }
643
1050
  this.logInfo("upsertPendingSyncOrders-结束", {
644
1051
  count: patchedOrders.length,
645
1052
  storeOrderCountAfter: this.store.list.length
646
1053
  });
647
1054
  await this.emitOrdersChanged(patchedOrders, "upsertPendingSyncOrders");
648
1055
  }
1056
+ /**
1057
+ * 将 POS 草稿订单按 SQLite storage key 落库。
1058
+ * 只有具备真实 order_id 的草稿进入 store;其余草稿仅供本地恢复查询。
1059
+ */
1060
+ async upsertLocalDraftOrders(draftOrders) {
1061
+ if (!(draftOrders == null ? void 0 : draftOrders.length)) {
1062
+ this.logInfo("upsertLocalDraftOrders-订单列表为空", {});
1063
+ return;
1064
+ }
1065
+ const draftMap = /* @__PURE__ */ new Map();
1066
+ const memoryDraftMap = /* @__PURE__ */ new Map();
1067
+ for (const order of draftOrders) {
1068
+ const draftOrder = {
1069
+ ...order,
1070
+ need_sync: 0,
1071
+ is_draft_order: 1
1072
+ };
1073
+ const storageKey = this.getOrderStorageKey(draftOrder);
1074
+ if (!storageKey)
1075
+ continue;
1076
+ draftMap.set(storageKey, draftOrder);
1077
+ const memoryDraftOrder = this.normalizeOrderForMemoryList(draftOrder);
1078
+ if (this.shouldKeepOrderInMemory(memoryDraftOrder)) {
1079
+ memoryDraftMap.set(storageKey, memoryDraftOrder);
1080
+ }
1081
+ }
1082
+ if (draftMap.size === 0) {
1083
+ this.logError("upsertLocalDraftOrders-订单缺少可落库标识", {
1084
+ count: draftOrders.length
1085
+ });
1086
+ return;
1087
+ }
1088
+ this.logInfo("upsertLocalDraftOrders-开始", {
1089
+ count: draftMap.size,
1090
+ memoryDraftCount: memoryDraftMap.size,
1091
+ sqliteOnlyDraftCount: draftMap.size - memoryDraftMap.size
1092
+ });
1093
+ const patchedOrders = [...draftMap.values()];
1094
+ const mergeActions = {};
1095
+ const updatedList = this.store.list.filter((order) => this.shouldKeepOrderInMemory(order));
1096
+ const identityKeyToIndex = /* @__PURE__ */ new Map();
1097
+ for (let index = 0; index < updatedList.length; index += 1) {
1098
+ for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
1099
+ if (!identityKeyToIndex.has(key))
1100
+ identityKeyToIndex.set(key, index);
1101
+ }
1102
+ }
1103
+ for (const [storageKey, draftOrder] of memoryDraftMap.entries()) {
1104
+ const matchIndex = this.lookupOrderIndexByIdentityKeys(
1105
+ identityKeyToIndex,
1106
+ this.getOrderIdentityMatchKeys(draftOrder)
1107
+ );
1108
+ if (matchIndex >= 0) {
1109
+ const mergedOrder = this.mergeOrderRecords(updatedList[matchIndex], draftOrder);
1110
+ const nextOrder = {
1111
+ ...mergedOrder,
1112
+ need_sync: 0,
1113
+ is_draft_order: 1
1114
+ };
1115
+ updatedList[matchIndex] = nextOrder;
1116
+ this.registerOrderIdentityKeys(identityKeyToIndex, nextOrder, matchIndex);
1117
+ mergeActions[storageKey] = "update";
1118
+ continue;
1119
+ }
1120
+ const insertIndex = updatedList.length;
1121
+ updatedList.push(draftOrder);
1122
+ this.registerOrderIdentityKeys(identityKeyToIndex, draftOrder, insertIndex);
1123
+ mergeActions[storageKey] = "insert";
1124
+ }
1125
+ const previousList = this.store.list;
1126
+ this.store.list = this.runOrderStoreSelfCheck(updatedList, "upsertLocalDraftOrders.store");
1127
+ this.syncOrdersMap();
1128
+ try {
1129
+ await this.patchOrdersInSQLite(
1130
+ patchedOrders,
1131
+ "upsertLocalDraftOrders",
1132
+ mergeActions,
1133
+ { throwOnError: true }
1134
+ );
1135
+ } catch (error) {
1136
+ this.store.list = previousList;
1137
+ this.syncOrdersMap();
1138
+ throw error;
1139
+ }
1140
+ this.logInfo("upsertLocalDraftOrders-结束", {
1141
+ count: patchedOrders.length,
1142
+ storeOrderCountAfter: this.store.list.length
1143
+ });
1144
+ const removedLegacyMemoryDraft = previousList.some(
1145
+ (order) => !this.shouldKeepOrderInMemory(order)
1146
+ );
1147
+ if (memoryDraftMap.size > 0 || removedLegacyMemoryDraft) {
1148
+ await this.emitOrdersChanged(
1149
+ patchedOrders.filter((order) => this.shouldKeepOrderInMemory(order)),
1150
+ "upsertLocalDraftOrders"
1151
+ );
1152
+ }
1153
+ }
649
1154
  /**
650
1155
  * 通过 SSE 按自定义 query 拉取订单(支持 select/with 精简字段)
651
1156
  */
@@ -678,6 +1183,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
678
1183
  super.destroy();
679
1184
  }
680
1185
  syncOrdersMap() {
1186
+ this.store.list = this.store.list.filter((order) => this.shouldKeepOrderInMemory(order));
681
1187
  this.store.map.clear();
682
1188
  for (const order of this.store.list) {
683
1189
  const primaryIdentity = this.getOrderMapKey(order);
@@ -969,7 +1475,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
969
1475
  const uniqueFreshCount = uniqueFreshOrders.length;
970
1476
  const patchedOrders = [];
971
1477
  const mergeActions = {};
972
- const updatedList = [...this.store.list];
1478
+ const updatedList = this.store.list.map(
1479
+ (order) => this.normalizeOrderForMemoryList(order, `${source}.existingMemory`)
1480
+ );
973
1481
  const identityKeyToIndex = /* @__PURE__ */ new Map();
974
1482
  for (let index = 0; index < updatedList.length; index += 1) {
975
1483
  const identityKeys = this.getOrderIdentityMatchKeys(updatedList[index]);
@@ -998,9 +1506,43 @@ var OrderModule = class extends import_BaseModule.BaseModule {
998
1506
  });
999
1507
  continue;
1000
1508
  }
1001
- const mergedOrder = this.mergeOrderRecords(existingOrder, fresh);
1002
- updatedList[matchIndex] = mergedOrder;
1003
- this.registerOrderIdentityKeys(identityKeyToIndex, mergedOrder, matchIndex);
1509
+ if (this.isDraftOrder(existingOrder) && this.shouldProtectDraftOrderFromIncoming(source)) {
1510
+ this.logInfo("mergeOrdersToStore-跳过 draft 订单远端覆盖", {
1511
+ source,
1512
+ order_id: existingOrder.order_id ?? fresh.order_id ?? null,
1513
+ external_sale_number: existingOrder.external_sale_number ?? fresh.external_sale_number ?? null,
1514
+ local_is_draft_order: existingOrder.is_draft_order ?? null,
1515
+ remote_is_draft_order: fresh.is_draft_order ?? null,
1516
+ reason: "protect_draft_order_from_remote_echo"
1517
+ });
1518
+ continue;
1519
+ }
1520
+ let mergedOrder = this.mergeOrderRecords(existingOrder, fresh);
1521
+ let adjustedMatchIndex = matchIndex;
1522
+ const duplicateIndexes = /* @__PURE__ */ new Set();
1523
+ for (const key of freshIdentityKeys) {
1524
+ const duplicateIndex = identityKeyToIndex.get(key);
1525
+ if (duplicateIndex === void 0 || duplicateIndex === matchIndex)
1526
+ continue;
1527
+ duplicateIndexes.add(duplicateIndex);
1528
+ }
1529
+ if (duplicateIndexes.size > 0) {
1530
+ for (const duplicateIndex of [...duplicateIndexes].sort((left, right) => right - left)) {
1531
+ mergedOrder = this.mergeOrderRecords(mergedOrder, updatedList[duplicateIndex]);
1532
+ updatedList.splice(duplicateIndex, 1);
1533
+ if (duplicateIndex < adjustedMatchIndex)
1534
+ adjustedMatchIndex -= 1;
1535
+ }
1536
+ identityKeyToIndex.clear();
1537
+ for (let index = 0; index < updatedList.length; index += 1) {
1538
+ for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
1539
+ if (!identityKeyToIndex.has(key))
1540
+ identityKeyToIndex.set(key, index);
1541
+ }
1542
+ }
1543
+ }
1544
+ updatedList[adjustedMatchIndex] = mergedOrder;
1545
+ this.registerOrderIdentityKeys(identityKeyToIndex, mergedOrder, adjustedMatchIndex);
1004
1546
  patchedOrders.push(mergedOrder);
1005
1547
  if (mergeKey)
1006
1548
  mergeActions[mergeKey] = "update";
@@ -1236,56 +1778,29 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1236
1778
  }
1237
1779
  return result;
1238
1780
  }
1239
- getPaymentMergeKey(payment) {
1240
- var _a;
1241
- const record = payment;
1242
- if (!record)
1243
- return "";
1244
- const uniquePaymentNumber = (_a = record.metadata) == null ? void 0 : _a.unique_payment_number;
1245
- if (!this.isBlankIdentityValue(uniquePaymentNumber)) {
1246
- return `unique:${String(uniquePaymentNumber)}`;
1247
- }
1248
- const orderPaymentId = record.order_payment_id;
1249
- if (!this.isBlankIdentityValue(orderPaymentId))
1250
- return `order_payment:${String(orderPaymentId)}`;
1251
- const code = record.code;
1252
- const customPaymentId = record.custom_payment_id;
1253
- if (!this.isBlankIdentityValue(code) && !this.isBlankIdentityValue(customPaymentId)) {
1254
- return `custom:${String(code)}#${String(customPaymentId)}`;
1255
- }
1256
- return "";
1257
- }
1258
1781
  mergeOrderPaymentLists(existing, incoming) {
1259
1782
  const existingList = Array.isArray(existing) ? existing : [];
1260
1783
  const incomingList = Array.isArray(incoming) ? incoming : [];
1261
1784
  if (incomingList.length === 0)
1262
1785
  return (0, import_lodash_es.cloneDeep)(existingList);
1263
- if (existingList.length === 0)
1264
- return (0, import_lodash_es.cloneDeep)(incomingList);
1265
- const existingByKey = /* @__PURE__ */ new Map();
1266
- for (const payment of existingList) {
1267
- const key = this.getPaymentMergeKey(payment);
1268
- if (!key)
1269
- continue;
1270
- existingByKey.set(key, payment);
1271
- }
1272
- return incomingList.map((payment) => {
1273
- const incomingPayment = payment;
1274
- const key = this.getPaymentMergeKey(incomingPayment);
1275
- const existingPayment = key ? existingByKey.get(key) : void 0;
1276
- if (!existingPayment)
1277
- return (0, import_lodash_es.cloneDeep)(incomingPayment);
1278
- return {
1279
- ...(0, import_lodash_es.cloneDeep)(existingPayment),
1280
- ...(0, import_lodash_es.cloneDeep)(incomingPayment),
1281
- metadata: {
1282
- ...(0, import_lodash_es.cloneDeep)(existingPayment.metadata || {}),
1283
- ...(0, import_lodash_es.cloneDeep)(incomingPayment.metadata || {})
1284
- }
1285
- };
1286
- });
1786
+ return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(existingList, incomingList);
1787
+ }
1788
+ getIdentifiedPendingPayments(order) {
1789
+ const payments = Array.isArray(order == null ? void 0 : order.payments) ? order.payments : [];
1790
+ return payments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment));
1287
1791
  }
1288
- mergeOrderRecords(existing, incoming, options) {
1792
+ shouldProtectLocalOrderFromRemoteSnapshot(order) {
1793
+ return this.isPendingSyncOrder(order) || this.isDraftOrder(order) || this.getIdentifiedPendingPayments(order).length > 0;
1794
+ }
1795
+ getUnmatchedIdentifiedPendingPayments(existing, incoming) {
1796
+ const existingPayments = Array.isArray(existing) ? existing : [];
1797
+ const incomingPayments = Array.isArray(incoming) ? incoming : [];
1798
+ const incomingIdentityKeys = new Set(
1799
+ incomingPayments.flatMap((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1800
+ );
1801
+ return existingPayments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment) && !(0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => incomingIdentityKeys.has(key)));
1802
+ }
1803
+ mergeOrderRecords(existing, incoming) {
1289
1804
  const preferred = this.pickPreferredOrder(existing, incoming);
1290
1805
  const secondary = preferred === existing ? incoming : existing;
1291
1806
  const merged = {
@@ -1306,8 +1821,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1306
1821
  "updated_at",
1307
1822
  "shop_discount",
1308
1823
  "summary",
1309
- "products",
1310
- "bookings",
1311
1824
  "note",
1312
1825
  "customer_id",
1313
1826
  "customer_name",
@@ -1316,13 +1829,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1316
1829
  "contacts_info",
1317
1830
  "phone",
1318
1831
  "email",
1319
- "relation_forms"
1832
+ "relation_forms",
1833
+ "is_draft_order"
1320
1834
  ];
1321
1835
  const mergedRecord = merged;
1322
1836
  const preferredRecord = preferred;
1323
1837
  const secondaryRecord = secondary;
1838
+ const existingRecord = existing;
1324
1839
  const incomingRecord = incoming;
1325
- const previousRecord = preferred === incoming ? secondaryRecord : preferredRecord;
1840
+ const childUidRemaps = [];
1326
1841
  for (const field of fieldsToPreserve) {
1327
1842
  if (!this.isBlankIdentityValue(preferredRecord[field])) {
1328
1843
  mergedRecord[field] = preferredRecord[field];
@@ -1332,8 +1847,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1332
1847
  mergedRecord[field] = secondaryRecord[field];
1333
1848
  }
1334
1849
  }
1335
- const hasIncomingProducts = Object.prototype.hasOwnProperty.call(incomingRecord, "products");
1336
- const shouldUseIncomingProductsSnapshot = (options == null ? void 0 : options.preferIncomingProducts) === true && hasIncomingProducts && incomingRecord.products !== void 0 && incomingRecord.products !== null;
1337
1850
  for (const field of incomingPatchFields) {
1338
1851
  if (!Object.prototype.hasOwnProperty.call(incomingRecord, field))
1339
1852
  continue;
@@ -1343,21 +1856,44 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1343
1856
  continue;
1344
1857
  mergedRecord[field] = (0, import_lodash_es.cloneDeep)(incomingRecord[field]);
1345
1858
  }
1346
- mergedRecord.products = shouldUseIncomingProductsSnapshot ? (0, import_lodash_es.cloneDeep)(incomingRecord.products) : this.mergeOrderProductLists(preferredRecord.products, secondaryRecord.products);
1347
- if (Object.prototype.hasOwnProperty.call(incomingRecord, "payments")) {
1348
- if (Array.isArray(incomingRecord.payments)) {
1349
- mergedRecord.payments = this.mergeOrderPaymentLists(
1350
- previousRecord.payments,
1351
- incomingRecord.payments
1859
+ for (const field of ORDER_AUTHORITATIVE_COLLECTION_FIELDS) {
1860
+ if (Array.isArray(incomingRecord[field])) {
1861
+ if (field === "payments") {
1862
+ const preservedPending = this.getUnmatchedIdentifiedPendingPayments(
1863
+ existingRecord[field],
1864
+ incomingRecord[field]
1865
+ );
1866
+ if (preservedPending.length > 0) {
1867
+ this.logInfo("mergeOrderRecords-保留本地 pending 支付项", {
1868
+ order_id: existing.order_id ?? incoming.order_id ?? null,
1869
+ external_sale_number: existingRecord.external_sale_number ?? incomingRecord.external_sale_number ?? null,
1870
+ preserved_pending_count: preservedPending.length,
1871
+ preserved_payment_identities: preservedPending.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1872
+ });
1873
+ }
1874
+ }
1875
+ mergedRecord[field] = this.mergeAuthoritativeOrderCollection(
1876
+ field,
1877
+ existingRecord[field],
1878
+ incomingRecord[field],
1879
+ childUidRemaps,
1880
+ { preserveIdentifiedPendingPayments: field === "payments" }
1352
1881
  );
1353
- } else if (incomingRecord.payments !== void 0 && incomingRecord.payments !== null) {
1354
- mergedRecord.payments = (0, import_lodash_es.cloneDeep)(incomingRecord.payments);
1882
+ continue;
1883
+ }
1884
+ if (Object.prototype.hasOwnProperty.call(existingRecord, field)) {
1885
+ mergedRecord[field] = (0, import_lodash_es.cloneDeep)(existingRecord[field]);
1886
+ } else {
1887
+ delete mergedRecord[field];
1355
1888
  }
1356
1889
  }
1357
1890
  if (!this.isPendingSyncOrder(preferred) || !this.isPendingSyncOrder(secondary)) {
1358
1891
  merged.need_sync = 0;
1359
1892
  }
1360
- return merged;
1893
+ return this.normalizeOrderCollectionsForIngress(
1894
+ (0, import_orderCollectionIdentity.applyOrderCollectionUidRemaps)(merged, childUidRemaps),
1895
+ "mergeOrderRecords"
1896
+ );
1361
1897
  }
1362
1898
  summarizeDuplicateOrders(orders) {
1363
1899
  const groups = /* @__PURE__ */ new Map();
@@ -1376,7 +1912,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1376
1912
  external_sale_number: order.external_sale_number ?? null,
1377
1913
  shop_order_number: order.shop_order_number ?? null,
1378
1914
  shop_full_order_number: order.shop_full_order_number ?? null,
1379
- need_sync: order.need_sync ?? null
1915
+ need_sync: order.need_sync ?? null,
1916
+ is_draft_order: order.is_draft_order ?? null
1380
1917
  }))
1381
1918
  }));
1382
1919
  }
@@ -1394,12 +1931,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1394
1931
  const list = [];
1395
1932
  let removedCount = 0;
1396
1933
  for (const order of orders) {
1397
- const matchIndex = this.findOrderIndexByIdentity(list, order);
1934
+ const normalizedOrder = this.normalizeOrderCollectionsForIngress(
1935
+ order,
1936
+ `${source}.order`
1937
+ );
1938
+ const matchIndex = this.findOrderIndexByIdentity(list, normalizedOrder);
1398
1939
  if (matchIndex < 0) {
1399
- list.push(order);
1940
+ list.push(normalizedOrder);
1400
1941
  continue;
1401
1942
  }
1402
- list[matchIndex] = this.mergeOrderRecords(list[matchIndex], order);
1943
+ list[matchIndex] = this.mergeOrderRecords(list[matchIndex], normalizedOrder);
1403
1944
  removedCount += 1;
1404
1945
  }
1405
1946
  if (removedCount > 0) {
@@ -1479,7 +2020,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1479
2020
  return [];
1480
2021
  try {
1481
2022
  const orders = await this.dbManager.getAll(INDEXDB_STORE_NAME);
1482
- return orders || [];
2023
+ return (orders || []).map(
2024
+ (order) => this.normalizeOrderCollectionsForIngress(order, "loadOrdersFromSQLite")
2025
+ );
1483
2026
  } catch {
1484
2027
  return [];
1485
2028
  }
@@ -1487,22 +2030,67 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1487
2030
  isPendingSyncOrder(order) {
1488
2031
  return Number(order == null ? void 0 : order.need_sync) === 1;
1489
2032
  }
2033
+ isDraftOrder(order) {
2034
+ return Number(order == null ? void 0 : order.is_draft_order) === 1;
2035
+ }
2036
+ shouldProtectDraftOrderFromIncoming(source) {
2037
+ return source !== "checkoutSync";
2038
+ }
1490
2039
  normalizeRemoteSyncedOrder(order) {
1491
- if (this.isPendingSyncOrder(order))
1492
- return order;
2040
+ const normalizedOrder = this.normalizeOrderCollectionsForIngress(
2041
+ order,
2042
+ "normalizeRemoteSyncedOrder"
2043
+ );
2044
+ if (this.isPendingSyncOrder(normalizedOrder))
2045
+ return {
2046
+ ...normalizedOrder,
2047
+ is_draft_order: 0
2048
+ };
1493
2049
  return {
1494
- ...order,
1495
- need_sync: 0
2050
+ ...normalizedOrder,
2051
+ need_sync: 0,
2052
+ is_draft_order: 0
2053
+ };
2054
+ }
2055
+ mergeRemoteIdentityIntoDraftOrder(draftOrder, remoteOrder) {
2056
+ const merged = {
2057
+ ...this.withoutSyntheticDraftOrderId(draftOrder)
1496
2058
  };
2059
+ const remote = remoteOrder;
2060
+ for (const field of [
2061
+ "order_id",
2062
+ "order_number",
2063
+ "shop_order_number",
2064
+ "shop_full_order_number"
2065
+ ]) {
2066
+ if (this.isBlankIdentityValue(merged[field]) && !this.isBlankIdentityValue(remote[field])) {
2067
+ merged[field] = remote[field];
2068
+ }
2069
+ }
2070
+ return this.normalizeOrderCollectionsForIngress(
2071
+ merged,
2072
+ "mergeRemoteIdentityIntoDraftOrder"
2073
+ );
1497
2074
  }
1498
2075
  mergeRemoteSnapshotWithPendingOrders(remoteOrders, existingOrders) {
1499
2076
  const merged = remoteOrders.map((order) => this.normalizeRemoteSyncedOrder(order));
1500
- for (const order of existingOrders) {
1501
- if (!this.isPendingSyncOrder(order))
2077
+ for (const rawOrder of existingOrders) {
2078
+ const order = this.normalizeOrderCollectionsForIngress(
2079
+ rawOrder,
2080
+ "mergeRemoteSnapshotWithPendingOrders.existingSQLite"
2081
+ );
2082
+ if (!this.shouldProtectLocalOrderFromRemoteSnapshot(order))
1502
2083
  continue;
1503
2084
  const matchIndex = this.findOrderIndexByIdentity(merged, order);
1504
2085
  if (matchIndex >= 0) {
1505
- merged[matchIndex] = this.mergeOrderRecords(order, merged[matchIndex]);
2086
+ if (this.isDraftOrder(order)) {
2087
+ merged[matchIndex] = this.mergeRemoteIdentityIntoDraftOrder(
2088
+ order,
2089
+ merged[matchIndex]
2090
+ );
2091
+ } else {
2092
+ merged[matchIndex] = this.mergeOrderRecords(order, merged[matchIndex]);
2093
+ }
1506
2094
  continue;
1507
2095
  }
1508
2096
  if (!this.getOrderStorageKey(order))
@@ -1530,11 +2118,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1530
2118
  * @example
1531
2119
  * await this.patchOrdersInSQLite(freshOrders)
1532
2120
  */
1533
- async patchOrdersInSQLite(orders, source, mergeActions = {}) {
1534
- if (!this.dbManager || orders.length === 0) {
2121
+ async patchOrdersInSQLite(orders, source, mergeActions = {}, options = {}) {
2122
+ if (orders.length === 0) {
2123
+ return;
2124
+ }
2125
+ if (!this.dbManager) {
2126
+ if (options.throwOnError)
2127
+ throw new Error("订单 SQLite 数据库未初始化");
1535
2128
  return;
1536
2129
  }
1537
- const ordersSnapshot = (0, import_lodash_es.cloneDeep)(orders).filter((order) => this.getOrderStorageKey(order));
2130
+ const ordersSnapshot = (0, import_lodash_es.cloneDeep)(orders).map((order) => this.normalizeOrderCollectionsForIngress(order, `${source}.sqliteIngress`)).filter((order) => this.getOrderStorageKey(order));
1538
2131
  if (ordersSnapshot.length === 0) {
1539
2132
  return;
1540
2133
  }
@@ -1569,6 +2162,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1569
2162
  for (const order of compactedToWrite) {
1570
2163
  await this.dbManager.update(INDEXDB_STORE_NAME, order);
1571
2164
  }
2165
+ } else if (options.throwOnError) {
2166
+ throw new Error("订单 SQLite 数据库不支持写入");
1572
2167
  }
1573
2168
  this.recordRecentSqliteWrite(source, compactedToWrite);
1574
2169
  this.logInfo("patchOrdersInSQLite-完成", {
@@ -1583,6 +2178,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1583
2178
  error: error instanceof Error ? error.message : String(error),
1584
2179
  orderCount: ordersSnapshot.length
1585
2180
  });
2181
+ if (options.throwOnError)
2182
+ throw error;
1586
2183
  }
1587
2184
  }
1588
2185
  /**
@@ -1591,11 +2188,21 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1591
2188
  * @example
1592
2189
  * await this.updateOrderInSQLite(freshOrder)
1593
2190
  */
1594
- async updateOrderInSQLite(order, source) {
1595
- if (!this.dbManager || !this.getOrderStorageKey(order)) {
2191
+ async updateOrderInSQLite(order, source, options = {}) {
2192
+ if (!this.getOrderStorageKey(order)) {
2193
+ if (options.throwOnError)
2194
+ throw new Error("订单缺少可用的 SQLite 存储主键");
1596
2195
  return;
1597
2196
  }
1598
- const orderSnapshot = (0, import_lodash_es.cloneDeep)(order);
2197
+ if (!this.dbManager) {
2198
+ if (options.throwOnError)
2199
+ throw new Error("订单 SQLite 数据库未初始化");
2200
+ return;
2201
+ }
2202
+ const orderSnapshot = this.normalizeOrderCollectionsForIngress(
2203
+ (0, import_lodash_es.cloneDeep)(order),
2204
+ `${source}.sqliteIngress`
2205
+ );
1599
2206
  try {
1600
2207
  await this.runInOrderSQLiteSaveQueue(async () => {
1601
2208
  let writeMethod = "none";
@@ -1613,6 +2220,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1613
2220
  } else if (typeof this.dbManager.bulkAdd === "function") {
1614
2221
  writeMethod = "bulkAdd";
1615
2222
  await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, [orderSnapshot]);
2223
+ } else if (options.throwOnError) {
2224
+ throw new Error("订单 SQLite 数据库不支持写入");
1616
2225
  }
1617
2226
  this.recordRecentSqliteWrite(source, [orderSnapshot]);
1618
2227
  this.logInfo("updateOrderInSQLite-完成", {
@@ -1626,22 +2235,27 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1626
2235
  error: error instanceof Error ? error.message : String(error),
1627
2236
  orderId: orderSnapshot.order_id ?? null
1628
2237
  });
2238
+ if (options.throwOnError)
2239
+ throw error;
1629
2240
  }
1630
2241
  }
1631
2242
  /**
1632
- * 全量快照替换 orders 表(clear + bulkAdd),用于 SSE 全量拉取与营业日窗口裁剪。
2243
+ * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync / pending 支付订单。
2244
+ * 用于 SSE 全量拉取与营业日窗口裁剪。
1633
2245
  *
1634
2246
  * @example
1635
2247
  * await this.replaceOrdersSnapshotInSQLite(orderList)
1636
2248
  */
1637
- async replaceOrdersSnapshotInSQLite(orderList, source) {
2249
+ async replaceOrdersSnapshotInSQLite(orderList, source, protectedOrdersBeforeRemoteFetch = []) {
1638
2250
  if (!this.dbManager) {
1639
2251
  return this.compactOrderListByIdentity(
1640
2252
  orderList.map((order) => this.normalizeRemoteSyncedOrder(order)),
1641
2253
  `${source}.snapshotNoDb`
1642
2254
  ).list;
1643
2255
  }
1644
- const remoteSnapshot = (0, import_lodash_es.cloneDeep)(orderList);
2256
+ const remoteSnapshot = (0, import_lodash_es.cloneDeep)(orderList).map(
2257
+ (order) => this.normalizeOrderCollectionsForIngress(order, `${source}.remoteIngress`)
2258
+ );
1645
2259
  let mergedSnapshot = this.compactOrderListByIdentity(
1646
2260
  remoteSnapshot.map((order) => this.normalizeRemoteSyncedOrder(order)),
1647
2261
  `${source}.remoteSnapshot`
@@ -1649,16 +2263,52 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1649
2263
  try {
1650
2264
  await this.runInOrderSQLiteSaveQueue(async () => {
1651
2265
  const existingOrders = typeof this.dbManager.getAll === "function" ? await this.dbManager.getAll(INDEXDB_STORE_NAME) : [];
2266
+ const protectedLocalOrders = protectedOrdersBeforeRemoteFetch.map((order) => this.normalizeOrderCollectionsForIngress(
2267
+ order,
2268
+ `${source}.protectedBeforeRemoteFetch`
2269
+ )).filter((order) => this.shouldProtectLocalOrderFromRemoteSnapshot(order));
2270
+ for (const rawCurrentOrder of existingOrders || []) {
2271
+ const currentOrder = this.normalizeOrderCollectionsForIngress(
2272
+ rawCurrentOrder,
2273
+ `${source}.currentSQLite`
2274
+ );
2275
+ const protectedIndex = this.findOrderIndexByIdentity(
2276
+ protectedLocalOrders,
2277
+ currentOrder
2278
+ );
2279
+ const currentNeedsProtection = this.shouldProtectLocalOrderFromRemoteSnapshot(currentOrder);
2280
+ if (protectedIndex >= 0) {
2281
+ if (currentNeedsProtection) {
2282
+ protectedLocalOrders[protectedIndex] = currentOrder;
2283
+ } else {
2284
+ protectedLocalOrders.splice(protectedIndex, 1);
2285
+ }
2286
+ continue;
2287
+ }
2288
+ if (currentNeedsProtection)
2289
+ protectedLocalOrders.push(currentOrder);
2290
+ }
1652
2291
  const orderListSnapshot = this.mergeRemoteSnapshotWithPendingOrders(
1653
2292
  remoteSnapshot,
1654
- existingOrders || []
2293
+ protectedLocalOrders
1655
2294
  );
1656
2295
  mergedSnapshot = this.compactOrderListByIdentity(orderListSnapshot, `${source}.sqliteSnapshot`).list;
1657
2296
  this.logInfo("replaceOrdersSnapshotInSQLite-开始", {
1658
2297
  source,
1659
2298
  count: mergedSnapshot.length,
1660
2299
  remoteCount: remoteSnapshot.length,
1661
- preservedPendingCount: mergedSnapshot.length - remoteSnapshot.length
2300
+ protectedBeforeRemoteFetchCount: protectedOrdersBeforeRemoteFetch.length,
2301
+ protectedLocalOrderCount: protectedLocalOrders.length,
2302
+ preservedLocalUnsyncedCount: mergedSnapshot.length - remoteSnapshot.length,
2303
+ protectedPendingPaymentCount: protectedLocalOrders.reduce(
2304
+ (count, order) => count + this.getIdentifiedPendingPayments(order).length,
2305
+ 0
2306
+ ),
2307
+ protectedPendingPaymentIdentities: protectedLocalOrders.flatMap((order) => this.getIdentifiedPendingPayments(order).map((payment) => ({
2308
+ order_id: order.order_id ?? null,
2309
+ external_sale_number: order.external_sale_number ?? null,
2310
+ payment_identities: (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment)
2311
+ })))
1662
2312
  });
1663
2313
  await this.dbManager.clear(INDEXDB_STORE_NAME);
1664
2314
  this.logInfo("replaceOrdersSnapshotInSQLite-clear完成", {