@pisell/pisellos 2.3.28 → 2.3.30

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 (57) hide show
  1. package/dist/modules/Order/index.d.ts +32 -8
  2. package/dist/modules/Order/index.js +883 -521
  3. package/dist/modules/Order/payment-utils.d.ts +23 -0
  4. package/dist/modules/Order/payment-utils.js +203 -0
  5. package/dist/modules/Order/types.d.ts +33 -1
  6. package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  7. package/dist/modules/Order/utils/orderCollectionIdentity.js +405 -0
  8. package/dist/modules/Order/utils.d.ts +2 -1
  9. package/dist/modules/Order/utils.js +6 -12
  10. package/dist/modules/Payment/index.d.ts +2 -0
  11. package/dist/modules/Payment/index.js +78 -49
  12. package/dist/modules/Payment/types.d.ts +26 -24
  13. package/dist/modules/Payment/types.js +2 -0
  14. package/dist/modules/Product/index.d.ts +1 -1
  15. package/dist/server/index.d.ts +14 -0
  16. package/dist/server/index.js +1826 -1000
  17. package/dist/server/modules/order/index.d.ts +47 -4
  18. package/dist/server/modules/order/index.js +1415 -711
  19. package/dist/server/modules/order/types.d.ts +11 -3
  20. package/dist/server/modules/order/types.js +1 -1
  21. package/dist/solution/BaseSales/index.d.ts +40 -4
  22. package/dist/solution/BaseSales/index.js +1268 -749
  23. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +9 -4
  24. package/dist/solution/BaseSales/utils/parseSalesResponse.js +6 -8
  25. package/dist/solution/BookingByStep/index.d.ts +1 -1
  26. package/dist/solution/BookingTicket/index.d.ts +13 -1
  27. package/dist/solution/BookingTicket/index.js +2 -1
  28. package/dist/utils/payment-number.d.ts +9 -0
  29. package/dist/utils/payment-number.js +69 -0
  30. package/lib/modules/Order/index.d.ts +32 -8
  31. package/lib/modules/Order/index.js +270 -64
  32. package/lib/modules/Order/payment-utils.d.ts +23 -0
  33. package/lib/modules/Order/payment-utils.js +193 -0
  34. package/lib/modules/Order/types.d.ts +33 -1
  35. package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  36. package/lib/modules/Order/utils/orderCollectionIdentity.js +415 -0
  37. package/lib/modules/Order/utils.d.ts +2 -1
  38. package/lib/modules/Order/utils.js +6 -14
  39. package/lib/modules/Payment/index.d.ts +2 -0
  40. package/lib/modules/Payment/index.js +33 -12
  41. package/lib/modules/Payment/types.d.ts +26 -24
  42. package/lib/modules/Product/index.d.ts +1 -1
  43. package/lib/server/index.d.ts +14 -0
  44. package/lib/server/index.js +604 -8
  45. package/lib/server/modules/order/index.d.ts +47 -4
  46. package/lib/server/modules/order/index.js +578 -116
  47. package/lib/server/modules/order/types.d.ts +11 -3
  48. package/lib/solution/BaseSales/index.d.ts +40 -4
  49. package/lib/solution/BaseSales/index.js +363 -37
  50. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +9 -4
  51. package/lib/solution/BaseSales/utils/parseSalesResponse.js +4 -5
  52. package/lib/solution/BookingByStep/index.d.ts +1 -1
  53. package/lib/solution/BookingTicket/index.d.ts +13 -1
  54. package/lib/solution/BookingTicket/index.js +2 -1
  55. package/lib/utils/payment-number.d.ts +9 -0
  56. package/lib/utils/payment-number.js +64 -0
  57. 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,18 @@ 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 ORDER_AUTHORITATIVE_COLLECTION_FIELDS = ["products", "bookings", "payments"];
57
+ var ORDER_COLLECTION_KIND_BY_FIELD = {
58
+ products: "product",
59
+ bookings: "booking",
60
+ payments: "payment"
61
+ };
52
62
  var OrderModule = class extends import_BaseModule.BaseModule {
53
63
  constructor(name, version) {
54
64
  super(name, version);
@@ -154,6 +164,96 @@ var OrderModule = class extends import_BaseModule.BaseModule {
154
164
  } catch {
155
165
  }
156
166
  }
167
+ /**
168
+ * 在订单进入内存或 SQLite 前统一压缩子项强身份重复并补齐协议 UID。
169
+ * 仅记录计数与订单标识,不输出商品、预约、支付或客户明细。
170
+ */
171
+ normalizeOrderCollectionsForIngress(order, source) {
172
+ const result = (0, import_orderCollectionIdentity.normalizeOrderCollections)(order);
173
+ const kinds = ["product", "booking", "payment"];
174
+ const hasChanges = kinds.some((kind) => {
175
+ const stats = result.stats[kind];
176
+ return stats.backfilledUidCount > 0 || stats.collapsedDuplicateCount > 0 || stats.uidConflictCount > 0 || stats.anonymousRowCount > 0;
177
+ });
178
+ if (hasChanges) {
179
+ const summarize = (stats) => ({
180
+ backfilled_uid_count: stats.backfilledUidCount,
181
+ collapsed_duplicate_count: stats.collapsedDuplicateCount,
182
+ uid_conflict_count: stats.uidConflictCount,
183
+ anonymous_row_count: stats.anonymousRowCount
184
+ });
185
+ const context = {
186
+ source,
187
+ order_id: (order == null ? void 0 : order.order_id) ?? null,
188
+ external_sale_number: (order == null ? void 0 : order.external_sale_number) ?? null,
189
+ products: summarize(result.stats.product),
190
+ bookings: summarize(result.stats.booking),
191
+ payments: summarize(result.stats.payment)
192
+ };
193
+ const hasUnsafeIdentity = kinds.some((kind) => {
194
+ const stats = result.stats[kind];
195
+ return stats.uidConflictCount > 0 || stats.anonymousRowCount > 0;
196
+ });
197
+ if (hasUnsafeIdentity) {
198
+ this.logWarning("订单子项身份存在冲突或匿名行", context);
199
+ } else {
200
+ this.logInfo("订单子项身份已规范化", context);
201
+ }
202
+ }
203
+ return result.order;
204
+ }
205
+ /**
206
+ * incoming 决定权威成员集合;同一持久化行仍从 existing 补齐 incoming 省略的本地展示字段。
207
+ */
208
+ mergeAuthoritativeOrderCollection(field, existing, incoming, uidRemaps = []) {
209
+ const kind = ORDER_COLLECTION_KIND_BY_FIELD[field];
210
+ const existingItems = Array.isArray(existing) ? existing : [];
211
+ return incoming.map((incomingItem) => {
212
+ const existingItem = existingItems.find(
213
+ (item) => (0, import_orderCollectionIdentity.isSameOrderCollectionItem)(kind, item, incomingItem)
214
+ );
215
+ if (!existingItem)
216
+ return (0, import_lodash_es.cloneDeep)(incomingItem);
217
+ const mergedItem = (0, import_orderCollectionIdentity.mergeOrderCollectionItems)(kind, existingItem, incomingItem);
218
+ const mergedUid = (0, import_orderCollectionIdentity.getOrderCollectionUid)(kind, mergedItem);
219
+ if (mergedUid) {
220
+ for (const from of /* @__PURE__ */ new Set([
221
+ (0, import_orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, existingItem),
222
+ (0, import_orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, incomingItem)
223
+ ])) {
224
+ if (!from || from === mergedUid)
225
+ continue;
226
+ uidRemaps.push({
227
+ kind,
228
+ from,
229
+ to: mergedUid,
230
+ persistentId: (0, import_orderCollectionIdentity.getOrderCollectionPersistentId)(kind, incomingItem) || (0, import_orderCollectionIdentity.getOrderCollectionPersistentId)(kind, existingItem)
231
+ });
232
+ }
233
+ }
234
+ return mergedItem;
235
+ });
236
+ }
237
+ reconcileOverwriteOrderCollections(existing, incoming) {
238
+ const reconciled = (0, import_lodash_es.cloneDeep)(incoming);
239
+ const existingRecord = existing;
240
+ const incomingRecord = incoming;
241
+ const uidRemaps = [];
242
+ for (const field of ORDER_AUTHORITATIVE_COLLECTION_FIELDS) {
243
+ if (!Array.isArray(incomingRecord[field]))
244
+ continue;
245
+ reconciled[field] = this.mergeAuthoritativeOrderCollection(
246
+ field,
247
+ existingRecord[field],
248
+ incomingRecord[field],
249
+ uidRemaps
250
+ );
251
+ }
252
+ return this.normalizeOrderCollectionsForIngress(
253
+ (0, import_orderCollectionIdentity.applyOrderCollectionUidRemaps)(reconciled, uidRemaps),
254
+ "overwriteExistingOrder.reconciled"
255
+ );
256
+ }
157
257
  /**
158
258
  * 记录订单最近一次 SQLite 写入,供 pubsub 回声去重使用。
159
259
  *
@@ -385,6 +485,27 @@ var OrderModule = class extends import_BaseModule.BaseModule {
385
485
  getOrderByOrderId(orderId) {
386
486
  return this.store.map.get(this.getIdKey(orderId));
387
487
  }
488
+ buildLocalPaymentOrderLogContext(order) {
489
+ if (!order)
490
+ return {};
491
+ return {
492
+ order_id: order.order_id ?? null,
493
+ external_sale_number: order.external_sale_number ?? null,
494
+ order_number: order.order_number ?? null,
495
+ shop_order_number: order.shop_order_number ?? null,
496
+ shop_full_order_number: order.shop_full_order_number ?? null,
497
+ order_status: order.status ?? null,
498
+ payment_status: order.payment_status ?? null,
499
+ is_draft_order: Number(order.is_draft_order || 0),
500
+ need_sync: Number(order.need_sync || 0),
501
+ platform: order.platform ?? null,
502
+ business_code: order.business_code ?? null,
503
+ order_sales_channel: order.order_sales_channel ?? null,
504
+ sales_channel: order.sales_channel ?? null,
505
+ order_type: order.type ?? null,
506
+ payments_count: Array.isArray(order.payments) ? order.payments.length : 0
507
+ };
508
+ }
388
509
  getLocalOrderFromMemoryByLookup(lookup) {
389
510
  const key = this.getIdKey(lookup);
390
511
  const memoryOrderById = this.store.map.get(key);
@@ -393,21 +514,176 @@ var OrderModule = class extends import_BaseModule.BaseModule {
393
514
  const memoryOrder = this.store.list.find((order) => this.isOrderLookupMatch(order, key));
394
515
  return memoryOrder || null;
395
516
  }
396
- async getLocalOrderByLookup(lookup) {
517
+ async getLocalOrderByLookup(lookup, options = {}) {
397
518
  const key = this.getIdKey(lookup);
519
+ const logContext = {
520
+ operation_id: options.operationId,
521
+ lookup: key,
522
+ memory_order_count: this.store.list.length
523
+ };
524
+ if (options.operationId) {
525
+ this.logInfo("getLocalOrderByLookup-localPayment-开始", logContext);
526
+ }
398
527
  const memoryOrderById = this.store.map.get(key);
399
- if (memoryOrderById)
528
+ if (memoryOrderById) {
529
+ if (options.operationId) {
530
+ this.logInfo("getLocalOrderByLookup-localPayment-命中内存映射", {
531
+ ...logContext,
532
+ ...this.buildLocalPaymentOrderLogContext(memoryOrderById)
533
+ });
534
+ }
400
535
  return memoryOrderById;
536
+ }
401
537
  const memoryOrder = this.store.list.find((order) => this.isOrderLookupMatch(order, key));
402
- if (memoryOrder)
538
+ if (memoryOrder) {
539
+ if (options.operationId) {
540
+ this.logInfo("getLocalOrderByLookup-localPayment-命中内存列表", {
541
+ ...logContext,
542
+ ...this.buildLocalPaymentOrderLogContext(memoryOrder)
543
+ });
544
+ }
403
545
  return memoryOrder;
546
+ }
547
+ if (options.operationId) {
548
+ this.logInfo("getLocalOrderByLookup-localPayment-开始读取SQLite", logContext);
549
+ }
404
550
  const orders = await this.loadOrdersFromSQLite();
405
551
  const localOrder = orders.find((order) => this.isOrderLookupMatch(order, key));
406
- if (!localOrder)
552
+ if (!localOrder) {
553
+ if (options.operationId) {
554
+ this.logWarning("getLocalOrderByLookup-localPayment-SQLite未命中", {
555
+ ...logContext,
556
+ sqlite_order_count: orders.length
557
+ });
558
+ }
407
559
  return null;
560
+ }
408
561
  this.store.list = orders.map((order) => this.normalizeOrderForMemoryList(order));
409
562
  this.syncOrdersMap();
410
- return this.normalizeOrderForMemoryList(localOrder);
563
+ const normalizedOrder = this.normalizeOrderForMemoryList(localOrder);
564
+ if (options.operationId) {
565
+ this.logInfo("getLocalOrderByLookup-localPayment-SQLite命中", {
566
+ ...logContext,
567
+ sqlite_order_count: orders.length,
568
+ ...this.buildLocalPaymentOrderLogContext(normalizedOrder)
569
+ });
570
+ }
571
+ return normalizedOrder;
572
+ }
573
+ async getLocalPayment(params) {
574
+ const logContext = {
575
+ operation_id: params.operationId,
576
+ sale_id: params.saleId,
577
+ payment_number: params.paymentNumber
578
+ };
579
+ this.logInfo("getLocalPayment-开始", logContext);
580
+ try {
581
+ const order = await this.getLocalOrderByLookup(params.saleId, {
582
+ operationId: params.operationId
583
+ });
584
+ if (!order) {
585
+ this.logWarning("getLocalPayment-订单未命中", logContext);
586
+ return null;
587
+ }
588
+ const payments = order.payments || [];
589
+ const match = (0, import_payment_utils.resolveOrderPaymentIdentity)(
590
+ payments,
591
+ params.paymentNumber,
592
+ "compat"
593
+ );
594
+ if (!match) {
595
+ this.logWarning("getLocalPayment-支付项未命中", {
596
+ ...logContext,
597
+ ...this.buildLocalPaymentOrderLogContext(order),
598
+ payments
599
+ });
600
+ return null;
601
+ }
602
+ this.logInfo("getLocalPayment-支付项命中", {
603
+ ...logContext,
604
+ ...this.buildLocalPaymentOrderLogContext(order),
605
+ matched_by: match.matchedBy,
606
+ payment_index: match.index,
607
+ payment: match.payment
608
+ });
609
+ return {
610
+ order,
611
+ payment: match.payment,
612
+ paymentIndex: match.index,
613
+ matchedBy: match.matchedBy
614
+ };
615
+ } catch (error) {
616
+ this.logError("getLocalPayment-查询失败", {
617
+ ...logContext,
618
+ error: error instanceof Error ? error.message : String(error)
619
+ });
620
+ throw error;
621
+ }
622
+ }
623
+ async updateLocalPayment(params) {
624
+ const logContext = {
625
+ operation_id: params.operationId,
626
+ sale_id: params.saleId,
627
+ payment_number: params.paymentNumber,
628
+ incoming_payment_update: params.updates
629
+ };
630
+ this.logInfo("updateLocalPayment-开始", logContext);
631
+ const found = await this.getLocalPayment(params);
632
+ if (!found) {
633
+ this.logWarning("updateLocalPayment-支付项未命中", logContext);
634
+ return null;
635
+ }
636
+ const previousPayment = (0, import_lodash_es.cloneDeep)(found.payment);
637
+ const nextPayment = (0, import_payment_utils.mergeOrderPaymentRecord)(found.payment, {
638
+ ...params.updates,
639
+ updated_at: params.updates.updated_at || (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
640
+ });
641
+ const nextOrder = {
642
+ ...found.order,
643
+ payments: (found.order.payments || []).map((payment, index) => index === found.paymentIndex ? nextPayment : payment),
644
+ updated_at: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
645
+ };
646
+ const paymentContext = {
647
+ ...logContext,
648
+ matched_by: found.matchedBy,
649
+ payment_index: found.paymentIndex,
650
+ ...this.buildLocalPaymentOrderLogContext(nextOrder),
651
+ previous_payment: previousPayment,
652
+ payment: nextPayment
653
+ };
654
+ this.logInfo("updateLocalPayment-支付项合并完成", paymentContext);
655
+ const targetIndex = this.findOrderIndexByIdentity(this.store.list, found.order);
656
+ if (targetIndex < 0) {
657
+ this.logError("updateLocalPayment-订单Store索引未命中", paymentContext);
658
+ return null;
659
+ }
660
+ const previousList = this.store.list;
661
+ this.store.list = this.store.list.map((order, index) => index === targetIndex ? nextOrder : order);
662
+ this.syncOrdersMap();
663
+ const storageOrder = this.withoutSyntheticDraftOrderId(nextOrder);
664
+ try {
665
+ this.logInfo("updateLocalPayment-SQLite写入开始", {
666
+ ...paymentContext,
667
+ storage_order_id: storageOrder.order_id ?? null
668
+ });
669
+ await this.updateOrderInSQLite(storageOrder, "updateLocalPayment", { throwOnError: true });
670
+ this.logInfo("updateLocalPayment-SQLite写入完成", {
671
+ ...paymentContext,
672
+ storage_order_id: storageOrder.order_id ?? null
673
+ });
674
+ } catch (error) {
675
+ this.store.list = previousList;
676
+ this.syncOrdersMap();
677
+ this.logError("updateLocalPayment-SQLite写入失败并回滚内存", {
678
+ ...paymentContext,
679
+ storage_order_id: storageOrder.order_id ?? null,
680
+ error: error instanceof Error ? error.message : String(error)
681
+ });
682
+ throw error;
683
+ }
684
+ await this.emitOrdersChanged([nextOrder], "updateLocalPayment");
685
+ this.logInfo("updateLocalPayment-变更事件完成", paymentContext);
686
+ return { order: nextOrder, payment: nextPayment, previousPayment };
411
687
  }
412
688
  async loadOrdersByServer() {
413
689
  var _a;
@@ -479,19 +755,29 @@ var OrderModule = class extends import_BaseModule.BaseModule {
479
755
  return this.store.list;
480
756
  }
481
757
  }
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;
758
+ normalizeOrderForMemoryList(order, source = "normalizeOrderForMemoryList") {
759
+ const normalizedOrder = this.normalizeOrderCollectionsForIngress(order, source);
760
+ const externalSaleNumber = normalizedOrder == null ? void 0 : normalizedOrder.external_sale_number;
761
+ 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
+ return normalizedOrder;
486
763
  }
487
764
  if (externalSaleNumber === void 0 || externalSaleNumber === null || externalSaleNumber === "") {
488
- return order;
765
+ return normalizedOrder;
489
766
  }
490
767
  return {
491
- ...order,
768
+ ...normalizedOrder,
492
769
  order_id: externalSaleNumber
493
770
  };
494
771
  }
772
+ withoutSyntheticDraftOrderId(order) {
773
+ const externalSaleNumber = order.external_sale_number;
774
+ if (Number(order.is_draft_order || 0) !== 1 || order.order_id === void 0 || externalSaleNumber === void 0 || String(order.order_id) !== String(externalSaleNumber)) {
775
+ return order;
776
+ }
777
+ const next = { ...order };
778
+ delete next.order_id;
779
+ return next;
780
+ }
495
781
  /**
496
782
  * 仅覆盖本地已存在的订单;不存在则直接跳过,不落库、不 emit。
497
783
  * 适用于"按 order_id 主动刷新本地订单详情"的代理场景。
@@ -511,32 +797,42 @@ var OrderModule = class extends import_BaseModule.BaseModule {
511
797
  orderId,
512
798
  storeOrderCountBefore: this.store.list.length
513
799
  });
800
+ const normalizedFresh = this.normalizeOrderForMemoryList(
801
+ fresh,
802
+ "overwriteExistingOrder.incoming"
803
+ );
804
+ const existingOrder = this.store.map.get(key);
805
+ const reconciledFresh = this.reconcileOverwriteOrderCollections(
806
+ existingOrder,
807
+ normalizedFresh
808
+ );
514
809
  this.store.list = this.store.list.map((order) => {
515
810
  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;
811
+ if (id === void 0 || id === null) {
812
+ return this.normalizeOrderForMemoryList(order, "overwriteExistingOrder.existingMemory");
813
+ }
814
+ return this.getIdKey(id) === key ? reconciledFresh : this.normalizeOrderForMemoryList(order, "overwriteExistingOrder.existingMemory");
519
815
  });
520
816
  this.syncOrdersMap();
521
- await this.updateOrderInSQLite(fresh, "overwriteExistingOrder");
817
+ await this.updateOrderInSQLite(reconciledFresh, "overwriteExistingOrder");
522
818
  this.logInfo("overwriteExistingOrder-结束", {
523
819
  orderId,
524
820
  storeOrderCountAfter: this.store.list.length
525
821
  });
526
- await this.emitOrdersChanged([fresh], "overwriteExistingOrder");
822
+ await this.emitOrdersChanged([reconciledFresh], "overwriteExistingOrder");
527
823
  return { overwritten: true };
528
824
  }
529
825
  /**
530
826
  * 将远端拉取的订单合并进本地 store(已存在则更新,不存在则追加),落库并 emit onOrdersChanged。
531
827
  * 供 /update/localOrder 等在「本地尚无该单」时写入新建单。
532
828
  */
533
- async upsertOrdersFromRemote(freshOrders) {
829
+ async upsertOrdersFromRemote(freshOrders, source = "upsertOrdersFromRemote") {
534
830
  if (!(freshOrders == null ? void 0 : freshOrders.length)) {
535
831
  this.logInfo("upsertOrdersFromRemote-订单列表为空", {});
536
832
  return;
537
833
  }
538
- this.logInfo("upsertOrdersFromRemote-开始", { count: freshOrders.length });
539
- await this.mergeOrdersToStore(freshOrders, "upsertOrdersFromRemote");
834
+ this.logInfo("upsertOrdersFromRemote-开始", { count: freshOrders.length, source });
835
+ await this.mergeOrdersToStore(freshOrders, source);
540
836
  }
541
837
  async markOrderSyncedByExternalSaleNumber(params) {
542
838
  const externalSaleNumber = params.externalSaleNumber;
@@ -562,7 +858,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
562
858
  ...existing,
563
859
  ...params.patch || {},
564
860
  external_sale_number: existing.external_sale_number ?? externalSaleNumber,
565
- need_sync: 0
861
+ need_sync: 0,
862
+ is_draft_order: 0
566
863
  });
567
864
  const storageKey = this.getOrderStorageKey(nextOrder) || key;
568
865
  this.store.list = this.store.list.map((order, index) => {
@@ -587,7 +884,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
587
884
  * 将本地待同步订单按 SQLite storage key 合并进 store 并落库。
588
885
  * checkout 离线兜底可能没有 order_id,但通常会有 external_sale_number。
589
886
  */
590
- async upsertPendingSyncOrders(pendingOrders) {
887
+ async upsertPendingSyncOrders(pendingOrders, options = {}) {
591
888
  if (!(pendingOrders == null ? void 0 : pendingOrders.length)) {
592
889
  this.logInfo("upsertPendingSyncOrders-订单列表为空", {});
593
890
  return;
@@ -595,11 +892,26 @@ var OrderModule = class extends import_BaseModule.BaseModule {
595
892
  const pendingMap = /* @__PURE__ */ new Map();
596
893
  const memoryPendingMap = /* @__PURE__ */ new Map();
597
894
  for (const order of pendingOrders) {
598
- const storageKey = this.getOrderStorageKey(order);
895
+ const normalizedOrder = this.normalizeOrderCollectionsForIngress(
896
+ order,
897
+ "upsertPendingSyncOrders.incoming"
898
+ );
899
+ const pendingOrder = {
900
+ ...normalizedOrder,
901
+ need_sync: 1,
902
+ is_draft_order: 0
903
+ };
904
+ const storageKey = this.getOrderStorageKey(pendingOrder);
599
905
  if (!storageKey)
600
906
  continue;
601
- pendingMap.set(storageKey, order);
602
- memoryPendingMap.set(storageKey, this.normalizeOrderForMemoryList(order));
907
+ pendingMap.set(storageKey, pendingOrder);
908
+ memoryPendingMap.set(
909
+ storageKey,
910
+ this.normalizeOrderForMemoryList(
911
+ pendingOrder,
912
+ "upsertPendingSyncOrders.memory"
913
+ )
914
+ );
603
915
  }
604
916
  if (pendingMap.size === 0) {
605
917
  this.logError("upsertPendingSyncOrders-订单缺少可落库标识", {
@@ -608,9 +920,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
608
920
  return;
609
921
  }
610
922
  this.logInfo("upsertPendingSyncOrders-开始", { count: pendingMap.size });
611
- const patchedOrders = [...pendingMap.values()];
612
923
  const mergeActions = {};
613
- const updatedList = [...this.store.list];
924
+ const updatedList = this.store.list.map(
925
+ (order) => this.normalizeOrderForMemoryList(order, "upsertPendingSyncOrders.existingMemory")
926
+ );
614
927
  const identityKeyToIndex = /* @__PURE__ */ new Map();
615
928
  for (let index = 0; index < updatedList.length; index += 1) {
616
929
  for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
@@ -624,11 +937,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
624
937
  this.getOrderIdentityMatchKeys(pendingOrder)
625
938
  );
626
939
  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);
940
+ const existingOrder = updatedList[matchIndex];
941
+ const mergedOrder = this.mergeOrderRecords(existingOrder, pendingOrder);
942
+ const nextOrder = {
943
+ ...mergedOrder,
944
+ need_sync: 1,
945
+ is_draft_order: 0
946
+ };
947
+ updatedList[matchIndex] = nextOrder;
948
+ const pendingSnapshot = pendingMap.get(storageKey);
949
+ if (pendingSnapshot) {
950
+ pendingMap.set(
951
+ storageKey,
952
+ this.reconcileOverwriteOrderCollections(existingOrder, pendingSnapshot)
953
+ );
954
+ }
955
+ this.registerOrderIdentityKeys(identityKeyToIndex, nextOrder, matchIndex);
632
956
  mergeActions[storageKey] = "update";
633
957
  continue;
634
958
  }
@@ -637,15 +961,99 @@ var OrderModule = class extends import_BaseModule.BaseModule {
637
961
  this.registerOrderIdentityKeys(identityKeyToIndex, pendingOrder, insertIndex);
638
962
  mergeActions[storageKey] = "insert";
639
963
  }
964
+ const patchedOrders = [...pendingMap.values()];
965
+ const previousList = this.store.list;
640
966
  this.store.list = this.runOrderStoreSelfCheck(updatedList, "upsertPendingSyncOrders.store");
641
967
  this.syncOrdersMap();
642
- await this.patchOrdersInSQLite(patchedOrders, "upsertPendingSyncOrders", mergeActions);
968
+ try {
969
+ await this.patchOrdersInSQLite(
970
+ patchedOrders,
971
+ "upsertPendingSyncOrders",
972
+ mergeActions,
973
+ options
974
+ );
975
+ } catch (error) {
976
+ this.store.list = previousList;
977
+ this.syncOrdersMap();
978
+ throw error;
979
+ }
643
980
  this.logInfo("upsertPendingSyncOrders-结束", {
644
981
  count: patchedOrders.length,
645
982
  storeOrderCountAfter: this.store.list.length
646
983
  });
647
984
  await this.emitOrdersChanged(patchedOrders, "upsertPendingSyncOrders");
648
985
  }
986
+ /**
987
+ * 将 POS 草稿订单按 SQLite storage key 合并进 store 并落库。
988
+ * 草稿只表示本地可恢复快照,不进入同步队列。
989
+ */
990
+ async upsertLocalDraftOrders(draftOrders) {
991
+ if (!(draftOrders == null ? void 0 : draftOrders.length)) {
992
+ this.logInfo("upsertLocalDraftOrders-订单列表为空", {});
993
+ return;
994
+ }
995
+ const draftMap = /* @__PURE__ */ new Map();
996
+ const memoryDraftMap = /* @__PURE__ */ new Map();
997
+ for (const order of draftOrders) {
998
+ const draftOrder = {
999
+ ...order,
1000
+ need_sync: 0,
1001
+ is_draft_order: 1
1002
+ };
1003
+ const storageKey = this.getOrderStorageKey(draftOrder);
1004
+ if (!storageKey)
1005
+ continue;
1006
+ draftMap.set(storageKey, draftOrder);
1007
+ memoryDraftMap.set(storageKey, this.normalizeOrderForMemoryList(draftOrder));
1008
+ }
1009
+ if (draftMap.size === 0) {
1010
+ this.logError("upsertLocalDraftOrders-订单缺少可落库标识", {
1011
+ count: draftOrders.length
1012
+ });
1013
+ return;
1014
+ }
1015
+ this.logInfo("upsertLocalDraftOrders-开始", { count: draftMap.size });
1016
+ const patchedOrders = [...draftMap.values()];
1017
+ const mergeActions = {};
1018
+ const updatedList = [...this.store.list];
1019
+ const identityKeyToIndex = /* @__PURE__ */ new Map();
1020
+ for (let index = 0; index < updatedList.length; index += 1) {
1021
+ for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
1022
+ if (!identityKeyToIndex.has(key))
1023
+ identityKeyToIndex.set(key, index);
1024
+ }
1025
+ }
1026
+ for (const [storageKey, draftOrder] of memoryDraftMap.entries()) {
1027
+ const matchIndex = this.lookupOrderIndexByIdentityKeys(
1028
+ identityKeyToIndex,
1029
+ this.getOrderIdentityMatchKeys(draftOrder)
1030
+ );
1031
+ if (matchIndex >= 0) {
1032
+ const mergedOrder = this.mergeOrderRecords(updatedList[matchIndex], draftOrder);
1033
+ const nextOrder = {
1034
+ ...mergedOrder,
1035
+ need_sync: 0,
1036
+ is_draft_order: 1
1037
+ };
1038
+ updatedList[matchIndex] = nextOrder;
1039
+ this.registerOrderIdentityKeys(identityKeyToIndex, nextOrder, matchIndex);
1040
+ mergeActions[storageKey] = "update";
1041
+ continue;
1042
+ }
1043
+ const insertIndex = updatedList.length;
1044
+ updatedList.push(draftOrder);
1045
+ this.registerOrderIdentityKeys(identityKeyToIndex, draftOrder, insertIndex);
1046
+ mergeActions[storageKey] = "insert";
1047
+ }
1048
+ this.store.list = this.runOrderStoreSelfCheck(updatedList, "upsertLocalDraftOrders.store");
1049
+ this.syncOrdersMap();
1050
+ await this.patchOrdersInSQLite(patchedOrders, "upsertLocalDraftOrders", mergeActions);
1051
+ this.logInfo("upsertLocalDraftOrders-结束", {
1052
+ count: patchedOrders.length,
1053
+ storeOrderCountAfter: this.store.list.length
1054
+ });
1055
+ await this.emitOrdersChanged(patchedOrders, "upsertLocalDraftOrders");
1056
+ }
649
1057
  /**
650
1058
  * 通过 SSE 按自定义 query 拉取订单(支持 select/with 精简字段)
651
1059
  */
@@ -969,7 +1377,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
969
1377
  const uniqueFreshCount = uniqueFreshOrders.length;
970
1378
  const patchedOrders = [];
971
1379
  const mergeActions = {};
972
- const updatedList = [...this.store.list];
1380
+ const updatedList = this.store.list.map(
1381
+ (order) => this.normalizeOrderForMemoryList(order, `${source}.existingMemory`)
1382
+ );
973
1383
  const identityKeyToIndex = /* @__PURE__ */ new Map();
974
1384
  for (let index = 0; index < updatedList.length; index += 1) {
975
1385
  const identityKeys = this.getOrderIdentityMatchKeys(updatedList[index]);
@@ -998,9 +1408,43 @@ var OrderModule = class extends import_BaseModule.BaseModule {
998
1408
  });
999
1409
  continue;
1000
1410
  }
1001
- const mergedOrder = this.mergeOrderRecords(existingOrder, fresh);
1002
- updatedList[matchIndex] = mergedOrder;
1003
- this.registerOrderIdentityKeys(identityKeyToIndex, mergedOrder, matchIndex);
1411
+ if (this.isDraftOrder(existingOrder) && this.shouldProtectDraftOrderFromIncoming(source)) {
1412
+ this.logInfo("mergeOrdersToStore-跳过 draft 订单远端覆盖", {
1413
+ source,
1414
+ order_id: existingOrder.order_id ?? fresh.order_id ?? null,
1415
+ external_sale_number: existingOrder.external_sale_number ?? fresh.external_sale_number ?? null,
1416
+ local_is_draft_order: existingOrder.is_draft_order ?? null,
1417
+ remote_is_draft_order: fresh.is_draft_order ?? null,
1418
+ reason: "protect_draft_order_from_remote_echo"
1419
+ });
1420
+ continue;
1421
+ }
1422
+ let mergedOrder = this.mergeOrderRecords(existingOrder, fresh);
1423
+ let adjustedMatchIndex = matchIndex;
1424
+ const duplicateIndexes = /* @__PURE__ */ new Set();
1425
+ for (const key of freshIdentityKeys) {
1426
+ const duplicateIndex = identityKeyToIndex.get(key);
1427
+ if (duplicateIndex === void 0 || duplicateIndex === matchIndex)
1428
+ continue;
1429
+ duplicateIndexes.add(duplicateIndex);
1430
+ }
1431
+ if (duplicateIndexes.size > 0) {
1432
+ for (const duplicateIndex of [...duplicateIndexes].sort((left, right) => right - left)) {
1433
+ mergedOrder = this.mergeOrderRecords(mergedOrder, updatedList[duplicateIndex]);
1434
+ updatedList.splice(duplicateIndex, 1);
1435
+ if (duplicateIndex < adjustedMatchIndex)
1436
+ adjustedMatchIndex -= 1;
1437
+ }
1438
+ identityKeyToIndex.clear();
1439
+ for (let index = 0; index < updatedList.length; index += 1) {
1440
+ for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
1441
+ if (!identityKeyToIndex.has(key))
1442
+ identityKeyToIndex.set(key, index);
1443
+ }
1444
+ }
1445
+ }
1446
+ updatedList[adjustedMatchIndex] = mergedOrder;
1447
+ this.registerOrderIdentityKeys(identityKeyToIndex, mergedOrder, adjustedMatchIndex);
1004
1448
  patchedOrders.push(mergedOrder);
1005
1449
  if (mergeKey)
1006
1450
  mergeActions[mergeKey] = "update";
@@ -1236,56 +1680,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1236
1680
  }
1237
1681
  return result;
1238
1682
  }
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
1683
  mergeOrderPaymentLists(existing, incoming) {
1259
1684
  const existingList = Array.isArray(existing) ? existing : [];
1260
1685
  const incomingList = Array.isArray(incoming) ? incoming : [];
1261
1686
  if (incomingList.length === 0)
1262
1687
  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
- });
1688
+ return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(existingList, incomingList);
1287
1689
  }
1288
- mergeOrderRecords(existing, incoming, options) {
1690
+ mergeOrderRecords(existing, incoming) {
1289
1691
  const preferred = this.pickPreferredOrder(existing, incoming);
1290
1692
  const secondary = preferred === existing ? incoming : existing;
1291
1693
  const merged = {
@@ -1306,8 +1708,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1306
1708
  "updated_at",
1307
1709
  "shop_discount",
1308
1710
  "summary",
1309
- "products",
1310
- "bookings",
1311
1711
  "note",
1312
1712
  "customer_id",
1313
1713
  "customer_name",
@@ -1316,13 +1716,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1316
1716
  "contacts_info",
1317
1717
  "phone",
1318
1718
  "email",
1319
- "relation_forms"
1719
+ "relation_forms",
1720
+ "is_draft_order"
1320
1721
  ];
1321
1722
  const mergedRecord = merged;
1322
1723
  const preferredRecord = preferred;
1323
1724
  const secondaryRecord = secondary;
1725
+ const existingRecord = existing;
1324
1726
  const incomingRecord = incoming;
1325
- const previousRecord = preferred === incoming ? secondaryRecord : preferredRecord;
1727
+ const childUidRemaps = [];
1326
1728
  for (const field of fieldsToPreserve) {
1327
1729
  if (!this.isBlankIdentityValue(preferredRecord[field])) {
1328
1730
  mergedRecord[field] = preferredRecord[field];
@@ -1332,8 +1734,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1332
1734
  mergedRecord[field] = secondaryRecord[field];
1333
1735
  }
1334
1736
  }
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
1737
  for (const field of incomingPatchFields) {
1338
1738
  if (!Object.prototype.hasOwnProperty.call(incomingRecord, field))
1339
1739
  continue;
@@ -1343,21 +1743,29 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1343
1743
  continue;
1344
1744
  mergedRecord[field] = (0, import_lodash_es.cloneDeep)(incomingRecord[field]);
1345
1745
  }
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
1746
+ for (const field of ORDER_AUTHORITATIVE_COLLECTION_FIELDS) {
1747
+ if (Array.isArray(incomingRecord[field])) {
1748
+ mergedRecord[field] = this.mergeAuthoritativeOrderCollection(
1749
+ field,
1750
+ existingRecord[field],
1751
+ incomingRecord[field],
1752
+ childUidRemaps
1352
1753
  );
1353
- } else if (incomingRecord.payments !== void 0 && incomingRecord.payments !== null) {
1354
- mergedRecord.payments = (0, import_lodash_es.cloneDeep)(incomingRecord.payments);
1754
+ continue;
1755
+ }
1756
+ if (Object.prototype.hasOwnProperty.call(existingRecord, field)) {
1757
+ mergedRecord[field] = (0, import_lodash_es.cloneDeep)(existingRecord[field]);
1758
+ } else {
1759
+ delete mergedRecord[field];
1355
1760
  }
1356
1761
  }
1357
1762
  if (!this.isPendingSyncOrder(preferred) || !this.isPendingSyncOrder(secondary)) {
1358
1763
  merged.need_sync = 0;
1359
1764
  }
1360
- return merged;
1765
+ return this.normalizeOrderCollectionsForIngress(
1766
+ (0, import_orderCollectionIdentity.applyOrderCollectionUidRemaps)(merged, childUidRemaps),
1767
+ "mergeOrderRecords"
1768
+ );
1361
1769
  }
1362
1770
  summarizeDuplicateOrders(orders) {
1363
1771
  const groups = /* @__PURE__ */ new Map();
@@ -1376,7 +1784,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1376
1784
  external_sale_number: order.external_sale_number ?? null,
1377
1785
  shop_order_number: order.shop_order_number ?? null,
1378
1786
  shop_full_order_number: order.shop_full_order_number ?? null,
1379
- need_sync: order.need_sync ?? null
1787
+ need_sync: order.need_sync ?? null,
1788
+ is_draft_order: order.is_draft_order ?? null
1380
1789
  }))
1381
1790
  }));
1382
1791
  }
@@ -1394,12 +1803,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1394
1803
  const list = [];
1395
1804
  let removedCount = 0;
1396
1805
  for (const order of orders) {
1397
- const matchIndex = this.findOrderIndexByIdentity(list, order);
1806
+ const normalizedOrder = this.normalizeOrderCollectionsForIngress(
1807
+ order,
1808
+ `${source}.order`
1809
+ );
1810
+ const matchIndex = this.findOrderIndexByIdentity(list, normalizedOrder);
1398
1811
  if (matchIndex < 0) {
1399
- list.push(order);
1812
+ list.push(normalizedOrder);
1400
1813
  continue;
1401
1814
  }
1402
- list[matchIndex] = this.mergeOrderRecords(list[matchIndex], order);
1815
+ list[matchIndex] = this.mergeOrderRecords(list[matchIndex], normalizedOrder);
1403
1816
  removedCount += 1;
1404
1817
  }
1405
1818
  if (removedCount > 0) {
@@ -1479,7 +1892,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1479
1892
  return [];
1480
1893
  try {
1481
1894
  const orders = await this.dbManager.getAll(INDEXDB_STORE_NAME);
1482
- return orders || [];
1895
+ return (orders || []).map(
1896
+ (order) => this.normalizeOrderCollectionsForIngress(order, "loadOrdersFromSQLite")
1897
+ );
1483
1898
  } catch {
1484
1899
  return [];
1485
1900
  }
@@ -1487,22 +1902,44 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1487
1902
  isPendingSyncOrder(order) {
1488
1903
  return Number(order == null ? void 0 : order.need_sync) === 1;
1489
1904
  }
1905
+ isDraftOrder(order) {
1906
+ return Number(order == null ? void 0 : order.is_draft_order) === 1;
1907
+ }
1908
+ shouldProtectDraftOrderFromIncoming(source) {
1909
+ return source !== "checkoutSync";
1910
+ }
1490
1911
  normalizeRemoteSyncedOrder(order) {
1491
- if (this.isPendingSyncOrder(order))
1492
- return order;
1912
+ const normalizedOrder = this.normalizeOrderCollectionsForIngress(
1913
+ order,
1914
+ "normalizeRemoteSyncedOrder"
1915
+ );
1916
+ if (this.isPendingSyncOrder(normalizedOrder))
1917
+ return {
1918
+ ...normalizedOrder,
1919
+ is_draft_order: 0
1920
+ };
1493
1921
  return {
1494
- ...order,
1495
- need_sync: 0
1922
+ ...normalizedOrder,
1923
+ need_sync: 0,
1924
+ is_draft_order: 0
1496
1925
  };
1497
1926
  }
1498
1927
  mergeRemoteSnapshotWithPendingOrders(remoteOrders, existingOrders) {
1499
1928
  const merged = remoteOrders.map((order) => this.normalizeRemoteSyncedOrder(order));
1500
- for (const order of existingOrders) {
1501
- if (!this.isPendingSyncOrder(order))
1929
+ for (const rawOrder of existingOrders) {
1930
+ const order = this.normalizeOrderCollectionsForIngress(
1931
+ rawOrder,
1932
+ "mergeRemoteSnapshotWithPendingOrders.existingSQLite"
1933
+ );
1934
+ if (!this.isPendingSyncOrder(order) && !this.isDraftOrder(order))
1502
1935
  continue;
1503
1936
  const matchIndex = this.findOrderIndexByIdentity(merged, order);
1504
1937
  if (matchIndex >= 0) {
1505
- merged[matchIndex] = this.mergeOrderRecords(order, merged[matchIndex]);
1938
+ if (this.isDraftOrder(order)) {
1939
+ merged[matchIndex] = order;
1940
+ } else {
1941
+ merged[matchIndex] = this.mergeOrderRecords(order, merged[matchIndex]);
1942
+ }
1506
1943
  continue;
1507
1944
  }
1508
1945
  if (!this.getOrderStorageKey(order))
@@ -1530,11 +1967,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1530
1967
  * @example
1531
1968
  * await this.patchOrdersInSQLite(freshOrders)
1532
1969
  */
1533
- async patchOrdersInSQLite(orders, source, mergeActions = {}) {
1534
- if (!this.dbManager || orders.length === 0) {
1970
+ async patchOrdersInSQLite(orders, source, mergeActions = {}, options = {}) {
1971
+ if (orders.length === 0) {
1972
+ return;
1973
+ }
1974
+ if (!this.dbManager) {
1975
+ if (options.throwOnError)
1976
+ throw new Error("订单 SQLite 数据库未初始化");
1535
1977
  return;
1536
1978
  }
1537
- const ordersSnapshot = (0, import_lodash_es.cloneDeep)(orders).filter((order) => this.getOrderStorageKey(order));
1979
+ const ordersSnapshot = (0, import_lodash_es.cloneDeep)(orders).map((order) => this.normalizeOrderCollectionsForIngress(order, `${source}.sqliteIngress`)).filter((order) => this.getOrderStorageKey(order));
1538
1980
  if (ordersSnapshot.length === 0) {
1539
1981
  return;
1540
1982
  }
@@ -1569,6 +2011,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1569
2011
  for (const order of compactedToWrite) {
1570
2012
  await this.dbManager.update(INDEXDB_STORE_NAME, order);
1571
2013
  }
2014
+ } else if (options.throwOnError) {
2015
+ throw new Error("订单 SQLite 数据库不支持写入");
1572
2016
  }
1573
2017
  this.recordRecentSqliteWrite(source, compactedToWrite);
1574
2018
  this.logInfo("patchOrdersInSQLite-完成", {
@@ -1583,6 +2027,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1583
2027
  error: error instanceof Error ? error.message : String(error),
1584
2028
  orderCount: ordersSnapshot.length
1585
2029
  });
2030
+ if (options.throwOnError)
2031
+ throw error;
1586
2032
  }
1587
2033
  }
1588
2034
  /**
@@ -1591,11 +2037,21 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1591
2037
  * @example
1592
2038
  * await this.updateOrderInSQLite(freshOrder)
1593
2039
  */
1594
- async updateOrderInSQLite(order, source) {
1595
- if (!this.dbManager || !this.getOrderStorageKey(order)) {
2040
+ async updateOrderInSQLite(order, source, options = {}) {
2041
+ if (!this.getOrderStorageKey(order)) {
2042
+ if (options.throwOnError)
2043
+ throw new Error("订单缺少可用的 SQLite 存储主键");
1596
2044
  return;
1597
2045
  }
1598
- const orderSnapshot = (0, import_lodash_es.cloneDeep)(order);
2046
+ if (!this.dbManager) {
2047
+ if (options.throwOnError)
2048
+ throw new Error("订单 SQLite 数据库未初始化");
2049
+ return;
2050
+ }
2051
+ const orderSnapshot = this.normalizeOrderCollectionsForIngress(
2052
+ (0, import_lodash_es.cloneDeep)(order),
2053
+ `${source}.sqliteIngress`
2054
+ );
1599
2055
  try {
1600
2056
  await this.runInOrderSQLiteSaveQueue(async () => {
1601
2057
  let writeMethod = "none";
@@ -1613,6 +2069,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1613
2069
  } else if (typeof this.dbManager.bulkAdd === "function") {
1614
2070
  writeMethod = "bulkAdd";
1615
2071
  await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, [orderSnapshot]);
2072
+ } else if (options.throwOnError) {
2073
+ throw new Error("订单 SQLite 数据库不支持写入");
1616
2074
  }
1617
2075
  this.recordRecentSqliteWrite(source, [orderSnapshot]);
1618
2076
  this.logInfo("updateOrderInSQLite-完成", {
@@ -1626,6 +2084,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1626
2084
  error: error instanceof Error ? error.message : String(error),
1627
2085
  orderId: orderSnapshot.order_id ?? null
1628
2086
  });
2087
+ if (options.throwOnError)
2088
+ throw error;
1629
2089
  }
1630
2090
  }
1631
2091
  /**
@@ -1641,7 +2101,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1641
2101
  `${source}.snapshotNoDb`
1642
2102
  ).list;
1643
2103
  }
1644
- const remoteSnapshot = (0, import_lodash_es.cloneDeep)(orderList);
2104
+ const remoteSnapshot = (0, import_lodash_es.cloneDeep)(orderList).map(
2105
+ (order) => this.normalizeOrderCollectionsForIngress(order, `${source}.remoteIngress`)
2106
+ );
1645
2107
  let mergedSnapshot = this.compactOrderListByIdentity(
1646
2108
  remoteSnapshot.map((order) => this.normalizeRemoteSyncedOrder(order)),
1647
2109
  `${source}.remoteSnapshot`
@@ -1658,7 +2120,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1658
2120
  source,
1659
2121
  count: mergedSnapshot.length,
1660
2122
  remoteCount: remoteSnapshot.length,
1661
- preservedPendingCount: mergedSnapshot.length - remoteSnapshot.length
2123
+ preservedLocalUnsyncedCount: mergedSnapshot.length - remoteSnapshot.length
1662
2124
  });
1663
2125
  await this.dbManager.clear(INDEXDB_STORE_NAME);
1664
2126
  this.logInfo("replaceOrdersSnapshotInSQLite-clear完成", {