@pisell/pisellos 2.3.29 → 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/model/strategy/adapter/index.d.ts +0 -4
- package/dist/model/strategy/adapter/index.js +1 -5
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/modules/Discount/index.d.ts +2 -5
- package/dist/modules/Discount/index.js +7 -30
- package/dist/modules/Discount/types.d.ts +0 -4
- package/dist/modules/Order/index.d.ts +28 -10
- package/dist/modules/Order/index.js +747 -498
- 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 -3
- package/dist/modules/Order/utils.js +4 -4
- 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/modules/Product/types.d.ts +0 -22
- package/dist/modules/ProductList/index.d.ts +1 -1
- package/dist/modules/ProductList/index.js +2 -4
- package/dist/modules/ProductList/types.d.ts +0 -2
- package/dist/server/index.d.ts +14 -50
- package/dist/server/index.js +1975 -1395
- package/dist/server/modules/order/index.d.ts +40 -3
- package/dist/server/modules/order/index.js +1200 -501
- package/dist/server/modules/order/types.d.ts +11 -3
- package/dist/server/modules/order/types.js +1 -1
- package/dist/server/modules/products/index.d.ts +7 -26
- package/dist/server/modules/products/index.js +76 -167
- package/dist/server/modules/products/types.d.ts +0 -14
- package/dist/solution/BaseSales/index.d.ts +33 -5
- package/dist/solution/BaseSales/index.js +622 -345
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +2 -1
- package/dist/solution/BookingTicket/types.d.ts +0 -2
- package/dist/solution/ShopDiscount/index.js +14 -15
- package/dist/utils/payment-number.d.ts +9 -0
- package/dist/utils/payment-number.js +69 -0
- package/lib/model/strategy/adapter/index.d.ts +0 -4
- package/lib/model/strategy/adapter/index.js +2 -13
- package/lib/modules/Discount/index.d.ts +2 -5
- package/lib/modules/Discount/index.js +3 -23
- package/lib/modules/Discount/types.d.ts +0 -4
- package/lib/modules/Order/index.d.ts +28 -10
- package/lib/modules/Order/index.js +181 -73
- 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 -3
- package/lib/modules/Order/utils.js +2 -3
- 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/modules/Product/types.d.ts +0 -22
- package/lib/modules/ProductList/index.d.ts +1 -1
- package/lib/modules/ProductList/index.js +2 -4
- package/lib/modules/ProductList/types.d.ts +0 -2
- package/lib/server/index.d.ts +14 -50
- package/lib/server/index.js +633 -214
- package/lib/server/modules/order/index.d.ts +40 -3
- package/lib/server/modules/order/index.js +434 -31
- package/lib/server/modules/order/types.d.ts +11 -3
- package/lib/server/modules/products/index.d.ts +7 -26
- package/lib/server/modules/products/index.js +35 -114
- package/lib/server/modules/products/types.d.ts +0 -14
- package/lib/solution/BaseSales/index.d.ts +33 -5
- package/lib/solution/BaseSales/index.js +170 -19
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +2 -1
- package/lib/solution/BookingTicket/types.d.ts +0 -2
- package/lib/solution/ShopDiscount/index.js +1 -2
- package/lib/utils/payment-number.d.ts +9 -0
- package/lib/utils/payment-number.js +64 -0
- package/package.json +1 -1
- package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +0 -50
- package/dist/model/strategy/adapter/dataVariant/adapter.js +0 -167
- package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -89
- package/dist/model/strategy/adapter/dataVariant/evaluator.js +0 -780
- package/dist/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
- package/dist/model/strategy/adapter/dataVariant/examples.js +0 -277
- package/dist/model/strategy/adapter/dataVariant/index.d.ts +0 -4
- package/dist/model/strategy/adapter/dataVariant/index.js +0 -4
- package/dist/model/strategy/adapter/dataVariant/type.d.ts +0 -148
- package/dist/model/strategy/adapter/dataVariant/type.js +0 -54
- package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +0 -50
- package/lib/model/strategy/adapter/dataVariant/adapter.js +0 -149
- package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +0 -89
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +0 -583
- package/lib/model/strategy/adapter/dataVariant/examples.d.ts +0 -39
- package/lib/model/strategy/adapter/dataVariant/examples.js +0 -293
- package/lib/model/strategy/adapter/dataVariant/index.d.ts +0 -4
- package/lib/model/strategy/adapter/dataVariant/index.js +0 -38
- package/lib/model/strategy/adapter/dataVariant/type.d.ts +0 -148
- package/lib/model/strategy/adapter/dataVariant/type.js +0 -31
|
@@ -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,8 +47,10 @@ 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;
|
|
53
56
|
var ORDER_AUTHORITATIVE_COLLECTION_FIELDS = ["products", "bookings", "payments"];
|
|
@@ -482,6 +485,27 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
482
485
|
getOrderByOrderId(orderId) {
|
|
483
486
|
return this.store.map.get(this.getIdKey(orderId));
|
|
484
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
|
+
}
|
|
485
509
|
getLocalOrderFromMemoryByLookup(lookup) {
|
|
486
510
|
const key = this.getIdKey(lookup);
|
|
487
511
|
const memoryOrderById = this.store.map.get(key);
|
|
@@ -490,21 +514,176 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
490
514
|
const memoryOrder = this.store.list.find((order) => this.isOrderLookupMatch(order, key));
|
|
491
515
|
return memoryOrder || null;
|
|
492
516
|
}
|
|
493
|
-
async getLocalOrderByLookup(lookup) {
|
|
517
|
+
async getLocalOrderByLookup(lookup, options = {}) {
|
|
494
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
|
+
}
|
|
495
527
|
const memoryOrderById = this.store.map.get(key);
|
|
496
|
-
if (memoryOrderById)
|
|
528
|
+
if (memoryOrderById) {
|
|
529
|
+
if (options.operationId) {
|
|
530
|
+
this.logInfo("getLocalOrderByLookup-localPayment-命中内存映射", {
|
|
531
|
+
...logContext,
|
|
532
|
+
...this.buildLocalPaymentOrderLogContext(memoryOrderById)
|
|
533
|
+
});
|
|
534
|
+
}
|
|
497
535
|
return memoryOrderById;
|
|
536
|
+
}
|
|
498
537
|
const memoryOrder = this.store.list.find((order) => this.isOrderLookupMatch(order, key));
|
|
499
|
-
if (memoryOrder)
|
|
538
|
+
if (memoryOrder) {
|
|
539
|
+
if (options.operationId) {
|
|
540
|
+
this.logInfo("getLocalOrderByLookup-localPayment-命中内存列表", {
|
|
541
|
+
...logContext,
|
|
542
|
+
...this.buildLocalPaymentOrderLogContext(memoryOrder)
|
|
543
|
+
});
|
|
544
|
+
}
|
|
500
545
|
return memoryOrder;
|
|
546
|
+
}
|
|
547
|
+
if (options.operationId) {
|
|
548
|
+
this.logInfo("getLocalOrderByLookup-localPayment-开始读取SQLite", logContext);
|
|
549
|
+
}
|
|
501
550
|
const orders = await this.loadOrdersFromSQLite();
|
|
502
551
|
const localOrder = orders.find((order) => this.isOrderLookupMatch(order, key));
|
|
503
|
-
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
|
+
}
|
|
504
559
|
return null;
|
|
560
|
+
}
|
|
505
561
|
this.store.list = orders.map((order) => this.normalizeOrderForMemoryList(order));
|
|
506
562
|
this.syncOrdersMap();
|
|
507
|
-
|
|
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 };
|
|
508
687
|
}
|
|
509
688
|
async loadOrdersByServer() {
|
|
510
689
|
var _a;
|
|
@@ -590,6 +769,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
590
769
|
order_id: externalSaleNumber
|
|
591
770
|
};
|
|
592
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
|
+
}
|
|
593
781
|
/**
|
|
594
782
|
* 仅覆盖本地已存在的订单;不存在则直接跳过,不落库、不 emit。
|
|
595
783
|
* 适用于"按 order_id 主动刷新本地订单详情"的代理场景。
|
|
@@ -638,13 +826,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
638
826
|
* 将远端拉取的订单合并进本地 store(已存在则更新,不存在则追加),落库并 emit onOrdersChanged。
|
|
639
827
|
* 供 /update/localOrder 等在「本地尚无该单」时写入新建单。
|
|
640
828
|
*/
|
|
641
|
-
async upsertOrdersFromRemote(freshOrders) {
|
|
829
|
+
async upsertOrdersFromRemote(freshOrders, source = "upsertOrdersFromRemote") {
|
|
642
830
|
if (!(freshOrders == null ? void 0 : freshOrders.length)) {
|
|
643
831
|
this.logInfo("upsertOrdersFromRemote-订单列表为空", {});
|
|
644
832
|
return;
|
|
645
833
|
}
|
|
646
|
-
this.logInfo("upsertOrdersFromRemote-开始", { count: freshOrders.length });
|
|
647
|
-
await this.mergeOrdersToStore(freshOrders,
|
|
834
|
+
this.logInfo("upsertOrdersFromRemote-开始", { count: freshOrders.length, source });
|
|
835
|
+
await this.mergeOrdersToStore(freshOrders, source);
|
|
648
836
|
}
|
|
649
837
|
async markOrderSyncedByExternalSaleNumber(params) {
|
|
650
838
|
const externalSaleNumber = params.externalSaleNumber;
|
|
@@ -670,7 +858,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
670
858
|
...existing,
|
|
671
859
|
...params.patch || {},
|
|
672
860
|
external_sale_number: existing.external_sale_number ?? externalSaleNumber,
|
|
673
|
-
need_sync: 0
|
|
861
|
+
need_sync: 0,
|
|
862
|
+
is_draft_order: 0
|
|
674
863
|
});
|
|
675
864
|
const storageKey = this.getOrderStorageKey(nextOrder) || key;
|
|
676
865
|
this.store.list = this.store.list.map((order, index) => {
|
|
@@ -695,7 +884,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
695
884
|
* 将本地待同步订单按 SQLite storage key 合并进 store 并落库。
|
|
696
885
|
* checkout 离线兜底可能没有 order_id,但通常会有 external_sale_number。
|
|
697
886
|
*/
|
|
698
|
-
async upsertPendingSyncOrders(pendingOrders) {
|
|
887
|
+
async upsertPendingSyncOrders(pendingOrders, options = {}) {
|
|
699
888
|
if (!(pendingOrders == null ? void 0 : pendingOrders.length)) {
|
|
700
889
|
this.logInfo("upsertPendingSyncOrders-订单列表为空", {});
|
|
701
890
|
return;
|
|
@@ -707,14 +896,19 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
707
896
|
order,
|
|
708
897
|
"upsertPendingSyncOrders.incoming"
|
|
709
898
|
);
|
|
710
|
-
const
|
|
899
|
+
const pendingOrder = {
|
|
900
|
+
...normalizedOrder,
|
|
901
|
+
need_sync: 1,
|
|
902
|
+
is_draft_order: 0
|
|
903
|
+
};
|
|
904
|
+
const storageKey = this.getOrderStorageKey(pendingOrder);
|
|
711
905
|
if (!storageKey)
|
|
712
906
|
continue;
|
|
713
|
-
pendingMap.set(storageKey,
|
|
907
|
+
pendingMap.set(storageKey, pendingOrder);
|
|
714
908
|
memoryPendingMap.set(
|
|
715
909
|
storageKey,
|
|
716
910
|
this.normalizeOrderForMemoryList(
|
|
717
|
-
|
|
911
|
+
pendingOrder,
|
|
718
912
|
"upsertPendingSyncOrders.memory"
|
|
719
913
|
)
|
|
720
914
|
);
|
|
@@ -745,7 +939,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
745
939
|
if (matchIndex >= 0) {
|
|
746
940
|
const existingOrder = updatedList[matchIndex];
|
|
747
941
|
const mergedOrder = this.mergeOrderRecords(existingOrder, pendingOrder);
|
|
748
|
-
|
|
942
|
+
const nextOrder = {
|
|
943
|
+
...mergedOrder,
|
|
944
|
+
need_sync: 1,
|
|
945
|
+
is_draft_order: 0
|
|
946
|
+
};
|
|
947
|
+
updatedList[matchIndex] = nextOrder;
|
|
749
948
|
const pendingSnapshot = pendingMap.get(storageKey);
|
|
750
949
|
if (pendingSnapshot) {
|
|
751
950
|
pendingMap.set(
|
|
@@ -753,7 +952,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
753
952
|
this.reconcileOverwriteOrderCollections(existingOrder, pendingSnapshot)
|
|
754
953
|
);
|
|
755
954
|
}
|
|
756
|
-
this.registerOrderIdentityKeys(identityKeyToIndex,
|
|
955
|
+
this.registerOrderIdentityKeys(identityKeyToIndex, nextOrder, matchIndex);
|
|
757
956
|
mergeActions[storageKey] = "update";
|
|
758
957
|
continue;
|
|
759
958
|
}
|
|
@@ -763,15 +962,98 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
763
962
|
mergeActions[storageKey] = "insert";
|
|
764
963
|
}
|
|
765
964
|
const patchedOrders = [...pendingMap.values()];
|
|
965
|
+
const previousList = this.store.list;
|
|
766
966
|
this.store.list = this.runOrderStoreSelfCheck(updatedList, "upsertPendingSyncOrders.store");
|
|
767
967
|
this.syncOrdersMap();
|
|
768
|
-
|
|
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
|
+
}
|
|
769
980
|
this.logInfo("upsertPendingSyncOrders-结束", {
|
|
770
981
|
count: patchedOrders.length,
|
|
771
982
|
storeOrderCountAfter: this.store.list.length
|
|
772
983
|
});
|
|
773
984
|
await this.emitOrdersChanged(patchedOrders, "upsertPendingSyncOrders");
|
|
774
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
|
+
}
|
|
775
1057
|
/**
|
|
776
1058
|
* 通过 SSE 按自定义 query 拉取订单(支持 select/with 精简字段)
|
|
777
1059
|
*/
|
|
@@ -1126,9 +1408,43 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1126
1408
|
});
|
|
1127
1409
|
continue;
|
|
1128
1410
|
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
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);
|
|
1132
1448
|
patchedOrders.push(mergedOrder);
|
|
1133
1449
|
if (mergeKey)
|
|
1134
1450
|
mergeActions[mergeKey] = "update";
|
|
@@ -1320,6 +1636,57 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1320
1636
|
return right;
|
|
1321
1637
|
return left;
|
|
1322
1638
|
}
|
|
1639
|
+
getProductIdentityKeys(product) {
|
|
1640
|
+
var _a;
|
|
1641
|
+
const record = product;
|
|
1642
|
+
if (!record)
|
|
1643
|
+
return [];
|
|
1644
|
+
const keys = [];
|
|
1645
|
+
const metadataUid = (_a = record.metadata) == null ? void 0 : _a.unique_identification_number;
|
|
1646
|
+
if (!this.isBlankIdentityValue(metadataUid))
|
|
1647
|
+
keys.push(`uid:${String(metadataUid)}`);
|
|
1648
|
+
const topLevelUid = record.unique_identification_number;
|
|
1649
|
+
if (!this.isBlankIdentityValue(topLevelUid))
|
|
1650
|
+
keys.push(`uid:${String(topLevelUid)}`);
|
|
1651
|
+
const orderDetailId = record.order_detail_id;
|
|
1652
|
+
if (!this.isBlankIdentityValue(orderDetailId))
|
|
1653
|
+
keys.push(`detail:${String(orderDetailId)}`);
|
|
1654
|
+
const bookingUid = record.booking_uid;
|
|
1655
|
+
if (!this.isBlankIdentityValue(bookingUid))
|
|
1656
|
+
keys.push(`booking:${String(bookingUid)}`);
|
|
1657
|
+
return keys;
|
|
1658
|
+
}
|
|
1659
|
+
mergeOrderProductLists(preferred, secondary) {
|
|
1660
|
+
const preferredList = Array.isArray(preferred) ? preferred : [];
|
|
1661
|
+
const secondaryList = Array.isArray(secondary) ? secondary : [];
|
|
1662
|
+
if (secondaryList.length === 0)
|
|
1663
|
+
return preferredList;
|
|
1664
|
+
if (preferredList.length === 0)
|
|
1665
|
+
return secondaryList;
|
|
1666
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
1667
|
+
for (const item of preferredList) {
|
|
1668
|
+
const keys = this.getProductIdentityKeys(item);
|
|
1669
|
+
for (const key of keys)
|
|
1670
|
+
seenKeys.add(key);
|
|
1671
|
+
}
|
|
1672
|
+
const result = [...preferredList];
|
|
1673
|
+
for (const item of secondaryList) {
|
|
1674
|
+
const keys = this.getProductIdentityKeys(item);
|
|
1675
|
+
if (keys.length === 0 || keys.some((key) => seenKeys.has(key)))
|
|
1676
|
+
continue;
|
|
1677
|
+
for (const key of keys)
|
|
1678
|
+
seenKeys.add(key);
|
|
1679
|
+
result.push((0, import_lodash_es.cloneDeep)(item));
|
|
1680
|
+
}
|
|
1681
|
+
return result;
|
|
1682
|
+
}
|
|
1683
|
+
mergeOrderPaymentLists(existing, incoming) {
|
|
1684
|
+
const existingList = Array.isArray(existing) ? existing : [];
|
|
1685
|
+
const incomingList = Array.isArray(incoming) ? incoming : [];
|
|
1686
|
+
if (incomingList.length === 0)
|
|
1687
|
+
return (0, import_lodash_es.cloneDeep)(existingList);
|
|
1688
|
+
return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(existingList, incomingList);
|
|
1689
|
+
}
|
|
1323
1690
|
mergeOrderRecords(existing, incoming) {
|
|
1324
1691
|
const preferred = this.pickPreferredOrder(existing, incoming);
|
|
1325
1692
|
const secondary = preferred === existing ? incoming : existing;
|
|
@@ -1349,7 +1716,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1349
1716
|
"contacts_info",
|
|
1350
1717
|
"phone",
|
|
1351
1718
|
"email",
|
|
1352
|
-
"relation_forms"
|
|
1719
|
+
"relation_forms",
|
|
1720
|
+
"is_draft_order"
|
|
1353
1721
|
];
|
|
1354
1722
|
const mergedRecord = merged;
|
|
1355
1723
|
const preferredRecord = preferred;
|
|
@@ -1416,7 +1784,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1416
1784
|
external_sale_number: order.external_sale_number ?? null,
|
|
1417
1785
|
shop_order_number: order.shop_order_number ?? null,
|
|
1418
1786
|
shop_full_order_number: order.shop_full_order_number ?? null,
|
|
1419
|
-
need_sync: order.need_sync ?? null
|
|
1787
|
+
need_sync: order.need_sync ?? null,
|
|
1788
|
+
is_draft_order: order.is_draft_order ?? null
|
|
1420
1789
|
}))
|
|
1421
1790
|
}));
|
|
1422
1791
|
}
|
|
@@ -1533,16 +1902,26 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1533
1902
|
isPendingSyncOrder(order) {
|
|
1534
1903
|
return Number(order == null ? void 0 : order.need_sync) === 1;
|
|
1535
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
|
+
}
|
|
1536
1911
|
normalizeRemoteSyncedOrder(order) {
|
|
1537
1912
|
const normalizedOrder = this.normalizeOrderCollectionsForIngress(
|
|
1538
1913
|
order,
|
|
1539
1914
|
"normalizeRemoteSyncedOrder"
|
|
1540
1915
|
);
|
|
1541
1916
|
if (this.isPendingSyncOrder(normalizedOrder))
|
|
1542
|
-
return
|
|
1917
|
+
return {
|
|
1918
|
+
...normalizedOrder,
|
|
1919
|
+
is_draft_order: 0
|
|
1920
|
+
};
|
|
1543
1921
|
return {
|
|
1544
1922
|
...normalizedOrder,
|
|
1545
|
-
need_sync: 0
|
|
1923
|
+
need_sync: 0,
|
|
1924
|
+
is_draft_order: 0
|
|
1546
1925
|
};
|
|
1547
1926
|
}
|
|
1548
1927
|
mergeRemoteSnapshotWithPendingOrders(remoteOrders, existingOrders) {
|
|
@@ -1552,11 +1931,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1552
1931
|
rawOrder,
|
|
1553
1932
|
"mergeRemoteSnapshotWithPendingOrders.existingSQLite"
|
|
1554
1933
|
);
|
|
1555
|
-
if (!this.isPendingSyncOrder(order))
|
|
1934
|
+
if (!this.isPendingSyncOrder(order) && !this.isDraftOrder(order))
|
|
1556
1935
|
continue;
|
|
1557
1936
|
const matchIndex = this.findOrderIndexByIdentity(merged, order);
|
|
1558
1937
|
if (matchIndex >= 0) {
|
|
1559
|
-
|
|
1938
|
+
if (this.isDraftOrder(order)) {
|
|
1939
|
+
merged[matchIndex] = order;
|
|
1940
|
+
} else {
|
|
1941
|
+
merged[matchIndex] = this.mergeOrderRecords(order, merged[matchIndex]);
|
|
1942
|
+
}
|
|
1560
1943
|
continue;
|
|
1561
1944
|
}
|
|
1562
1945
|
if (!this.getOrderStorageKey(order))
|
|
@@ -1584,8 +1967,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1584
1967
|
* @example
|
|
1585
1968
|
* await this.patchOrdersInSQLite(freshOrders)
|
|
1586
1969
|
*/
|
|
1587
|
-
async patchOrdersInSQLite(orders, source, mergeActions = {}) {
|
|
1588
|
-
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 数据库未初始化");
|
|
1589
1977
|
return;
|
|
1590
1978
|
}
|
|
1591
1979
|
const ordersSnapshot = (0, import_lodash_es.cloneDeep)(orders).map((order) => this.normalizeOrderCollectionsForIngress(order, `${source}.sqliteIngress`)).filter((order) => this.getOrderStorageKey(order));
|
|
@@ -1623,6 +2011,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1623
2011
|
for (const order of compactedToWrite) {
|
|
1624
2012
|
await this.dbManager.update(INDEXDB_STORE_NAME, order);
|
|
1625
2013
|
}
|
|
2014
|
+
} else if (options.throwOnError) {
|
|
2015
|
+
throw new Error("订单 SQLite 数据库不支持写入");
|
|
1626
2016
|
}
|
|
1627
2017
|
this.recordRecentSqliteWrite(source, compactedToWrite);
|
|
1628
2018
|
this.logInfo("patchOrdersInSQLite-完成", {
|
|
@@ -1637,6 +2027,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1637
2027
|
error: error instanceof Error ? error.message : String(error),
|
|
1638
2028
|
orderCount: ordersSnapshot.length
|
|
1639
2029
|
});
|
|
2030
|
+
if (options.throwOnError)
|
|
2031
|
+
throw error;
|
|
1640
2032
|
}
|
|
1641
2033
|
}
|
|
1642
2034
|
/**
|
|
@@ -1645,8 +2037,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1645
2037
|
* @example
|
|
1646
2038
|
* await this.updateOrderInSQLite(freshOrder)
|
|
1647
2039
|
*/
|
|
1648
|
-
async updateOrderInSQLite(order, source) {
|
|
1649
|
-
if (!this.
|
|
2040
|
+
async updateOrderInSQLite(order, source, options = {}) {
|
|
2041
|
+
if (!this.getOrderStorageKey(order)) {
|
|
2042
|
+
if (options.throwOnError)
|
|
2043
|
+
throw new Error("订单缺少可用的 SQLite 存储主键");
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
2046
|
+
if (!this.dbManager) {
|
|
2047
|
+
if (options.throwOnError)
|
|
2048
|
+
throw new Error("订单 SQLite 数据库未初始化");
|
|
1650
2049
|
return;
|
|
1651
2050
|
}
|
|
1652
2051
|
const orderSnapshot = this.normalizeOrderCollectionsForIngress(
|
|
@@ -1670,6 +2069,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1670
2069
|
} else if (typeof this.dbManager.bulkAdd === "function") {
|
|
1671
2070
|
writeMethod = "bulkAdd";
|
|
1672
2071
|
await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, [orderSnapshot]);
|
|
2072
|
+
} else if (options.throwOnError) {
|
|
2073
|
+
throw new Error("订单 SQLite 数据库不支持写入");
|
|
1673
2074
|
}
|
|
1674
2075
|
this.recordRecentSqliteWrite(source, [orderSnapshot]);
|
|
1675
2076
|
this.logInfo("updateOrderInSQLite-完成", {
|
|
@@ -1683,6 +2084,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1683
2084
|
error: error instanceof Error ? error.message : String(error),
|
|
1684
2085
|
orderId: orderSnapshot.order_id ?? null
|
|
1685
2086
|
});
|
|
2087
|
+
if (options.throwOnError)
|
|
2088
|
+
throw error;
|
|
1686
2089
|
}
|
|
1687
2090
|
}
|
|
1688
2091
|
/**
|
|
@@ -1717,7 +2120,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1717
2120
|
source,
|
|
1718
2121
|
count: mergedSnapshot.length,
|
|
1719
2122
|
remoteCount: remoteSnapshot.length,
|
|
1720
|
-
|
|
2123
|
+
preservedLocalUnsyncedCount: mergedSnapshot.length - remoteSnapshot.length
|
|
1721
2124
|
});
|
|
1722
2125
|
await this.dbManager.clear(INDEXDB_STORE_NAME);
|
|
1723
2126
|
this.logInfo("replaceOrdersSnapshotInSQLite-clear完成", {
|