@pisell/pisellos 2.3.66 → 2.3.68
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/promotion/index.js +0 -9
- package/dist/modules/BaseModule.d.ts +1 -0
- package/dist/modules/BaseModule.js +24 -28
- package/dist/modules/Order/index.d.ts +22 -2
- package/dist/modules/Order/index.js +313 -142
- package/dist/modules/Order/types.d.ts +13 -1
- package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +15 -0
- package/dist/modules/Order/utils/orderCollectionIdentity.js +75 -0
- package/dist/modules/Order/utils.js +0 -1
- package/dist/modules/Payment/index.d.ts +4 -0
- package/dist/modules/Payment/index.js +14 -4
- package/dist/modules/Payment/walletpass.js +21 -7
- package/dist/modules/Rules/index.js +46 -31
- package/dist/solution/BaseSales/index.d.ts +3 -1
- package/dist/solution/BaseSales/index.js +99 -82
- package/dist/solution/BaseSales/utils.js +31 -20
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +4 -2
- package/dist/solution/BookingTicket/index.js +89 -65
- package/dist/solution/ScanOrder/utils.js +31 -20
- package/dist/solution/UnifiedBookingSales/index.d.ts +25 -0
- package/dist/solution/UnifiedBookingSales/index.js +640 -321
- package/dist/solution/UnifiedBookingSales/types.d.ts +7 -0
- package/lib/model/strategy/adapter/promotion/index.js +0 -51
- package/lib/modules/BaseModule.d.ts +1 -0
- package/lib/modules/BaseModule.js +24 -37
- package/lib/modules/Order/index.d.ts +22 -2
- package/lib/modules/Order/index.js +212 -54
- package/lib/modules/Order/types.d.ts +13 -1
- package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +15 -0
- package/lib/modules/Order/utils/orderCollectionIdentity.js +70 -0
- package/lib/modules/Order/utils.js +0 -1
- package/lib/modules/Payment/index.d.ts +4 -0
- package/lib/modules/Payment/index.js +7 -0
- package/lib/modules/Payment/walletpass.js +12 -0
- package/lib/modules/Rules/index.js +17 -1
- package/lib/solution/BaseSales/index.d.ts +3 -1
- package/lib/solution/BaseSales/index.js +29 -16
- package/lib/solution/BaseSales/utils.js +29 -18
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +4 -2
- package/lib/solution/BookingTicket/index.js +35 -12
- package/lib/solution/ScanOrder/utils.js +29 -18
- package/lib/solution/UnifiedBookingSales/index.d.ts +25 -0
- package/lib/solution/UnifiedBookingSales/index.js +188 -0
- package/lib/solution/UnifiedBookingSales/types.d.ts +7 -0
- package/package.json +1 -1
|
@@ -66,8 +66,7 @@ function isSameDiscountList(left, right) {
|
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
68
|
function isManualProductDiscountProduct(product) {
|
|
69
|
-
|
|
70
|
-
return ((_a = product == null ? void 0 : product.metadata) == null ? void 0 : _a.is_manual_discount) === true || ((_b = product == null ? void 0 : product.metadata) == null ? void 0 : _b.is_manual_discount) === 1 || ((product == null ? void 0 : product.discount_list) || []).some((item) => (item == null ? void 0 : item.type) === "product");
|
|
69
|
+
return (0, import_manualProductDiscount.hasManualProductDiscountFlag)(product == null ? void 0 : product.metadata) || ((product == null ? void 0 : product.discount_list) || []).some((item) => (item == null ? void 0 : item.type) === "product");
|
|
71
70
|
}
|
|
72
71
|
var ORDER_PAYMENT_STATUS_PAID = "paid";
|
|
73
72
|
var ORDER_PAYMENT_STATUS_PENDING = "payment_pending";
|
|
@@ -114,6 +113,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
114
113
|
super(name || "order", version);
|
|
115
114
|
this.defaultName = "order";
|
|
116
115
|
this.defaultVersion = "1.0.0";
|
|
116
|
+
this.openCache = false;
|
|
117
|
+
this.sessionStoragePersistEnabled = false;
|
|
118
|
+
this.sessionStorageRestoreRecord = null;
|
|
117
119
|
// ─── 促销/赠品 ────────────────────────────────────
|
|
118
120
|
/** 评估器引用;由 SalesSdkProvider 注入,未注入时 applyPromotion 静默跳过 */
|
|
119
121
|
this.promotionEvaluator = null;
|
|
@@ -330,11 +332,32 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
330
332
|
return product;
|
|
331
333
|
});
|
|
332
334
|
}
|
|
335
|
+
syncSessionStorageOptions(otherParams) {
|
|
336
|
+
this.cacheId = otherParams.cacheId;
|
|
337
|
+
this.fatherModule = otherParams.fatherModule;
|
|
338
|
+
this.openCache = Boolean(
|
|
339
|
+
this.cacheId && otherParams.openCache !== false
|
|
340
|
+
);
|
|
341
|
+
this.sessionStoragePersistEnabled = Boolean(
|
|
342
|
+
this.openCache && otherParams.enableSessionStoragePersist === true
|
|
343
|
+
);
|
|
344
|
+
}
|
|
333
345
|
async initialize(core, options) {
|
|
334
346
|
var _a, _b, _c, _d;
|
|
335
347
|
this.core = core;
|
|
336
348
|
this.store = options.store;
|
|
337
|
-
|
|
349
|
+
const otherParams = options.otherParams || {};
|
|
350
|
+
this.syncSessionStorageOptions(otherParams);
|
|
351
|
+
if (this.sessionStoragePersistEnabled) {
|
|
352
|
+
const cachedTempOrder = this.store.tempOrder;
|
|
353
|
+
this.sessionStorageRestoreRecord = (0, import_utils.isTempOrder)(cachedTempOrder) ? (0, import_lodash_es.cloneDeep)(cachedTempOrder) : null;
|
|
354
|
+
this.store.tempOrder = null;
|
|
355
|
+
this.store.summary = (0, import_utils.createEmptySummary)();
|
|
356
|
+
this.store.availableWalletIds = [];
|
|
357
|
+
this.store.lastOrderInfo = void 0;
|
|
358
|
+
this.store.syncState = void 0;
|
|
359
|
+
this.store.discountList = [];
|
|
360
|
+
} else if (!this.store.tempOrder) {
|
|
338
361
|
this.store.tempOrder = null;
|
|
339
362
|
}
|
|
340
363
|
if (!this.store.summary) {
|
|
@@ -351,8 +374,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
351
374
|
const app = (_a = appPlugin == null ? void 0 : appPlugin.getApp) == null ? void 0 : _a.call(appPlugin);
|
|
352
375
|
this.logger = app == null ? void 0 : app.logger;
|
|
353
376
|
this.window = this.core.getPlugin("window");
|
|
354
|
-
const otherParams = options.otherParams || {};
|
|
355
|
-
this.cacheId = otherParams.cacheId;
|
|
356
377
|
this.salesSummaryModuleName = otherParams.salesSummaryModuleName;
|
|
357
378
|
this.rulesHooksOverride = (_b = otherParams.rules) == null ? void 0 : _b.hooks;
|
|
358
379
|
this.moduleHooksOverride = options.hooks;
|
|
@@ -363,6 +384,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
363
384
|
}
|
|
364
385
|
async destroy() {
|
|
365
386
|
var _a, _b;
|
|
387
|
+
this.sessionStorageRestoreRecord = null;
|
|
366
388
|
const childModules = [(_a = this.store) == null ? void 0 : _a.discount, (_b = this.store) == null ? void 0 : _b.rules];
|
|
367
389
|
for (const childModule of childModules) {
|
|
368
390
|
if (!childModule || typeof childModule.destroy !== "function")
|
|
@@ -392,7 +414,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
392
414
|
updateOtherParams(params) {
|
|
393
415
|
var _a, _b, _c;
|
|
394
416
|
const otherParams = params || {};
|
|
395
|
-
this.
|
|
417
|
+
this.syncSessionStorageOptions(otherParams);
|
|
396
418
|
this.salesSummaryModuleName = otherParams.salesSummaryModuleName;
|
|
397
419
|
this.rulesHooksOverride = (_a = otherParams.rules) == null ? void 0 : _a.hooks;
|
|
398
420
|
this.orderHooks = this.moduleHooksOverride || ((_b = otherParams.order) == null ? void 0 : _b.hooks) || ((_c = otherParams.hooks) == null ? void 0 : _c.order);
|
|
@@ -437,14 +459,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
437
459
|
// ─── Discount: 子模块注册 ───
|
|
438
460
|
registerDiscountModules(options) {
|
|
439
461
|
let targetCacheData = {};
|
|
440
|
-
if (this.cacheId && this.window) {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
462
|
+
if (!this.sessionStoragePersistEnabled && this.openCache && this.cacheId && this.window) {
|
|
463
|
+
try {
|
|
464
|
+
const sessionData = this.window.sessionStorage.getItem(this.name);
|
|
465
|
+
if (sessionData) {
|
|
444
466
|
const data = JSON.parse(sessionData);
|
|
445
467
|
targetCacheData = (data == null ? void 0 : data[this.cacheId]) || {};
|
|
446
|
-
} catch {
|
|
447
468
|
}
|
|
469
|
+
} catch {
|
|
448
470
|
}
|
|
449
471
|
}
|
|
450
472
|
const discount = new import_Discount.DiscountModule(`${this.name}_discount`);
|
|
@@ -452,7 +474,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
452
474
|
initialState: targetCacheData == null ? void 0 : targetCacheData[discount.name],
|
|
453
475
|
otherParams: {
|
|
454
476
|
fatherModule: this.name,
|
|
455
|
-
|
|
477
|
+
// Unified 的单快照由 Order 管理;其他 Solution 保持原有 Discount 缓存语义。
|
|
478
|
+
openCache: this.openCache && !this.sessionStoragePersistEnabled,
|
|
456
479
|
cacheId: this.cacheId
|
|
457
480
|
}
|
|
458
481
|
});
|
|
@@ -870,7 +893,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
870
893
|
}
|
|
871
894
|
/**
|
|
872
895
|
* 控制 IndexedDB 草稿(saveDraft)是否写入。
|
|
873
|
-
*
|
|
896
|
+
* 此开关仅影响 saveDraft;可选 sessionStorage 会话恢复由
|
|
897
|
+
* enableSessionStoragePersist 独立控制。
|
|
874
898
|
*
|
|
875
899
|
* @example
|
|
876
900
|
* order.setEnableTempOrderPersist(false); // BigSale 弹窗:跳过 ~1s 的 dbUpdate
|
|
@@ -882,8 +906,70 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
882
906
|
isTempOrderPersistEnabled() {
|
|
883
907
|
return this.draftPersistEnabled;
|
|
884
908
|
}
|
|
885
|
-
/**
|
|
909
|
+
/**
|
|
910
|
+
* 在 UnifiedBookingSales 显式开启会话恢复时,将完整 tempOrder 写入
|
|
911
|
+
* sessionStorage 的 cacheId 分桶。写入失败由 BaseModule 静默降级。
|
|
912
|
+
*/
|
|
886
913
|
persistTempOrder() {
|
|
914
|
+
if (!this.sessionStoragePersistEnabled || !this.store.tempOrder)
|
|
915
|
+
return;
|
|
916
|
+
this.checkSaveCache({
|
|
917
|
+
cacheId: this.cacheId,
|
|
918
|
+
fatherModule: this.fatherModule,
|
|
919
|
+
store: { tempOrder: this.store.tempOrder },
|
|
920
|
+
cacheKey: ["tempOrder"]
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* 终止当前模块实例的 sessionStorage 订单恢复会话。
|
|
925
|
+
*
|
|
926
|
+
* 支付跳转等终态场景需要同时删除当前 cacheId 的 tempOrder 快照,并关闭
|
|
927
|
+
* 本实例后续异步任务的再次写入;新模块实例初始化时会按 otherParams 重新启用。
|
|
928
|
+
*/
|
|
929
|
+
clearSessionStoragePersistedTempOrder() {
|
|
930
|
+
var _a;
|
|
931
|
+
this.sessionStorageRestoreRecord = null;
|
|
932
|
+
if (!this.sessionStoragePersistEnabled)
|
|
933
|
+
return;
|
|
934
|
+
this.sessionStoragePersistEnabled = false;
|
|
935
|
+
if (!this.cacheId || !this.fatherModule || !((_a = this.window) == null ? void 0 : _a.sessionStorage)) {
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
const sessionStorage = this.window.sessionStorage;
|
|
939
|
+
const rawCacheData = sessionStorage.getItem(this.fatherModule);
|
|
940
|
+
if (!rawCacheData)
|
|
941
|
+
return;
|
|
942
|
+
let parsedCacheData;
|
|
943
|
+
try {
|
|
944
|
+
parsedCacheData = JSON.parse(rawCacheData);
|
|
945
|
+
} catch {
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
if (!parsedCacheData || typeof parsedCacheData !== "object" || Array.isArray(parsedCacheData)) {
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
const cacheRoot = parsedCacheData;
|
|
952
|
+
const cacheBucket = cacheRoot[this.cacheId];
|
|
953
|
+
if (!cacheBucket || typeof cacheBucket !== "object" || Array.isArray(cacheBucket)) {
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
const moduleBucket = cacheBucket[this.name];
|
|
957
|
+
if (!moduleBucket || typeof moduleBucket !== "object" || Array.isArray(moduleBucket)) {
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
delete moduleBucket.tempOrder;
|
|
961
|
+
if (Object.keys(moduleBucket).length === 0) {
|
|
962
|
+
delete cacheBucket[this.name];
|
|
963
|
+
}
|
|
964
|
+
if (Object.keys(cacheBucket).length === 0) {
|
|
965
|
+
delete cacheRoot[this.cacheId];
|
|
966
|
+
}
|
|
967
|
+
sessionStorage.setItem(this.fatherModule, JSON.stringify(cacheRoot));
|
|
968
|
+
}
|
|
969
|
+
consumeSessionStorageRestore() {
|
|
970
|
+
const record = this.sessionStorageRestoreRecord;
|
|
971
|
+
this.sessionStorageRestoreRecord = null;
|
|
972
|
+
return record ? (0, import_lodash_es.cloneDeep)(record) : null;
|
|
887
973
|
}
|
|
888
974
|
notifyTempOrderChanged() {
|
|
889
975
|
if (!this.store.tempOrder)
|
|
@@ -1084,7 +1170,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1084
1170
|
paidAmount: netPaidAmount
|
|
1085
1171
|
});
|
|
1086
1172
|
const isOrderFullyPaid = orderExpectedAmount.lte(0) ? true : netPaidAmount.gte(orderExpectedAmount);
|
|
1087
|
-
const paymentStage = this.isDepositOrder(tempOrder, depositAmount) && !isDepositFullyPaid ? "deposit" : "normal";
|
|
1173
|
+
const paymentStage = this.isDepositOrder(tempOrder, depositAmount) && !isDepositFullyPaid && !this.hasPaidNormalPayment(paymentList) ? "deposit" : "normal";
|
|
1088
1174
|
return {
|
|
1089
1175
|
isFullyPaid: isOrderFullyPaid,
|
|
1090
1176
|
isOrderFullyPaid,
|
|
@@ -1105,12 +1191,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1105
1191
|
return sum.plus(this.calculatePaymentGapAmount(paymentRecord));
|
|
1106
1192
|
}, new import_decimal.default(0));
|
|
1107
1193
|
}
|
|
1194
|
+
hasPaidNormalPayment(payments) {
|
|
1195
|
+
return (payments || []).some((payment) => {
|
|
1196
|
+
const paymentRecord = payment;
|
|
1197
|
+
if (!isPaidPaymentRecord(paymentRecord))
|
|
1198
|
+
return false;
|
|
1199
|
+
return paymentRecord.order_payment_type !== "deposit" && paymentRecord.type !== "deposit";
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1108
1202
|
resolveNextOrderPaymentType(tempOrder) {
|
|
1109
1203
|
const depositAmount = new import_decimal.default(tempOrder.deposit_amount || "0.00");
|
|
1110
1204
|
if (!this.isDepositOrder(tempOrder, depositAmount))
|
|
1111
1205
|
return "normal";
|
|
1112
1206
|
if (depositAmount.lte(0))
|
|
1113
1207
|
return "normal";
|
|
1208
|
+
if (this.hasPaidNormalPayment(tempOrder.payments || []))
|
|
1209
|
+
return "normal";
|
|
1114
1210
|
const depositPaidAmount = this.calculateDepositPaidAmount(tempOrder.payments || []);
|
|
1115
1211
|
return depositPaidAmount.lt(depositAmount) ? "deposit" : "normal";
|
|
1116
1212
|
}
|
|
@@ -1408,24 +1504,28 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1408
1504
|
}
|
|
1409
1505
|
}
|
|
1410
1506
|
calculateSummaryAmountGap(params) {
|
|
1411
|
-
const { tempOrder, summary, orderPaidAmount } = params;
|
|
1507
|
+
const { tempOrder, summary, orderPaidAmount, payments } = params;
|
|
1412
1508
|
const refundAmount = this.getSummaryRefundAmount(summary);
|
|
1413
1509
|
const netOrderPaidAmount = import_decimal.default.max(orderPaidAmount.minus(refundAmount), 0);
|
|
1414
1510
|
const targetAmount = this.calculatePaymentTargetAmount(
|
|
1415
1511
|
tempOrder,
|
|
1416
1512
|
summary,
|
|
1417
|
-
netOrderPaidAmount
|
|
1513
|
+
netOrderPaidAmount,
|
|
1514
|
+
payments
|
|
1418
1515
|
);
|
|
1419
1516
|
return targetAmount.minus(netOrderPaidAmount).toFixed(2);
|
|
1420
1517
|
}
|
|
1421
1518
|
getSummaryRefundAmount(summary) {
|
|
1422
1519
|
return import_decimal.default.max(new import_decimal.default((summary == null ? void 0 : summary.total_refund_amount) || 0), 0);
|
|
1423
1520
|
}
|
|
1424
|
-
calculatePaymentTargetAmount(tempOrder, summary, paidAmount = new import_decimal.default(0)) {
|
|
1521
|
+
calculatePaymentTargetAmount(tempOrder, summary, paidAmount = new import_decimal.default(0), payments = tempOrder.payments || []) {
|
|
1425
1522
|
const depositAmount = this.getDepositAmount(tempOrder, summary);
|
|
1426
1523
|
if (!this.isDepositOrder(tempOrder, depositAmount)) {
|
|
1427
1524
|
return this.getOrderExpectedAmount(summary);
|
|
1428
1525
|
}
|
|
1526
|
+
if (this.hasPaidNormalPayment(payments)) {
|
|
1527
|
+
return this.getOrderExpectedAmount(summary);
|
|
1528
|
+
}
|
|
1429
1529
|
if (this.isDepositCovered({ tempOrder, summary, paidAmount })) {
|
|
1430
1530
|
return this.getOrderExpectedAmount(summary);
|
|
1431
1531
|
}
|
|
@@ -1605,19 +1705,21 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1605
1705
|
return snapshot;
|
|
1606
1706
|
}
|
|
1607
1707
|
isSnapshotPayableAmountUnchanged(tempOrder, snapshot, snapshotSummary) {
|
|
1608
|
-
const
|
|
1708
|
+
const currentPayments = tempOrder.payments || [];
|
|
1709
|
+
const currentPaidPaymentSummary = this.calculatePaidPaymentSummary(currentPayments);
|
|
1609
1710
|
const currentAmountGap = this.calculateSummaryAmountGap({
|
|
1610
1711
|
tempOrder,
|
|
1611
1712
|
summary: snapshotSummary,
|
|
1612
|
-
orderPaidAmount: currentPaidPaymentSummary.gapPaidAmount
|
|
1713
|
+
orderPaidAmount: currentPaidPaymentSummary.gapPaidAmount,
|
|
1714
|
+
payments: currentPayments
|
|
1613
1715
|
});
|
|
1614
|
-
const
|
|
1615
|
-
|
|
1616
|
-
);
|
|
1716
|
+
const snapshotPayments = Array.isArray(snapshot.payments) ? snapshot.payments : [];
|
|
1717
|
+
const snapshotPaidPaymentSummary = this.calculatePaidPaymentSummary(snapshotPayments);
|
|
1617
1718
|
const snapshotAmountGap = this.calculateSummaryAmountGap({
|
|
1618
1719
|
tempOrder,
|
|
1619
1720
|
summary: snapshotSummary,
|
|
1620
|
-
orderPaidAmount: snapshotPaidPaymentSummary.gapPaidAmount
|
|
1721
|
+
orderPaidAmount: snapshotPaidPaymentSummary.gapPaidAmount,
|
|
1722
|
+
payments: snapshotPayments
|
|
1621
1723
|
});
|
|
1622
1724
|
return currentAmountGap === snapshotAmountGap;
|
|
1623
1725
|
}
|
|
@@ -1659,6 +1761,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1659
1761
|
const isPayableAmountUnchanged = this.isSnapshotPayableAmountUnchanged(tempOrder, snapshot, summary);
|
|
1660
1762
|
if (!isPayableAmountUnchanged)
|
|
1661
1763
|
return null;
|
|
1764
|
+
const currentPaidPaymentSummary = this.calculatePaidPaymentSummary(tempOrder.payments || []);
|
|
1765
|
+
summary.amount_gap = this.calculateSummaryAmountGap({
|
|
1766
|
+
tempOrder,
|
|
1767
|
+
summary,
|
|
1768
|
+
orderPaidAmount: currentPaidPaymentSummary.gapPaidAmount
|
|
1769
|
+
});
|
|
1662
1770
|
if (Array.isArray(snapshot.products)) {
|
|
1663
1771
|
tempOrder.products = (0, import_lodash_es.cloneDeep)(snapshot.products);
|
|
1664
1772
|
}
|
|
@@ -1738,6 +1846,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1738
1846
|
restoreOrder() {
|
|
1739
1847
|
var _a, _b;
|
|
1740
1848
|
this.logInfo("restoreOrder start", {});
|
|
1849
|
+
this.sessionStorageRestoreRecord = null;
|
|
1741
1850
|
const freshTempOrder = this.createDefaultTempOrderInstance();
|
|
1742
1851
|
this.ensureExternalSaleNumber(freshTempOrder);
|
|
1743
1852
|
this.store.tempOrder = freshTempOrder;
|
|
@@ -1756,6 +1865,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1756
1865
|
if (!(0, import_utils.isTempOrder)(tempOrder)) {
|
|
1757
1866
|
throw new Error("无效的 tempOrder 数据");
|
|
1758
1867
|
}
|
|
1868
|
+
this.sessionStorageRestoreRecord = null;
|
|
1759
1869
|
const nextTempOrder = this.normalizeTempOrderForRuntime(
|
|
1760
1870
|
(0, import_lodash_es.cloneDeep)(tempOrder),
|
|
1761
1871
|
{ ensureIdentity: false }
|
|
@@ -1894,6 +2004,23 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1894
2004
|
}
|
|
1895
2005
|
return tempOrder._extend;
|
|
1896
2006
|
}
|
|
2007
|
+
repairDuplicateProductLineIdentities(tempOrder) {
|
|
2008
|
+
var _a;
|
|
2009
|
+
const result = (0, import_orderCollectionIdentity.repairDuplicateProductLineIdentities)(
|
|
2010
|
+
tempOrder.products,
|
|
2011
|
+
(_a = tempOrder._extend) == null ? void 0 : _a.productsByUid
|
|
2012
|
+
);
|
|
2013
|
+
if (!result.repairs.length)
|
|
2014
|
+
return;
|
|
2015
|
+
tempOrder.products = result.products;
|
|
2016
|
+
if (result.productsByUid) {
|
|
2017
|
+
this.ensureExtend(tempOrder).productsByUid = result.productsByUid;
|
|
2018
|
+
}
|
|
2019
|
+
this.logWarning("Repaired duplicate product line identities", {
|
|
2020
|
+
repairCount: result.repairs.length,
|
|
2021
|
+
repairs: result.repairs
|
|
2022
|
+
});
|
|
2023
|
+
}
|
|
1897
2024
|
captureProductRuntime(tempOrder, rawProduct, normalizedProduct, existedUid) {
|
|
1898
2025
|
var _a;
|
|
1899
2026
|
const uid = existedUid || this.getProductUid(normalizedProduct);
|
|
@@ -2949,15 +3076,18 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2949
3076
|
normalizedIncoming
|
|
2950
3077
|
);
|
|
2951
3078
|
const hasIncomingProductNote = this.hasOrderProductLineNote(normalizedIncoming);
|
|
3079
|
+
const hasIncomingManualProductDiscount = isManualProductDiscountProduct(normalizedIncoming);
|
|
2952
3080
|
const hasIncomingBookingUid = this.hasLinkedBookingUid(productToAdd) || this.hasLinkedBookingUid(normalizedIncoming);
|
|
2953
3081
|
const isIncomingCustomItem = ((_e = (_d = productToAdd.metadata) == null ? void 0 : _d.origin) == null ? void 0 : _e.isCustomItem) === true || ((_f = productToAdd._origin) == null ? void 0 : _f.isCustomItem) === true;
|
|
2954
|
-
const shouldForceNewLine = !!booking || hasIncomingProductNote || hasIncomingBookingUid || isIncomingCustomItem || isWeighingProduct;
|
|
3082
|
+
const shouldForceNewLine = !!booking || hasIncomingProductNote || hasIncomingManualProductDiscount || hasIncomingBookingUid || isIncomingCustomItem || isWeighingProduct;
|
|
2955
3083
|
const matchedIndex = hasIncomingGoodPass || shouldForceNewLine ? -1 : tempOrder.products.findIndex((item) => {
|
|
2956
3084
|
var _a2;
|
|
2957
3085
|
if (this.hasGoodPassDiscount(item))
|
|
2958
3086
|
return false;
|
|
2959
3087
|
if (this.hasOrderProductLineNote(item))
|
|
2960
3088
|
return false;
|
|
3089
|
+
if (isManualProductDiscountProduct(item))
|
|
3090
|
+
return false;
|
|
2961
3091
|
if (item.order_detail_id !== void 0 && item.order_detail_id !== null)
|
|
2962
3092
|
return false;
|
|
2963
3093
|
if ((_a2 = item.metadata) == null ? void 0 : _a2.is_edit_for_runtime)
|
|
@@ -3019,17 +3149,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3019
3149
|
normalizedProduct.discount_list
|
|
3020
3150
|
);
|
|
3021
3151
|
const nextNum = (0, import_utils3.getSafeProductNum)(targetProduct.num + normalizedProduct.num);
|
|
3022
|
-
const targetIsManualProductDiscount = isManualProductDiscountProduct(targetProduct);
|
|
3023
|
-
const nextDiscountList = targetIsManualProductDiscount ? (0, import_utils.normalizeOrderProductDiscountList)(
|
|
3024
|
-
(0, import_manualProductDiscount.syncManualProductDiscountProductNum)(
|
|
3025
|
-
targetProduct.discount_list,
|
|
3026
|
-
nextNum
|
|
3027
|
-
)
|
|
3028
|
-
) : normalizedProduct.discount_list;
|
|
3029
3152
|
tempOrder.products[matchedIndex] = {
|
|
3030
3153
|
...targetProduct,
|
|
3031
3154
|
...normalizedProduct,
|
|
3032
|
-
discount_list:
|
|
3155
|
+
discount_list: normalizedProduct.discount_list,
|
|
3033
3156
|
metadata: {
|
|
3034
3157
|
...targetProduct.metadata || {},
|
|
3035
3158
|
...normalizedProduct.metadata || {},
|
|
@@ -3040,16 +3163,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3040
3163
|
...normalizedProduct.product_sku || { option: [] },
|
|
3041
3164
|
option: (0, import_utils.getProductSkuOptions)(normalizedProduct)
|
|
3042
3165
|
},
|
|
3043
|
-
...targetIsManualProductDiscount ? {
|
|
3044
|
-
selling_price: targetProduct.selling_price,
|
|
3045
|
-
original_price: targetProduct.original_price,
|
|
3046
|
-
payment_price: targetProduct.payment_price,
|
|
3047
|
-
metadata: {
|
|
3048
|
-
...normalizedProduct.metadata || {},
|
|
3049
|
-
...targetProduct.metadata || {},
|
|
3050
|
-
unique_identification_number: targetUid
|
|
3051
|
-
}
|
|
3052
|
-
} : {},
|
|
3053
3166
|
note: targetProduct.note,
|
|
3054
3167
|
order_detail_id: targetProduct.order_detail_id,
|
|
3055
3168
|
num: nextNum
|
|
@@ -3522,6 +3635,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3522
3635
|
product_bundle
|
|
3523
3636
|
} = params;
|
|
3524
3637
|
const tempOrder = this.ensureTempOrder();
|
|
3638
|
+
this.repairDuplicateProductLineIdentities(tempOrder);
|
|
3525
3639
|
const identityLookup = {
|
|
3526
3640
|
product_id,
|
|
3527
3641
|
product_variant_id
|
|
@@ -3632,6 +3746,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3632
3746
|
async removeProductsFromOrder(identities, options) {
|
|
3633
3747
|
var _a, _b, _c, _d;
|
|
3634
3748
|
const tempOrder = this.ensureTempOrder();
|
|
3749
|
+
this.repairDuplicateProductLineIdentities(tempOrder);
|
|
3635
3750
|
if (!identities.length) {
|
|
3636
3751
|
return tempOrder.products;
|
|
3637
3752
|
}
|
|
@@ -4368,24 +4483,39 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
4368
4483
|
* 例如数组字段、商品行唯一值、价格 metadata、summary 派生状态和 _extend。
|
|
4369
4484
|
*/
|
|
4370
4485
|
async hydrateTempOrderFromRecord(record, options) {
|
|
4371
|
-
var _a, _b, _c;
|
|
4486
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4372
4487
|
const sourceRaw = record && typeof record === "object" && record.data && record.order_id == null ? record.data : record || {};
|
|
4488
|
+
const duplicateProductIdentityRepair = (0, import_orderCollectionIdentity.repairDuplicateProductLineIdentities)(
|
|
4489
|
+
Array.isArray(sourceRaw.products) ? sourceRaw.products : [],
|
|
4490
|
+
(_a = sourceRaw._extend) == null ? void 0 : _a.productsByUid
|
|
4491
|
+
);
|
|
4492
|
+
const duplicateIdentityReadySource = duplicateProductIdentityRepair.repairs.length ? {
|
|
4493
|
+
...sourceRaw,
|
|
4494
|
+
products: duplicateProductIdentityRepair.products,
|
|
4495
|
+
...duplicateProductIdentityRepair.productsByUid ? {
|
|
4496
|
+
_extend: {
|
|
4497
|
+
...sourceRaw._extend || {},
|
|
4498
|
+
productsByUid: duplicateProductIdentityRepair.productsByUid
|
|
4499
|
+
}
|
|
4500
|
+
} : {}
|
|
4501
|
+
} : sourceRaw;
|
|
4373
4502
|
const identityReadySource = this.seedAnonymousBookingUidsFromProducts(
|
|
4374
|
-
|
|
4503
|
+
duplicateIdentityReadySource
|
|
4375
4504
|
);
|
|
4376
4505
|
const normalizedCollections = (0, import_orderCollectionIdentity.normalizeOrderCollections)(identityReadySource);
|
|
4377
4506
|
const raw = normalizedCollections.order;
|
|
4378
|
-
const hasIdentityChanges = Object.values(normalizedCollections.stats).some(
|
|
4507
|
+
const hasIdentityChanges = duplicateProductIdentityRepair.repairs.length > 0 || Object.values(normalizedCollections.stats).some(
|
|
4379
4508
|
(stats) => stats.backfilledUidCount > 0 || stats.collapsedDuplicateCount > 0 || stats.uidConflictCount > 0 || stats.anonymousRowCount > 0
|
|
4380
4509
|
);
|
|
4381
4510
|
if (hasIdentityChanges) {
|
|
4382
4511
|
const identityLogMetadata = {
|
|
4383
4512
|
collections: normalizedCollections.stats,
|
|
4384
|
-
uidRemapCount: normalizedCollections.uidRemaps.length
|
|
4513
|
+
uidRemapCount: normalizedCollections.uidRemaps.length,
|
|
4514
|
+
duplicateProductUidRepairCount: duplicateProductIdentityRepair.repairs.length
|
|
4385
4515
|
};
|
|
4386
4516
|
const hasIdentityWarnings = Object.values(normalizedCollections.stats).some(
|
|
4387
4517
|
(stats) => stats.uidConflictCount > 0 || stats.anonymousRowCount > 0
|
|
4388
|
-
);
|
|
4518
|
+
) || duplicateProductIdentityRepair.repairs.length > 0;
|
|
4389
4519
|
if (hasIdentityWarnings) {
|
|
4390
4520
|
this.logWarning(
|
|
4391
4521
|
"Normalized hydrated order collection identities",
|
|
@@ -4398,8 +4528,37 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
4398
4528
|
);
|
|
4399
4529
|
}
|
|
4400
4530
|
}
|
|
4401
|
-
const
|
|
4402
|
-
const
|
|
4531
|
+
const isSessionStorageHydrate = (options == null ? void 0 : options.source) === "sessionStorage";
|
|
4532
|
+
const nextTempOrder = this.normalizeTempOrderForRuntime(raw, {
|
|
4533
|
+
makeEditMark: !isSessionStorageHydrate
|
|
4534
|
+
});
|
|
4535
|
+
this.store.tempOrder = nextTempOrder;
|
|
4536
|
+
if (isSessionStorageHydrate) {
|
|
4537
|
+
const restoredSessionDiscounts = Array.isArray(raw.discount_list) ? (0, import_lodash_es.cloneDeep)(raw.discount_list) : [];
|
|
4538
|
+
const nextExtend = { ...nextTempOrder._extend || {} };
|
|
4539
|
+
delete nextExtend.originalSalesSnapshot;
|
|
4540
|
+
nextTempOrder._extend = nextExtend;
|
|
4541
|
+
nextTempOrder.products.forEach((product) => {
|
|
4542
|
+
if (product.metadata) {
|
|
4543
|
+
delete product.metadata.is_edit_for_runtime;
|
|
4544
|
+
}
|
|
4545
|
+
});
|
|
4546
|
+
nextTempOrder.discount_list = restoredSessionDiscounts;
|
|
4547
|
+
this.store.summary = (0, import_utils.createEmptySummary)();
|
|
4548
|
+
this.store.lastOrderInfo = void 0;
|
|
4549
|
+
await ((_b = this.store.discount) == null ? void 0 : _b.setOriginalDiscountList(
|
|
4550
|
+
(0, import_lodash_es.cloneDeep)(restoredSessionDiscounts)
|
|
4551
|
+
));
|
|
4552
|
+
await ((_c = this.store.discount) == null ? void 0 : _c.setDiscountList(
|
|
4553
|
+
(0, import_lodash_es.cloneDeep)(restoredSessionDiscounts)
|
|
4554
|
+
));
|
|
4555
|
+
if (options == null ? void 0 : options.recalcOnHydrate) {
|
|
4556
|
+
await this.recalculateSummary({ createIfMissing: false });
|
|
4557
|
+
}
|
|
4558
|
+
this.persistTempOrder();
|
|
4559
|
+
return nextTempOrder;
|
|
4560
|
+
}
|
|
4561
|
+
const sourceLastOrderInfo = sourceRaw.lastOrderInfo || sourceRaw;
|
|
4403
4562
|
const isDraftOrder = Number(nextTempOrder.is_draft_order || 0) === 1;
|
|
4404
4563
|
const syntheticIdentityOptions = {
|
|
4405
4564
|
isDraftOrder,
|
|
@@ -4407,7 +4566,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
4407
4566
|
};
|
|
4408
4567
|
const rawSummary = raw.summary && typeof raw.summary === "object" ? raw.summary : {};
|
|
4409
4568
|
const summarySurcharges = Array.isArray(rawSummary.surcharges) ? rawSummary.surcharges.map((s) => ({ ...s || {} })) : (0, import_lodash_es.cloneDeep)(nextTempOrder.surcharges || []);
|
|
4410
|
-
this.store.tempOrder = nextTempOrder;
|
|
4411
4569
|
this.store.summary = {
|
|
4412
4570
|
...(0, import_utils.createEmptySummary)(),
|
|
4413
4571
|
...rawSummary,
|
|
@@ -4434,7 +4592,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
4434
4592
|
this.store.syncState = "local";
|
|
4435
4593
|
}
|
|
4436
4594
|
const hydratedEditDiscounts = this.collectHydratedEditDiscounts(nextTempOrder.products);
|
|
4437
|
-
const currentDiscounts = typeof ((
|
|
4595
|
+
const currentDiscounts = typeof ((_d = this.store.discount) == null ? void 0 : _d.getDiscountList) === "function" ? this.store.discount.getDiscountList() || [] : [];
|
|
4438
4596
|
const currentScanDiscounts = currentDiscounts.filter((discount) => discount == null ? void 0 : discount.isScan);
|
|
4439
4597
|
const hydratedDiscountIds = new Set(
|
|
4440
4598
|
hydratedEditDiscounts.map((discount) => discount == null ? void 0 : discount.id)
|
|
@@ -4452,8 +4610,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
4452
4610
|
nextTempOrder.products,
|
|
4453
4611
|
nextDiscounts
|
|
4454
4612
|
);
|
|
4455
|
-
await ((
|
|
4456
|
-
await ((
|
|
4613
|
+
await ((_e = this.store.discount) == null ? void 0 : _e.setOriginalDiscountList(nextDiscounts));
|
|
4614
|
+
await ((_f = this.store.discount) == null ? void 0 : _f.setDiscountList(nextDiscounts));
|
|
4457
4615
|
}
|
|
4458
4616
|
if (options == null ? void 0 : options.recalcOnHydrate) {
|
|
4459
4617
|
await this.recalculateSummary({ createIfMissing: false });
|
|
@@ -579,6 +579,10 @@ export interface LoadSalesDetailParams {
|
|
|
579
579
|
* 存在时 loadSalesDetail 会跳过远端 lookup,直接复用 hydrate 后半段逻辑。
|
|
580
580
|
*/
|
|
581
581
|
preloadedSalesDetail?: Record<string, any>;
|
|
582
|
+
/**
|
|
583
|
+
* sessionStorage 快照复用详情 hydrate 时使用;不带该值时保持既有编辑订单语义。
|
|
584
|
+
*/
|
|
585
|
+
hydrateSource?: 'sessionStorage';
|
|
582
586
|
forceRemote?: boolean;
|
|
583
587
|
merge?: boolean;
|
|
584
588
|
}
|
|
@@ -749,8 +753,15 @@ export interface OrderModuleAPI {
|
|
|
749
753
|
removeProductFromOrder: (identity: OrderProductIdentity, options?: RemoveProductsFromOrderOptions) => Promise<OrderProduct[]>;
|
|
750
754
|
/** 批量删除购物车行,末尾仅触发一次促销重算与 summary 刷新 */
|
|
751
755
|
removeProductsFromOrder: (identities: OrderProductIdentity[], options?: RemoveProductsFromOrderOptions) => Promise<OrderProduct[]>;
|
|
752
|
-
/**
|
|
756
|
+
/** 在显式开启时保存当前 tempOrder 的 sessionStorage 会话快照。 */
|
|
753
757
|
persistTempOrder: () => void;
|
|
758
|
+
/**
|
|
759
|
+
* 删除当前 cacheId 的 tempOrder 会话快照,并阻止当前模块实例再次写入。
|
|
760
|
+
* 新模块实例初始化时会按 otherParams 重新启用持久化。
|
|
761
|
+
*/
|
|
762
|
+
clearSessionStoragePersistedTempOrder: () => void;
|
|
763
|
+
/** 取出一次待恢复的 sessionStorage tempOrder 快照。 */
|
|
764
|
+
consumeSessionStorageRestore: () => Record<string, any> | null;
|
|
754
765
|
/**
|
|
755
766
|
* 控制 IndexedDB 草稿(saveDraft)开关;localStorage tempOrder 持久化已废弃。
|
|
756
767
|
* BigSale 弹窗等场景传 false 可跳过 saveDraft。
|
|
@@ -808,6 +819,7 @@ export interface OrderModuleAPI {
|
|
|
808
819
|
saveDraft: () => Promise<void>;
|
|
809
820
|
hydrateTempOrderFromRecord: (record: Record<string, any>, options?: {
|
|
810
821
|
recalcOnHydrate?: boolean;
|
|
822
|
+
source?: 'salesDetail' | 'sessionStorage';
|
|
811
823
|
}) => Promise<OrderTempOrder>;
|
|
812
824
|
syncPaymentsToOrder: <T = any>(params: SyncPaymentsToOrderParams) => Promise<SyncPaymentsToOrderResult<T>>;
|
|
813
825
|
getSalesOrderByLookup: (params: SalesOrderLookupParams) => Promise<any>;
|
|
@@ -24,6 +24,16 @@ export interface NormalizeOrderCollectionsResult<T> {
|
|
|
24
24
|
stats: Record<OrderCollectionKind, OrderCollectionIdentityStats>;
|
|
25
25
|
uidRemaps: OrderCollectionUidRemap[];
|
|
26
26
|
}
|
|
27
|
+
export interface ProductLineIdentityRepair {
|
|
28
|
+
index: number;
|
|
29
|
+
from: string;
|
|
30
|
+
to: string;
|
|
31
|
+
}
|
|
32
|
+
export interface RepairDuplicateProductLineIdentitiesResult<T> {
|
|
33
|
+
products: T[];
|
|
34
|
+
productsByUid?: Record<string, Record<string, any>>;
|
|
35
|
+
repairs: ProductLineIdentityRepair[];
|
|
36
|
+
}
|
|
27
37
|
export declare function createUuidV4(): string;
|
|
28
38
|
export declare function isBlankOrderCollectionIdentity(value: unknown): boolean;
|
|
29
39
|
export declare function getOrderCollectionPersistentId(kind: OrderCollectionKind, item: unknown): string | null;
|
|
@@ -31,6 +41,11 @@ export declare function getOrderCollectionUid(kind: OrderCollectionKind, item: u
|
|
|
31
41
|
export declare function buildOrderCollectionFallbackUid(kind: OrderCollectionKind, persistentId: string | number): string;
|
|
32
42
|
export declare function getOrderCollectionReferenceUid(kind: OrderCollectionKind, item: unknown): string | null;
|
|
33
43
|
export declare function setOrderCollectionUid<T>(kind: OrderCollectionKind, item: T, uid: string): T;
|
|
44
|
+
/**
|
|
45
|
+
* Rules 会把同一商品按商品券拆成多条真实订单行。拆行结果会继承原商品 UID,
|
|
46
|
+
* 因此必须在通用 collection normalization 之前为后续行派生稳定身份,避免被折叠。
|
|
47
|
+
*/
|
|
48
|
+
export declare function repairDuplicateProductLineIdentities<T extends Record<string, any>>(products: T[] | null | undefined, productsByUid?: Record<string, Record<string, any>> | null): RepairDuplicateProductLineIdentitiesResult<T>;
|
|
34
49
|
/**
|
|
35
50
|
* 持久化行 ID 是服务端事实主键;只有至少一侧尚未持久化时,才允许用 runtime UID 对齐。
|
|
36
51
|
*/
|
|
@@ -30,6 +30,7 @@ __export(orderCollectionIdentity_exports, {
|
|
|
30
30
|
mergeOrderCollectionItems: () => mergeOrderCollectionItems,
|
|
31
31
|
normalizeOrderCollection: () => normalizeOrderCollection,
|
|
32
32
|
normalizeOrderCollections: () => normalizeOrderCollections,
|
|
33
|
+
repairDuplicateProductLineIdentities: () => repairDuplicateProductLineIdentities,
|
|
33
34
|
setOrderCollectionUid: () => setOrderCollectionUid
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(orderCollectionIdentity_exports);
|
|
@@ -105,6 +106,74 @@ function setOrderCollectionUid(kind, item, uid) {
|
|
|
105
106
|
delete record[uidField];
|
|
106
107
|
return record;
|
|
107
108
|
}
|
|
109
|
+
function getGoodPassResourceId(product) {
|
|
110
|
+
var _a;
|
|
111
|
+
const goodPass = (product.discount_list || []).find((item) => {
|
|
112
|
+
var _a2, _b;
|
|
113
|
+
const type = (item == null ? void 0 : item.type) || (item == null ? void 0 : item.tag) || ((_a2 = item == null ? void 0 : item.discount) == null ? void 0 : _a2.type) || ((_b = item == null ? void 0 : item.discount) == null ? void 0 : _b.tag);
|
|
114
|
+
return type === "good_pass";
|
|
115
|
+
});
|
|
116
|
+
if (!goodPass)
|
|
117
|
+
return null;
|
|
118
|
+
const resourceId = ((_a = goodPass.discount) == null ? void 0 : _a.resource_id) ?? goodPass.resource_id ?? goodPass.discount_id ?? goodPass.id;
|
|
119
|
+
return isBlankOrderCollectionIdentity(resourceId) ? null : String(resourceId);
|
|
120
|
+
}
|
|
121
|
+
function buildSplitProductUid(originalUid, product, duplicateOrdinal) {
|
|
122
|
+
const encodedOriginalUid = encodeURIComponent(originalUid);
|
|
123
|
+
const resourceId = getGoodPassResourceId(product);
|
|
124
|
+
if (resourceId) {
|
|
125
|
+
return `os-split:product:${encodedOriginalUid}:good-pass:${encodeURIComponent(resourceId)}:${duplicateOrdinal}`;
|
|
126
|
+
}
|
|
127
|
+
return `os-split:product:${encodedOriginalUid}:duplicate:${duplicateOrdinal}`;
|
|
128
|
+
}
|
|
129
|
+
function repairDuplicateProductLineIdentities(products, productsByUid) {
|
|
130
|
+
const repairedProducts = (0, import_lodash_es.cloneDeep)(products || []);
|
|
131
|
+
const repairedProductsByUid = productsByUid ? (0, import_lodash_es.cloneDeep)(productsByUid) : void 0;
|
|
132
|
+
const occupiedUids = new Set(
|
|
133
|
+
repairedProducts.map((product) => getOrderCollectionUid("product", product)).filter((uid) => Boolean(uid))
|
|
134
|
+
);
|
|
135
|
+
Object.keys(repairedProductsByUid || {}).forEach((uid) => occupiedUids.add(uid));
|
|
136
|
+
const occurrences = /* @__PURE__ */ new Map();
|
|
137
|
+
const repairs = [];
|
|
138
|
+
repairedProducts.forEach((product, index) => {
|
|
139
|
+
const originalUid = getOrderCollectionUid("product", product);
|
|
140
|
+
if (!originalUid)
|
|
141
|
+
return;
|
|
142
|
+
const occurrence = (occurrences.get(originalUid) || 0) + 1;
|
|
143
|
+
occurrences.set(originalUid, occurrence);
|
|
144
|
+
if (occurrence === 1)
|
|
145
|
+
return;
|
|
146
|
+
const duplicateOrdinal = occurrence - 1;
|
|
147
|
+
const baseCandidate = buildSplitProductUid(
|
|
148
|
+
originalUid,
|
|
149
|
+
product,
|
|
150
|
+
duplicateOrdinal
|
|
151
|
+
);
|
|
152
|
+
let nextUid = baseCandidate;
|
|
153
|
+
let conflictOrdinal = 1;
|
|
154
|
+
while (occupiedUids.has(nextUid)) {
|
|
155
|
+
nextUid = `${baseCandidate}:conflict:${conflictOrdinal}`;
|
|
156
|
+
conflictOrdinal += 1;
|
|
157
|
+
}
|
|
158
|
+
const repairedProduct = setOrderCollectionUid("product", product, nextUid);
|
|
159
|
+
repairedProduct.identity_key = nextUid;
|
|
160
|
+
repairedProducts[index] = repairedProduct;
|
|
161
|
+
occupiedUids.add(nextUid);
|
|
162
|
+
repairs.push({ index, from: originalUid, to: nextUid });
|
|
163
|
+
const runtimeSource = repairedProductsByUid == null ? void 0 : repairedProductsByUid[originalUid];
|
|
164
|
+
if (runtimeSource && repairedProductsByUid) {
|
|
165
|
+
repairedProductsByUid[nextUid] = {
|
|
166
|
+
...(0, import_lodash_es.cloneDeep)(runtimeSource),
|
|
167
|
+
...runtimeSource.rowKey !== void 0 ? { rowKey: nextUid } : {}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
return {
|
|
172
|
+
products: repairedProducts,
|
|
173
|
+
...repairedProductsByUid ? { productsByUid: repairedProductsByUid } : {},
|
|
174
|
+
repairs
|
|
175
|
+
};
|
|
176
|
+
}
|
|
108
177
|
function isSameOrderCollectionItem(kind, left, right) {
|
|
109
178
|
const leftPersistentId = getOrderCollectionPersistentId(kind, left);
|
|
110
179
|
const rightPersistentId = getOrderCollectionPersistentId(kind, right);
|
|
@@ -414,5 +483,6 @@ function normalizeOrderCollections(sourceOrder, options) {
|
|
|
414
483
|
mergeOrderCollectionItems,
|
|
415
484
|
normalizeOrderCollection,
|
|
416
485
|
normalizeOrderCollections,
|
|
486
|
+
repairDuplicateProductLineIdentities,
|
|
417
487
|
setOrderCollectionUid
|
|
418
488
|
});
|