@pisell/pisellos 2.2.291 → 2.2.293
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 +7 -0
- package/dist/core/index.js +108 -65
- package/dist/model/strategy/adapter/itemRule/adapter.d.ts +4 -1
- package/dist/model/strategy/adapter/itemRule/adapter.js +135 -35
- package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
- package/dist/model/strategy/adapter/itemRule/evaluator.js +25 -1
- package/dist/model/strategy/adapter/itemRule/type.d.ts +44 -0
- package/dist/model/strategy/adapter/itemRule/type.js +19 -1
- package/dist/model/strategy/adapter/promotion/index.js +0 -9
- package/dist/modules/BookingContext/index.d.ts +3 -0
- package/dist/modules/BookingContext/index.js +42 -13
- package/dist/modules/BookingContext/types.d.ts +4 -4
- package/dist/modules/BookingContext/types.js +3 -3
- package/dist/modules/OpenData/types.d.ts +1 -0
- package/dist/modules/Order/index.d.ts +18 -3
- package/dist/modules/Order/index.js +885 -485
- package/dist/modules/Order/salesNotes.d.ts +31 -0
- package/dist/modules/Order/salesNotes.js +492 -0
- package/dist/modules/Order/types.d.ts +93 -5
- package/dist/modules/Order/types.js +5 -0
- package/dist/modules/Order/utils.d.ts +12 -0
- package/dist/modules/Order/utils.js +96 -31
- package/dist/modules/Product/types.d.ts +2 -0
- package/dist/modules/ProductList/clientDataVariants.d.ts +50 -0
- package/dist/modules/ProductList/clientDataVariants.js +216 -0
- package/dist/modules/ProductList/index.d.ts +18 -3
- package/dist/modules/ProductList/index.js +220 -38
- package/dist/modules/ProductList/types.d.ts +10 -0
- package/dist/modules/Quotation/index.d.ts +22 -0
- package/dist/modules/Quotation/index.js +293 -28
- package/dist/modules/ResourcePlanner/index.d.ts +0 -22
- package/dist/modules/ResourcePlanner/index.js +1 -180
- package/dist/modules/ResourcePlanner/localClock.d.ts +33 -0
- package/dist/modules/ResourcePlanner/localClock.js +183 -0
- package/dist/modules/ResourcePlanner/planner.d.ts +5 -14
- package/dist/modules/ResourcePlanner/planner.js +2111 -958
- package/dist/modules/ResourcePlanner/types.d.ts +359 -187
- package/dist/modules/ResourcePlanner/types.js +33 -1
- package/dist/plugins/request.d.ts +1 -0
- package/dist/server/index.d.ts +17 -2
- package/dist/server/index.js +1134 -932
- package/dist/server/modules/floor-plan/index.d.ts +4 -0
- package/dist/server/modules/floor-plan/index.js +240 -98
- package/dist/server/modules/menu/index.js +48 -23
- package/dist/server/modules/order/index.d.ts +17 -7
- package/dist/server/modules/order/index.js +419 -207
- package/dist/server/modules/products/index.d.ts +10 -4
- package/dist/server/modules/products/index.js +177 -84
- package/dist/server/modules/resource/index.js +21 -13
- package/dist/server/utils/product.d.ts +1 -1
- package/dist/server/utils/product.js +186 -22
- package/dist/server/utils/small-ticket.d.ts +9 -1
- package/dist/server/utils/small-ticket.js +131 -84
- package/dist/solution/BaseSales/index.d.ts +26 -3
- package/dist/solution/BaseSales/index.js +1384 -905
- package/dist/solution/BaseSales/types.d.ts +2 -0
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +10 -3
- package/dist/solution/BaseSales/utils.js +6 -3
- package/dist/solution/BookingByStep/index.d.ts +4 -4
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +4 -2
- package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +2 -1
- package/dist/solution/BookingTicket/utils/addProductDecision.js +6 -3
- package/dist/solution/BookingTicket/utils/orderCustomer.js +3 -2
- package/dist/solution/RegisterAndLogin/config.d.ts +9 -3
- package/dist/solution/RegisterAndLogin/config.js +95 -40
- package/dist/solution/RegisterAndLogin/index.js +4 -1
- package/dist/solution/ScanOrder/index.d.ts +1 -0
- package/dist/solution/ScanOrder/index.js +31 -27
- package/dist/solution/ScanOrder/types.d.ts +2 -0
- package/dist/solution/ScanOrder/utils.d.ts +1 -0
- package/dist/solution/ScanOrder/utils.js +8 -3
- package/dist/solution/UnifiedBookingSales/index.d.ts +128 -74
- package/dist/solution/UnifiedBookingSales/index.js +3877 -963
- package/dist/solution/UnifiedBookingSales/remoteOccupancyCache.d.ts +49 -0
- package/dist/solution/UnifiedBookingSales/remoteOccupancyCache.js +430 -0
- package/dist/solution/UnifiedBookingSales/types.d.ts +161 -77
- package/dist/solution/UnifiedBookingSales/types.js +4 -9
- package/dist/solution/VenueBooking/index.d.ts +3 -0
- package/dist/solution/VenueBooking/index.js +549 -497
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.js +3 -1
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +2 -0
- package/dist/solution/VenueBooking/utils/slotMerge.js +3 -1
- package/dist/utils/platform.d.ts +8 -0
- package/dist/utils/platform.js +15 -0
- package/lib/core/index.d.ts +7 -0
- package/lib/core/index.js +20 -2
- package/lib/model/strategy/adapter/itemRule/adapter.d.ts +4 -1
- package/lib/model/strategy/adapter/itemRule/adapter.js +73 -4
- package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
- package/lib/model/strategy/adapter/itemRule/evaluator.js +23 -1
- package/lib/model/strategy/adapter/itemRule/type.d.ts +44 -0
- package/lib/model/strategy/adapter/itemRule/type.js +19 -1
- package/lib/modules/BookingContext/index.d.ts +3 -0
- package/lib/modules/BookingContext/index.js +35 -8
- package/lib/modules/BookingContext/types.d.ts +4 -4
- package/lib/modules/BookingContext/types.js +3 -3
- package/lib/modules/OpenData/types.d.ts +1 -0
- package/lib/modules/Order/index.d.ts +18 -3
- package/lib/modules/Order/index.js +325 -28
- package/lib/modules/Order/salesNotes.d.ts +31 -0
- package/lib/modules/Order/salesNotes.js +382 -0
- package/lib/modules/Order/types.d.ts +93 -5
- package/lib/modules/Order/types.js +4 -0
- package/lib/modules/Order/utils.d.ts +12 -0
- package/lib/modules/Order/utils.js +85 -16
- package/lib/modules/Product/types.d.ts +2 -0
- package/lib/modules/ProductList/clientDataVariants.d.ts +50 -0
- package/lib/modules/ProductList/clientDataVariants.js +204 -0
- package/lib/modules/ProductList/index.d.ts +18 -3
- package/lib/modules/ProductList/index.js +137 -8
- package/lib/modules/ProductList/types.d.ts +10 -0
- package/lib/modules/Quotation/index.d.ts +22 -0
- package/lib/modules/Quotation/index.js +158 -11
- package/lib/modules/ResourcePlanner/index.d.ts +0 -22
- package/lib/modules/ResourcePlanner/index.js +9 -129
- package/lib/modules/ResourcePlanner/localClock.d.ts +33 -0
- package/lib/modules/ResourcePlanner/localClock.js +205 -0
- package/lib/modules/ResourcePlanner/planner.d.ts +5 -14
- package/lib/modules/ResourcePlanner/planner.js +1807 -783
- package/lib/modules/ResourcePlanner/types.d.ts +359 -187
- package/lib/modules/ResourcePlanner/types.js +13 -1
- package/lib/plugins/request.d.ts +1 -0
- package/lib/server/index.d.ts +17 -2
- package/lib/server/index.js +149 -21
- package/lib/server/modules/floor-plan/index.d.ts +4 -0
- package/lib/server/modules/floor-plan/index.js +60 -7
- package/lib/server/modules/menu/index.js +26 -4
- package/lib/server/modules/order/index.d.ts +17 -7
- package/lib/server/modules/order/index.js +194 -57
- package/lib/server/modules/products/index.d.ts +10 -4
- package/lib/server/modules/products/index.js +93 -23
- package/lib/server/modules/resource/index.js +12 -2
- package/lib/server/utils/product.d.ts +1 -1
- package/lib/server/utils/product.js +163 -3
- package/lib/server/utils/small-ticket.d.ts +9 -1
- package/lib/server/utils/small-ticket.js +123 -79
- package/lib/solution/BaseSales/index.d.ts +26 -3
- package/lib/solution/BaseSales/index.js +396 -70
- package/lib/solution/BaseSales/types.d.ts +2 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +9 -2
- package/lib/solution/BaseSales/utils.js +3 -0
- package/lib/solution/BookingByStep/index.d.ts +4 -4
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +2 -1
- package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +2 -1
- package/lib/solution/BookingTicket/utils/addProductDecision.js +5 -2
- package/lib/solution/BookingTicket/utils/orderCustomer.js +2 -1
- package/lib/solution/RegisterAndLogin/config.d.ts +9 -3
- package/lib/solution/RegisterAndLogin/config.js +49 -8
- package/lib/solution/RegisterAndLogin/index.js +4 -1
- package/lib/solution/ScanOrder/index.d.ts +1 -0
- package/lib/solution/ScanOrder/index.js +5 -1
- package/lib/solution/ScanOrder/types.d.ts +2 -0
- package/lib/solution/ScanOrder/utils.d.ts +1 -0
- package/lib/solution/ScanOrder/utils.js +4 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +128 -74
- package/lib/solution/UnifiedBookingSales/index.js +2592 -424
- package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.d.ts +49 -0
- package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.js +316 -0
- package/lib/solution/UnifiedBookingSales/types.d.ts +161 -77
- package/lib/solution/UnifiedBookingSales/types.js +4 -6
- package/lib/solution/VenueBooking/index.d.ts +3 -0
- package/lib/solution/VenueBooking/index.js +33 -9
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.js +3 -1
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +2 -0
- package/lib/solution/VenueBooking/utils/slotMerge.js +3 -1
- package/lib/utils/platform.d.ts +8 -0
- package/lib/utils/platform.js +22 -0
- package/package.json +1 -1
|
@@ -17,6 +17,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
17
17
|
const INDEXDB_STORE_NAME = 'orders';
|
|
18
18
|
const ORDER_STORAGE_KEY_FIELD = '__order_storage_key';
|
|
19
19
|
const ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY = 'server_order_last_full_fetch_at';
|
|
20
|
+
const ORDER_LAST_FULL_FETCH_SHOP_ID_STORAGE_KEY = 'server_order_last_full_fetch_shop_id';
|
|
20
21
|
const ORDER_SYNC_THROTTLE_MS_STORAGE_KEY = 'order_sync_throttle_ms';
|
|
21
22
|
const DEFAULT_ORDER_SYNC_THROTTLE_MS = 2_000;
|
|
22
23
|
/** pubsub 回声写入去重窗口:业务 API 刚写入后,跳过同单 SQLite patch */
|
|
@@ -182,19 +183,25 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
182
183
|
* 仅记录计数与订单标识,不输出商品、预约、支付或客户明细。
|
|
183
184
|
*/
|
|
184
185
|
normalizeOrderCollectionsForIngress(order, source) {
|
|
185
|
-
const
|
|
186
|
-
|
|
186
|
+
const sourceOrderRecord = order;
|
|
187
|
+
let sourceOrder = sourceOrderRecord;
|
|
187
188
|
if (Array.isArray(sourceOrderRecord.payments)) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
189
|
+
sourceOrder = {
|
|
190
|
+
...sourceOrderRecord,
|
|
191
|
+
payments: sourceOrderRecord.payments.map(payment => {
|
|
192
|
+
if (!(0, _paymentUtils.isPendingOrderPayment)(payment) || (0, _paymentUtils.getOrderPaymentIdentityKeys)(payment).some(key => key.startsWith('unique_payment_number:'))) {
|
|
193
|
+
return payment;
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
...payment,
|
|
197
|
+
[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER]: true
|
|
198
|
+
};
|
|
199
|
+
})
|
|
200
|
+
};
|
|
197
201
|
}
|
|
202
|
+
|
|
203
|
+
// normalizeOrderCollections 内部已经 cloneDeep;这里只浅复制被改写的 payments,
|
|
204
|
+
// 既不修改调用方对象,也避免对整笔订单重复深拷贝。
|
|
198
205
|
const result = (0, _orderCollectionIdentity.normalizeOrderCollections)(sourceOrder);
|
|
199
206
|
const normalizedOrderRecord = result.order;
|
|
200
207
|
if (Array.isArray(normalizedOrderRecord.payments)) {
|
|
@@ -528,27 +535,68 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
528
535
|
return DEFAULT_ORDER_SYNC_THROTTLE_MS;
|
|
529
536
|
}
|
|
530
537
|
async preload() {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
538
|
+
const preloadStartedAt = Date.now();
|
|
539
|
+
let cachedOrders = null;
|
|
540
|
+
let sqliteLoadTimings;
|
|
541
|
+
if (this.dbManager) {
|
|
542
|
+
try {
|
|
543
|
+
cachedOrders = await this.loadOrdersFromSQLite({
|
|
544
|
+
throwOnError: true,
|
|
545
|
+
onTiming: timings => {
|
|
546
|
+
sqliteLoadTimings = timings;
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
} catch (error) {
|
|
550
|
+
this.logWarning('preload-SQLite读取失败,回退远端全量拉取', {
|
|
551
|
+
error: error instanceof Error ? error.message : String(error)
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (cachedOrders !== null && this.hasPulledOrdersToday()) {
|
|
556
|
+
const memoryPrepareStartedAt = performance.now();
|
|
557
|
+
const memoryOrders = this.prepareNormalizedOrdersForMemoryList(cachedOrders);
|
|
558
|
+
const memoryPrepareMs = +(performance.now() - memoryPrepareStartedAt).toFixed(2);
|
|
546
559
|
|
|
547
|
-
|
|
560
|
+
// loadOrdersFromSQLite 已返回独立且完成集合规范化的新对象;直接进入 store,
|
|
561
|
+
// 不再进行第二轮 normalize 和没有隔离收益的最终 cloneDeep。
|
|
562
|
+
this.store.list = memoryOrders;
|
|
563
|
+
const syncMapStartedAt = performance.now();
|
|
564
|
+
this.syncOrdersMap();
|
|
565
|
+
const syncMapMs = +(performance.now() - syncMapStartedAt).toFixed(2);
|
|
566
|
+
const onOrdersLoadedStartedAt = performance.now();
|
|
567
|
+
await this.core.effects.emit(_types.OrderHooks.onOrdersLoaded, this.store.list);
|
|
568
|
+
const onOrdersLoadedMs = +(performance.now() - onOrdersLoadedStartedAt).toFixed(2);
|
|
569
|
+
const emitOrdersChangedStartedAt = performance.now();
|
|
570
|
+
await this.emitOrdersChanged([], 'preload.sqlite');
|
|
571
|
+
const emitOrdersChangedMs = +(performance.now() - emitOrdersChangedStartedAt).toFixed(2);
|
|
572
|
+
this.logInfo('预加载完成', {
|
|
573
|
+
trigger: 'preload',
|
|
574
|
+
source: 'SQLite',
|
|
575
|
+
orderCount: this.store.list.length,
|
|
576
|
+
duration: `${Date.now() - preloadStartedAt}ms`,
|
|
577
|
+
stages: {
|
|
578
|
+
...(sqliteLoadTimings || {}),
|
|
579
|
+
memoryPrepareMs,
|
|
580
|
+
syncMapMs,
|
|
581
|
+
onOrdersLoadedMs,
|
|
582
|
+
emitOrdersChangedMs
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
const orders = await this.loadOrdersByServer({
|
|
588
|
+
trigger: 'preload'
|
|
589
|
+
});
|
|
548
590
|
this.store.list = (0, _lodashEs.cloneDeep)(orders);
|
|
549
591
|
this.syncOrdersMap();
|
|
550
592
|
await this.emitOrdersChanged([], 'preload');
|
|
551
593
|
await this.core.effects.emit(_types.OrderHooks.onOrdersSyncCompleted, null);
|
|
594
|
+
this.logInfo('预加载完成', {
|
|
595
|
+
trigger: 'preload',
|
|
596
|
+
source: 'Server',
|
|
597
|
+
orderCount: this.store.list.length,
|
|
598
|
+
duration: `${Date.now() - preloadStartedAt}ms`
|
|
599
|
+
});
|
|
552
600
|
}
|
|
553
601
|
getOrders() {
|
|
554
602
|
return this.store.list;
|
|
@@ -764,10 +812,13 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
764
812
|
previousPayment
|
|
765
813
|
};
|
|
766
814
|
}
|
|
767
|
-
async loadOrdersByServer() {
|
|
815
|
+
async loadOrdersByServer(options = {}) {
|
|
768
816
|
let orderList = [];
|
|
817
|
+
let hasFetchedRemoteSnapshot = false;
|
|
818
|
+
const trigger = options.trigger || 'unknown';
|
|
769
819
|
const protectedOrdersBeforeRemoteFetch = (await this.loadOrdersFromSQLite()).filter(order => this.shouldProtectLocalOrderFromRemoteSnapshot(order));
|
|
770
820
|
this.logInfo('loadOrdersByServer-开始', {
|
|
821
|
+
trigger,
|
|
771
822
|
hasOrderDataSource: !!this.orderDataSource,
|
|
772
823
|
query: this.store?.createdAtQuery || null,
|
|
773
824
|
protectedLocalOrderCount: protectedOrdersBeforeRemoteFetch.length,
|
|
@@ -782,18 +833,29 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
782
833
|
});
|
|
783
834
|
orderList = data || [];
|
|
784
835
|
this.logInfo('loadOrdersByServer-SSE拉取成功', {
|
|
836
|
+
trigger,
|
|
785
837
|
count: orderList.length
|
|
786
838
|
});
|
|
787
|
-
|
|
839
|
+
hasFetchedRemoteSnapshot = true;
|
|
788
840
|
this.lastServerFullFetchAtMs = Date.now();
|
|
789
841
|
} catch {
|
|
790
842
|
this.logInfo('loadOrdersByServer-SSE拉取失败,保持当前内存订单');
|
|
791
843
|
return this.store.list;
|
|
792
844
|
}
|
|
793
845
|
}
|
|
794
|
-
|
|
846
|
+
if (hasFetchedRemoteSnapshot) {
|
|
847
|
+
this.clearOrderSnapshotMarker();
|
|
848
|
+
}
|
|
849
|
+
const {
|
|
850
|
+
orders: mergedOrders,
|
|
851
|
+
persisted: isRemoteSnapshotPersisted
|
|
852
|
+
} = await this.replaceOrdersSnapshotInSQLite(orderList, 'loadOrdersByServer', protectedOrdersBeforeRemoteFetch);
|
|
853
|
+
if (hasFetchedRemoteSnapshot && isRemoteSnapshotPersisted) {
|
|
854
|
+
this.markOrderPulledAtNow();
|
|
855
|
+
}
|
|
795
856
|
const memoryOrders = this.normalizeOrdersForMemoryList(mergedOrders, 'loadOrdersByServer.memory');
|
|
796
857
|
this.logInfo('loadOrdersByServer-结束', {
|
|
858
|
+
trigger,
|
|
797
859
|
count: memoryOrders.length,
|
|
798
860
|
persistedCount: mergedOrders.length,
|
|
799
861
|
sqliteOnlyDraftCount: mergedOrders.length - memoryOrders.length
|
|
@@ -807,22 +869,37 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
807
869
|
* 拿到完整数据后一次性替换 store,触发订单变更与同步完成事件
|
|
808
870
|
* @returns 刷新后的订单列表
|
|
809
871
|
*/
|
|
810
|
-
async silentRefresh() {
|
|
872
|
+
async silentRefresh(options = {}) {
|
|
811
873
|
const startTime = Date.now();
|
|
874
|
+
const trigger = options.trigger || 'background';
|
|
812
875
|
const elapsedSinceFullFetch = Date.now() - this.lastServerFullFetchAtMs;
|
|
813
876
|
if (this.lastServerFullFetchAtMs > 0 && elapsedSinceFullFetch < ORDER_SILENT_REFRESH_MIN_INTERVAL_MS) {
|
|
877
|
+
this.logInfo('silentRefresh 跳过全量 SSE', {
|
|
878
|
+
trigger,
|
|
879
|
+
reason: 'within_min_interval',
|
|
880
|
+
minIntervalMs: ORDER_SILENT_REFRESH_MIN_INTERVAL_MS,
|
|
881
|
+
elapsedSinceFullFetchMs: elapsedSinceFullFetch,
|
|
882
|
+
orderCount: this.store.list.length
|
|
883
|
+
});
|
|
814
884
|
return this.store.list;
|
|
815
885
|
}
|
|
816
|
-
this.logInfo('silentRefresh 开始'
|
|
886
|
+
this.logInfo('silentRefresh 开始', {
|
|
887
|
+
trigger,
|
|
888
|
+
elapsedSinceFullFetchMs: elapsedSinceFullFetch,
|
|
889
|
+
orderCount: this.store.list.length
|
|
890
|
+
});
|
|
817
891
|
try {
|
|
818
892
|
// 刷新前,需要更新当前营业日边界(store.createdAtQuery)
|
|
819
893
|
this.updateCreateStore();
|
|
820
|
-
const orders = await this.loadOrdersByServer(
|
|
894
|
+
const orders = await this.loadOrdersByServer({
|
|
895
|
+
trigger
|
|
896
|
+
});
|
|
821
897
|
this.store.list = (0, _lodashEs.cloneDeep)(orders);
|
|
822
898
|
this.syncOrdersMap();
|
|
823
899
|
await this.emitOrdersChanged([], 'silentRefresh');
|
|
824
900
|
await this.core.effects.emit(_types.OrderHooks.onOrdersSyncCompleted, null);
|
|
825
901
|
this.logInfo('silentRefresh 完成', {
|
|
902
|
+
trigger,
|
|
826
903
|
orderCount: orders.length,
|
|
827
904
|
duration: `${Date.now() - startTime}ms`
|
|
828
905
|
});
|
|
@@ -830,6 +907,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
830
907
|
} catch (error) {
|
|
831
908
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
832
909
|
this.logError('silentRefresh 失败', {
|
|
910
|
+
trigger,
|
|
833
911
|
duration: `${Date.now() - startTime}ms`,
|
|
834
912
|
error: errorMessage
|
|
835
913
|
});
|
|
@@ -838,6 +916,13 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
838
916
|
}
|
|
839
917
|
normalizeOrderForMemoryList(order, source = 'normalizeOrderForMemoryList') {
|
|
840
918
|
const normalizedOrder = this.normalizeOrderCollectionsForIngress(order, source);
|
|
919
|
+
return this.prepareNormalizedOrderForMemoryList(normalizedOrder);
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/**
|
|
923
|
+
* 将已经完成集合规范化的订单转换为内存身份,不重复扫描 products/bookings/payments。
|
|
924
|
+
*/
|
|
925
|
+
prepareNormalizedOrderForMemoryList(normalizedOrder) {
|
|
841
926
|
const externalSaleNumber = normalizedOrder?.external_sale_number;
|
|
842
927
|
if (this.isDraftOrder(normalizedOrder) && !this.hasRealOrderId(normalizedOrder)) {
|
|
843
928
|
return normalizedOrder;
|
|
@@ -853,6 +938,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
853
938
|
order_id: externalSaleNumber
|
|
854
939
|
};
|
|
855
940
|
}
|
|
941
|
+
prepareNormalizedOrdersForMemoryList(orders) {
|
|
942
|
+
return orders.map(order => this.prepareNormalizedOrderForMemoryList(order)).filter(order => this.shouldKeepOrderInMemory(order));
|
|
943
|
+
}
|
|
856
944
|
normalizeOrdersForMemoryList(orders, source) {
|
|
857
945
|
return orders.map(order => this.normalizeOrderForMemoryList(order, source)).filter(order => this.shouldKeepOrderInMemory(order));
|
|
858
946
|
}
|
|
@@ -2021,22 +2109,29 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2021
2109
|
}
|
|
2022
2110
|
|
|
2023
2111
|
/**
|
|
2024
|
-
*
|
|
2025
|
-
*
|
|
2026
|
-
* - 无法解析时退化为自然日窗口
|
|
2112
|
+
* 当前订单缓存可复用窗口。
|
|
2113
|
+
* start_time 模式使用精确的营业日起止时间;配置缺失或异常时退化为自然日。
|
|
2027
2114
|
*/
|
|
2028
|
-
|
|
2115
|
+
getCurrentOrderCacheWindow() {
|
|
2029
2116
|
const now = (0, _dayjs.default)();
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
const
|
|
2033
|
-
const
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2117
|
+
try {
|
|
2118
|
+
const appPlugin = this.core.getPlugin('app');
|
|
2119
|
+
const app = appPlugin?.getApp();
|
|
2120
|
+
const coreData = app?.data.store.getStore().getDataByModel('core');
|
|
2121
|
+
const boundary = coreData?.core?.operating_day_boundary;
|
|
2122
|
+
if (boundary?.type === 'start_time') {
|
|
2123
|
+
const boundaryTime = String(boundary.time || '').trim();
|
|
2124
|
+
const todayBoundary = (0, _dayjs.default)(`${now.format('YYYY-MM-DD')} ${boundaryTime}`);
|
|
2125
|
+
if (todayBoundary.isValid()) {
|
|
2126
|
+
const startAt = now.isBefore(todayBoundary) ? todayBoundary.subtract(1, 'day') : todayBoundary;
|
|
2127
|
+
return {
|
|
2128
|
+
startAt,
|
|
2129
|
+
endExclusiveAt: startAt.add(1, 'day')
|
|
2130
|
+
};
|
|
2131
|
+
}
|
|
2039
2132
|
}
|
|
2133
|
+
} catch {
|
|
2134
|
+
// 读取营业日配置失败时按自然日兜底,不影响启动。
|
|
2040
2135
|
}
|
|
2041
2136
|
const startAt = now.startOf('day');
|
|
2042
2137
|
return {
|
|
@@ -2047,19 +2142,41 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2047
2142
|
hasPulledOrdersToday() {
|
|
2048
2143
|
const lastFullFetchAt = this.getStorageItem(ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY);
|
|
2049
2144
|
if (!lastFullFetchAt) return false;
|
|
2145
|
+
const currentShopId = this.getCurrentShopId();
|
|
2146
|
+
const lastFullFetchShopId = this.getStorageItem(ORDER_LAST_FULL_FETCH_SHOP_ID_STORAGE_KEY);
|
|
2147
|
+
if (!currentShopId || !lastFullFetchShopId || currentShopId !== lastFullFetchShopId) {
|
|
2148
|
+
return false;
|
|
2149
|
+
}
|
|
2050
2150
|
const parsed = (0, _dayjs.default)(lastFullFetchAt);
|
|
2051
2151
|
if (!parsed.isValid()) return false;
|
|
2052
|
-
|
|
2053
|
-
// 按当前拉取窗口判断,而不是自然日判断。
|
|
2054
|
-
// 这样在营业日跨日边界(start_time)场景下也能正确判定是否需要重新拉取。
|
|
2055
2152
|
const {
|
|
2056
2153
|
startAt,
|
|
2057
2154
|
endExclusiveAt
|
|
2058
|
-
} = this.
|
|
2155
|
+
} = this.getCurrentOrderCacheWindow();
|
|
2059
2156
|
return (parsed.isAfter(startAt) || parsed.isSame(startAt)) && parsed.isBefore(endExclusiveAt);
|
|
2060
2157
|
}
|
|
2061
2158
|
markOrderPulledAtNow() {
|
|
2159
|
+
const currentShopId = this.getCurrentShopId();
|
|
2160
|
+
if (!currentShopId) return;
|
|
2062
2161
|
this.setStorageItem(ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY, (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss'));
|
|
2162
|
+
this.setStorageItem(ORDER_LAST_FULL_FETCH_SHOP_ID_STORAGE_KEY, currentShopId);
|
|
2163
|
+
}
|
|
2164
|
+
clearOrderSnapshotMarker() {
|
|
2165
|
+
this.setStorageItem(ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY, '');
|
|
2166
|
+
this.setStorageItem(ORDER_LAST_FULL_FETCH_SHOP_ID_STORAGE_KEY, '');
|
|
2167
|
+
}
|
|
2168
|
+
getCurrentShopId() {
|
|
2169
|
+
try {
|
|
2170
|
+
const appPlugin = this.core.getPlugin('app');
|
|
2171
|
+
const app = appPlugin?.getApp();
|
|
2172
|
+
if (!app) return null;
|
|
2173
|
+
const coreData = app.data.store.getStore().getDataByModel('core');
|
|
2174
|
+
const shopId = coreData?.core?.id;
|
|
2175
|
+
if (shopId === undefined || shopId === null || shopId === '') return null;
|
|
2176
|
+
return String(shopId);
|
|
2177
|
+
} catch {
|
|
2178
|
+
return null;
|
|
2179
|
+
}
|
|
2063
2180
|
}
|
|
2064
2181
|
getStorageItem(key) {
|
|
2065
2182
|
try {
|
|
@@ -2085,12 +2202,24 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2085
2202
|
// 忽略存储异常,避免影响主流程
|
|
2086
2203
|
}
|
|
2087
2204
|
}
|
|
2088
|
-
async loadOrdersFromSQLite() {
|
|
2205
|
+
async loadOrdersFromSQLite(options = {}) {
|
|
2089
2206
|
if (!this.dbManager) return [];
|
|
2090
2207
|
try {
|
|
2208
|
+
const loadStartedAt = performance.now();
|
|
2209
|
+
const rawReadStartedAt = performance.now();
|
|
2091
2210
|
const orders = await this.dbManager.getAll(INDEXDB_STORE_NAME);
|
|
2092
|
-
|
|
2093
|
-
|
|
2211
|
+
const sqliteRawReadMs = +(performance.now() - rawReadStartedAt).toFixed(2);
|
|
2212
|
+
const normalizeStartedAt = performance.now();
|
|
2213
|
+
const normalizedOrders = (orders || []).map(order => this.normalizeOrderCollectionsForIngress(order, 'loadOrdersFromSQLite'));
|
|
2214
|
+
const sqliteNormalizeMs = +(performance.now() - normalizeStartedAt).toFixed(2);
|
|
2215
|
+
options.onTiming?.({
|
|
2216
|
+
sqliteRawReadMs,
|
|
2217
|
+
sqliteNormalizeMs,
|
|
2218
|
+
sqliteLoadTotalMs: +(performance.now() - loadStartedAt).toFixed(2)
|
|
2219
|
+
});
|
|
2220
|
+
return normalizedOrders;
|
|
2221
|
+
} catch (error) {
|
|
2222
|
+
if (options.throwOnError) throw error;
|
|
2094
2223
|
return [];
|
|
2095
2224
|
}
|
|
2096
2225
|
}
|
|
@@ -2323,14 +2452,18 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2323
2452
|
* 用于 SSE 全量拉取与营业日窗口裁剪。
|
|
2324
2453
|
*
|
|
2325
2454
|
* @example
|
|
2326
|
-
* await this.replaceOrdersSnapshotInSQLite(orderList)
|
|
2455
|
+
* const { orders, persisted } = await this.replaceOrdersSnapshotInSQLite(orderList, 'refresh')
|
|
2327
2456
|
*/
|
|
2328
2457
|
async replaceOrdersSnapshotInSQLite(orderList, source, protectedOrdersBeforeRemoteFetch = []) {
|
|
2329
2458
|
if (!this.dbManager) {
|
|
2330
|
-
return
|
|
2459
|
+
return {
|
|
2460
|
+
orders: this.compactOrderListByIdentity(orderList.map(order => this.normalizeRemoteSyncedOrder(order)), `${source}.snapshotNoDb`).list,
|
|
2461
|
+
persisted: false
|
|
2462
|
+
};
|
|
2331
2463
|
}
|
|
2332
2464
|
const remoteSnapshot = (0, _lodashEs.cloneDeep)(orderList).map(order => this.normalizeOrderCollectionsForIngress(order, `${source}.remoteIngress`));
|
|
2333
2465
|
let mergedSnapshot = this.compactOrderListByIdentity(remoteSnapshot.map(order => this.normalizeRemoteSyncedOrder(order)), `${source}.remoteSnapshot`).list;
|
|
2466
|
+
let persisted = false;
|
|
2334
2467
|
try {
|
|
2335
2468
|
await this.runInOrderSQLiteSaveQueue(async () => {
|
|
2336
2469
|
const existingOrders = typeof this.dbManager.getAll === 'function' ? await this.dbManager.getAll(INDEXDB_STORE_NAME) : [];
|
|
@@ -2379,13 +2512,17 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2379
2512
|
count: mergedSnapshot.length
|
|
2380
2513
|
});
|
|
2381
2514
|
});
|
|
2515
|
+
persisted = true;
|
|
2382
2516
|
} catch (error) {
|
|
2383
2517
|
this.logError('全量保存订单到 SQLite 失败', {
|
|
2384
2518
|
error: error instanceof Error ? error.message : String(error),
|
|
2385
2519
|
orderList: remoteSnapshot.length
|
|
2386
2520
|
});
|
|
2387
2521
|
}
|
|
2388
|
-
return
|
|
2522
|
+
return {
|
|
2523
|
+
orders: mergedSnapshot,
|
|
2524
|
+
persisted
|
|
2525
|
+
};
|
|
2389
2526
|
}
|
|
2390
2527
|
|
|
2391
2528
|
/**
|
|
@@ -2402,7 +2539,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2402
2539
|
await this.dbManager.clear(INDEXDB_STORE_NAME);
|
|
2403
2540
|
});
|
|
2404
2541
|
}
|
|
2405
|
-
this.
|
|
2542
|
+
this.clearOrderSnapshotMarker();
|
|
2406
2543
|
this.emitOrdersChanged([], 'clear');
|
|
2407
2544
|
}
|
|
2408
2545
|
}
|
|
@@ -25,6 +25,7 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
25
25
|
private quotationBridgeLoadedKey?;
|
|
26
26
|
private quotationBridgeRefreshPromise?;
|
|
27
27
|
private quotationBridgeRefreshKey?;
|
|
28
|
+
private quotationBridgeUpdatedCallback?;
|
|
28
29
|
private quotationScheduleCache;
|
|
29
30
|
private quotationScheduleCacheSource;
|
|
30
31
|
private quotationScheduleCacheLoaded;
|
|
@@ -72,6 +73,7 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
72
73
|
scheduleModule?: any;
|
|
73
74
|
channel?: string;
|
|
74
75
|
customer_id?: number | string;
|
|
76
|
+
onQuotationUpdated?: () => void;
|
|
75
77
|
}): Promise<void>;
|
|
76
78
|
/**
|
|
77
79
|
* 刷新桥接器内的报价单列表。
|
|
@@ -87,8 +89,8 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
87
89
|
private buildBundleGroupPriceData;
|
|
88
90
|
/**
|
|
89
91
|
* 获取应用了价格的商品列表(带缓存)
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
+
* 使用时间、客户、策略、商品范围和语言作为缓存 key
|
|
93
|
+
* 缓存的是已经应用了价格与多语言的完整商品列表,避免重复转换
|
|
92
94
|
* @param schedule_date 日期
|
|
93
95
|
* @param extraContext 额外的上下文数据(可选,由 Server 层传入)
|
|
94
96
|
* @param options 可选参数
|
|
@@ -181,7 +183,9 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
181
183
|
/**
|
|
182
184
|
* 通过 ProductDataSource SSE 加载完整商品列表
|
|
183
185
|
*/
|
|
184
|
-
loadProductsByServer(
|
|
186
|
+
loadProductsByServer(options?: {
|
|
187
|
+
trigger?: string;
|
|
188
|
+
}): Promise<any>;
|
|
185
189
|
/**
|
|
186
190
|
* 纯请求方法:通过 HTTP 接口获取商品列表(无副作用,不触发事件、不写 IndexDB)
|
|
187
191
|
* @param params 查询参数
|
|
@@ -331,7 +335,9 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
331
335
|
* 拿到完整数据后一次性替换 store,清除价格缓存,触发 onProductsSyncCompleted
|
|
332
336
|
* @returns 刷新后的商品列表
|
|
333
337
|
*/
|
|
334
|
-
silentRefresh(
|
|
338
|
+
silentRefresh(options?: {
|
|
339
|
+
trigger?: string;
|
|
340
|
+
}): Promise<ProductData[]>;
|
|
335
341
|
/**
|
|
336
342
|
* 销毁同步资源(取消 pubsub 订阅、清除定时器)
|
|
337
343
|
*/
|