@pisell/pisellos 2.3.39 → 2.3.41
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/core/index.d.ts +2 -0
- package/dist/core/index.js +7 -0
- package/dist/model/strategy/adapter/promotion/adapter.d.ts +4 -0
- package/dist/model/strategy/adapter/promotion/adapter.js +23 -0
- package/dist/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
- package/dist/model/strategy/adapter/promotion/evaluator.js +279 -6
- package/dist/model/strategy/adapter/promotion/examples.d.ts +86 -0
- package/dist/model/strategy/adapter/promotion/examples.js +99 -0
- package/dist/model/strategy/adapter/promotion/index.d.ts +1 -1
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/model/strategy/adapter/promotion/type.d.ts +90 -2
- package/dist/model/strategy/adapter/promotion/type.js +45 -0
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +5 -3
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +6 -3
- package/dist/modules/Discount/index.d.ts +0 -1
- package/dist/modules/Discount/index.js +11 -40
- package/dist/modules/Discount/types.d.ts +0 -1
- package/dist/modules/OpenData/index.d.ts +2 -0
- package/dist/modules/OpenData/index.js +10 -2
- package/dist/modules/Order/index.d.ts +29 -12
- package/dist/modules/Order/index.js +750 -509
- package/dist/modules/Order/payment-utils.d.ts +26 -0
- package/dist/modules/Order/payment-utils.js +225 -0
- package/dist/modules/Order/types.d.ts +33 -10
- package/dist/modules/Order/utils/orderCollectionIdentity.js +7 -2
- package/dist/modules/Order/utils.d.ts +0 -10
- package/dist/modules/Order/utils.js +13 -41
- package/dist/modules/Payment/index.d.ts +2 -0
- package/dist/modules/Payment/index.js +79 -50
- package/dist/modules/Payment/types.d.ts +99 -28
- package/dist/modules/Payment/types.js +20 -3
- package/dist/modules/Payment/walletpass.d.ts +25 -1
- package/dist/modules/Payment/walletpass.js +707 -157
- package/dist/modules/Product/types.d.ts +0 -1
- package/dist/modules/ProductList/index.js +14 -33
- package/dist/modules/Quotation/index.d.ts +1 -1
- package/dist/modules/Quotation/index.js +2 -2
- package/dist/modules/Rules/index.d.ts +1 -0
- package/dist/modules/Rules/index.js +89 -96
- package/dist/modules/SalesSummary/index.js +13 -12
- package/dist/modules/ScanOrderLogger/index.d.ts +0 -2
- package/dist/modules/ScanOrderLogger/index.js +2 -15
- package/dist/modules/ScanOrderLogger/providers/feishu.js +27 -45
- package/dist/modules/ScanOrderLogger/types.d.ts +0 -1
- package/dist/modules/Schedule/index.d.ts +1 -3
- package/dist/modules/Schedule/index.js +16 -21
- package/dist/modules/Summary/utils.js +13 -38
- package/dist/modules/index.d.ts +0 -2
- package/dist/modules/index.js +1 -3
- package/dist/plugins/window.d.ts +0 -1
- package/dist/server/index.d.ts +16 -14
- package/dist/server/index.js +1925 -1143
- package/dist/server/modules/order/index.d.ts +54 -4
- package/dist/server/modules/order/index.js +1600 -700
- 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 +109 -20
- package/dist/solution/BaseSales/index.js +1800 -480
- package/dist/solution/BaseSales/types.d.ts +52 -0
- package/dist/solution/BaseSales/types.js +2 -1
- package/dist/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
- package/dist/solution/BaseSales/utils/cartPromotion.js +90 -31
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/dist/solution/BookingByStep/index.d.ts +2 -17
- package/dist/solution/BookingByStep/index.js +215 -294
- package/dist/solution/BookingByStep/types.d.ts +1 -2
- package/dist/solution/BookingByStep/types.js +1 -3
- package/dist/solution/BookingByStep/utils/capacity.js +1 -17
- package/dist/solution/BookingByStep/utils/timeslots.d.ts +1 -3
- package/dist/solution/BookingByStep/utils/timeslots.js +12 -19
- package/dist/solution/BookingTicket/index.d.ts +7 -3
- package/dist/solution/BookingTicket/index.js +132 -49
- package/dist/solution/BookingTicket/utils/addProductDecision.js +6 -0
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +172 -82
- package/dist/solution/BookingTicket/utils/weighingProductSku.d.ts +5 -0
- package/dist/solution/BookingTicket/utils/weighingProductSku.js +45 -0
- package/dist/solution/Sales/index.d.ts +1 -0
- package/dist/solution/Sales/index.js +10 -2
- package/dist/solution/ScanOrder/index.d.ts +14 -26
- package/dist/solution/ScanOrder/index.js +756 -1148
- package/dist/solution/ScanOrder/types.d.ts +1 -21
- package/dist/solution/ScanOrder/utils.d.ts +0 -8
- package/dist/solution/ScanOrder/utils.js +25 -66
- package/dist/solution/ShopDiscount/index.d.ts +0 -1
- package/dist/solution/ShopDiscount/index.js +87 -125
- package/dist/solution/VenueBooking/index.d.ts +11 -39
- package/dist/solution/VenueBooking/index.js +860 -1176
- package/dist/solution/VenueBooking/types.d.ts +0 -3
- package/dist/solution/VenueBooking/utils/resource.js +0 -1
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +4 -4
- package/dist/solution/VenueBooking/utils/slotMerge.js +5 -10
- package/dist/solution/index.d.ts +0 -1
- package/dist/solution/index.js +1 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/payment-number.d.ts +9 -0
- package/dist/utils/payment-number.js +69 -0
- package/lib/core/index.d.ts +2 -0
- package/lib/core/index.js +4 -0
- package/lib/model/strategy/adapter/promotion/adapter.d.ts +4 -0
- package/lib/model/strategy/adapter/promotion/adapter.js +20 -0
- package/lib/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
- package/lib/model/strategy/adapter/promotion/evaluator.js +235 -0
- package/lib/model/strategy/adapter/promotion/examples.d.ts +86 -0
- package/lib/model/strategy/adapter/promotion/examples.js +91 -0
- package/lib/model/strategy/adapter/promotion/index.d.ts +1 -1
- package/lib/model/strategy/adapter/promotion/index.js +51 -0
- package/lib/model/strategy/adapter/promotion/type.d.ts +90 -2
- package/lib/model/strategy/adapter/promotion/type.js +2 -0
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +2 -1
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -1
- package/lib/modules/Discount/index.d.ts +0 -1
- package/lib/modules/Discount/index.js +0 -9
- package/lib/modules/Discount/types.d.ts +0 -1
- package/lib/modules/OpenData/index.d.ts +2 -0
- package/lib/modules/OpenData/index.js +6 -1
- package/lib/modules/Order/index.d.ts +29 -12
- package/lib/modules/Order/index.js +196 -86
- package/lib/modules/Order/payment-utils.d.ts +26 -0
- package/lib/modules/Order/payment-utils.js +224 -0
- package/lib/modules/Order/types.d.ts +33 -10
- package/lib/modules/Order/utils/orderCollectionIdentity.js +3 -0
- package/lib/modules/Order/utils.d.ts +0 -10
- package/lib/modules/Order/utils.js +16 -40
- package/lib/modules/Payment/index.d.ts +2 -0
- package/lib/modules/Payment/index.js +34 -13
- package/lib/modules/Payment/types.d.ts +99 -28
- package/lib/modules/Payment/types.js +4 -3
- package/lib/modules/Payment/walletpass.d.ts +25 -1
- package/lib/modules/Payment/walletpass.js +470 -21
- package/lib/modules/Product/types.d.ts +0 -1
- package/lib/modules/ProductList/index.js +31 -40
- package/lib/modules/Quotation/index.d.ts +1 -1
- package/lib/modules/Quotation/index.js +2 -2
- package/lib/modules/Rules/index.d.ts +1 -0
- package/lib/modules/Rules/index.js +47 -40
- package/lib/modules/SalesSummary/index.js +7 -6
- package/lib/modules/ScanOrderLogger/index.d.ts +0 -2
- package/lib/modules/ScanOrderLogger/index.js +1 -13
- package/lib/modules/ScanOrderLogger/providers/feishu.js +6 -15
- package/lib/modules/ScanOrderLogger/types.d.ts +0 -1
- package/lib/modules/Schedule/index.d.ts +1 -3
- package/lib/modules/Schedule/index.js +8 -10
- package/lib/modules/Summary/utils.js +1 -21
- package/lib/modules/index.d.ts +0 -2
- package/lib/modules/index.js +1 -5
- package/lib/plugins/window.d.ts +0 -1
- package/lib/server/index.d.ts +16 -14
- package/lib/server/index.js +675 -83
- package/lib/server/modules/order/index.d.ts +54 -4
- package/lib/server/modules/order/index.js +679 -66
- package/lib/server/modules/order/types.d.ts +11 -3
- package/lib/solution/BaseSales/index.d.ts +109 -20
- package/lib/solution/BaseSales/index.js +883 -70
- package/lib/solution/BaseSales/types.d.ts +52 -0
- package/lib/solution/BaseSales/types.js +2 -1
- package/lib/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
- package/lib/solution/BaseSales/utils/cartPromotion.js +63 -12
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/lib/solution/BookingByStep/index.d.ts +2 -17
- package/lib/solution/BookingByStep/index.js +18 -60
- package/lib/solution/BookingByStep/types.d.ts +1 -2
- package/lib/solution/BookingByStep/types.js +0 -5
- package/lib/solution/BookingByStep/utils/capacity.js +1 -20
- package/lib/solution/BookingByStep/utils/timeslots.d.ts +1 -3
- package/lib/solution/BookingByStep/utils/timeslots.js +11 -19
- package/lib/solution/BookingTicket/index.d.ts +7 -3
- package/lib/solution/BookingTicket/index.js +62 -9
- package/lib/solution/BookingTicket/utils/addProductDecision.js +4 -0
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +36 -4
- package/lib/solution/BookingTicket/utils/weighingProductSku.d.ts +5 -0
- package/lib/solution/BookingTicket/utils/weighingProductSku.js +63 -0
- package/lib/solution/Sales/index.d.ts +1 -0
- package/lib/solution/Sales/index.js +5 -3
- package/lib/solution/ScanOrder/index.d.ts +14 -26
- package/lib/solution/ScanOrder/index.js +190 -449
- package/lib/solution/ScanOrder/types.d.ts +1 -21
- package/lib/solution/ScanOrder/utils.d.ts +0 -8
- package/lib/solution/ScanOrder/utils.js +0 -31
- package/lib/solution/ShopDiscount/index.d.ts +0 -1
- package/lib/solution/ShopDiscount/index.js +0 -14
- package/lib/solution/VenueBooking/index.d.ts +11 -39
- package/lib/solution/VenueBooking/index.js +123 -328
- package/lib/solution/VenueBooking/types.d.ts +0 -3
- package/lib/solution/VenueBooking/utils/resource.js +0 -1
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +4 -4
- package/lib/solution/VenueBooking/utils/slotMerge.js +4 -6
- package/lib/solution/index.d.ts +0 -1
- package/lib/solution/index.js +1 -3
- package/lib/types/index.d.ts +1 -1
- package/lib/utils/payment-number.d.ts +9 -0
- package/lib/utils/payment-number.js +64 -0
- package/package.json +1 -1
- package/dist/modules/Holder/index.d.ts +0 -48
- package/dist/modules/Holder/index.js +0 -640
- package/dist/modules/Holder/types.d.ts +0 -123
- package/dist/modules/Holder/types.js +0 -1
- package/dist/modules/Holder/utils.d.ts +0 -13
- package/dist/modules/Holder/utils.js +0 -34
- package/dist/modules/ResourcePlanner/index.d.ts +0 -24
- package/dist/modules/ResourcePlanner/index.js +0 -181
- package/dist/modules/ResourcePlanner/planner.d.ts +0 -14
- package/dist/modules/ResourcePlanner/planner.js +0 -1069
- package/dist/modules/ResourcePlanner/types.d.ts +0 -227
- package/dist/modules/ResourcePlanner/types.js +0 -1
- package/dist/solution/UnifiedBookingSales/index.d.ts +0 -183
- package/dist/solution/UnifiedBookingSales/index.js +0 -1871
- package/dist/solution/UnifiedBookingSales/types.d.ts +0 -143
- package/dist/solution/UnifiedBookingSales/types.js +0 -11
- package/lib/modules/Holder/index.d.ts +0 -48
- package/lib/modules/Holder/index.js +0 -402
- package/lib/modules/Holder/types.d.ts +0 -123
- package/lib/modules/Holder/types.js +0 -17
- package/lib/modules/Holder/utils.d.ts +0 -13
- package/lib/modules/Holder/utils.js +0 -71
- package/lib/modules/ResourcePlanner/index.d.ts +0 -24
- package/lib/modules/ResourcePlanner/index.js +0 -148
- package/lib/modules/ResourcePlanner/planner.d.ts +0 -14
- package/lib/modules/ResourcePlanner/planner.js +0 -933
- package/lib/modules/ResourcePlanner/types.d.ts +0 -227
- package/lib/modules/ResourcePlanner/types.js +0 -17
- package/lib/solution/UnifiedBookingSales/index.d.ts +0 -183
- package/lib/solution/UnifiedBookingSales/index.js +0 -1076
- package/lib/solution/UnifiedBookingSales/types.d.ts +0 -143
- package/lib/solution/UnifiedBookingSales/types.js +0 -33
|
@@ -37,6 +37,7 @@ var import_dayjs = __toESM(require("dayjs"));
|
|
|
37
37
|
var import_BaseModule = require("../../../modules/BaseModule");
|
|
38
38
|
var import_orderCollectionIdentity = require("../../../modules/Order/utils/orderCollectionIdentity");
|
|
39
39
|
var import_types = require("./types");
|
|
40
|
+
var import_payment_utils = require("../../../modules/Order/payment-utils");
|
|
40
41
|
var INDEXDB_STORE_NAME = "orders";
|
|
41
42
|
var ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY = "server_order_last_full_fetch_at";
|
|
42
43
|
var ORDER_SYNC_THROTTLE_MS_STORAGE_KEY = "order_sync_throttle_ms";
|
|
@@ -46,10 +47,13 @@ var ORDER_SILENT_REFRESH_MIN_INTERVAL_MS = 3e4;
|
|
|
46
47
|
var ORDER_BUSINESS_WRITE_SOURCES = /* @__PURE__ */ new Set([
|
|
47
48
|
"upsertOrdersFromRemote",
|
|
48
49
|
"upsertPendingSyncOrders",
|
|
50
|
+
"upsertLocalDraftOrders",
|
|
49
51
|
"overwriteExistingOrder",
|
|
50
|
-
"markOrderSyncedByExternalSaleNumber"
|
|
52
|
+
"markOrderSyncedByExternalSaleNumber",
|
|
53
|
+
"updateLocalPayment"
|
|
51
54
|
]);
|
|
52
55
|
var ORDER_MERGE_SELF_CHECK = false;
|
|
56
|
+
var PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER = "__pisell_os_pending_payment_without_unique_number__";
|
|
53
57
|
var ORDER_AUTHORITATIVE_COLLECTION_FIELDS = ["products", "bookings", "payments"];
|
|
54
58
|
var ORDER_COLLECTION_KIND_BY_FIELD = {
|
|
55
59
|
products: "product",
|
|
@@ -100,7 +104,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
100
104
|
this.updateCreateStore();
|
|
101
105
|
}
|
|
102
106
|
if (Array.isArray((_a = options == null ? void 0 : options.initialState) == null ? void 0 : _a.list)) {
|
|
103
|
-
this.store.list =
|
|
107
|
+
this.store.list = this.normalizeOrdersForMemoryList(
|
|
108
|
+
options.initialState.list,
|
|
109
|
+
"initialState"
|
|
110
|
+
);
|
|
104
111
|
this.syncOrdersMap();
|
|
105
112
|
this.emitOrdersChanged([], "initialState");
|
|
106
113
|
} else {
|
|
@@ -166,7 +173,35 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
166
173
|
* 仅记录计数与订单标识,不输出商品、预约、支付或客户明细。
|
|
167
174
|
*/
|
|
168
175
|
normalizeOrderCollectionsForIngress(order, source) {
|
|
169
|
-
const
|
|
176
|
+
const sourceOrder = (0, import_lodash_es.cloneDeep)(order);
|
|
177
|
+
const sourceOrderRecord = sourceOrder;
|
|
178
|
+
if (Array.isArray(sourceOrderRecord.payments)) {
|
|
179
|
+
sourceOrderRecord.payments = sourceOrderRecord.payments.map((payment) => {
|
|
180
|
+
if (!(0, import_payment_utils.isPendingOrderPayment)(payment) || (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => key.startsWith("unique_payment_number:"))) {
|
|
181
|
+
return payment;
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
...payment,
|
|
185
|
+
[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER]: true
|
|
186
|
+
};
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
const result = (0, import_orderCollectionIdentity.normalizeOrderCollections)(sourceOrder);
|
|
190
|
+
const normalizedOrderRecord = result.order;
|
|
191
|
+
if (Array.isArray(normalizedOrderRecord.payments)) {
|
|
192
|
+
normalizedOrderRecord.payments = normalizedOrderRecord.payments.map(
|
|
193
|
+
(payment) => {
|
|
194
|
+
if (!(payment == null ? void 0 : payment[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER]))
|
|
195
|
+
return payment;
|
|
196
|
+
const nextPayment = { ...payment };
|
|
197
|
+
const metadata = { ...nextPayment.metadata || {} };
|
|
198
|
+
delete metadata.unique_payment_number;
|
|
199
|
+
delete nextPayment[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER];
|
|
200
|
+
nextPayment.metadata = metadata;
|
|
201
|
+
return nextPayment;
|
|
202
|
+
}
|
|
203
|
+
);
|
|
204
|
+
}
|
|
170
205
|
const kinds = ["product", "booking", "payment"];
|
|
171
206
|
const hasChanges = kinds.some((kind) => {
|
|
172
207
|
const stats = result.stats[kind];
|
|
@@ -202,9 +237,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
202
237
|
/**
|
|
203
238
|
* incoming 决定权威成员集合;同一持久化行仍从 existing 补齐 incoming 省略的本地展示字段。
|
|
204
239
|
*/
|
|
205
|
-
mergeAuthoritativeOrderCollection(field, existing, incoming, uidRemaps = []) {
|
|
240
|
+
mergeAuthoritativeOrderCollection(field, existing, incoming, uidRemaps = [], options = {}) {
|
|
206
241
|
const kind = ORDER_COLLECTION_KIND_BY_FIELD[field];
|
|
207
242
|
const existingItems = Array.isArray(existing) ? existing : [];
|
|
243
|
+
if (field === "payments" && options.preserveIdentifiedPendingPayments) {
|
|
244
|
+
return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(
|
|
245
|
+
existingItems,
|
|
246
|
+
incoming,
|
|
247
|
+
{ preserveUnmatchedExistingWhen: import_payment_utils.isIdentifiedPendingOrderPayment }
|
|
248
|
+
);
|
|
249
|
+
}
|
|
208
250
|
return incoming.map((incomingItem) => {
|
|
209
251
|
const existingItem = existingItems.find(
|
|
210
252
|
(item) => (0, import_orderCollectionIdentity.isSameOrderCollectionItem)(kind, item, incomingItem)
|
|
@@ -460,17 +502,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
460
502
|
return DEFAULT_ORDER_SYNC_THROTTLE_MS;
|
|
461
503
|
}
|
|
462
504
|
async preload() {
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
this.store.list = (0, import_lodash_es.cloneDeep)(orders);
|
|
469
|
-
this.syncOrdersMap();
|
|
470
|
-
this.emitOrdersChanged([], "preload");
|
|
471
|
-
this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
|
|
472
|
-
};
|
|
473
|
-
getData();
|
|
505
|
+
const orders = await this.loadOrdersByServer();
|
|
506
|
+
this.store.list = (0, import_lodash_es.cloneDeep)(orders);
|
|
507
|
+
this.syncOrdersMap();
|
|
508
|
+
await this.emitOrdersChanged([], "preload");
|
|
509
|
+
await this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
|
|
474
510
|
}
|
|
475
511
|
getOrders() {
|
|
476
512
|
return this.store.list;
|
|
@@ -482,6 +518,27 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
482
518
|
getOrderByOrderId(orderId) {
|
|
483
519
|
return this.store.map.get(this.getIdKey(orderId));
|
|
484
520
|
}
|
|
521
|
+
buildLocalPaymentOrderLogContext(order) {
|
|
522
|
+
if (!order)
|
|
523
|
+
return {};
|
|
524
|
+
return {
|
|
525
|
+
order_id: order.order_id ?? null,
|
|
526
|
+
external_sale_number: order.external_sale_number ?? null,
|
|
527
|
+
order_number: order.order_number ?? null,
|
|
528
|
+
shop_order_number: order.shop_order_number ?? null,
|
|
529
|
+
shop_full_order_number: order.shop_full_order_number ?? null,
|
|
530
|
+
order_status: order.status ?? null,
|
|
531
|
+
payment_status: order.payment_status ?? null,
|
|
532
|
+
is_draft_order: Number(order.is_draft_order || 0),
|
|
533
|
+
need_sync: Number(order.need_sync || 0),
|
|
534
|
+
platform: order.platform ?? null,
|
|
535
|
+
business_code: order.business_code ?? null,
|
|
536
|
+
order_sales_channel: order.order_sales_channel ?? null,
|
|
537
|
+
sales_channel: order.sales_channel ?? null,
|
|
538
|
+
order_type: order.type ?? null,
|
|
539
|
+
payments_count: Array.isArray(order.payments) ? order.payments.length : 0
|
|
540
|
+
};
|
|
541
|
+
}
|
|
485
542
|
getLocalOrderFromMemoryByLookup(lookup) {
|
|
486
543
|
const key = this.getIdKey(lookup);
|
|
487
544
|
const memoryOrderById = this.store.map.get(key);
|
|
@@ -490,28 +547,200 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
490
547
|
const memoryOrder = this.store.list.find((order) => this.isOrderLookupMatch(order, key));
|
|
491
548
|
return memoryOrder || null;
|
|
492
549
|
}
|
|
493
|
-
async getLocalOrderByLookup(lookup) {
|
|
550
|
+
async getLocalOrderByLookup(lookup, options = {}) {
|
|
494
551
|
const key = this.getIdKey(lookup);
|
|
552
|
+
const logContext = {
|
|
553
|
+
operation_id: options.operationId,
|
|
554
|
+
lookup: key,
|
|
555
|
+
memory_order_count: this.store.list.length
|
|
556
|
+
};
|
|
557
|
+
if (options.operationId) {
|
|
558
|
+
this.logInfo("getLocalOrderByLookup-localPayment-开始", logContext);
|
|
559
|
+
}
|
|
495
560
|
const memoryOrderById = this.store.map.get(key);
|
|
496
|
-
if (memoryOrderById)
|
|
561
|
+
if (memoryOrderById) {
|
|
562
|
+
if (options.operationId) {
|
|
563
|
+
this.logInfo("getLocalOrderByLookup-localPayment-命中内存映射", {
|
|
564
|
+
...logContext,
|
|
565
|
+
...this.buildLocalPaymentOrderLogContext(memoryOrderById)
|
|
566
|
+
});
|
|
567
|
+
}
|
|
497
568
|
return memoryOrderById;
|
|
569
|
+
}
|
|
498
570
|
const memoryOrder = this.store.list.find((order) => this.isOrderLookupMatch(order, key));
|
|
499
|
-
if (memoryOrder)
|
|
571
|
+
if (memoryOrder) {
|
|
572
|
+
if (options.operationId) {
|
|
573
|
+
this.logInfo("getLocalOrderByLookup-localPayment-命中内存列表", {
|
|
574
|
+
...logContext,
|
|
575
|
+
...this.buildLocalPaymentOrderLogContext(memoryOrder)
|
|
576
|
+
});
|
|
577
|
+
}
|
|
500
578
|
return memoryOrder;
|
|
579
|
+
}
|
|
580
|
+
if (options.operationId) {
|
|
581
|
+
this.logInfo("getLocalOrderByLookup-localPayment-开始读取SQLite", logContext);
|
|
582
|
+
}
|
|
501
583
|
const orders = await this.loadOrdersFromSQLite();
|
|
502
584
|
const localOrder = orders.find((order) => this.isOrderLookupMatch(order, key));
|
|
503
|
-
if (!localOrder)
|
|
585
|
+
if (!localOrder) {
|
|
586
|
+
if (options.operationId) {
|
|
587
|
+
this.logWarning("getLocalOrderByLookup-localPayment-SQLite未命中", {
|
|
588
|
+
...logContext,
|
|
589
|
+
sqlite_order_count: orders.length
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
this.store.list = this.normalizeOrdersForMemoryList(
|
|
595
|
+
orders,
|
|
596
|
+
"getLocalOrderByLookup.sqliteMemory"
|
|
597
|
+
);
|
|
598
|
+
this.syncOrdersMap();
|
|
599
|
+
const normalizedOrder = this.normalizeOrderForMemoryList(localOrder);
|
|
600
|
+
if (options.operationId) {
|
|
601
|
+
this.logInfo("getLocalOrderByLookup-localPayment-SQLite命中", {
|
|
602
|
+
...logContext,
|
|
603
|
+
sqlite_order_count: orders.length,
|
|
604
|
+
...this.buildLocalPaymentOrderLogContext(normalizedOrder)
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
return normalizedOrder;
|
|
608
|
+
}
|
|
609
|
+
async getLocalPayment(params) {
|
|
610
|
+
const logContext = {
|
|
611
|
+
operation_id: params.operationId,
|
|
612
|
+
sale_id: params.saleId,
|
|
613
|
+
payment_number: params.paymentNumber
|
|
614
|
+
};
|
|
615
|
+
this.logInfo("getLocalPayment-开始", logContext);
|
|
616
|
+
try {
|
|
617
|
+
const order = await this.getLocalOrderByLookup(params.saleId, {
|
|
618
|
+
operationId: params.operationId
|
|
619
|
+
});
|
|
620
|
+
if (!order) {
|
|
621
|
+
this.logWarning("getLocalPayment-订单未命中", logContext);
|
|
622
|
+
return null;
|
|
623
|
+
}
|
|
624
|
+
const payments = order.payments || [];
|
|
625
|
+
const match = (0, import_payment_utils.resolveOrderPaymentIdentity)(
|
|
626
|
+
payments,
|
|
627
|
+
params.paymentNumber,
|
|
628
|
+
"compat"
|
|
629
|
+
);
|
|
630
|
+
if (!match) {
|
|
631
|
+
this.logWarning("getLocalPayment-支付项未命中", {
|
|
632
|
+
...logContext,
|
|
633
|
+
...this.buildLocalPaymentOrderLogContext(order),
|
|
634
|
+
payments
|
|
635
|
+
});
|
|
636
|
+
return null;
|
|
637
|
+
}
|
|
638
|
+
this.logInfo("getLocalPayment-支付项命中", {
|
|
639
|
+
...logContext,
|
|
640
|
+
...this.buildLocalPaymentOrderLogContext(order),
|
|
641
|
+
matched_by: match.matchedBy,
|
|
642
|
+
payment_index: match.index,
|
|
643
|
+
payment: match.payment
|
|
644
|
+
});
|
|
645
|
+
return {
|
|
646
|
+
order,
|
|
647
|
+
payment: match.payment,
|
|
648
|
+
paymentIndex: match.index,
|
|
649
|
+
matchedBy: match.matchedBy
|
|
650
|
+
};
|
|
651
|
+
} catch (error) {
|
|
652
|
+
this.logError("getLocalPayment-查询失败", {
|
|
653
|
+
...logContext,
|
|
654
|
+
error: error instanceof Error ? error.message : String(error)
|
|
655
|
+
});
|
|
656
|
+
throw error;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
async updateLocalPayment(params) {
|
|
660
|
+
const logContext = {
|
|
661
|
+
operation_id: params.operationId,
|
|
662
|
+
sale_id: params.saleId,
|
|
663
|
+
payment_number: params.paymentNumber,
|
|
664
|
+
incoming_payment_update: params.updates
|
|
665
|
+
};
|
|
666
|
+
this.logInfo("updateLocalPayment-开始", logContext);
|
|
667
|
+
const found = await this.getLocalPayment(params);
|
|
668
|
+
if (!found) {
|
|
669
|
+
this.logWarning("updateLocalPayment-支付项未命中", logContext);
|
|
504
670
|
return null;
|
|
505
|
-
|
|
671
|
+
}
|
|
672
|
+
const previousPayment = (0, import_lodash_es.cloneDeep)(found.payment);
|
|
673
|
+
const nextPayment = (0, import_payment_utils.mergeOrderPaymentRecord)(found.payment, {
|
|
674
|
+
...params.updates,
|
|
675
|
+
updated_at: params.updates.updated_at || (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
|
|
676
|
+
});
|
|
677
|
+
const nextOrder = {
|
|
678
|
+
...found.order,
|
|
679
|
+
payments: (found.order.payments || []).map((payment, index) => index === found.paymentIndex ? nextPayment : payment),
|
|
680
|
+
updated_at: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
|
|
681
|
+
};
|
|
682
|
+
const paymentContext = {
|
|
683
|
+
...logContext,
|
|
684
|
+
matched_by: found.matchedBy,
|
|
685
|
+
payment_index: found.paymentIndex,
|
|
686
|
+
...this.buildLocalPaymentOrderLogContext(nextOrder),
|
|
687
|
+
previous_payment: previousPayment,
|
|
688
|
+
payment: nextPayment
|
|
689
|
+
};
|
|
690
|
+
this.logInfo("updateLocalPayment-支付项合并完成", paymentContext);
|
|
691
|
+
const targetIndex = this.findOrderIndexByIdentity(this.store.list, found.order);
|
|
692
|
+
const shouldKeepInMemory = this.shouldKeepOrderInMemory(nextOrder);
|
|
693
|
+
if (targetIndex < 0 && shouldKeepInMemory) {
|
|
694
|
+
this.logError("updateLocalPayment-订单Store索引未命中", paymentContext);
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
const previousList = this.store.list;
|
|
698
|
+
this.store.list = shouldKeepInMemory ? this.store.list.map((order, index) => index === targetIndex ? nextOrder : order) : this.store.list.filter((_, index) => index !== targetIndex);
|
|
506
699
|
this.syncOrdersMap();
|
|
507
|
-
|
|
700
|
+
const storageOrder = this.withoutSyntheticDraftOrderId(nextOrder);
|
|
701
|
+
try {
|
|
702
|
+
this.logInfo("updateLocalPayment-SQLite写入开始", {
|
|
703
|
+
...paymentContext,
|
|
704
|
+
storage_order_id: storageOrder.order_id ?? null
|
|
705
|
+
});
|
|
706
|
+
await this.updateOrderInSQLite(storageOrder, "updateLocalPayment", { throwOnError: true });
|
|
707
|
+
this.logInfo("updateLocalPayment-SQLite写入完成", {
|
|
708
|
+
...paymentContext,
|
|
709
|
+
storage_order_id: storageOrder.order_id ?? null
|
|
710
|
+
});
|
|
711
|
+
} catch (error) {
|
|
712
|
+
this.store.list = previousList;
|
|
713
|
+
this.syncOrdersMap();
|
|
714
|
+
this.logError("updateLocalPayment-SQLite写入失败并回滚内存", {
|
|
715
|
+
...paymentContext,
|
|
716
|
+
storage_order_id: storageOrder.order_id ?? null,
|
|
717
|
+
error: error instanceof Error ? error.message : String(error)
|
|
718
|
+
});
|
|
719
|
+
throw error;
|
|
720
|
+
}
|
|
721
|
+
if (shouldKeepInMemory || targetIndex >= 0) {
|
|
722
|
+
await this.emitOrdersChanged(
|
|
723
|
+
shouldKeepInMemory ? [nextOrder] : [],
|
|
724
|
+
shouldKeepInMemory ? "updateLocalPayment" : "updateLocalPayment.sqliteOnlyDraft"
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
this.logInfo("updateLocalPayment-变更事件完成", paymentContext);
|
|
728
|
+
return { order: nextOrder, payment: nextPayment, previousPayment };
|
|
508
729
|
}
|
|
509
730
|
async loadOrdersByServer() {
|
|
510
731
|
var _a;
|
|
511
732
|
let orderList = [];
|
|
733
|
+
const protectedOrdersBeforeRemoteFetch = (await this.loadOrdersFromSQLite()).filter(
|
|
734
|
+
(order) => this.shouldProtectLocalOrderFromRemoteSnapshot(order)
|
|
735
|
+
);
|
|
512
736
|
this.logInfo("loadOrdersByServer-开始", {
|
|
513
737
|
hasOrderDataSource: !!this.orderDataSource,
|
|
514
|
-
query: ((_a = this.store) == null ? void 0 : _a.createdAtQuery) || null
|
|
738
|
+
query: ((_a = this.store) == null ? void 0 : _a.createdAtQuery) || null,
|
|
739
|
+
protectedLocalOrderCount: protectedOrdersBeforeRemoteFetch.length,
|
|
740
|
+
protectedPendingPaymentCount: protectedOrdersBeforeRemoteFetch.reduce(
|
|
741
|
+
(count, order) => count + this.getIdentifiedPendingPayments(order).length,
|
|
742
|
+
0
|
|
743
|
+
)
|
|
515
744
|
});
|
|
516
745
|
if (this.orderDataSource) {
|
|
517
746
|
try {
|
|
@@ -531,10 +760,19 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
531
760
|
return this.store.list;
|
|
532
761
|
}
|
|
533
762
|
}
|
|
534
|
-
const mergedOrders = await this.replaceOrdersSnapshotInSQLite(
|
|
535
|
-
|
|
763
|
+
const mergedOrders = await this.replaceOrdersSnapshotInSQLite(
|
|
764
|
+
orderList,
|
|
765
|
+
"loadOrdersByServer",
|
|
766
|
+
protectedOrdersBeforeRemoteFetch
|
|
767
|
+
);
|
|
768
|
+
const memoryOrders = this.normalizeOrdersForMemoryList(
|
|
769
|
+
mergedOrders,
|
|
770
|
+
"loadOrdersByServer.memory"
|
|
771
|
+
);
|
|
536
772
|
this.logInfo("loadOrdersByServer-结束", {
|
|
537
|
-
count: memoryOrders.length
|
|
773
|
+
count: memoryOrders.length,
|
|
774
|
+
persistedCount: mergedOrders.length,
|
|
775
|
+
sqliteOnlyDraftCount: mergedOrders.length - memoryOrders.length
|
|
538
776
|
});
|
|
539
777
|
await this.core.effects.emit(import_types.OrderHooks.onOrdersLoaded, memoryOrders);
|
|
540
778
|
return memoryOrders;
|
|
@@ -554,18 +792,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
554
792
|
try {
|
|
555
793
|
this.updateCreateStore();
|
|
556
794
|
const orders = await this.loadOrdersByServer();
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
});
|
|
566
|
-
} else {
|
|
567
|
-
this.logInfo("silentRefresh: 服务器未返回数据");
|
|
568
|
-
}
|
|
795
|
+
this.store.list = (0, import_lodash_es.cloneDeep)(orders);
|
|
796
|
+
this.syncOrdersMap();
|
|
797
|
+
await this.emitOrdersChanged([], "silentRefresh");
|
|
798
|
+
await this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
|
|
799
|
+
this.logInfo("silentRefresh 完成", {
|
|
800
|
+
orderCount: orders.length,
|
|
801
|
+
duration: `${Date.now() - startTime}ms`
|
|
802
|
+
});
|
|
569
803
|
return this.store.list;
|
|
570
804
|
} catch (error) {
|
|
571
805
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -579,6 +813,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
579
813
|
normalizeOrderForMemoryList(order, source = "normalizeOrderForMemoryList") {
|
|
580
814
|
const normalizedOrder = this.normalizeOrderCollectionsForIngress(order, source);
|
|
581
815
|
const externalSaleNumber = normalizedOrder == null ? void 0 : normalizedOrder.external_sale_number;
|
|
816
|
+
if (this.isDraftOrder(normalizedOrder) && !this.hasRealOrderId(normalizedOrder)) {
|
|
817
|
+
return normalizedOrder;
|
|
818
|
+
}
|
|
582
819
|
if ((normalizedOrder == null ? void 0 : normalizedOrder.order_id) !== void 0 && (normalizedOrder == null ? void 0 : normalizedOrder.order_id) !== null && (normalizedOrder == null ? void 0 : normalizedOrder.order_id) !== "") {
|
|
583
820
|
return normalizedOrder;
|
|
584
821
|
}
|
|
@@ -590,6 +827,27 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
590
827
|
order_id: externalSaleNumber
|
|
591
828
|
};
|
|
592
829
|
}
|
|
830
|
+
normalizeOrdersForMemoryList(orders, source) {
|
|
831
|
+
return orders.map((order) => this.normalizeOrderForMemoryList(order, source)).filter((order) => this.shouldKeepOrderInMemory(order));
|
|
832
|
+
}
|
|
833
|
+
hasRealOrderId(order) {
|
|
834
|
+
if (!order || this.isBlankIdentityValue(order.order_id))
|
|
835
|
+
return false;
|
|
836
|
+
const externalSaleNumber = order.external_sale_number;
|
|
837
|
+
return !(this.isDraftOrder(order) && !this.isBlankIdentityValue(externalSaleNumber) && String(order.order_id) === String(externalSaleNumber));
|
|
838
|
+
}
|
|
839
|
+
shouldKeepOrderInMemory(order) {
|
|
840
|
+
return !this.isDraftOrder(order) || this.hasRealOrderId(order);
|
|
841
|
+
}
|
|
842
|
+
withoutSyntheticDraftOrderId(order) {
|
|
843
|
+
const externalSaleNumber = order.external_sale_number;
|
|
844
|
+
if (Number(order.is_draft_order || 0) !== 1 || order.order_id === void 0 || externalSaleNumber === void 0 || String(order.order_id) !== String(externalSaleNumber)) {
|
|
845
|
+
return order;
|
|
846
|
+
}
|
|
847
|
+
const next = { ...order };
|
|
848
|
+
delete next.order_id;
|
|
849
|
+
return next;
|
|
850
|
+
}
|
|
593
851
|
/**
|
|
594
852
|
* 仅覆盖本地已存在的订单;不存在则直接跳过,不落库、不 emit。
|
|
595
853
|
* 适用于"按 order_id 主动刷新本地订单详情"的代理场景。
|
|
@@ -638,13 +896,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
638
896
|
* 将远端拉取的订单合并进本地 store(已存在则更新,不存在则追加),落库并 emit onOrdersChanged。
|
|
639
897
|
* 供 /update/localOrder 等在「本地尚无该单」时写入新建单。
|
|
640
898
|
*/
|
|
641
|
-
async upsertOrdersFromRemote(freshOrders) {
|
|
899
|
+
async upsertOrdersFromRemote(freshOrders, source = "upsertOrdersFromRemote") {
|
|
642
900
|
if (!(freshOrders == null ? void 0 : freshOrders.length)) {
|
|
643
901
|
this.logInfo("upsertOrdersFromRemote-订单列表为空", {});
|
|
644
902
|
return;
|
|
645
903
|
}
|
|
646
|
-
this.logInfo("upsertOrdersFromRemote-开始", { count: freshOrders.length });
|
|
647
|
-
await this.mergeOrdersToStore(freshOrders,
|
|
904
|
+
this.logInfo("upsertOrdersFromRemote-开始", { count: freshOrders.length, source });
|
|
905
|
+
await this.mergeOrdersToStore(freshOrders, source);
|
|
648
906
|
}
|
|
649
907
|
async markOrderSyncedByExternalSaleNumber(params) {
|
|
650
908
|
const externalSaleNumber = params.externalSaleNumber;
|
|
@@ -670,7 +928,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
670
928
|
...existing,
|
|
671
929
|
...params.patch || {},
|
|
672
930
|
external_sale_number: existing.external_sale_number ?? externalSaleNumber,
|
|
673
|
-
need_sync: 0
|
|
931
|
+
need_sync: 0,
|
|
932
|
+
is_draft_order: 0
|
|
674
933
|
});
|
|
675
934
|
const storageKey = this.getOrderStorageKey(nextOrder) || key;
|
|
676
935
|
this.store.list = this.store.list.map((order, index) => {
|
|
@@ -695,7 +954,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
695
954
|
* 将本地待同步订单按 SQLite storage key 合并进 store 并落库。
|
|
696
955
|
* checkout 离线兜底可能没有 order_id,但通常会有 external_sale_number。
|
|
697
956
|
*/
|
|
698
|
-
async upsertPendingSyncOrders(pendingOrders) {
|
|
957
|
+
async upsertPendingSyncOrders(pendingOrders, options = {}) {
|
|
699
958
|
if (!(pendingOrders == null ? void 0 : pendingOrders.length)) {
|
|
700
959
|
this.logInfo("upsertPendingSyncOrders-订单列表为空", {});
|
|
701
960
|
return;
|
|
@@ -707,14 +966,19 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
707
966
|
order,
|
|
708
967
|
"upsertPendingSyncOrders.incoming"
|
|
709
968
|
);
|
|
710
|
-
const
|
|
969
|
+
const pendingOrder = {
|
|
970
|
+
...normalizedOrder,
|
|
971
|
+
need_sync: 1,
|
|
972
|
+
is_draft_order: 0
|
|
973
|
+
};
|
|
974
|
+
const storageKey = this.getOrderStorageKey(pendingOrder);
|
|
711
975
|
if (!storageKey)
|
|
712
976
|
continue;
|
|
713
|
-
pendingMap.set(storageKey,
|
|
977
|
+
pendingMap.set(storageKey, pendingOrder);
|
|
714
978
|
memoryPendingMap.set(
|
|
715
979
|
storageKey,
|
|
716
980
|
this.normalizeOrderForMemoryList(
|
|
717
|
-
|
|
981
|
+
pendingOrder,
|
|
718
982
|
"upsertPendingSyncOrders.memory"
|
|
719
983
|
)
|
|
720
984
|
);
|
|
@@ -745,7 +1009,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
745
1009
|
if (matchIndex >= 0) {
|
|
746
1010
|
const existingOrder = updatedList[matchIndex];
|
|
747
1011
|
const mergedOrder = this.mergeOrderRecords(existingOrder, pendingOrder);
|
|
748
|
-
|
|
1012
|
+
const nextOrder = {
|
|
1013
|
+
...mergedOrder,
|
|
1014
|
+
need_sync: 1,
|
|
1015
|
+
is_draft_order: 0
|
|
1016
|
+
};
|
|
1017
|
+
updatedList[matchIndex] = nextOrder;
|
|
749
1018
|
const pendingSnapshot = pendingMap.get(storageKey);
|
|
750
1019
|
if (pendingSnapshot) {
|
|
751
1020
|
pendingMap.set(
|
|
@@ -753,7 +1022,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
753
1022
|
this.reconcileOverwriteOrderCollections(existingOrder, pendingSnapshot)
|
|
754
1023
|
);
|
|
755
1024
|
}
|
|
756
|
-
this.registerOrderIdentityKeys(identityKeyToIndex,
|
|
1025
|
+
this.registerOrderIdentityKeys(identityKeyToIndex, nextOrder, matchIndex);
|
|
757
1026
|
mergeActions[storageKey] = "update";
|
|
758
1027
|
continue;
|
|
759
1028
|
}
|
|
@@ -763,15 +1032,131 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
763
1032
|
mergeActions[storageKey] = "insert";
|
|
764
1033
|
}
|
|
765
1034
|
const patchedOrders = [...pendingMap.values()];
|
|
1035
|
+
const previousList = this.store.list;
|
|
766
1036
|
this.store.list = this.runOrderStoreSelfCheck(updatedList, "upsertPendingSyncOrders.store");
|
|
767
1037
|
this.syncOrdersMap();
|
|
768
|
-
|
|
1038
|
+
try {
|
|
1039
|
+
await this.patchOrdersInSQLite(
|
|
1040
|
+
patchedOrders,
|
|
1041
|
+
"upsertPendingSyncOrders",
|
|
1042
|
+
mergeActions,
|
|
1043
|
+
options
|
|
1044
|
+
);
|
|
1045
|
+
} catch (error) {
|
|
1046
|
+
this.store.list = previousList;
|
|
1047
|
+
this.syncOrdersMap();
|
|
1048
|
+
throw error;
|
|
1049
|
+
}
|
|
769
1050
|
this.logInfo("upsertPendingSyncOrders-结束", {
|
|
770
1051
|
count: patchedOrders.length,
|
|
771
1052
|
storeOrderCountAfter: this.store.list.length
|
|
772
1053
|
});
|
|
773
1054
|
await this.emitOrdersChanged(patchedOrders, "upsertPendingSyncOrders");
|
|
774
1055
|
}
|
|
1056
|
+
/**
|
|
1057
|
+
* 将 POS 草稿订单按 SQLite storage key 落库。
|
|
1058
|
+
* 只有具备真实 order_id 的草稿进入 store;其余草稿仅供本地恢复查询。
|
|
1059
|
+
*/
|
|
1060
|
+
async upsertLocalDraftOrders(draftOrders) {
|
|
1061
|
+
if (!(draftOrders == null ? void 0 : draftOrders.length)) {
|
|
1062
|
+
this.logInfo("upsertLocalDraftOrders-订单列表为空", {});
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
const draftMap = /* @__PURE__ */ new Map();
|
|
1066
|
+
const memoryDraftMap = /* @__PURE__ */ new Map();
|
|
1067
|
+
for (const order of draftOrders) {
|
|
1068
|
+
const draftOrder = {
|
|
1069
|
+
...order,
|
|
1070
|
+
need_sync: 0,
|
|
1071
|
+
is_draft_order: 1
|
|
1072
|
+
};
|
|
1073
|
+
const storageKey = this.getOrderStorageKey(draftOrder);
|
|
1074
|
+
if (!storageKey)
|
|
1075
|
+
continue;
|
|
1076
|
+
draftMap.set(storageKey, draftOrder);
|
|
1077
|
+
const memoryDraftOrder = this.normalizeOrderForMemoryList(draftOrder);
|
|
1078
|
+
if (this.shouldKeepOrderInMemory(memoryDraftOrder)) {
|
|
1079
|
+
memoryDraftMap.set(storageKey, memoryDraftOrder);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
if (draftMap.size === 0) {
|
|
1083
|
+
this.logError("upsertLocalDraftOrders-订单缺少可落库标识", {
|
|
1084
|
+
count: draftOrders.length
|
|
1085
|
+
});
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
this.logInfo("upsertLocalDraftOrders-开始", {
|
|
1089
|
+
count: draftMap.size,
|
|
1090
|
+
memoryDraftCount: memoryDraftMap.size,
|
|
1091
|
+
sqliteOnlyDraftCount: draftMap.size - memoryDraftMap.size
|
|
1092
|
+
});
|
|
1093
|
+
const mergeActions = {};
|
|
1094
|
+
const updatedList = this.store.list.filter((order) => this.shouldKeepOrderInMemory(order));
|
|
1095
|
+
const identityKeyToIndex = /* @__PURE__ */ new Map();
|
|
1096
|
+
for (let index = 0; index < updatedList.length; index += 1) {
|
|
1097
|
+
for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
|
|
1098
|
+
if (!identityKeyToIndex.has(key))
|
|
1099
|
+
identityKeyToIndex.set(key, index);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
for (const [storageKey, draftOrder] of memoryDraftMap.entries()) {
|
|
1103
|
+
const matchIndex = this.lookupOrderIndexByIdentityKeys(
|
|
1104
|
+
identityKeyToIndex,
|
|
1105
|
+
this.getOrderIdentityMatchKeys(draftOrder)
|
|
1106
|
+
);
|
|
1107
|
+
if (matchIndex >= 0) {
|
|
1108
|
+
const existingOrder = updatedList[matchIndex];
|
|
1109
|
+
const reconciledDraftOrder = this.preserveExistingBusinessCodeForDraft(
|
|
1110
|
+
existingOrder,
|
|
1111
|
+
draftOrder
|
|
1112
|
+
);
|
|
1113
|
+
const mergedOrder = this.mergeOrderRecords(existingOrder, reconciledDraftOrder);
|
|
1114
|
+
const nextOrder = {
|
|
1115
|
+
...mergedOrder,
|
|
1116
|
+
need_sync: 0,
|
|
1117
|
+
is_draft_order: 1
|
|
1118
|
+
};
|
|
1119
|
+
updatedList[matchIndex] = nextOrder;
|
|
1120
|
+
draftMap.set(storageKey, reconciledDraftOrder);
|
|
1121
|
+
this.registerOrderIdentityKeys(identityKeyToIndex, nextOrder, matchIndex);
|
|
1122
|
+
mergeActions[storageKey] = "update";
|
|
1123
|
+
continue;
|
|
1124
|
+
}
|
|
1125
|
+
const insertIndex = updatedList.length;
|
|
1126
|
+
updatedList.push(draftOrder);
|
|
1127
|
+
this.registerOrderIdentityKeys(identityKeyToIndex, draftOrder, insertIndex);
|
|
1128
|
+
mergeActions[storageKey] = "insert";
|
|
1129
|
+
}
|
|
1130
|
+
const patchedOrders = [...draftMap.values()];
|
|
1131
|
+
const previousList = this.store.list;
|
|
1132
|
+
this.store.list = this.runOrderStoreSelfCheck(updatedList, "upsertLocalDraftOrders.store");
|
|
1133
|
+
this.syncOrdersMap();
|
|
1134
|
+
try {
|
|
1135
|
+
await this.patchOrdersInSQLite(
|
|
1136
|
+
patchedOrders,
|
|
1137
|
+
"upsertLocalDraftOrders",
|
|
1138
|
+
mergeActions,
|
|
1139
|
+
{ throwOnError: true }
|
|
1140
|
+
);
|
|
1141
|
+
} catch (error) {
|
|
1142
|
+
this.store.list = previousList;
|
|
1143
|
+
this.syncOrdersMap();
|
|
1144
|
+
throw error;
|
|
1145
|
+
}
|
|
1146
|
+
this.logInfo("upsertLocalDraftOrders-结束", {
|
|
1147
|
+
count: patchedOrders.length,
|
|
1148
|
+
storeOrderCountAfter: this.store.list.length
|
|
1149
|
+
});
|
|
1150
|
+
const removedLegacyMemoryDraft = previousList.some(
|
|
1151
|
+
(order) => !this.shouldKeepOrderInMemory(order)
|
|
1152
|
+
);
|
|
1153
|
+
if (memoryDraftMap.size > 0 || removedLegacyMemoryDraft) {
|
|
1154
|
+
await this.emitOrdersChanged(
|
|
1155
|
+
patchedOrders.filter((order) => this.shouldKeepOrderInMemory(order)),
|
|
1156
|
+
"upsertLocalDraftOrders"
|
|
1157
|
+
);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
775
1160
|
/**
|
|
776
1161
|
* 通过 SSE 按自定义 query 拉取订单(支持 select/with 精简字段)
|
|
777
1162
|
*/
|
|
@@ -804,6 +1189,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
804
1189
|
super.destroy();
|
|
805
1190
|
}
|
|
806
1191
|
syncOrdersMap() {
|
|
1192
|
+
this.store.list = this.store.list.filter((order) => this.shouldKeepOrderInMemory(order));
|
|
807
1193
|
this.store.map.clear();
|
|
808
1194
|
for (const order of this.store.list) {
|
|
809
1195
|
const primaryIdentity = this.getOrderMapKey(order);
|
|
@@ -827,6 +1213,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
827
1213
|
isBlankIdentityValue(value) {
|
|
828
1214
|
return value === void 0 || value === null || value === "";
|
|
829
1215
|
}
|
|
1216
|
+
/**
|
|
1217
|
+
* `/sales/draft` 的旧调用方可能把未设置的 business_code 传成空串。
|
|
1218
|
+
* 对同一真实订单,空值不能覆盖已有的分类,否则 booking 查询会把该订单从 Party 列表过滤掉。
|
|
1219
|
+
*/
|
|
1220
|
+
preserveExistingBusinessCodeForDraft(existingOrder, draftOrder) {
|
|
1221
|
+
const existingBusinessCode = existingOrder.business_code;
|
|
1222
|
+
const draftBusinessCode = draftOrder.business_code;
|
|
1223
|
+
const hasExistingBusinessCode = typeof existingBusinessCode === "string" && existingBusinessCode.trim() !== "";
|
|
1224
|
+
const hasDraftBusinessCode = typeof draftBusinessCode === "string" && draftBusinessCode.trim() !== "";
|
|
1225
|
+
if (!hasExistingBusinessCode || hasDraftBusinessCode)
|
|
1226
|
+
return draftOrder;
|
|
1227
|
+
return {
|
|
1228
|
+
...draftOrder,
|
|
1229
|
+
business_code: existingBusinessCode
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
830
1232
|
getOrderIdentityEntries(order) {
|
|
831
1233
|
if (!order)
|
|
832
1234
|
return [];
|
|
@@ -1126,9 +1528,43 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1126
1528
|
});
|
|
1127
1529
|
continue;
|
|
1128
1530
|
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1531
|
+
if (this.isDraftOrder(existingOrder) && this.shouldProtectDraftOrderFromIncoming(source)) {
|
|
1532
|
+
this.logInfo("mergeOrdersToStore-跳过 draft 订单远端覆盖", {
|
|
1533
|
+
source,
|
|
1534
|
+
order_id: existingOrder.order_id ?? fresh.order_id ?? null,
|
|
1535
|
+
external_sale_number: existingOrder.external_sale_number ?? fresh.external_sale_number ?? null,
|
|
1536
|
+
local_is_draft_order: existingOrder.is_draft_order ?? null,
|
|
1537
|
+
remote_is_draft_order: fresh.is_draft_order ?? null,
|
|
1538
|
+
reason: "protect_draft_order_from_remote_echo"
|
|
1539
|
+
});
|
|
1540
|
+
continue;
|
|
1541
|
+
}
|
|
1542
|
+
let mergedOrder = this.mergeOrderRecords(existingOrder, fresh);
|
|
1543
|
+
let adjustedMatchIndex = matchIndex;
|
|
1544
|
+
const duplicateIndexes = /* @__PURE__ */ new Set();
|
|
1545
|
+
for (const key of freshIdentityKeys) {
|
|
1546
|
+
const duplicateIndex = identityKeyToIndex.get(key);
|
|
1547
|
+
if (duplicateIndex === void 0 || duplicateIndex === matchIndex)
|
|
1548
|
+
continue;
|
|
1549
|
+
duplicateIndexes.add(duplicateIndex);
|
|
1550
|
+
}
|
|
1551
|
+
if (duplicateIndexes.size > 0) {
|
|
1552
|
+
for (const duplicateIndex of [...duplicateIndexes].sort((left, right) => right - left)) {
|
|
1553
|
+
mergedOrder = this.mergeOrderRecords(mergedOrder, updatedList[duplicateIndex]);
|
|
1554
|
+
updatedList.splice(duplicateIndex, 1);
|
|
1555
|
+
if (duplicateIndex < adjustedMatchIndex)
|
|
1556
|
+
adjustedMatchIndex -= 1;
|
|
1557
|
+
}
|
|
1558
|
+
identityKeyToIndex.clear();
|
|
1559
|
+
for (let index = 0; index < updatedList.length; index += 1) {
|
|
1560
|
+
for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
|
|
1561
|
+
if (!identityKeyToIndex.has(key))
|
|
1562
|
+
identityKeyToIndex.set(key, index);
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
updatedList[adjustedMatchIndex] = mergedOrder;
|
|
1567
|
+
this.registerOrderIdentityKeys(identityKeyToIndex, mergedOrder, adjustedMatchIndex);
|
|
1132
1568
|
patchedOrders.push(mergedOrder);
|
|
1133
1569
|
if (mergeKey)
|
|
1134
1570
|
mergeActions[mergeKey] = "update";
|
|
@@ -1320,6 +1756,72 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1320
1756
|
return right;
|
|
1321
1757
|
return left;
|
|
1322
1758
|
}
|
|
1759
|
+
getProductIdentityKeys(product) {
|
|
1760
|
+
var _a;
|
|
1761
|
+
const record = product;
|
|
1762
|
+
if (!record)
|
|
1763
|
+
return [];
|
|
1764
|
+
const keys = [];
|
|
1765
|
+
const metadataUid = (_a = record.metadata) == null ? void 0 : _a.unique_identification_number;
|
|
1766
|
+
if (!this.isBlankIdentityValue(metadataUid))
|
|
1767
|
+
keys.push(`uid:${String(metadataUid)}`);
|
|
1768
|
+
const topLevelUid = record.unique_identification_number;
|
|
1769
|
+
if (!this.isBlankIdentityValue(topLevelUid))
|
|
1770
|
+
keys.push(`uid:${String(topLevelUid)}`);
|
|
1771
|
+
const orderDetailId = record.order_detail_id;
|
|
1772
|
+
if (!this.isBlankIdentityValue(orderDetailId))
|
|
1773
|
+
keys.push(`detail:${String(orderDetailId)}`);
|
|
1774
|
+
const bookingUid = record.booking_uid;
|
|
1775
|
+
if (!this.isBlankIdentityValue(bookingUid))
|
|
1776
|
+
keys.push(`booking:${String(bookingUid)}`);
|
|
1777
|
+
return keys;
|
|
1778
|
+
}
|
|
1779
|
+
mergeOrderProductLists(preferred, secondary) {
|
|
1780
|
+
const preferredList = Array.isArray(preferred) ? preferred : [];
|
|
1781
|
+
const secondaryList = Array.isArray(secondary) ? secondary : [];
|
|
1782
|
+
if (secondaryList.length === 0)
|
|
1783
|
+
return preferredList;
|
|
1784
|
+
if (preferredList.length === 0)
|
|
1785
|
+
return secondaryList;
|
|
1786
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
1787
|
+
for (const item of preferredList) {
|
|
1788
|
+
const keys = this.getProductIdentityKeys(item);
|
|
1789
|
+
for (const key of keys)
|
|
1790
|
+
seenKeys.add(key);
|
|
1791
|
+
}
|
|
1792
|
+
const result = [...preferredList];
|
|
1793
|
+
for (const item of secondaryList) {
|
|
1794
|
+
const keys = this.getProductIdentityKeys(item);
|
|
1795
|
+
if (keys.length === 0 || keys.some((key) => seenKeys.has(key)))
|
|
1796
|
+
continue;
|
|
1797
|
+
for (const key of keys)
|
|
1798
|
+
seenKeys.add(key);
|
|
1799
|
+
result.push((0, import_lodash_es.cloneDeep)(item));
|
|
1800
|
+
}
|
|
1801
|
+
return result;
|
|
1802
|
+
}
|
|
1803
|
+
mergeOrderPaymentLists(existing, incoming) {
|
|
1804
|
+
const existingList = Array.isArray(existing) ? existing : [];
|
|
1805
|
+
const incomingList = Array.isArray(incoming) ? incoming : [];
|
|
1806
|
+
if (incomingList.length === 0)
|
|
1807
|
+
return (0, import_lodash_es.cloneDeep)(existingList);
|
|
1808
|
+
return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(existingList, incomingList);
|
|
1809
|
+
}
|
|
1810
|
+
getIdentifiedPendingPayments(order) {
|
|
1811
|
+
const payments = Array.isArray(order == null ? void 0 : order.payments) ? order.payments : [];
|
|
1812
|
+
return payments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment));
|
|
1813
|
+
}
|
|
1814
|
+
shouldProtectLocalOrderFromRemoteSnapshot(order) {
|
|
1815
|
+
return this.isPendingSyncOrder(order) || this.isDraftOrder(order) || this.getIdentifiedPendingPayments(order).length > 0;
|
|
1816
|
+
}
|
|
1817
|
+
getUnmatchedIdentifiedPendingPayments(existing, incoming) {
|
|
1818
|
+
const existingPayments = Array.isArray(existing) ? existing : [];
|
|
1819
|
+
const incomingPayments = Array.isArray(incoming) ? incoming : [];
|
|
1820
|
+
const incomingIdentityKeys = new Set(
|
|
1821
|
+
incomingPayments.flatMap((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
|
|
1822
|
+
);
|
|
1823
|
+
return existingPayments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment) && !(0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => incomingIdentityKeys.has(key)));
|
|
1824
|
+
}
|
|
1323
1825
|
mergeOrderRecords(existing, incoming) {
|
|
1324
1826
|
const preferred = this.pickPreferredOrder(existing, incoming);
|
|
1325
1827
|
const secondary = preferred === existing ? incoming : existing;
|
|
@@ -1349,7 +1851,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1349
1851
|
"contacts_info",
|
|
1350
1852
|
"phone",
|
|
1351
1853
|
"email",
|
|
1352
|
-
"relation_forms"
|
|
1854
|
+
"relation_forms",
|
|
1855
|
+
"is_draft_order"
|
|
1353
1856
|
];
|
|
1354
1857
|
const mergedRecord = merged;
|
|
1355
1858
|
const preferredRecord = preferred;
|
|
@@ -1377,11 +1880,26 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1377
1880
|
}
|
|
1378
1881
|
for (const field of ORDER_AUTHORITATIVE_COLLECTION_FIELDS) {
|
|
1379
1882
|
if (Array.isArray(incomingRecord[field])) {
|
|
1883
|
+
if (field === "payments") {
|
|
1884
|
+
const preservedPending = this.getUnmatchedIdentifiedPendingPayments(
|
|
1885
|
+
existingRecord[field],
|
|
1886
|
+
incomingRecord[field]
|
|
1887
|
+
);
|
|
1888
|
+
if (preservedPending.length > 0) {
|
|
1889
|
+
this.logInfo("mergeOrderRecords-保留本地 pending 支付项", {
|
|
1890
|
+
order_id: existing.order_id ?? incoming.order_id ?? null,
|
|
1891
|
+
external_sale_number: existingRecord.external_sale_number ?? incomingRecord.external_sale_number ?? null,
|
|
1892
|
+
preserved_pending_count: preservedPending.length,
|
|
1893
|
+
preserved_payment_identities: preservedPending.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1380
1897
|
mergedRecord[field] = this.mergeAuthoritativeOrderCollection(
|
|
1381
1898
|
field,
|
|
1382
1899
|
existingRecord[field],
|
|
1383
1900
|
incomingRecord[field],
|
|
1384
|
-
childUidRemaps
|
|
1901
|
+
childUidRemaps,
|
|
1902
|
+
{ preserveIdentifiedPendingPayments: field === "payments" }
|
|
1385
1903
|
);
|
|
1386
1904
|
continue;
|
|
1387
1905
|
}
|
|
@@ -1416,7 +1934,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1416
1934
|
external_sale_number: order.external_sale_number ?? null,
|
|
1417
1935
|
shop_order_number: order.shop_order_number ?? null,
|
|
1418
1936
|
shop_full_order_number: order.shop_full_order_number ?? null,
|
|
1419
|
-
need_sync: order.need_sync ?? null
|
|
1937
|
+
need_sync: order.need_sync ?? null,
|
|
1938
|
+
is_draft_order: order.is_draft_order ?? null
|
|
1420
1939
|
}))
|
|
1421
1940
|
}));
|
|
1422
1941
|
}
|
|
@@ -1533,18 +2052,48 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1533
2052
|
isPendingSyncOrder(order) {
|
|
1534
2053
|
return Number(order == null ? void 0 : order.need_sync) === 1;
|
|
1535
2054
|
}
|
|
2055
|
+
isDraftOrder(order) {
|
|
2056
|
+
return Number(order == null ? void 0 : order.is_draft_order) === 1;
|
|
2057
|
+
}
|
|
2058
|
+
shouldProtectDraftOrderFromIncoming(source) {
|
|
2059
|
+
return source !== "checkoutSync";
|
|
2060
|
+
}
|
|
1536
2061
|
normalizeRemoteSyncedOrder(order) {
|
|
1537
2062
|
const normalizedOrder = this.normalizeOrderCollectionsForIngress(
|
|
1538
2063
|
order,
|
|
1539
2064
|
"normalizeRemoteSyncedOrder"
|
|
1540
2065
|
);
|
|
1541
2066
|
if (this.isPendingSyncOrder(normalizedOrder))
|
|
1542
|
-
return
|
|
2067
|
+
return {
|
|
2068
|
+
...normalizedOrder,
|
|
2069
|
+
is_draft_order: 0
|
|
2070
|
+
};
|
|
1543
2071
|
return {
|
|
1544
2072
|
...normalizedOrder,
|
|
1545
|
-
need_sync: 0
|
|
2073
|
+
need_sync: 0,
|
|
2074
|
+
is_draft_order: 0
|
|
1546
2075
|
};
|
|
1547
2076
|
}
|
|
2077
|
+
mergeRemoteIdentityIntoDraftOrder(draftOrder, remoteOrder) {
|
|
2078
|
+
const merged = {
|
|
2079
|
+
...this.withoutSyntheticDraftOrderId(draftOrder)
|
|
2080
|
+
};
|
|
2081
|
+
const remote = remoteOrder;
|
|
2082
|
+
for (const field of [
|
|
2083
|
+
"order_id",
|
|
2084
|
+
"order_number",
|
|
2085
|
+
"shop_order_number",
|
|
2086
|
+
"shop_full_order_number"
|
|
2087
|
+
]) {
|
|
2088
|
+
if (this.isBlankIdentityValue(merged[field]) && !this.isBlankIdentityValue(remote[field])) {
|
|
2089
|
+
merged[field] = remote[field];
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
return this.normalizeOrderCollectionsForIngress(
|
|
2093
|
+
merged,
|
|
2094
|
+
"mergeRemoteIdentityIntoDraftOrder"
|
|
2095
|
+
);
|
|
2096
|
+
}
|
|
1548
2097
|
mergeRemoteSnapshotWithPendingOrders(remoteOrders, existingOrders) {
|
|
1549
2098
|
const merged = remoteOrders.map((order) => this.normalizeRemoteSyncedOrder(order));
|
|
1550
2099
|
for (const rawOrder of existingOrders) {
|
|
@@ -1552,11 +2101,18 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1552
2101
|
rawOrder,
|
|
1553
2102
|
"mergeRemoteSnapshotWithPendingOrders.existingSQLite"
|
|
1554
2103
|
);
|
|
1555
|
-
if (!this.
|
|
2104
|
+
if (!this.shouldProtectLocalOrderFromRemoteSnapshot(order))
|
|
1556
2105
|
continue;
|
|
1557
2106
|
const matchIndex = this.findOrderIndexByIdentity(merged, order);
|
|
1558
2107
|
if (matchIndex >= 0) {
|
|
1559
|
-
|
|
2108
|
+
if (this.isDraftOrder(order)) {
|
|
2109
|
+
merged[matchIndex] = this.mergeRemoteIdentityIntoDraftOrder(
|
|
2110
|
+
order,
|
|
2111
|
+
merged[matchIndex]
|
|
2112
|
+
);
|
|
2113
|
+
} else {
|
|
2114
|
+
merged[matchIndex] = this.mergeOrderRecords(order, merged[matchIndex]);
|
|
2115
|
+
}
|
|
1560
2116
|
continue;
|
|
1561
2117
|
}
|
|
1562
2118
|
if (!this.getOrderStorageKey(order))
|
|
@@ -1584,8 +2140,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1584
2140
|
* @example
|
|
1585
2141
|
* await this.patchOrdersInSQLite(freshOrders)
|
|
1586
2142
|
*/
|
|
1587
|
-
async patchOrdersInSQLite(orders, source, mergeActions = {}) {
|
|
1588
|
-
if (
|
|
2143
|
+
async patchOrdersInSQLite(orders, source, mergeActions = {}, options = {}) {
|
|
2144
|
+
if (orders.length === 0) {
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
if (!this.dbManager) {
|
|
2148
|
+
if (options.throwOnError)
|
|
2149
|
+
throw new Error("订单 SQLite 数据库未初始化");
|
|
1589
2150
|
return;
|
|
1590
2151
|
}
|
|
1591
2152
|
const ordersSnapshot = (0, import_lodash_es.cloneDeep)(orders).map((order) => this.normalizeOrderCollectionsForIngress(order, `${source}.sqliteIngress`)).filter((order) => this.getOrderStorageKey(order));
|
|
@@ -1623,6 +2184,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1623
2184
|
for (const order of compactedToWrite) {
|
|
1624
2185
|
await this.dbManager.update(INDEXDB_STORE_NAME, order);
|
|
1625
2186
|
}
|
|
2187
|
+
} else if (options.throwOnError) {
|
|
2188
|
+
throw new Error("订单 SQLite 数据库不支持写入");
|
|
1626
2189
|
}
|
|
1627
2190
|
this.recordRecentSqliteWrite(source, compactedToWrite);
|
|
1628
2191
|
this.logInfo("patchOrdersInSQLite-完成", {
|
|
@@ -1637,6 +2200,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1637
2200
|
error: error instanceof Error ? error.message : String(error),
|
|
1638
2201
|
orderCount: ordersSnapshot.length
|
|
1639
2202
|
});
|
|
2203
|
+
if (options.throwOnError)
|
|
2204
|
+
throw error;
|
|
1640
2205
|
}
|
|
1641
2206
|
}
|
|
1642
2207
|
/**
|
|
@@ -1645,8 +2210,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1645
2210
|
* @example
|
|
1646
2211
|
* await this.updateOrderInSQLite(freshOrder)
|
|
1647
2212
|
*/
|
|
1648
|
-
async updateOrderInSQLite(order, source) {
|
|
1649
|
-
if (!this.
|
|
2213
|
+
async updateOrderInSQLite(order, source, options = {}) {
|
|
2214
|
+
if (!this.getOrderStorageKey(order)) {
|
|
2215
|
+
if (options.throwOnError)
|
|
2216
|
+
throw new Error("订单缺少可用的 SQLite 存储主键");
|
|
2217
|
+
return;
|
|
2218
|
+
}
|
|
2219
|
+
if (!this.dbManager) {
|
|
2220
|
+
if (options.throwOnError)
|
|
2221
|
+
throw new Error("订单 SQLite 数据库未初始化");
|
|
1650
2222
|
return;
|
|
1651
2223
|
}
|
|
1652
2224
|
const orderSnapshot = this.normalizeOrderCollectionsForIngress(
|
|
@@ -1670,6 +2242,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1670
2242
|
} else if (typeof this.dbManager.bulkAdd === "function") {
|
|
1671
2243
|
writeMethod = "bulkAdd";
|
|
1672
2244
|
await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, [orderSnapshot]);
|
|
2245
|
+
} else if (options.throwOnError) {
|
|
2246
|
+
throw new Error("订单 SQLite 数据库不支持写入");
|
|
1673
2247
|
}
|
|
1674
2248
|
this.recordRecentSqliteWrite(source, [orderSnapshot]);
|
|
1675
2249
|
this.logInfo("updateOrderInSQLite-完成", {
|
|
@@ -1683,15 +2257,18 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1683
2257
|
error: error instanceof Error ? error.message : String(error),
|
|
1684
2258
|
orderId: orderSnapshot.order_id ?? null
|
|
1685
2259
|
});
|
|
2260
|
+
if (options.throwOnError)
|
|
2261
|
+
throw error;
|
|
1686
2262
|
}
|
|
1687
2263
|
}
|
|
1688
2264
|
/**
|
|
1689
|
-
* 全量快照替换 orders 表(clear + bulkAdd
|
|
2265
|
+
* 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync / pending 支付订单。
|
|
2266
|
+
* 用于 SSE 全量拉取与营业日窗口裁剪。
|
|
1690
2267
|
*
|
|
1691
2268
|
* @example
|
|
1692
2269
|
* await this.replaceOrdersSnapshotInSQLite(orderList)
|
|
1693
2270
|
*/
|
|
1694
|
-
async replaceOrdersSnapshotInSQLite(orderList, source) {
|
|
2271
|
+
async replaceOrdersSnapshotInSQLite(orderList, source, protectedOrdersBeforeRemoteFetch = []) {
|
|
1695
2272
|
if (!this.dbManager) {
|
|
1696
2273
|
return this.compactOrderListByIdentity(
|
|
1697
2274
|
orderList.map((order) => this.normalizeRemoteSyncedOrder(order)),
|
|
@@ -1708,16 +2285,52 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1708
2285
|
try {
|
|
1709
2286
|
await this.runInOrderSQLiteSaveQueue(async () => {
|
|
1710
2287
|
const existingOrders = typeof this.dbManager.getAll === "function" ? await this.dbManager.getAll(INDEXDB_STORE_NAME) : [];
|
|
2288
|
+
const protectedLocalOrders = protectedOrdersBeforeRemoteFetch.map((order) => this.normalizeOrderCollectionsForIngress(
|
|
2289
|
+
order,
|
|
2290
|
+
`${source}.protectedBeforeRemoteFetch`
|
|
2291
|
+
)).filter((order) => this.shouldProtectLocalOrderFromRemoteSnapshot(order));
|
|
2292
|
+
for (const rawCurrentOrder of existingOrders || []) {
|
|
2293
|
+
const currentOrder = this.normalizeOrderCollectionsForIngress(
|
|
2294
|
+
rawCurrentOrder,
|
|
2295
|
+
`${source}.currentSQLite`
|
|
2296
|
+
);
|
|
2297
|
+
const protectedIndex = this.findOrderIndexByIdentity(
|
|
2298
|
+
protectedLocalOrders,
|
|
2299
|
+
currentOrder
|
|
2300
|
+
);
|
|
2301
|
+
const currentNeedsProtection = this.shouldProtectLocalOrderFromRemoteSnapshot(currentOrder);
|
|
2302
|
+
if (protectedIndex >= 0) {
|
|
2303
|
+
if (currentNeedsProtection) {
|
|
2304
|
+
protectedLocalOrders[protectedIndex] = currentOrder;
|
|
2305
|
+
} else {
|
|
2306
|
+
protectedLocalOrders.splice(protectedIndex, 1);
|
|
2307
|
+
}
|
|
2308
|
+
continue;
|
|
2309
|
+
}
|
|
2310
|
+
if (currentNeedsProtection)
|
|
2311
|
+
protectedLocalOrders.push(currentOrder);
|
|
2312
|
+
}
|
|
1711
2313
|
const orderListSnapshot = this.mergeRemoteSnapshotWithPendingOrders(
|
|
1712
2314
|
remoteSnapshot,
|
|
1713
|
-
|
|
2315
|
+
protectedLocalOrders
|
|
1714
2316
|
);
|
|
1715
2317
|
mergedSnapshot = this.compactOrderListByIdentity(orderListSnapshot, `${source}.sqliteSnapshot`).list;
|
|
1716
2318
|
this.logInfo("replaceOrdersSnapshotInSQLite-开始", {
|
|
1717
2319
|
source,
|
|
1718
2320
|
count: mergedSnapshot.length,
|
|
1719
2321
|
remoteCount: remoteSnapshot.length,
|
|
1720
|
-
|
|
2322
|
+
protectedBeforeRemoteFetchCount: protectedOrdersBeforeRemoteFetch.length,
|
|
2323
|
+
protectedLocalOrderCount: protectedLocalOrders.length,
|
|
2324
|
+
preservedLocalUnsyncedCount: mergedSnapshot.length - remoteSnapshot.length,
|
|
2325
|
+
protectedPendingPaymentCount: protectedLocalOrders.reduce(
|
|
2326
|
+
(count, order) => count + this.getIdentifiedPendingPayments(order).length,
|
|
2327
|
+
0
|
|
2328
|
+
),
|
|
2329
|
+
protectedPendingPaymentIdentities: protectedLocalOrders.flatMap((order) => this.getIdentifiedPendingPayments(order).map((payment) => ({
|
|
2330
|
+
order_id: order.order_id ?? null,
|
|
2331
|
+
external_sale_number: order.external_sale_number ?? null,
|
|
2332
|
+
payment_identities: (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment)
|
|
2333
|
+
})))
|
|
1721
2334
|
});
|
|
1722
2335
|
await this.dbManager.clear(INDEXDB_STORE_NAME);
|
|
1723
2336
|
this.logInfo("replaceOrdersSnapshotInSQLite-clear完成", {
|