@pisell/pisellos 0.10.6 → 0.10.8
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 +9 -0
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +12 -10
- package/dist/modules/Order/index.d.ts +14 -6
- package/dist/modules/Order/index.js +373 -246
- package/dist/modules/Order/types.d.ts +26 -3
- package/dist/modules/Order/types.js +11 -0
- package/dist/modules/Order/utils/discountProductLineIdentity.d.ts +45 -0
- package/dist/modules/Order/utils/discountProductLineIdentity.js +227 -0
- package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +15 -0
- package/dist/modules/Order/utils/orderCollectionIdentity.js +75 -0
- package/dist/modules/Rules/index.js +125 -52
- package/dist/modules/SalesSummary/utils.js +7 -1
- package/dist/server/index.d.ts +6 -0
- package/dist/server/index.js +810 -729
- package/dist/server/modules/order/index.d.ts +1 -0
- package/dist/server/modules/order/index.js +9 -2
- package/dist/server/modules/order/types.d.ts +1 -1
- package/dist/solution/BaseSales/index.d.ts +15 -5
- package/dist/solution/BaseSales/index.js +211 -159
- package/dist/solution/BaseSales/utils/cartPromotion.js +26 -3
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +1 -1
- package/dist/solution/BaseSales/utils.js +31 -20
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +13 -1
- package/dist/solution/BookingTicket/index.js +19 -22
- package/dist/solution/BookingTicket/types.d.ts +3 -0
- package/dist/solution/BookingTicket/utils/cartView.js +44 -32
- package/dist/solution/Sales/index.d.ts +1 -0
- package/dist/solution/Sales/index.js +16 -2
- package/dist/solution/ScanOrder/utils.js +31 -20
- package/dist/solution/UnifiedBookingSales/index.d.ts +16 -4
- package/dist/solution/UnifiedBookingSales/index.js +113 -48
- package/lib/model/strategy/adapter/promotion/index.js +0 -51
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +3 -1
- package/lib/modules/Order/index.d.ts +14 -6
- package/lib/modules/Order/index.js +192 -52
- package/lib/modules/Order/types.d.ts +26 -3
- package/lib/modules/Order/utils/discountProductLineIdentity.d.ts +45 -0
- package/lib/modules/Order/utils/discountProductLineIdentity.js +170 -0
- package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +15 -0
- package/lib/modules/Order/utils/orderCollectionIdentity.js +70 -0
- package/lib/modules/Rules/index.js +100 -20
- package/lib/modules/SalesSummary/utils.js +5 -1
- package/lib/server/index.d.ts +6 -0
- package/lib/server/index.js +51 -0
- package/lib/server/modules/order/index.d.ts +1 -0
- package/lib/server/modules/order/index.js +9 -3
- package/lib/server/modules/order/types.d.ts +1 -1
- package/lib/solution/BaseSales/index.d.ts +15 -5
- package/lib/solution/BaseSales/index.js +64 -16
- package/lib/solution/BaseSales/utils/cartPromotion.js +26 -2
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +1 -1
- package/lib/solution/BaseSales/utils.js +29 -18
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +13 -1
- package/lib/solution/BookingTicket/index.js +6 -9
- package/lib/solution/BookingTicket/types.d.ts +3 -0
- package/lib/solution/BookingTicket/utils/cartView.js +43 -30
- package/lib/solution/Sales/index.d.ts +1 -0
- package/lib/solution/Sales/index.js +15 -3
- package/lib/solution/ScanOrder/utils.js +29 -18
- package/lib/solution/UnifiedBookingSales/index.d.ts +16 -4
- package/lib/solution/UnifiedBookingSales/index.js +80 -26
- package/package.json +1 -1
|
@@ -44,6 +44,7 @@ var import_utils3 = require("../../solution/ScanOrder/utils");
|
|
|
44
44
|
var import_manualProductDiscount = require("./utils/manualProductDiscount");
|
|
45
45
|
var import_bundleDiscountHydration = require("./utils/bundleDiscountHydration");
|
|
46
46
|
var import_orderCollectionIdentity = require("./utils/orderCollectionIdentity");
|
|
47
|
+
var import_discountProductLineIdentity = require("./utils/discountProductLineIdentity");
|
|
47
48
|
var import_Discount = require("../Discount");
|
|
48
49
|
var import_Rules = require("../Rules");
|
|
49
50
|
var import_types2 = require("../Rules/types");
|
|
@@ -65,8 +66,7 @@ function isSameDiscountList(left, right) {
|
|
|
65
66
|
);
|
|
66
67
|
}
|
|
67
68
|
function isManualProductDiscountProduct(product) {
|
|
68
|
-
|
|
69
|
-
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");
|
|
70
70
|
}
|
|
71
71
|
var ORDER_PAYMENT_STATUS_PAID = "paid";
|
|
72
72
|
var ORDER_PAYMENT_STATUS_PENDING = "payment_pending";
|
|
@@ -136,7 +136,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
136
136
|
this.draftPersistEnabled = true;
|
|
137
137
|
}
|
|
138
138
|
collectHydratedEditDiscounts(products) {
|
|
139
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
139
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
140
140
|
const discountMap = /* @__PURE__ */ new Map();
|
|
141
141
|
for (const product of (0, import_bundleDiscountHydration.expandHydratedProductsForDiscountCollection)(products)) {
|
|
142
142
|
for (const item of (product == null ? void 0 : product.discount_list) || []) {
|
|
@@ -151,16 +151,18 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
151
151
|
const key = Number.isFinite(id) ? id : String(resourceId);
|
|
152
152
|
const title = ((_b = item == null ? void 0 : item.discount) == null ? void 0 : _b.title) ?? {};
|
|
153
153
|
const amount = Number((item == null ? void 0 : item.amount) || 0);
|
|
154
|
+
const discountCardType = (_c = item == null ? void 0 : item.discount) == null ? void 0 : _c.discount_card_type;
|
|
155
|
+
const parValue = isDiscountCard ? discountCardType === "fixed_amount" ? ((_d = item == null ? void 0 : item.discount) == null ? void 0 : _d.fixed_amount) ?? (item == null ? void 0 : item.amount) : (_e = item == null ? void 0 : item.discount) == null ? void 0 : _e.percent : "0";
|
|
154
156
|
const detail = {
|
|
155
157
|
amount: String((item == null ? void 0 : item.amount) ?? "0"),
|
|
156
158
|
type,
|
|
157
159
|
resource_id: key,
|
|
158
160
|
title,
|
|
159
|
-
original_amount: String(((
|
|
160
|
-
num: Number(((
|
|
161
|
+
original_amount: String(((_f = item == null ? void 0 : item.discount) == null ? void 0 : _f.original_amount) ?? (item == null ? void 0 : item.amount) ?? "0"),
|
|
162
|
+
num: Number(((_g = item == null ? void 0 : item.metadata) == null ? void 0 : _g.num) ?? (product == null ? void 0 : product.num) ?? (product == null ? void 0 : product.product_quantity) ?? 1) || 1,
|
|
161
163
|
metadata: item == null ? void 0 : item.metadata,
|
|
162
164
|
discount: item == null ? void 0 : item.discount,
|
|
163
|
-
_num: Number(((
|
|
165
|
+
_num: Number(((_h = item == null ? void 0 : item.metadata) == null ? void 0 : _h.num) ?? (product == null ? void 0 : product.num) ?? (product == null ? void 0 : product.product_quantity) ?? 1) || 1
|
|
164
166
|
};
|
|
165
167
|
const existed = discountMap.get(key);
|
|
166
168
|
if (existed) {
|
|
@@ -169,7 +171,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
169
171
|
if (!isDiscountCard) {
|
|
170
172
|
existed.balance = String(Number(existed.balance || 0) + amount);
|
|
171
173
|
}
|
|
172
|
-
const productIds = Array.isArray((
|
|
174
|
+
const productIds = Array.isArray((_i = existed.limited_relation_product_data) == null ? void 0 : _i.product_ids) ? existed.limited_relation_product_data.product_ids : [];
|
|
173
175
|
if ((product == null ? void 0 : product.product_id) !== void 0 && (product == null ? void 0 : product.product_id) !== null && !productIds.includes(product.product_id)) {
|
|
174
176
|
existed.limited_relation_product_data = {
|
|
175
177
|
...existed.limited_relation_product_data || {},
|
|
@@ -192,9 +194,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
192
194
|
encoded: "",
|
|
193
195
|
code: "",
|
|
194
196
|
tag: type,
|
|
195
|
-
product_id: ((
|
|
197
|
+
product_id: ((_j = item == null ? void 0 : item.discount) == null ? void 0 : _j.discount_product_id) ?? (product == null ? void 0 : product.product_id) ?? 0,
|
|
196
198
|
relation_type: "",
|
|
197
|
-
par_value: String(
|
|
199
|
+
par_value: String(parValue ?? "0"),
|
|
198
200
|
used_par_value: String((item == null ? void 0 : item.amount) ?? "0"),
|
|
199
201
|
limit_status: "enable",
|
|
200
202
|
limited_relation_product_data: {
|
|
@@ -224,8 +226,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
224
226
|
discount: {
|
|
225
227
|
...(item == null ? void 0 : item.discount) || {},
|
|
226
228
|
resource_id: key,
|
|
227
|
-
discount_product_id: ((
|
|
228
|
-
discount_calculation_mode: ((
|
|
229
|
+
discount_product_id: ((_k = item == null ? void 0 : item.discount) == null ? void 0 : _k.discount_product_id) ?? (product == null ? void 0 : product.product_id) ?? 0,
|
|
230
|
+
discount_calculation_mode: ((_l = item == null ? void 0 : item.discount) == null ? void 0 : _l.discount_calculation_mode) ?? "item_level"
|
|
229
231
|
},
|
|
230
232
|
applicableProductDetails: [detail],
|
|
231
233
|
appliedProductDetails: [detail]
|
|
@@ -277,7 +279,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
277
279
|
const isPersistedBundleProduct = isPersistedProduct || Boolean(
|
|
278
280
|
(bundle == null ? void 0 : bundle.order_detail_id) || (bundle == null ? void 0 : bundle.orderDetailId) || (bundle == null ? void 0 : bundle.booking_id)
|
|
279
281
|
);
|
|
280
|
-
const bundleQty =
|
|
282
|
+
const bundleQty = Number(qty) || 1;
|
|
281
283
|
for (const pd of (bundle == null ? void 0 : bundle.discount_list) || []) {
|
|
282
284
|
addProductDiscountAmount(pd, bundleQty, isPersistedBundleProduct);
|
|
283
285
|
}
|
|
@@ -694,6 +696,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
694
696
|
};
|
|
695
697
|
})
|
|
696
698
|
);
|
|
699
|
+
(0, import_discountProductLineIdentity.ensureUniqueProductLineUids)(tempOrder);
|
|
700
|
+
(0, import_discountProductLineIdentity.consolidateDiscountFreeProductLines)(tempOrder);
|
|
697
701
|
}
|
|
698
702
|
if (result == null ? void 0 : result.discountList) {
|
|
699
703
|
OrderModule.populateSavedAmounts(
|
|
@@ -916,6 +920,52 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
916
920
|
cacheKey: ["tempOrder"]
|
|
917
921
|
});
|
|
918
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
|
+
}
|
|
919
969
|
consumeSessionStorageRestore() {
|
|
920
970
|
const record = this.sessionStorageRestoreRecord;
|
|
921
971
|
this.sessionStorageRestoreRecord = null;
|
|
@@ -1921,6 +1971,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1921
1971
|
tempOrder.products = (tempOrder.products || []).map(
|
|
1922
1972
|
(product) => this.sanitizeOrderProductForTempOrder(product)
|
|
1923
1973
|
);
|
|
1974
|
+
(0, import_discountProductLineIdentity.ensureUniqueProductLineUids)(tempOrder);
|
|
1924
1975
|
}
|
|
1925
1976
|
ensureExtend(tempOrder) {
|
|
1926
1977
|
if (!tempOrder._extend || typeof tempOrder._extend !== "object") {
|
|
@@ -1931,6 +1982,23 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1931
1982
|
}
|
|
1932
1983
|
return tempOrder._extend;
|
|
1933
1984
|
}
|
|
1985
|
+
repairDuplicateProductLineIdentities(tempOrder) {
|
|
1986
|
+
var _a;
|
|
1987
|
+
const result = (0, import_orderCollectionIdentity.repairDuplicateProductLineIdentities)(
|
|
1988
|
+
tempOrder.products,
|
|
1989
|
+
(_a = tempOrder._extend) == null ? void 0 : _a.productsByUid
|
|
1990
|
+
);
|
|
1991
|
+
if (!result.repairs.length)
|
|
1992
|
+
return;
|
|
1993
|
+
tempOrder.products = result.products;
|
|
1994
|
+
if (result.productsByUid) {
|
|
1995
|
+
this.ensureExtend(tempOrder).productsByUid = result.productsByUid;
|
|
1996
|
+
}
|
|
1997
|
+
this.logWarning("Repaired duplicate product line identities", {
|
|
1998
|
+
repairCount: result.repairs.length,
|
|
1999
|
+
repairs: result.repairs
|
|
2000
|
+
});
|
|
2001
|
+
}
|
|
1934
2002
|
captureProductRuntime(tempOrder, rawProduct, normalizedProduct, existedUid) {
|
|
1935
2003
|
var _a;
|
|
1936
2004
|
const uid = existedUid || this.getProductUid(normalizedProduct);
|
|
@@ -2576,6 +2644,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2576
2644
|
delete tempOrder._extend.customerSnapshot;
|
|
2577
2645
|
this.store.availableWalletIds = [];
|
|
2578
2646
|
this.clearCustomerBoundDiscounts(tempOrder);
|
|
2647
|
+
this.applyDiscount();
|
|
2579
2648
|
this.persistTempOrder();
|
|
2580
2649
|
this.saveDraftInBackground();
|
|
2581
2650
|
this.core.effects.emit(import_types.OrderHooks.OnOrderCustomerChange, null);
|
|
@@ -2940,8 +3009,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2940
3009
|
* @example
|
|
2941
3010
|
* await this.appendProductLineToTempOrder(tempOrder, { product_id: 1, num: 1 }, booking);
|
|
2942
3011
|
*/
|
|
2943
|
-
async appendProductLineToTempOrder(tempOrder, product, booking) {
|
|
2944
|
-
var _a, _b;
|
|
3012
|
+
async appendProductLineToTempOrder(tempOrder, product, booking, options) {
|
|
3013
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2945
3014
|
const linked = booking ? this.createLinkedProductAndBooking({ product, booking }) : null;
|
|
2946
3015
|
const productToAdd = (linked == null ? void 0 : linked.product) || product;
|
|
2947
3016
|
const incomingFingerprint = (0, import_utils3.buildProductLineFingerprint)(
|
|
@@ -2952,7 +3021,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2952
3021
|
productToAdd,
|
|
2953
3022
|
(0, import_utils3.normalizeOrderProduct)(productToAdd)
|
|
2954
3023
|
);
|
|
2955
|
-
const
|
|
3024
|
+
const isWeighingProduct = Number(((_a = normalizedIncoming.product_sku) == null ? void 0 : _a.open_sold_weight) || 0) === 1;
|
|
3025
|
+
const netWeight = Number((_b = normalizedIncoming.product_sku) == null ? void 0 : _b.net_weight);
|
|
3026
|
+
if (isWeighingProduct && (!Number.isFinite(netWeight) || netWeight <= 0)) {
|
|
3027
|
+
throw new Error("[Order] 称重商品净重必须大于 0");
|
|
3028
|
+
}
|
|
3029
|
+
const incomingBookingUid = productToAdd.booking_uid ?? ((_c = productToAdd.metadata) == null ? void 0 : _c.booking_uid);
|
|
2956
3030
|
if (incomingBookingUid !== void 0 && incomingBookingUid !== null && String(incomingBookingUid) !== "") {
|
|
2957
3031
|
normalizedIncoming.booking_uid = String(incomingBookingUid);
|
|
2958
3032
|
normalizedIncoming.metadata = {
|
|
@@ -2967,14 +3041,18 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2967
3041
|
normalizedIncoming
|
|
2968
3042
|
);
|
|
2969
3043
|
const hasIncomingProductNote = this.hasOrderProductLineNote(normalizedIncoming);
|
|
3044
|
+
const hasIncomingManualProductDiscount = isManualProductDiscountProduct(normalizedIncoming);
|
|
2970
3045
|
const hasIncomingBookingUid = this.hasLinkedBookingUid(productToAdd) || this.hasLinkedBookingUid(normalizedIncoming);
|
|
2971
|
-
const
|
|
3046
|
+
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;
|
|
3047
|
+
const shouldForceNewLine = !!booking || hasIncomingProductNote || hasIncomingManualProductDiscount || hasIncomingBookingUid || isIncomingCustomItem || isWeighingProduct;
|
|
2972
3048
|
const matchedIndex = hasIncomingGoodPass || shouldForceNewLine ? -1 : tempOrder.products.findIndex((item) => {
|
|
2973
3049
|
var _a2;
|
|
2974
3050
|
if (this.hasGoodPassDiscount(item))
|
|
2975
3051
|
return false;
|
|
2976
3052
|
if (this.hasOrderProductLineNote(item))
|
|
2977
3053
|
return false;
|
|
3054
|
+
if (isManualProductDiscountProduct(item))
|
|
3055
|
+
return false;
|
|
2978
3056
|
if (item.order_detail_id !== void 0 && item.order_detail_id !== null)
|
|
2979
3057
|
return false;
|
|
2980
3058
|
if ((_a2 = item.metadata) == null ? void 0 : _a2.is_edit_for_runtime)
|
|
@@ -3017,10 +3095,19 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3017
3095
|
booking_uid: linked.bookingUid
|
|
3018
3096
|
};
|
|
3019
3097
|
}
|
|
3020
|
-
|
|
3098
|
+
const insertAtIndex = options == null ? void 0 : options.insertAtIndex;
|
|
3099
|
+
if (Number.isInteger(insertAtIndex) && Number(insertAtIndex) >= 0 && Number(insertAtIndex) < tempOrder.products.length) {
|
|
3100
|
+
tempOrder.products = [
|
|
3101
|
+
...tempOrder.products.slice(0, insertAtIndex),
|
|
3102
|
+
normalizedIncoming,
|
|
3103
|
+
...tempOrder.products.slice(insertAtIndex)
|
|
3104
|
+
];
|
|
3105
|
+
} else {
|
|
3106
|
+
tempOrder.products = [...tempOrder.products, normalizedIncoming];
|
|
3107
|
+
}
|
|
3021
3108
|
} else {
|
|
3022
3109
|
const targetProduct = matchedProduct;
|
|
3023
|
-
const targetUid = (
|
|
3110
|
+
const targetUid = (_g = targetProduct.metadata) == null ? void 0 : _g.unique_identification_number;
|
|
3024
3111
|
const normalizedProduct = (0, import_utils.mergeOrderProductDisplayFields)(
|
|
3025
3112
|
targetProduct,
|
|
3026
3113
|
(0, import_utils3.normalizeOrderProduct)({
|
|
@@ -3035,17 +3122,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3035
3122
|
normalizedProduct.discount_list
|
|
3036
3123
|
);
|
|
3037
3124
|
const nextNum = (0, import_utils3.getSafeProductNum)(targetProduct.num + normalizedProduct.num);
|
|
3038
|
-
const targetIsManualProductDiscount = isManualProductDiscountProduct(targetProduct);
|
|
3039
|
-
const nextDiscountList = targetIsManualProductDiscount ? (0, import_utils.normalizeOrderProductDiscountList)(
|
|
3040
|
-
(0, import_manualProductDiscount.syncManualProductDiscountProductNum)(
|
|
3041
|
-
targetProduct.discount_list,
|
|
3042
|
-
nextNum
|
|
3043
|
-
)
|
|
3044
|
-
) : normalizedProduct.discount_list;
|
|
3045
3125
|
tempOrder.products[matchedIndex] = {
|
|
3046
3126
|
...targetProduct,
|
|
3047
3127
|
...normalizedProduct,
|
|
3048
|
-
discount_list:
|
|
3128
|
+
discount_list: normalizedProduct.discount_list,
|
|
3049
3129
|
metadata: {
|
|
3050
3130
|
...targetProduct.metadata || {},
|
|
3051
3131
|
...normalizedProduct.metadata || {},
|
|
@@ -3056,16 +3136,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3056
3136
|
...normalizedProduct.product_sku || { option: [] },
|
|
3057
3137
|
option: (0, import_utils.getProductSkuOptions)(normalizedProduct)
|
|
3058
3138
|
},
|
|
3059
|
-
...targetIsManualProductDiscount ? {
|
|
3060
|
-
selling_price: targetProduct.selling_price,
|
|
3061
|
-
original_price: targetProduct.original_price,
|
|
3062
|
-
payment_price: targetProduct.payment_price,
|
|
3063
|
-
metadata: {
|
|
3064
|
-
...normalizedProduct.metadata || {},
|
|
3065
|
-
...targetProduct.metadata || {},
|
|
3066
|
-
unique_identification_number: targetUid
|
|
3067
|
-
}
|
|
3068
|
-
} : {},
|
|
3069
3139
|
note: targetProduct.note,
|
|
3070
3140
|
order_detail_id: targetProduct.order_detail_id,
|
|
3071
3141
|
num: nextNum
|
|
@@ -3076,6 +3146,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3076
3146
|
tempOrder.products[matchedIndex],
|
|
3077
3147
|
targetUid
|
|
3078
3148
|
);
|
|
3149
|
+
if (matchedIndex !== tempOrder.products.length - 1) {
|
|
3150
|
+
const mergedProduct = tempOrder.products[matchedIndex];
|
|
3151
|
+
tempOrder.products = [
|
|
3152
|
+
...tempOrder.products.slice(0, matchedIndex),
|
|
3153
|
+
...tempOrder.products.slice(matchedIndex + 1),
|
|
3154
|
+
mergedProduct
|
|
3155
|
+
];
|
|
3156
|
+
}
|
|
3079
3157
|
}
|
|
3080
3158
|
if (linked) {
|
|
3081
3159
|
tempOrder.bookings = [...tempOrder.bookings || [], linked.booking];
|
|
@@ -3088,8 +3166,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3088
3166
|
* await order.addProductToOrder({ product_id: 1, num: 3 }, { start_time: '10:00' });
|
|
3089
3167
|
* // → tempOrder.products 新增 3 行,每行 num=1,bookings 3 条
|
|
3090
3168
|
*/
|
|
3091
|
-
async addProductToOrder(product, booking) {
|
|
3169
|
+
async addProductToOrder(product, booking, options) {
|
|
3092
3170
|
const tempOrder = this.ensureTempOrder();
|
|
3171
|
+
const insertAfterProductUid = options == null ? void 0 : options.insertAfterProductUid;
|
|
3172
|
+
const anchorIndex = booking && insertAfterProductUid ? tempOrder.products.findIndex((line) => {
|
|
3173
|
+
var _a;
|
|
3174
|
+
const uid = ((_a = line.metadata) == null ? void 0 : _a.unique_identification_number) || line.unique_identification_number;
|
|
3175
|
+
return uid !== void 0 && uid !== null && String(uid) === String(insertAfterProductUid);
|
|
3176
|
+
}) : -1;
|
|
3177
|
+
let insertAtIndex = anchorIndex >= 0 ? anchorIndex + 1 : void 0;
|
|
3093
3178
|
if (booking) {
|
|
3094
3179
|
const productRecord = product;
|
|
3095
3180
|
const splitCount = (0, import_utils3.getSafeProductNum)(
|
|
@@ -3103,14 +3188,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3103
3188
|
await this.appendProductLineToTempOrder(
|
|
3104
3189
|
tempOrder,
|
|
3105
3190
|
singleLine,
|
|
3106
|
-
(0, import_lodash_es.cloneDeep)(booking)
|
|
3191
|
+
(0, import_lodash_es.cloneDeep)(booking),
|
|
3192
|
+
{ insertAtIndex }
|
|
3107
3193
|
);
|
|
3194
|
+
if (insertAtIndex !== void 0)
|
|
3195
|
+
insertAtIndex += 1;
|
|
3108
3196
|
}
|
|
3109
3197
|
await this.finalizeProductOrderMutation(tempOrder);
|
|
3110
3198
|
return tempOrder.products;
|
|
3111
3199
|
}
|
|
3112
3200
|
}
|
|
3113
|
-
await this.appendProductLineToTempOrder(
|
|
3201
|
+
await this.appendProductLineToTempOrder(
|
|
3202
|
+
tempOrder,
|
|
3203
|
+
product,
|
|
3204
|
+
booking,
|
|
3205
|
+
{ insertAtIndex }
|
|
3206
|
+
);
|
|
3114
3207
|
await this.finalizeProductOrderMutation(tempOrder);
|
|
3115
3208
|
this.logInfo("addProductToOrder success", {
|
|
3116
3209
|
product_id: product.product_id,
|
|
@@ -3484,6 +3577,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3484
3577
|
product_bundle
|
|
3485
3578
|
} = params;
|
|
3486
3579
|
const tempOrder = this.ensureTempOrder();
|
|
3580
|
+
this.repairDuplicateProductLineIdentities(tempOrder);
|
|
3487
3581
|
const identityLookup = {
|
|
3488
3582
|
product_id,
|
|
3489
3583
|
product_variant_id
|
|
@@ -3591,14 +3685,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3591
3685
|
* @example
|
|
3592
3686
|
* await order.removeProductsFromOrder([identityA, identityB]);
|
|
3593
3687
|
*/
|
|
3594
|
-
async removeProductsFromOrder(identities) {
|
|
3688
|
+
async removeProductsFromOrder(identities, options) {
|
|
3595
3689
|
var _a, _b, _c, _d;
|
|
3596
3690
|
const tempOrder = this.ensureTempOrder();
|
|
3691
|
+
this.repairDuplicateProductLineIdentities(tempOrder);
|
|
3597
3692
|
if (!identities.length) {
|
|
3598
3693
|
return tempOrder.products;
|
|
3599
3694
|
}
|
|
3600
3695
|
const productsBeforeRemove = tempOrder.products || [];
|
|
3601
3696
|
const bookingsBeforeRemove = tempOrder.bookings || [];
|
|
3697
|
+
const preserveDisplayPosition = options == null ? void 0 : options.preserveDisplayPosition;
|
|
3698
|
+
const anchorIndex = preserveDisplayPosition ? productsBeforeRemove.findIndex((item) => {
|
|
3699
|
+
var _a2;
|
|
3700
|
+
const uid = ((_a2 = item.metadata) == null ? void 0 : _a2.unique_identification_number) || item.unique_identification_number;
|
|
3701
|
+
return uid !== void 0 && uid !== null && String(uid) === String(preserveDisplayPosition.anchorProductUid);
|
|
3702
|
+
}) : -1;
|
|
3703
|
+
const productsAfterAnchor = anchorIndex >= 0 ? productsBeforeRemove.slice(anchorIndex + 1) : [];
|
|
3602
3704
|
const matchedProducts = productsBeforeRemove.filter((item) => {
|
|
3603
3705
|
return identities.some((identity) => (0, import_utils3.isIdentityMatch)(item, identity));
|
|
3604
3706
|
});
|
|
@@ -3639,14 +3741,37 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3639
3741
|
return !(isAddTimeProduct && lineBookingUid !== void 0 && lineBookingUid !== null && linkedBookingUidsToRemove.has(String(lineBookingUid)));
|
|
3640
3742
|
});
|
|
3641
3743
|
}
|
|
3744
|
+
if (preserveDisplayPosition && anchorIndex >= 0) {
|
|
3745
|
+
const remainingProductIndex = tempOrder.products.findIndex((item) => {
|
|
3746
|
+
var _a2;
|
|
3747
|
+
const uid = ((_a2 = item.metadata) == null ? void 0 : _a2.unique_identification_number) || item.unique_identification_number;
|
|
3748
|
+
return uid !== void 0 && uid !== null && String(uid) === String(preserveDisplayPosition.remainingProductUid);
|
|
3749
|
+
});
|
|
3750
|
+
if (remainingProductIndex >= 0) {
|
|
3751
|
+
const remainingProduct = tempOrder.products[remainingProductIndex];
|
|
3752
|
+
const nextProduct = productsAfterAnchor.find(
|
|
3753
|
+
(item) => tempOrder.products.includes(item)
|
|
3754
|
+
);
|
|
3755
|
+
const productsWithoutRemaining = [
|
|
3756
|
+
...tempOrder.products.slice(0, remainingProductIndex),
|
|
3757
|
+
...tempOrder.products.slice(remainingProductIndex + 1)
|
|
3758
|
+
];
|
|
3759
|
+
const nextProductIndex = nextProduct ? productsWithoutRemaining.indexOf(nextProduct) : -1;
|
|
3760
|
+
tempOrder.products = nextProductIndex >= 0 ? [
|
|
3761
|
+
...productsWithoutRemaining.slice(0, nextProductIndex),
|
|
3762
|
+
remainingProduct,
|
|
3763
|
+
...productsWithoutRemaining.slice(nextProductIndex)
|
|
3764
|
+
] : [...productsWithoutRemaining, remainingProduct];
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3642
3767
|
await this.finalizeAfterProductsMutation(tempOrder);
|
|
3643
3768
|
this.logInfo("removeProductsFromOrder success", {
|
|
3644
3769
|
identities
|
|
3645
3770
|
});
|
|
3646
3771
|
return tempOrder.products;
|
|
3647
3772
|
}
|
|
3648
|
-
async removeProductFromOrder(identity) {
|
|
3649
|
-
return this.removeProductsFromOrder([identity]);
|
|
3773
|
+
async removeProductFromOrder(identity, options) {
|
|
3774
|
+
return this.removeProductsFromOrder([identity], options);
|
|
3650
3775
|
}
|
|
3651
3776
|
/**
|
|
3652
3777
|
* 仅清空购物车行(products / bookings),不重置整单。
|
|
@@ -4300,24 +4425,39 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
4300
4425
|
* 例如数组字段、商品行唯一值、价格 metadata、summary 派生状态和 _extend。
|
|
4301
4426
|
*/
|
|
4302
4427
|
async hydrateTempOrderFromRecord(record, options) {
|
|
4303
|
-
var _a, _b, _c, _d, _e;
|
|
4428
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4304
4429
|
const sourceRaw = record && typeof record === "object" && record.data && record.order_id == null ? record.data : record || {};
|
|
4430
|
+
const duplicateProductIdentityRepair = (0, import_orderCollectionIdentity.repairDuplicateProductLineIdentities)(
|
|
4431
|
+
Array.isArray(sourceRaw.products) ? sourceRaw.products : [],
|
|
4432
|
+
(_a = sourceRaw._extend) == null ? void 0 : _a.productsByUid
|
|
4433
|
+
);
|
|
4434
|
+
const duplicateIdentityReadySource = duplicateProductIdentityRepair.repairs.length ? {
|
|
4435
|
+
...sourceRaw,
|
|
4436
|
+
products: duplicateProductIdentityRepair.products,
|
|
4437
|
+
...duplicateProductIdentityRepair.productsByUid ? {
|
|
4438
|
+
_extend: {
|
|
4439
|
+
...sourceRaw._extend || {},
|
|
4440
|
+
productsByUid: duplicateProductIdentityRepair.productsByUid
|
|
4441
|
+
}
|
|
4442
|
+
} : {}
|
|
4443
|
+
} : sourceRaw;
|
|
4305
4444
|
const identityReadySource = this.seedAnonymousBookingUidsFromProducts(
|
|
4306
|
-
|
|
4445
|
+
duplicateIdentityReadySource
|
|
4307
4446
|
);
|
|
4308
4447
|
const normalizedCollections = (0, import_orderCollectionIdentity.normalizeOrderCollections)(identityReadySource);
|
|
4309
4448
|
const raw = normalizedCollections.order;
|
|
4310
|
-
const hasIdentityChanges = Object.values(normalizedCollections.stats).some(
|
|
4449
|
+
const hasIdentityChanges = duplicateProductIdentityRepair.repairs.length > 0 || Object.values(normalizedCollections.stats).some(
|
|
4311
4450
|
(stats) => stats.backfilledUidCount > 0 || stats.collapsedDuplicateCount > 0 || stats.uidConflictCount > 0 || stats.anonymousRowCount > 0
|
|
4312
4451
|
);
|
|
4313
4452
|
if (hasIdentityChanges) {
|
|
4314
4453
|
const identityLogMetadata = {
|
|
4315
4454
|
collections: normalizedCollections.stats,
|
|
4316
|
-
uidRemapCount: normalizedCollections.uidRemaps.length
|
|
4455
|
+
uidRemapCount: normalizedCollections.uidRemaps.length,
|
|
4456
|
+
duplicateProductUidRepairCount: duplicateProductIdentityRepair.repairs.length
|
|
4317
4457
|
};
|
|
4318
4458
|
const hasIdentityWarnings = Object.values(normalizedCollections.stats).some(
|
|
4319
4459
|
(stats) => stats.uidConflictCount > 0 || stats.anonymousRowCount > 0
|
|
4320
|
-
);
|
|
4460
|
+
) || duplicateProductIdentityRepair.repairs.length > 0;
|
|
4321
4461
|
if (hasIdentityWarnings) {
|
|
4322
4462
|
this.logWarning(
|
|
4323
4463
|
"Normalized hydrated order collection identities",
|
|
@@ -4348,10 +4488,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
4348
4488
|
nextTempOrder.discount_list = restoredSessionDiscounts;
|
|
4349
4489
|
this.store.summary = (0, import_utils.createEmptySummary)();
|
|
4350
4490
|
this.store.lastOrderInfo = void 0;
|
|
4351
|
-
await ((
|
|
4491
|
+
await ((_b = this.store.discount) == null ? void 0 : _b.setOriginalDiscountList(
|
|
4352
4492
|
(0, import_lodash_es.cloneDeep)(restoredSessionDiscounts)
|
|
4353
4493
|
));
|
|
4354
|
-
await ((
|
|
4494
|
+
await ((_c = this.store.discount) == null ? void 0 : _c.setDiscountList(
|
|
4355
4495
|
(0, import_lodash_es.cloneDeep)(restoredSessionDiscounts)
|
|
4356
4496
|
));
|
|
4357
4497
|
if (options == null ? void 0 : options.recalcOnHydrate) {
|
|
@@ -4394,7 +4534,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
4394
4534
|
this.store.syncState = "local";
|
|
4395
4535
|
}
|
|
4396
4536
|
const hydratedEditDiscounts = this.collectHydratedEditDiscounts(nextTempOrder.products);
|
|
4397
|
-
const currentDiscounts = typeof ((
|
|
4537
|
+
const currentDiscounts = typeof ((_d = this.store.discount) == null ? void 0 : _d.getDiscountList) === "function" ? this.store.discount.getDiscountList() || [] : [];
|
|
4398
4538
|
const currentScanDiscounts = currentDiscounts.filter((discount) => discount == null ? void 0 : discount.isScan);
|
|
4399
4539
|
const hydratedDiscountIds = new Set(
|
|
4400
4540
|
hydratedEditDiscounts.map((discount) => discount == null ? void 0 : discount.id)
|
|
@@ -4412,8 +4552,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
4412
4552
|
nextTempOrder.products,
|
|
4413
4553
|
nextDiscounts
|
|
4414
4554
|
);
|
|
4415
|
-
await ((
|
|
4416
|
-
await ((
|
|
4555
|
+
await ((_e = this.store.discount) == null ? void 0 : _e.setOriginalDiscountList(nextDiscounts));
|
|
4556
|
+
await ((_f = this.store.discount) == null ? void 0 : _f.setDiscountList(nextDiscounts));
|
|
4417
4557
|
}
|
|
4418
4558
|
if (options == null ? void 0 : options.recalcOnHydrate) {
|
|
4419
4559
|
await this.recalculateSummary({ createIfMissing: false });
|
|
@@ -321,6 +321,24 @@ export interface ReplaceTempOrderOptions {
|
|
|
321
321
|
saveDraft?: boolean;
|
|
322
322
|
}
|
|
323
323
|
export type AddProductBookingInput = Record<string, any>;
|
|
324
|
+
/**
|
|
325
|
+
* 添加商品行时的顺序控制。
|
|
326
|
+
* 默认追加到 products 尾部;预约数量同步可插入到既有预约组的最新行之后,
|
|
327
|
+
* 避免步进器修改数量改变该组展示位置。
|
|
328
|
+
*/
|
|
329
|
+
export interface AddProductToOrderOptions {
|
|
330
|
+
insertAfterProductUid?: string;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* 删除商品后的可选位置保持策略。
|
|
334
|
+
* 预约合并行减量时仍删除最新真实行,再把剩余代表行移动到被删除代表行原位置。
|
|
335
|
+
*/
|
|
336
|
+
export interface RemoveProductsFromOrderOptions {
|
|
337
|
+
preserveDisplayPosition?: {
|
|
338
|
+
remainingProductUid: string;
|
|
339
|
+
anchorProductUid: string;
|
|
340
|
+
};
|
|
341
|
+
}
|
|
324
342
|
/** 更新购物车行:仅传 SKU 时命中同 SKU 第一行;多行同 SKU 须传 unique_identification_number / 选项指纹等 */
|
|
325
343
|
export interface UpdateOrderProductParams {
|
|
326
344
|
product_id: number | null;
|
|
@@ -726,17 +744,22 @@ export interface OrderModuleAPI {
|
|
|
726
744
|
updateTempOrderCustomer: (customer: UpdateTempOrderCustomerInput) => OrderSnapshot['customer'];
|
|
727
745
|
updateTempOrderBuzzer: (buzzer: string) => string;
|
|
728
746
|
updateTempOrderContactsInfo: (contactsInfo: Record<string, any> | null) => Record<string, any> | null;
|
|
729
|
-
addProductToOrder: (product: Partial<OrderProduct> & OrderProductIdentity, booking?: AddProductBookingInput) => Promise<OrderProduct[]>;
|
|
747
|
+
addProductToOrder: (product: Partial<OrderProduct> & OrderProductIdentity, booking?: AddProductBookingInput, options?: AddProductToOrderOptions) => Promise<OrderProduct[]>;
|
|
730
748
|
updateOrderProduct: (params: UpdateOrderProductParams) => Promise<OrderProduct[]>;
|
|
731
749
|
/** 批量更新购物车行,末尾仅触发一次促销重算与 summary 刷新 */
|
|
732
750
|
updateOrderProducts: (paramsList: UpdateOrderProductParams[]) => Promise<OrderProduct[]>;
|
|
733
751
|
updateOrderProductQuantity: (params: UpdateOrderProductQuantityParams) => Promise<OrderProduct[]>;
|
|
734
752
|
updateOrderBooking: (params: UpdateOrderBookingParams) => any[];
|
|
735
|
-
removeProductFromOrder: (identity: OrderProductIdentity) => Promise<OrderProduct[]>;
|
|
753
|
+
removeProductFromOrder: (identity: OrderProductIdentity, options?: RemoveProductsFromOrderOptions) => Promise<OrderProduct[]>;
|
|
736
754
|
/** 批量删除购物车行,末尾仅触发一次促销重算与 summary 刷新 */
|
|
737
|
-
removeProductsFromOrder: (identities: OrderProductIdentity[]) => Promise<OrderProduct[]>;
|
|
755
|
+
removeProductsFromOrder: (identities: OrderProductIdentity[], options?: RemoveProductsFromOrderOptions) => Promise<OrderProduct[]>;
|
|
738
756
|
/** 在显式开启时保存当前 tempOrder 的 sessionStorage 会话快照。 */
|
|
739
757
|
persistTempOrder: () => void;
|
|
758
|
+
/**
|
|
759
|
+
* 删除当前 cacheId 的 tempOrder 会话快照,并阻止当前模块实例再次写入。
|
|
760
|
+
* 新模块实例初始化时会按 otherParams 重新启用持久化。
|
|
761
|
+
*/
|
|
762
|
+
clearSessionStoragePersistedTempOrder: () => void;
|
|
740
763
|
/** 取出一次待恢复的 sessionStorage tempOrder 快照。 */
|
|
741
764
|
consumeSessionStorageRestore: () => Record<string, any> | null;
|
|
742
765
|
/**
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { OrderTempOrder } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* 商品券拆行的身份与回并工具。
|
|
4
|
+
*
|
|
5
|
+
* 背景:
|
|
6
|
+
* Rules.calcDiscount 应用 good_pass 时,会把一个数量行拆成若干「用券行」和
|
|
7
|
+
* 「普通余量行」。Rules 返回的拆分行可能复制同一份
|
|
8
|
+
* metadata.unique_identification_number,进而造成:
|
|
9
|
+
* - 按 UID 删除时同时命中多行;
|
|
10
|
+
* - UI 把不同券行视为同一个商品;
|
|
11
|
+
* - 后续商品更新无法准确定位目标行。
|
|
12
|
+
*
|
|
13
|
+
* 处理原则:
|
|
14
|
+
* 1. 拆分后每一行必须拥有独立 UID;
|
|
15
|
+
* 2. 原始拆分来源仅记录在 tempOrder._extend.productsByUid 的运行态索引中,
|
|
16
|
+
* 不写入商品 metadata,不污染提交协议;
|
|
17
|
+
* 3. 券被移除后,只回并被本工具确认来自同一折扣拆分源的行;
|
|
18
|
+
* 4. 预约、赠品、促销、手动折扣、备注、称重、holder 和已落库行均为硬边界。
|
|
19
|
+
*
|
|
20
|
+
* 两个导出函数都会原地更新 tempOrder。调用顺序必须是:
|
|
21
|
+
* ensureUniqueProductLineUids -> consolidateDiscountFreeProductLines。
|
|
22
|
+
*/
|
|
23
|
+
/** productsByUid 运行态记录中用于关联同一次折扣拆分的字段。 */
|
|
24
|
+
export declare const DISCOUNT_SPLIT_ORIGIN_UID_KEY = "discountSplitOriginUid";
|
|
25
|
+
/**
|
|
26
|
+
* 修复 Rules 折扣拆行复制 UID 的问题,并为拆分行记录共同来源。
|
|
27
|
+
*
|
|
28
|
+
* 第一条商品保留原 UID,后续重复行生成新 UUID;对应的 productsByUid.runtime
|
|
29
|
+
* 会复制原行 runtime(包括 origin),以保证删除、编辑及展示字段回读仍可工作。
|
|
30
|
+
*
|
|
31
|
+
* 没有 UID 的裸商品不会被补写 UID。这是为了兼容 Rules/mock 的历史协议形状;
|
|
32
|
+
* 正常 Order 写路径会在 normalize 阶段提前创建 UID。
|
|
33
|
+
*/
|
|
34
|
+
export declare function ensureUniqueProductLineUids(tempOrder: OrderTempOrder): void;
|
|
35
|
+
/**
|
|
36
|
+
* 把券移除后已经恢复原价的同源折扣拆分行重新合并。
|
|
37
|
+
*
|
|
38
|
+
* 此函数刻意不执行通用的「同 SKU 合并」:没有 discountSplitOriginUid 的普通行
|
|
39
|
+
* 可能是业务 hook、导入订单或其它流程主动拆开的,不能在折扣重算时擅自合并。
|
|
40
|
+
*
|
|
41
|
+
* payment_price、tax_fee、surcharge_fee 属于 summary 计算层的派生值。券行与普通行
|
|
42
|
+
* 在回并前可能暂时不同,因此它们不参与 mergeKey;原始价格、SKU/option/bundle
|
|
43
|
+
* 结构以及税务/商品类型配置仍参与比较,防止不同商品语义被误合并。
|
|
44
|
+
*/
|
|
45
|
+
export declare function consolidateDiscountFreeProductLines(tempOrder: OrderTempOrder): void;
|