@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.
- package/dist/modules/Order/index.d.ts +32 -8
- package/dist/modules/Order/index.js +883 -521
- package/dist/modules/Order/payment-utils.d.ts +23 -0
- package/dist/modules/Order/payment-utils.js +203 -0
- package/dist/modules/Order/types.d.ts +33 -1
- package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
- package/dist/modules/Order/utils/orderCollectionIdentity.js +405 -0
- package/dist/modules/Order/utils.d.ts +2 -1
- package/dist/modules/Order/utils.js +6 -12
- package/dist/modules/Payment/index.d.ts +2 -0
- package/dist/modules/Payment/index.js +78 -49
- package/dist/modules/Payment/types.d.ts +26 -24
- package/dist/modules/Payment/types.js +2 -0
- package/dist/modules/Product/index.d.ts +1 -1
- package/dist/server/index.d.ts +14 -0
- package/dist/server/index.js +1826 -1000
- package/dist/server/modules/order/index.d.ts +47 -4
- package/dist/server/modules/order/index.js +1415 -711
- package/dist/server/modules/order/types.d.ts +11 -3
- package/dist/server/modules/order/types.js +1 -1
- package/dist/solution/BaseSales/index.d.ts +40 -4
- package/dist/solution/BaseSales/index.js +1268 -749
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +9 -4
- package/dist/solution/BaseSales/utils/parseSalesResponse.js +6 -8
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +13 -1
- package/dist/solution/BookingTicket/index.js +2 -1
- package/dist/utils/payment-number.d.ts +9 -0
- package/dist/utils/payment-number.js +69 -0
- package/lib/modules/Order/index.d.ts +32 -8
- package/lib/modules/Order/index.js +270 -64
- package/lib/modules/Order/payment-utils.d.ts +23 -0
- package/lib/modules/Order/payment-utils.js +193 -0
- package/lib/modules/Order/types.d.ts +33 -1
- package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
- package/lib/modules/Order/utils/orderCollectionIdentity.js +415 -0
- package/lib/modules/Order/utils.d.ts +2 -1
- package/lib/modules/Order/utils.js +6 -14
- package/lib/modules/Payment/index.d.ts +2 -0
- package/lib/modules/Payment/index.js +33 -12
- package/lib/modules/Payment/types.d.ts +26 -24
- package/lib/modules/Product/index.d.ts +1 -1
- package/lib/server/index.d.ts +14 -0
- package/lib/server/index.js +604 -8
- package/lib/server/modules/order/index.d.ts +47 -4
- package/lib/server/modules/order/index.js +578 -116
- package/lib/server/modules/order/types.d.ts +11 -3
- package/lib/solution/BaseSales/index.d.ts +40 -4
- package/lib/solution/BaseSales/index.js +363 -37
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +9 -4
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +4 -5
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +13 -1
- package/lib/solution/BookingTicket/index.js +2 -1
- package/lib/utils/payment-number.d.ts +9 -0
- package/lib/utils/payment-number.js +64 -0
- 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
|
-
|
|
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
|
|
484
|
-
|
|
485
|
-
|
|
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
|
|
765
|
+
return normalizedOrder;
|
|
489
766
|
}
|
|
490
767
|
return {
|
|
491
|
-
...
|
|
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
|
-
|
|
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(
|
|
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([
|
|
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,
|
|
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
|
|
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,
|
|
602
|
-
memoryPendingMap.set(
|
|
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 =
|
|
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
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
incomingRecord
|
|
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
|
-
|
|
1354
|
-
|
|
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
|
|
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
|
|
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(
|
|
1812
|
+
list.push(normalizedOrder);
|
|
1400
1813
|
continue;
|
|
1401
1814
|
}
|
|
1402
|
-
list[matchIndex] = this.mergeOrderRecords(list[matchIndex],
|
|
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
|
-
|
|
1492
|
-
|
|
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
|
-
...
|
|
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
|
|
1501
|
-
|
|
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
|
-
|
|
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 (
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
2123
|
+
preservedLocalUnsyncedCount: mergedSnapshot.length - remoteSnapshot.length
|
|
1662
2124
|
});
|
|
1663
2125
|
await this.dbManager.clear(INDEXDB_STORE_NAME);
|
|
1664
2126
|
this.logInfo("replaceOrdersSnapshotInSQLite-clear完成", {
|