@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
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/modules/Order/utils/discountProductLineIdentity.ts
|
|
20
|
+
var discountProductLineIdentity_exports = {};
|
|
21
|
+
__export(discountProductLineIdentity_exports, {
|
|
22
|
+
DISCOUNT_SPLIT_ORIGIN_UID_KEY: () => DISCOUNT_SPLIT_ORIGIN_UID_KEY,
|
|
23
|
+
consolidateDiscountFreeProductLines: () => consolidateDiscountFreeProductLines,
|
|
24
|
+
ensureUniqueProductLineUids: () => ensureUniqueProductLineUids
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(discountProductLineIdentity_exports);
|
|
27
|
+
var import_lodash_es = require("lodash-es");
|
|
28
|
+
var import_utils = require("../../../solution/ScanOrder/utils");
|
|
29
|
+
var import_orderCollectionIdentity = require("./orderCollectionIdentity");
|
|
30
|
+
var DISCOUNT_SPLIT_ORIGIN_UID_KEY = "discountSplitOriginUid";
|
|
31
|
+
function getProductLineUid(product) {
|
|
32
|
+
var _a;
|
|
33
|
+
if (!product || typeof product !== "object")
|
|
34
|
+
return null;
|
|
35
|
+
const uid = ((_a = product.metadata) == null ? void 0 : _a.unique_identification_number) ?? product.unique_identification_number;
|
|
36
|
+
if (uid === void 0 || uid === null || uid === "")
|
|
37
|
+
return null;
|
|
38
|
+
return String(uid);
|
|
39
|
+
}
|
|
40
|
+
function getProductSkuOptions(product) {
|
|
41
|
+
var _a;
|
|
42
|
+
return Array.isArray((_a = product.product_sku) == null ? void 0 : _a.option) ? product.product_sku.option : [];
|
|
43
|
+
}
|
|
44
|
+
function hasProductLineNote(product) {
|
|
45
|
+
return typeof product.note === "string" && product.note.trim().length > 0;
|
|
46
|
+
}
|
|
47
|
+
function isManualProductDiscountLine(product) {
|
|
48
|
+
var _a, _b;
|
|
49
|
+
return ((_a = product.metadata) == null ? void 0 : _a.is_manual_discount) === true || ((_b = product.metadata) == null ? void 0 : _b.is_manual_discount) === 1 || (product.discount_list || []).some((item) => (item == null ? void 0 : item.type) === "product");
|
|
50
|
+
}
|
|
51
|
+
function ensureProductsByUid(tempOrder) {
|
|
52
|
+
if (!tempOrder._extend || typeof tempOrder._extend !== "object") {
|
|
53
|
+
tempOrder._extend = { productsByUid: {} };
|
|
54
|
+
}
|
|
55
|
+
if (!tempOrder._extend.productsByUid) {
|
|
56
|
+
tempOrder._extend.productsByUid = {};
|
|
57
|
+
}
|
|
58
|
+
return tempOrder._extend.productsByUid;
|
|
59
|
+
}
|
|
60
|
+
function ensureUniqueProductLineUids(tempOrder) {
|
|
61
|
+
const usedUids = /* @__PURE__ */ new Set();
|
|
62
|
+
const productsByUid = ensureProductsByUid(tempOrder);
|
|
63
|
+
tempOrder.products = (tempOrder.products || []).map((product) => {
|
|
64
|
+
const sourceUid = getProductLineUid(product);
|
|
65
|
+
if (!sourceUid)
|
|
66
|
+
return product;
|
|
67
|
+
if (!usedUids.has(sourceUid)) {
|
|
68
|
+
usedUids.add(sourceUid);
|
|
69
|
+
return product;
|
|
70
|
+
}
|
|
71
|
+
let splitUid = (0, import_orderCollectionIdentity.createUuidV4)();
|
|
72
|
+
while (usedUids.has(splitUid)) {
|
|
73
|
+
splitUid = (0, import_orderCollectionIdentity.createUuidV4)();
|
|
74
|
+
}
|
|
75
|
+
product.metadata = {
|
|
76
|
+
...product.metadata || {},
|
|
77
|
+
unique_identification_number: splitUid
|
|
78
|
+
};
|
|
79
|
+
const sourceRuntime = productsByUid[sourceUid] || {};
|
|
80
|
+
const discountSplitOriginUid = String(
|
|
81
|
+
sourceRuntime[DISCOUNT_SPLIT_ORIGIN_UID_KEY] || sourceUid
|
|
82
|
+
);
|
|
83
|
+
productsByUid[sourceUid] = {
|
|
84
|
+
...sourceRuntime,
|
|
85
|
+
[DISCOUNT_SPLIT_ORIGIN_UID_KEY]: discountSplitOriginUid
|
|
86
|
+
};
|
|
87
|
+
productsByUid[splitUid] = {
|
|
88
|
+
...(0, import_lodash_es.cloneDeep)(sourceRuntime),
|
|
89
|
+
[DISCOUNT_SPLIT_ORIGIN_UID_KEY]: discountSplitOriginUid
|
|
90
|
+
};
|
|
91
|
+
usedUids.add(splitUid);
|
|
92
|
+
return product;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function consolidateDiscountFreeProductLines(tempOrder) {
|
|
96
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
97
|
+
const consolidatedProducts = [];
|
|
98
|
+
const productIndexByKey = /* @__PURE__ */ new Map();
|
|
99
|
+
for (const product of tempOrder.products || []) {
|
|
100
|
+
const productBundle = Array.isArray(product.product_bundle) ? product.product_bundle : [];
|
|
101
|
+
const hasDiscount = (product.discount_list || []).length > 0 || productBundle.some((bundle) => ((bundle == null ? void 0 : bundle.discount_list) || []).length > 0);
|
|
102
|
+
const bookingUid = product.booking_uid ?? ((_a = product.metadata) == null ? void 0 : _a.booking_uid);
|
|
103
|
+
const bookingId = product.booking_id ?? ((_b = product.metadata) == null ? void 0 : _b.booking_id);
|
|
104
|
+
const orderDetailId = product.order_detail_id ?? product.orderDetailId;
|
|
105
|
+
const holderId = product.holder_id ?? ((_c = product.metadata) == null ? void 0 : _c.holder_id);
|
|
106
|
+
const hasMergeBoundary = hasDiscount || Boolean(((_d = product.metadata) == null ? void 0 : _d._giftInfo) || product._giftInfo) || Boolean((_e = product.metadata) == null ? void 0 : _e._promotion) || isManualProductDiscountLine(product) || hasProductLineNote(product) || Number(((_f = product.product_sku) == null ? void 0 : _f.open_sold_weight) || 0) === 1 || ((_g = product.metadata) == null ? void 0 : _g.is_edit_for_runtime) === true || bookingId !== void 0 && bookingId !== null && bookingId !== 0 && bookingId !== "0" || bookingUid !== void 0 && bookingUid !== null && String(bookingUid) !== "" || holderId !== void 0 && holderId !== null && String(holderId) !== "" || orderDetailId !== void 0 && orderDetailId !== null && orderDetailId !== "";
|
|
107
|
+
if (hasMergeBoundary) {
|
|
108
|
+
consolidatedProducts.push(product);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const productUid = getProductLineUid(product);
|
|
112
|
+
const discountSplitOriginUid = productUid ? (_j = (_i = (_h = tempOrder._extend) == null ? void 0 : _h.productsByUid) == null ? void 0 : _i[productUid]) == null ? void 0 : _j[DISCOUNT_SPLIT_ORIGIN_UID_KEY] : void 0;
|
|
113
|
+
if (!discountSplitOriginUid) {
|
|
114
|
+
consolidatedProducts.push(product);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const fingerprint = (0, import_utils.buildProductLineFingerprint)(
|
|
118
|
+
getProductSkuOptions(product),
|
|
119
|
+
productBundle
|
|
120
|
+
);
|
|
121
|
+
const priceSignature = JSON.stringify({
|
|
122
|
+
selling_price: String(product.selling_price ?? ""),
|
|
123
|
+
original_price: String(product.original_price ?? ""),
|
|
124
|
+
custom_price: String(product.custom_price ?? ""),
|
|
125
|
+
is_charge_tax: Number(product.is_charge_tax ?? 0),
|
|
126
|
+
gift_card: Number(product.gift_card ?? 0),
|
|
127
|
+
bundle_edit: Number(product.bundle_edit ?? 0),
|
|
128
|
+
price_schema_version: ((_k = product.metadata) == null ? void 0 : _k.price_schema_version) ?? "",
|
|
129
|
+
source_product_price: String(((_l = product.metadata) == null ? void 0 : _l.source_product_price) ?? ""),
|
|
130
|
+
main_product_selling_price: String(
|
|
131
|
+
((_m = product.metadata) == null ? void 0 : _m.main_product_selling_price) ?? ""
|
|
132
|
+
),
|
|
133
|
+
main_product_original_price: String(
|
|
134
|
+
((_n = product.metadata) == null ? void 0 : _n.main_product_original_price) ?? ""
|
|
135
|
+
),
|
|
136
|
+
bundle: productBundle.map((bundle) => ({
|
|
137
|
+
bundle_id: (bundle == null ? void 0 : bundle.bundle_id) ?? (bundle == null ? void 0 : bundle.id) ?? "",
|
|
138
|
+
product_id: (bundle == null ? void 0 : bundle.bundle_product_id) ?? (bundle == null ? void 0 : bundle._bundle_product_id) ?? (bundle == null ? void 0 : bundle.product_id) ?? "",
|
|
139
|
+
product_variant_id: (bundle == null ? void 0 : bundle.bundle_variant_id) ?? (bundle == null ? void 0 : bundle.variant_id) ?? (bundle == null ? void 0 : bundle.product_variant_id) ?? 0,
|
|
140
|
+
price: String((bundle == null ? void 0 : bundle.price) ?? ""),
|
|
141
|
+
original_price: String((bundle == null ? void 0 : bundle.original_price) ?? ""),
|
|
142
|
+
bundle_selling_price: String((bundle == null ? void 0 : bundle.bundle_selling_price) ?? "")
|
|
143
|
+
}))
|
|
144
|
+
});
|
|
145
|
+
const mergeKey = [
|
|
146
|
+
discountSplitOriginUid,
|
|
147
|
+
product.product_id,
|
|
148
|
+
product.product_variant_id ?? 0,
|
|
149
|
+
fingerprint,
|
|
150
|
+
priceSignature
|
|
151
|
+
].join("#");
|
|
152
|
+
const matchedIndex = productIndexByKey.get(mergeKey);
|
|
153
|
+
if (matchedIndex === void 0) {
|
|
154
|
+
productIndexByKey.set(mergeKey, consolidatedProducts.length);
|
|
155
|
+
consolidatedProducts.push(product);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const matchedProduct = consolidatedProducts[matchedIndex];
|
|
159
|
+
matchedProduct.num = (0, import_utils.getSafeProductNum)(
|
|
160
|
+
Number(matchedProduct.num || 0) + Number(product.num || 0)
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
tempOrder.products = consolidatedProducts;
|
|
164
|
+
}
|
|
165
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
166
|
+
0 && (module.exports = {
|
|
167
|
+
DISCOUNT_SPLIT_ORIGIN_UID_KEY,
|
|
168
|
+
consolidateDiscountFreeProductLines,
|
|
169
|
+
ensureUniqueProductLineUids
|
|
170
|
+
});
|
|
@@ -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
|
});
|
|
@@ -243,7 +243,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
243
243
|
const discountType = selectedDiscount.tag || selectedDiscount.type;
|
|
244
244
|
return selectedDiscount.isEditMode === true && selectedDiscount.isSelected === true && ["good_pass", "discount_card", "product_discount_card"].includes(discountType);
|
|
245
245
|
};
|
|
246
|
-
const
|
|
246
|
+
const resolveReapplyBookingDiscountPercent = (originProduct, selectedDiscount) => {
|
|
247
247
|
var _a2;
|
|
248
248
|
if (!shouldReapplyBookingDiscount(originProduct, selectedDiscount))
|
|
249
249
|
return void 0;
|
|
@@ -318,6 +318,9 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
318
318
|
bundleIndex,
|
|
319
319
|
// 虚拟商品属性
|
|
320
320
|
price: Number(bundleItem.price || 0),
|
|
321
|
+
// 新增商品运行态通常带 _bundle_product_id;订单 hydrate 后只有
|
|
322
|
+
// bundle_product_id。Change time 必须兼容两种结构,否则 bundle
|
|
323
|
+
// 子项无法命中折扣卡的 limited_relation_product_data.product_ids。
|
|
321
324
|
id: bundleItem.bundle_product_id ?? bundleItem._bundle_product_id ?? bundleItem.product_id,
|
|
322
325
|
_id: `${product._id}_bundle_${bundleIndex}`,
|
|
323
326
|
parentId: product._id,
|
|
@@ -779,13 +782,6 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
779
782
|
if (isPersistedProduct && hasExistingWalletDiscount) {
|
|
780
783
|
if (flatItem.type === "main") {
|
|
781
784
|
processedProductsMap.set(product._id, [originProduct]);
|
|
782
|
-
} else {
|
|
783
|
-
processedFlatItemsMap.set(flatItem._id, [
|
|
784
|
-
{
|
|
785
|
-
...flatItem,
|
|
786
|
-
processed: true
|
|
787
|
-
}
|
|
788
|
-
]);
|
|
789
785
|
}
|
|
790
786
|
return;
|
|
791
787
|
}
|
|
@@ -862,15 +858,46 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
862
858
|
}
|
|
863
859
|
return false;
|
|
864
860
|
});
|
|
865
|
-
const
|
|
861
|
+
const explicitlySelectedDiscount = (options == null ? void 0 : options.isSelected) === true && options.discountId !== void 0 ? applicableDiscounts.find((discount) => {
|
|
866
862
|
const discountType = discount.tag || discount.type;
|
|
867
|
-
return String(discount.id) === String(options.discountId) && ["discount_card", "product_discount_card"].includes(
|
|
863
|
+
return String(discount.id) === String(options.discountId) && ["good_pass", "discount_card", "product_discount_card"].includes(
|
|
864
|
+
discountType
|
|
865
|
+
);
|
|
868
866
|
}) : void 0;
|
|
867
|
+
const explicitlySelectedDiscountCard = explicitlySelectedDiscount && (explicitlySelectedDiscount.tag || explicitlySelectedDiscount.type) !== "good_pass" ? explicitlySelectedDiscount : void 0;
|
|
868
|
+
const appliedDiscountCardIds = new Set(
|
|
869
|
+
(product.discount_list || []).filter(
|
|
870
|
+
(item) => ["discount_card", "product_discount_card"].includes(
|
|
871
|
+
(item == null ? void 0 : item.tag) || (item == null ? void 0 : item.type)
|
|
872
|
+
)
|
|
873
|
+
).map(
|
|
874
|
+
(item) => {
|
|
875
|
+
var _a3;
|
|
876
|
+
return ((_a3 = item == null ? void 0 : item.discount) == null ? void 0 : _a3.resource_id) ?? (item == null ? void 0 : item.resource_id) ?? (item == null ? void 0 : item.id);
|
|
877
|
+
}
|
|
878
|
+
).filter((id) => id !== void 0 && id !== null).map(String)
|
|
879
|
+
);
|
|
880
|
+
const appliedDiscountCard = (options == null ? void 0 : options.scan) ? void 0 : applicableDiscounts.find((discount) => {
|
|
881
|
+
const discountType = discount.tag || discount.type;
|
|
882
|
+
return discount.isSelected === true && ["discount_card", "product_discount_card"].includes(discountType) && appliedDiscountCardIds.has(String(discount.id));
|
|
883
|
+
});
|
|
869
884
|
const scannedSelectedDiscountCard = applicableDiscounts.find(
|
|
870
885
|
(n) => n.isScan && n.isSelected && (n.tag || n.type) !== "good_pass"
|
|
871
886
|
);
|
|
872
|
-
const selectedDiscountCard = explicitlySelectedDiscountCard || scannedSelectedDiscountCard;
|
|
873
|
-
const selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
|
|
887
|
+
const selectedDiscountCard = explicitlySelectedDiscountCard || appliedDiscountCard || scannedSelectedDiscountCard;
|
|
888
|
+
const selectedDiscount = explicitlySelectedDiscount || selectedDiscountCard || applicableDiscounts[0];
|
|
889
|
+
const prioritizedApplicableDiscounts = explicitlySelectedDiscount && (explicitlySelectedDiscount.tag || explicitlySelectedDiscount.type) === "good_pass" ? [
|
|
890
|
+
explicitlySelectedDiscount,
|
|
891
|
+
...applicableDiscounts.filter(
|
|
892
|
+
(discount) => {
|
|
893
|
+
const discountType = discount.tag || discount.type;
|
|
894
|
+
return discountType === "good_pass" && String(discount.id) !== String(explicitlySelectedDiscount.id);
|
|
895
|
+
}
|
|
896
|
+
),
|
|
897
|
+
...applicableDiscounts.filter(
|
|
898
|
+
(discount) => (discount.tag || discount.type) !== "good_pass"
|
|
899
|
+
)
|
|
900
|
+
] : applicableDiscounts;
|
|
874
901
|
let isManualDiscount = false;
|
|
875
902
|
let isItemRewardProductDiscount = false;
|
|
876
903
|
if (flatItem.type === "main") {
|
|
@@ -1049,21 +1076,65 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
1049
1076
|
const arr = [];
|
|
1050
1077
|
if (flatItem.type === "main") {
|
|
1051
1078
|
if (splitCount < totalQuantity && isNeedSplit) {
|
|
1079
|
+
const remainingQuantity = totalQuantity - splitCount;
|
|
1080
|
+
const applicableNonGoodPassById = new Map(
|
|
1081
|
+
applicableDiscounts.filter((discount) => (discount.tag || discount.type) !== "good_pass").map((discount) => [String(discount.id), discount])
|
|
1082
|
+
);
|
|
1083
|
+
const remainderDiscountList = (product.discount_list || []).filter((discount) => {
|
|
1084
|
+
var _a3;
|
|
1085
|
+
const discountType = discount.tag || discount.type;
|
|
1086
|
+
if (discountType === "promotion")
|
|
1087
|
+
return true;
|
|
1088
|
+
if (discountType === "good_pass")
|
|
1089
|
+
return false;
|
|
1090
|
+
const resourceId = ((_a3 = discount.discount) == null ? void 0 : _a3.resource_id) ?? discount.id;
|
|
1091
|
+
return resourceId !== void 0 && resourceId !== null && applicableNonGoodPassById.has(String(resourceId));
|
|
1092
|
+
}).map((discount) => {
|
|
1093
|
+
var _a3;
|
|
1094
|
+
if ((discount.tag || discount.type) === "promotion")
|
|
1095
|
+
return discount;
|
|
1096
|
+
const resourceId = ((_a3 = discount.discount) == null ? void 0 : _a3.resource_id) ?? discount.id;
|
|
1097
|
+
const matchedDiscount = applicableNonGoodPassById.get(String(resourceId));
|
|
1098
|
+
if (matchedDiscount) {
|
|
1099
|
+
usedDiscounts.set(matchedDiscount.id, true);
|
|
1100
|
+
const appliedProducts = appliedDiscountProducts.get(matchedDiscount.id) || [];
|
|
1101
|
+
appliedProducts.push({
|
|
1102
|
+
...discount,
|
|
1103
|
+
_num: remainingQuantity
|
|
1104
|
+
});
|
|
1105
|
+
appliedDiscountProducts.set(matchedDiscount.id, appliedProducts);
|
|
1106
|
+
}
|
|
1107
|
+
return {
|
|
1108
|
+
...discount,
|
|
1109
|
+
// _num 是 Rules 运行态的行数量;Order 写回 tempOrder 时会裁剪该字段。
|
|
1110
|
+
_num: remainingQuantity
|
|
1111
|
+
};
|
|
1112
|
+
});
|
|
1113
|
+
const hasRetainedWalletDiscount = remainderDiscountList.some(
|
|
1114
|
+
(discount) => !["promotion", "good_pass"].includes(discount.tag || discount.type)
|
|
1115
|
+
);
|
|
1052
1116
|
let total = product.origin_total ?? product.total;
|
|
1053
1117
|
if ((product.discount_list || []).some((item) => item.type === "promotion")) {
|
|
1054
1118
|
total = product.total ?? product.origin_total;
|
|
1055
1119
|
}
|
|
1056
1120
|
arr.push(
|
|
1057
1121
|
this.hooks.setProduct(originProduct, {
|
|
1058
|
-
|
|
1059
|
-
|
|
1122
|
+
// 商品券只替换被拆出的 splitCount 件。余量行原本仍有效的折扣卡
|
|
1123
|
+
// 不能随 good_pass 拆分一起清除;已取消或已失效的折扣不会进入此列表。
|
|
1124
|
+
discount_list: remainderDiscountList,
|
|
1125
|
+
quantity: remainingQuantity,
|
|
1060
1126
|
_id: product._id.split("___")[0],
|
|
1061
|
-
total
|
|
1127
|
+
total,
|
|
1128
|
+
// 保留余量行当前的折后主价;Order.applyProductDiscountPrices 随后会基于
|
|
1129
|
+
// source_product_price + discount_list 再归一化,避免出现重复折扣。
|
|
1130
|
+
...hasRetainedWalletDiscount ? {
|
|
1131
|
+
main_product_selling_price: product.main_product_selling_price ?? product.price
|
|
1132
|
+
} : {}
|
|
1062
1133
|
})
|
|
1063
1134
|
);
|
|
1064
1135
|
}
|
|
1065
1136
|
for (let i = 0; i < splitCount; i++) {
|
|
1066
|
-
const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[i];
|
|
1137
|
+
const selectedDiscount2 = isNeedSplit ? prioritizedApplicableDiscounts[i] : selectedDiscountCard || applicableDiscounts[i];
|
|
1067
1138
|
usedDiscounts.set(selectedDiscount2.id, true);
|
|
1068
1139
|
if ((selectedDiscount2.tag || selectedDiscount2.type) === "good_pass") {
|
|
1069
1140
|
const currentCount = usedProductIdCounts.get(selectedDiscount2.product_id) || 0;
|
|
@@ -1091,8 +1162,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
1091
1162
|
amount = productAllocation.discountAmount;
|
|
1092
1163
|
productDiscountDifference = productAllocation.difference;
|
|
1093
1164
|
mainProductSellingPrice = Math.max(new import_decimal.default(product.price).minus(amount).toNumber(), 0);
|
|
1094
|
-
} else if (
|
|
1095
|
-
const percent =
|
|
1165
|
+
} else if (resolveReapplyBookingDiscountPercent(originProduct, selectedDiscount2) !== void 0) {
|
|
1166
|
+
const percent = resolveReapplyBookingDiscountPercent(originProduct, selectedDiscount2);
|
|
1096
1167
|
reapplyDiscountPercent = new import_decimal.default(percent).toFixed(2);
|
|
1097
1168
|
mainProductSellingPrice = new import_decimal.default(product.price || 0).mul(new import_decimal.default(100).minus(percent)).div(100).toDecimalPlaces(2).toNumber();
|
|
1098
1169
|
amount = new import_decimal.default(product.price).minus(mainProductSellingPrice).toNumber();
|
|
@@ -1190,7 +1261,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
1190
1261
|
const discountNum = splitCount;
|
|
1191
1262
|
const normalNum = totalQuantity - discountNum;
|
|
1192
1263
|
for (let i = 0; i < discountNum; i++) {
|
|
1193
|
-
const selectedDiscount2 =
|
|
1264
|
+
const selectedDiscount2 = prioritizedApplicableDiscounts[i];
|
|
1194
1265
|
usedDiscounts.set(selectedDiscount2.id, true);
|
|
1195
1266
|
if ((selectedDiscount2.tag || selectedDiscount2.type) === "good_pass") {
|
|
1196
1267
|
const currentCount = usedProductIdCounts.get(selectedDiscount2.product_id) || 0;
|
|
@@ -1267,10 +1338,19 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
1267
1338
|
let targetProductTotal;
|
|
1268
1339
|
let fixedAmountPerItem;
|
|
1269
1340
|
let productDiscountDifference;
|
|
1341
|
+
let reapplyDiscountPercent;
|
|
1270
1342
|
if (isOrderLevel && productAllocation) {
|
|
1271
1343
|
fixedAmountPerItem = productAllocation.discountAmount;
|
|
1272
1344
|
productDiscountDifference = productAllocation.difference;
|
|
1273
1345
|
targetProductTotal = Math.max(new import_decimal.default(productOriginTotal).minus(fixedAmountPerItem).toNumber(), 0);
|
|
1346
|
+
} else if (resolveReapplyBookingDiscountPercent(originProduct, selectedDiscount2) !== void 0) {
|
|
1347
|
+
const percent = resolveReapplyBookingDiscountPercent(
|
|
1348
|
+
originProduct,
|
|
1349
|
+
selectedDiscount2
|
|
1350
|
+
);
|
|
1351
|
+
reapplyDiscountPercent = new import_decimal.default(percent).toFixed(2);
|
|
1352
|
+
targetProductTotal = new import_decimal.default(productOriginTotal).mul(new import_decimal.default(100).minus(percent)).div(100).toDecimalPlaces(2).toNumber();
|
|
1353
|
+
fixedAmountPerItem = new import_decimal.default(productOriginTotal).minus(targetProductTotal).toNumber();
|
|
1274
1354
|
} else {
|
|
1275
1355
|
targetProductTotal = (0, import_utils.getDiscountAmount)(
|
|
1276
1356
|
selectedDiscount2,
|
|
@@ -1292,7 +1372,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
1292
1372
|
title: selectedDiscount2.format_title,
|
|
1293
1373
|
original_amount: product.original_price,
|
|
1294
1374
|
product_id: product.id || product.product_id,
|
|
1295
|
-
percent: selectedDiscount2.par_value,
|
|
1375
|
+
percent: reapplyDiscountPercent ?? selectedDiscount2.par_value,
|
|
1296
1376
|
discount_product_id: selectedDiscount2.product_id
|
|
1297
1377
|
},
|
|
1298
1378
|
metadata: {
|
|
@@ -99,7 +99,11 @@ function getUnitOriginalTotal(product) {
|
|
|
99
99
|
function isGeneratedVoucherProduct(product) {
|
|
100
100
|
const record = product;
|
|
101
101
|
const metadata = (record == null ? void 0 : record.metadata) || {};
|
|
102
|
-
|
|
102
|
+
const isGeneratedChild = metadata.parent_order_detail_id !== void 0 || metadata.gift_card_type !== void 0;
|
|
103
|
+
if (isGeneratedChild)
|
|
104
|
+
return true;
|
|
105
|
+
const isPersisted = (record == null ? void 0 : record.order_detail_id) !== void 0 && (record == null ? void 0 : record.order_detail_id) !== null;
|
|
106
|
+
return (record == null ? void 0 : record.extension_type) === "product_voucher" && !isPersisted;
|
|
103
107
|
}
|
|
104
108
|
function buildSurchargeServiceItems(products) {
|
|
105
109
|
return products.map((product) => {
|
package/lib/server/index.d.ts
CHANGED
|
@@ -164,6 +164,12 @@ declare class Server {
|
|
|
164
164
|
* 不影响当前界面展示,适用于切回前台、定时刷新等场景
|
|
165
165
|
*/
|
|
166
166
|
refreshOrdersInBackground(): Promise<void>;
|
|
167
|
+
/**
|
|
168
|
+
* 编辑正式订单时强制查询 Server 最新快照并覆盖本地缓存。
|
|
169
|
+
* 商品成员增删由 OrderModule 在 SQLite/Store 更新完成后广播,
|
|
170
|
+
* UI 可复用 order:onRemoteProductMembershipChanged 处理冲突。
|
|
171
|
+
*/
|
|
172
|
+
checkRemoteOrderProductMembership(orderId: string | number): Promise<void>;
|
|
167
173
|
/**
|
|
168
174
|
* 清空所有server模块的IndexedDB缓存
|
|
169
175
|
* @returns Promise<void>
|
package/lib/server/index.js
CHANGED
|
@@ -1789,6 +1789,57 @@ var Server = class {
|
|
|
1789
1789
|
});
|
|
1790
1790
|
}
|
|
1791
1791
|
}
|
|
1792
|
+
/**
|
|
1793
|
+
* 编辑正式订单时强制查询 Server 最新快照并覆盖本地缓存。
|
|
1794
|
+
* 商品成员增删由 OrderModule 在 SQLite/Store 更新完成后广播,
|
|
1795
|
+
* UI 可复用 order:onRemoteProductMembershipChanged 处理冲突。
|
|
1796
|
+
*/
|
|
1797
|
+
async checkRemoteOrderProductMembership(orderId) {
|
|
1798
|
+
const normalizedOrderId = String(orderId ?? "").trim();
|
|
1799
|
+
if (!normalizedOrderId || normalizedOrderId.startsWith("local_order")) {
|
|
1800
|
+
this.logInfo("checkRemoteOrderProductMembership: 跳过非正式订单", {
|
|
1801
|
+
orderId
|
|
1802
|
+
});
|
|
1803
|
+
return;
|
|
1804
|
+
}
|
|
1805
|
+
if (!this.order) {
|
|
1806
|
+
const error = new Error("Order 模块未注册");
|
|
1807
|
+
this.logWarning("checkRemoteOrderProductMembership: Order 模块未注册", {
|
|
1808
|
+
orderId: normalizedOrderId
|
|
1809
|
+
});
|
|
1810
|
+
throw error;
|
|
1811
|
+
}
|
|
1812
|
+
this.logInfo("checkRemoteOrderProductMembership 开始", {
|
|
1813
|
+
orderId: normalizedOrderId
|
|
1814
|
+
});
|
|
1815
|
+
const startTime = Date.now();
|
|
1816
|
+
try {
|
|
1817
|
+
const freshOrders = await this.order.fetchOrdersByHttp([
|
|
1818
|
+
normalizedOrderId
|
|
1819
|
+
]);
|
|
1820
|
+
const freshOrder = freshOrders.find(
|
|
1821
|
+
(order) => String(order == null ? void 0 : order.order_id) === normalizedOrderId
|
|
1822
|
+
);
|
|
1823
|
+
if (!freshOrder) {
|
|
1824
|
+
throw new Error("Server 未返回目标订单最新快照");
|
|
1825
|
+
}
|
|
1826
|
+
await this.order.upsertOrdersFromRemote(
|
|
1827
|
+
[freshOrder],
|
|
1828
|
+
"manual.editOpenRemoteCheck"
|
|
1829
|
+
);
|
|
1830
|
+
this.logInfo("checkRemoteOrderProductMembership 完成", {
|
|
1831
|
+
orderId: normalizedOrderId,
|
|
1832
|
+
duration: `${Date.now() - startTime}ms`
|
|
1833
|
+
});
|
|
1834
|
+
} catch (error) {
|
|
1835
|
+
this.logError("checkRemoteOrderProductMembership 失败", {
|
|
1836
|
+
orderId: normalizedOrderId,
|
|
1837
|
+
duration: `${Date.now() - startTime}ms`,
|
|
1838
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1839
|
+
});
|
|
1840
|
+
throw error;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1792
1843
|
/**
|
|
1793
1844
|
* 清空所有server模块的IndexedDB缓存
|
|
1794
1845
|
* @returns Promise<void>
|
|
@@ -235,6 +235,7 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
235
235
|
*/
|
|
236
236
|
private lookupOrderIndexByIdentityKeys;
|
|
237
237
|
private isRemoteEchoMergeSource;
|
|
238
|
+
private isRemoteProductMembershipChangeSource;
|
|
238
239
|
private getProductMembershipKey;
|
|
239
240
|
private doProductsHaveStableMembershipIdentity;
|
|
240
241
|
/**
|
|
@@ -920,10 +920,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
920
920
|
*/
|
|
921
921
|
async upsertOrdersFromRemote(freshOrders, source = "upsertOrdersFromRemote") {
|
|
922
922
|
if (!(freshOrders == null ? void 0 : freshOrders.length)) {
|
|
923
|
-
this.logInfo("upsertOrdersFromRemote-订单列表为空", {});
|
|
923
|
+
this.logInfo("upsertOrdersFromRemote-订单列表为空", { source });
|
|
924
924
|
return;
|
|
925
925
|
}
|
|
926
|
-
this.logInfo("upsertOrdersFromRemote-开始", {
|
|
926
|
+
this.logInfo("upsertOrdersFromRemote-开始", {
|
|
927
|
+
count: freshOrders.length,
|
|
928
|
+
source
|
|
929
|
+
});
|
|
927
930
|
await this.mergeOrdersToStore(freshOrders, source);
|
|
928
931
|
}
|
|
929
932
|
async markOrderSyncedByExternalSaleNumber(params) {
|
|
@@ -1685,6 +1688,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1685
1688
|
isRemoteEchoMergeSource(source) {
|
|
1686
1689
|
return source === "pubsub.bodyUpsert" || source === "pubsub.httpRefresh";
|
|
1687
1690
|
}
|
|
1691
|
+
isRemoteProductMembershipChangeSource(source) {
|
|
1692
|
+
return this.isRemoteEchoMergeSource(source) || source === "manual.editOpenRemoteCheck";
|
|
1693
|
+
}
|
|
1688
1694
|
getProductMembershipKey(product) {
|
|
1689
1695
|
const persistentId = (0, import_orderCollectionIdentity.getOrderCollectionPersistentId)("product", product);
|
|
1690
1696
|
if (persistentId)
|
|
@@ -1717,7 +1723,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1717
1723
|
* 对比合并前后的商品成员集合。商品字段修改与数组重排不会产生 diff。
|
|
1718
1724
|
*/
|
|
1719
1725
|
getRemoteProductMembershipChange(existingOrder, mergedOrder, source) {
|
|
1720
|
-
if (!this.
|
|
1726
|
+
if (!this.isRemoteProductMembershipChangeSource(source))
|
|
1721
1727
|
return null;
|
|
1722
1728
|
const previousProducts = Array.isArray(existingOrder.products) ? existingOrder.products : [];
|
|
1723
1729
|
const currentProducts = Array.isArray(mergedOrder.products) ? mergedOrder.products : [];
|
|
@@ -568,7 +568,7 @@ export interface OrderChangedPayload {
|
|
|
568
568
|
/** 触发来源,便于订阅者区分 pubsub / 远端覆盖 / 清空等场景 */
|
|
569
569
|
source?: string;
|
|
570
570
|
}
|
|
571
|
-
export type RemoteProductMembershipChangeSource = 'pubsub.bodyUpsert' | 'pubsub.httpRefresh';
|
|
571
|
+
export type RemoteProductMembershipChangeSource = 'pubsub.bodyUpsert' | 'pubsub.httpRefresh' | 'manual.editOpenRemoteCheck';
|
|
572
572
|
/**
|
|
573
573
|
* 远端订单快照相对本地订单产生商品成员增删时的广播载荷。
|
|
574
574
|
* 只表达商品行成员关系变化,不包含数量、价格、备注等字段级修改。
|