@pisell/pisellos 2.3.18 → 2.3.19
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/modules/Order/index.d.ts +3 -1
- package/dist/modules/Order/index.js +19 -7
- package/dist/modules/Order/types.d.ts +13 -0
- package/dist/modules/Product/index.d.ts +1 -1
- package/dist/modules/Rules/index.d.ts +2 -8
- package/dist/modules/Rules/index.js +55 -9
- package/dist/modules/Rules/types.d.ts +10 -1
- package/dist/server/modules/order/index.js +1 -2
- package/dist/solution/BaseSales/index.d.ts +6 -0
- package/dist/solution/BaseSales/index.js +772 -651
- package/dist/solution/BookingTicket/index.d.ts +13 -1
- package/lib/modules/Order/index.d.ts +3 -1
- package/lib/modules/Order/index.js +21 -9
- package/lib/modules/Order/types.d.ts +13 -0
- package/lib/modules/Product/index.d.ts +1 -1
- package/lib/modules/Rules/index.d.ts +2 -8
- package/lib/modules/Rules/index.js +57 -6
- package/lib/modules/Rules/types.d.ts +10 -1
- package/lib/server/modules/order/index.js +1 -2
- package/lib/solution/BaseSales/index.d.ts +6 -0
- package/lib/solution/BaseSales/index.js +96 -24
- package/lib/solution/BookingTicket/index.d.ts +13 -1
- package/package.json +1 -1
|
@@ -441,7 +441,19 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
441
441
|
* 加车两阶段主决策(规格弹窗 / 资源编辑 / 直接加车)。
|
|
442
442
|
* 与 ticketBooking `handleSelectProduct` + `handleBooking4Service` 等价。
|
|
443
443
|
*/
|
|
444
|
-
decideAddProduct(item: any, options?: Partial<AddProductDecideContext>):
|
|
444
|
+
decideAddProduct(item: any, options?: Partial<AddProductDecideContext>): {
|
|
445
|
+
action: "reloadCatalog";
|
|
446
|
+
} | {
|
|
447
|
+
action: "add";
|
|
448
|
+
cacheItem: any;
|
|
449
|
+
} | {
|
|
450
|
+
action: "requiresDetail";
|
|
451
|
+
payload: AddProductRequiresDetailPayload;
|
|
452
|
+
} | {
|
|
453
|
+
action: "requiresBookingEdit";
|
|
454
|
+
cacheItem: any;
|
|
455
|
+
payload: import("./utils/addProductDecision").AddProductRequiresBookingEditPayload;
|
|
456
|
+
};
|
|
445
457
|
/** 规格弹窗 callback 后的第二段决策。 */
|
|
446
458
|
decideAfterDetail(cacheItem: any, options?: Partial<AddProductDecideContext>): import("./utils/addProductDecision").AddProductDecision;
|
|
447
459
|
/**
|
|
@@ -84,7 +84,9 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
84
84
|
unavailableReasonKey?: string | null;
|
|
85
85
|
scannedDiscountList?: Discount[];
|
|
86
86
|
}>;
|
|
87
|
-
applyDiscount(
|
|
87
|
+
applyDiscount(options?: {
|
|
88
|
+
reapplyBookingDiscountProductUids?: string[];
|
|
89
|
+
}): void;
|
|
88
90
|
/**
|
|
89
91
|
* 注入促销评估器。
|
|
90
92
|
*
|
|
@@ -107,7 +107,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
107
107
|
this.draftPersistEnabled = true;
|
|
108
108
|
}
|
|
109
109
|
collectHydratedEditDiscounts(products) {
|
|
110
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
110
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
111
111
|
const discountMap = /* @__PURE__ */ new Map();
|
|
112
112
|
for (const product of (0, import_bundleDiscountHydration.expandHydratedProductsForDiscountCollection)(products)) {
|
|
113
113
|
for (const item of (product == null ? void 0 : product.discount_list) || []) {
|
|
@@ -137,6 +137,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
137
137
|
existed.amount = Number(existed.amount || 0) + amount;
|
|
138
138
|
existed.used_par_value = String(Number(existed.used_par_value || 0) + amount);
|
|
139
139
|
existed.balance = String(Number(existed.balance || 0) + amount);
|
|
140
|
+
const productIds = Array.isArray((_f = existed.limited_relation_product_data) == null ? void 0 : _f.product_ids) ? existed.limited_relation_product_data.product_ids : [];
|
|
141
|
+
if ((product == null ? void 0 : product.product_id) !== void 0 && (product == null ? void 0 : product.product_id) !== null && !productIds.includes(product.product_id)) {
|
|
142
|
+
existed.limited_relation_product_data = {
|
|
143
|
+
...existed.limited_relation_product_data || {},
|
|
144
|
+
product_ids: [...productIds, product.product_id]
|
|
145
|
+
};
|
|
146
|
+
}
|
|
140
147
|
existed.applicableProductDetails = [
|
|
141
148
|
...existed.applicableProductDetails || [],
|
|
142
149
|
detail
|
|
@@ -153,9 +160,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
153
160
|
encoded: "",
|
|
154
161
|
code: "",
|
|
155
162
|
tag: type,
|
|
156
|
-
product_id: ((
|
|
163
|
+
product_id: ((_g = item == null ? void 0 : item.discount) == null ? void 0 : _g.discount_product_id) ?? (product == null ? void 0 : product.product_id) ?? 0,
|
|
157
164
|
relation_type: "",
|
|
158
|
-
par_value: String(((
|
|
165
|
+
par_value: String(((_h = item == null ? void 0 : item.discount) == null ? void 0 : _h.original_amount) ?? (item == null ? void 0 : item.amount) ?? "0"),
|
|
159
166
|
used_par_value: String((item == null ? void 0 : item.amount) ?? "0"),
|
|
160
167
|
limit_status: "enable",
|
|
161
168
|
limited_relation_product_data: {
|
|
@@ -185,8 +192,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
185
192
|
discount: {
|
|
186
193
|
...(item == null ? void 0 : item.discount) || {},
|
|
187
194
|
resource_id: key,
|
|
188
|
-
discount_product_id: ((
|
|
189
|
-
discount_calculation_mode: ((
|
|
195
|
+
discount_product_id: ((_i = item == null ? void 0 : item.discount) == null ? void 0 : _i.discount_product_id) ?? (product == null ? void 0 : product.product_id) ?? 0,
|
|
196
|
+
discount_calculation_mode: ((_j = item == null ? void 0 : item.discount) == null ? void 0 : _j.discount_calculation_mode) ?? "item_level"
|
|
190
197
|
},
|
|
191
198
|
applicableProductDetails: [detail],
|
|
192
199
|
appliedProductDetails: [detail]
|
|
@@ -539,7 +546,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
539
546
|
unavailableReason
|
|
540
547
|
};
|
|
541
548
|
}
|
|
542
|
-
applyDiscount() {
|
|
549
|
+
applyDiscount(options) {
|
|
543
550
|
var _a, _b, _c, _d;
|
|
544
551
|
const tempOrder = this.store.tempOrder;
|
|
545
552
|
if (!tempOrder)
|
|
@@ -560,6 +567,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
560
567
|
holders,
|
|
561
568
|
isFormSubject: (product) => (0, import_utils.resolveIsFormSubject)(tempOrder, product),
|
|
562
569
|
orderTotalAmount: Number(((_c = this.store.summary) == null ? void 0 : _c.total_amount) || 0)
|
|
570
|
+
}, {
|
|
571
|
+
reapplyBookingDiscountProductUids: options == null ? void 0 : options.reapplyBookingDiscountProductUids
|
|
563
572
|
});
|
|
564
573
|
if (result == null ? void 0 : result.productList) {
|
|
565
574
|
const previousProductsByUid = (0, import_utils.indexOrderProductsByUid)(tempOrder.products);
|
|
@@ -2974,7 +2983,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
2974
2983
|
});
|
|
2975
2984
|
}
|
|
2976
2985
|
applyOrderProductUpdateToTempOrder(tempOrder, params) {
|
|
2977
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
|
|
2986
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
2978
2987
|
const {
|
|
2979
2988
|
product_id,
|
|
2980
2989
|
product_variant_id,
|
|
@@ -3128,12 +3137,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
3128
3137
|
tempOrder.products[productIndex],
|
|
3129
3138
|
(_q = tempOrder.products[productIndex].metadata) == null ? void 0 : _q.unique_identification_number
|
|
3130
3139
|
);
|
|
3140
|
+
return (_r = tempOrder.products[productIndex].metadata) == null ? void 0 : _r.unique_identification_number;
|
|
3131
3141
|
}
|
|
3132
3142
|
async updateOrderProduct(params) {
|
|
3133
3143
|
const tempOrder = this.ensureTempOrder();
|
|
3134
|
-
this.applyOrderProductUpdateToTempOrder(tempOrder, params);
|
|
3144
|
+
const updatedProductUid = this.applyOrderProductUpdateToTempOrder(tempOrder, params);
|
|
3135
3145
|
await this.applyPromotion();
|
|
3136
|
-
this.applyDiscount(
|
|
3146
|
+
this.applyDiscount({
|
|
3147
|
+
reapplyBookingDiscountProductUids: params.allow_booking_discount_reapply && updatedProductUid ? [String(updatedProductUid)] : void 0
|
|
3148
|
+
});
|
|
3137
3149
|
this.sanitizeTempOrderProducts(tempOrder);
|
|
3138
3150
|
await this.recalculateSummary({ createIfMissing: true });
|
|
3139
3151
|
this.persistTempOrder();
|
|
@@ -340,6 +340,19 @@ export interface UpdateOrderProductParams {
|
|
|
340
340
|
* });
|
|
341
341
|
*/
|
|
342
342
|
allow_booking_reprice?: boolean;
|
|
343
|
+
/**
|
|
344
|
+
* Change time 重报价后,允许当前预约商品行重新应用已选编辑态折扣卡。
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* await order.updateOrderProduct({
|
|
348
|
+
* product_id: 1,
|
|
349
|
+
* product_variant_id: 0,
|
|
350
|
+
* updates: { discount_list: [] },
|
|
351
|
+
* booking: { duration: 2 },
|
|
352
|
+
* allow_booking_discount_reapply: true,
|
|
353
|
+
* });
|
|
354
|
+
*/
|
|
355
|
+
allow_booking_discount_reapply?: boolean;
|
|
343
356
|
}
|
|
344
357
|
/** 仅更新购物车行数量;行定位语义与 updateOrderProduct / removeProductFromOrder 保持一致 */
|
|
345
358
|
export interface UpdateOrderProductQuantityParams extends OrderProductIdentity {
|
|
@@ -49,5 +49,5 @@ export declare class Product extends BaseModule implements Module {
|
|
|
49
49
|
getCategories(): ProductCategory[];
|
|
50
50
|
setOtherParams(key: string, value: any): void;
|
|
51
51
|
getOtherParams(): any;
|
|
52
|
-
getProductType(): "
|
|
52
|
+
getProductType(): "normal" | "duration" | "session";
|
|
53
53
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Module, PisellCore, ModuleOptions } from '../../types';
|
|
2
2
|
import { BaseModule } from '../BaseModule';
|
|
3
|
-
import { Rules, RulesModuleAPI, DiscountResult, RulesFormSubject, UnavailableReason } from './types';
|
|
3
|
+
import { Rules, RulesModuleAPI, DiscountResult, RulesFormSubject, RulesCalcDiscountOptions, UnavailableReason } from './types';
|
|
4
4
|
import { Discount } from '../Discount/types';
|
|
5
|
-
import { SetDiscountSelectedParams } from '../../solution/ShopDiscount/types';
|
|
6
5
|
import { WindowPlugin } from '../../plugins';
|
|
7
6
|
export declare class RulesModule extends BaseModule implements Module, RulesModuleAPI {
|
|
8
7
|
protected defaultName: string;
|
|
@@ -45,12 +44,7 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
|
|
|
45
44
|
}[];
|
|
46
45
|
isFormSubject: RulesFormSubject;
|
|
47
46
|
orderTotalAmount: number;
|
|
48
|
-
}, options?:
|
|
49
|
-
isSelected?: boolean;
|
|
50
|
-
discountId?: number;
|
|
51
|
-
selectedList?: SetDiscountSelectedParams[];
|
|
52
|
-
scan?: boolean;
|
|
53
|
-
}): DiscountResult;
|
|
47
|
+
}, options?: RulesCalcDiscountOptions): DiscountResult;
|
|
54
48
|
/**
|
|
55
49
|
* 检查优惠是否符合 PackageSubItemUsageRules 配置
|
|
56
50
|
* @param discount 优惠券
|
|
@@ -209,6 +209,36 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
209
209
|
var _a;
|
|
210
210
|
const resolveIsFormSubject = (product) => typeof isFormSubject === "function" ? Boolean(isFormSubject(product)) : Boolean(isFormSubject);
|
|
211
211
|
const isEditModeAddNewProduct = productList.find((n) => n.booking_id) && productList.find((n) => !n.booking_id);
|
|
212
|
+
const reapplyBookingDiscountProductUids = new Set(
|
|
213
|
+
((options == null ? void 0 : options.reapplyBookingDiscountProductUids) || []).filter((uid) => uid !== void 0 && uid !== null && uid !== "").map(String)
|
|
214
|
+
);
|
|
215
|
+
const getOriginProductUid = (originProduct) => {
|
|
216
|
+
var _a2;
|
|
217
|
+
const uid = ((_a2 = originProduct == null ? void 0 : originProduct.metadata) == null ? void 0 : _a2.unique_identification_number) ?? (originProduct == null ? void 0 : originProduct.unique_identification_number);
|
|
218
|
+
if (uid === void 0 || uid === null || uid === "")
|
|
219
|
+
return void 0;
|
|
220
|
+
return String(uid);
|
|
221
|
+
};
|
|
222
|
+
const shouldReapplyBookingDiscount = (originProduct, selectedDiscount) => {
|
|
223
|
+
if (!selectedDiscount)
|
|
224
|
+
return false;
|
|
225
|
+
const uid = getOriginProductUid(originProduct);
|
|
226
|
+
if (!uid || !reapplyBookingDiscountProductUids.has(uid))
|
|
227
|
+
return false;
|
|
228
|
+
const discountType = selectedDiscount.tag || selectedDiscount.type;
|
|
229
|
+
return selectedDiscount.isEditMode === true && selectedDiscount.isSelected === true && ["good_pass", "discount_card", "product_discount_card"].includes(discountType);
|
|
230
|
+
};
|
|
231
|
+
const resolveReapplyEditModeDiscountPercent = (originProduct, selectedDiscount) => {
|
|
232
|
+
var _a2;
|
|
233
|
+
if (!shouldReapplyBookingDiscount(originProduct, selectedDiscount))
|
|
234
|
+
return void 0;
|
|
235
|
+
const discountType = (selectedDiscount == null ? void 0 : selectedDiscount.tag) || (selectedDiscount == null ? void 0 : selectedDiscount.type);
|
|
236
|
+
if (discountType !== "discount_card" && discountType !== "product_discount_card") {
|
|
237
|
+
return void 0;
|
|
238
|
+
}
|
|
239
|
+
const percent = Number((_a2 = selectedDiscount.discount) == null ? void 0 : _a2.percent);
|
|
240
|
+
return Number.isFinite(percent) ? percent : void 0;
|
|
241
|
+
};
|
|
212
242
|
const editModeDiscount = [];
|
|
213
243
|
const addModeDiscount = [];
|
|
214
244
|
discountList.forEach((discount) => {
|
|
@@ -232,9 +262,6 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
232
262
|
}
|
|
233
263
|
});
|
|
234
264
|
}
|
|
235
|
-
const filteredDiscountList = addModeDiscount.filter((discount) => {
|
|
236
|
-
return !discount.isManualSelect;
|
|
237
|
-
});
|
|
238
265
|
const hasDiscountInput = editModeDiscount.length > 0 || addModeDiscount.length > 0 || Boolean(options == null ? void 0 : options.discountId) || Boolean((_a = options == null ? void 0 : options.selectedList) == null ? void 0 : _a.length) || Boolean(options == null ? void 0 : options.scan);
|
|
239
266
|
if (!hasDiscountInput) {
|
|
240
267
|
return {
|
|
@@ -242,6 +269,14 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
242
269
|
productList
|
|
243
270
|
};
|
|
244
271
|
}
|
|
272
|
+
const canUseEditModeDiscountForReapply = (discount) => {
|
|
273
|
+
const discountType = discount.tag || discount.type;
|
|
274
|
+
return reapplyBookingDiscountProductUids.size > 0 && discount.isEditMode === true && discount.isSelected === true && ["good_pass", "discount_card", "product_discount_card"].includes(discountType);
|
|
275
|
+
};
|
|
276
|
+
const filteredDiscountList = [
|
|
277
|
+
...addModeDiscount.filter((discount) => !discount.isManualSelect),
|
|
278
|
+
...editModeDiscount.filter(canUseEditModeDiscountForReapply)
|
|
279
|
+
];
|
|
245
280
|
const flattenProductsWithBundle = (productList2) => {
|
|
246
281
|
const flattened = [];
|
|
247
282
|
productList2.forEach((originProduct) => {
|
|
@@ -737,9 +772,18 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
737
772
|
const applicableDiscounts = sortedDiscountList.filter((discount) => {
|
|
738
773
|
var _a3, _b2, _c2, _d2;
|
|
739
774
|
const discountType = discount.tag || discount.type;
|
|
775
|
+
const currentOriginUid = getOriginProductUid(originProduct);
|
|
776
|
+
const isReapplyEditModeDiscountForProduct = discount.isEditMode && reapplyBookingDiscountProductUids.size > 0 && currentOriginUid && reapplyBookingDiscountProductUids.has(String(currentOriginUid)) && discount.isSelected === true;
|
|
777
|
+
if (discount.isEditMode && reapplyBookingDiscountProductUids.size > 0) {
|
|
778
|
+
const uid = currentOriginUid;
|
|
779
|
+
if (!uid || !reapplyBookingDiscountProductUids.has(uid))
|
|
780
|
+
return false;
|
|
781
|
+
if (!discount.isSelected)
|
|
782
|
+
return false;
|
|
783
|
+
}
|
|
740
784
|
if (["good_pass", "discount_card", "product_discount_card"].includes(
|
|
741
785
|
discountType
|
|
742
|
-
)) {
|
|
786
|
+
) && !isReapplyEditModeDiscountForProduct) {
|
|
743
787
|
if (discount.config === void 0 || !((_a3 = discount == null ? void 0 : discount.config) == null ? void 0 : _a3.isAvailable)) {
|
|
744
788
|
return false;
|
|
745
789
|
}
|
|
@@ -955,7 +999,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
955
999
|
}
|
|
956
1000
|
return;
|
|
957
1001
|
}
|
|
958
|
-
|
|
1002
|
+
const shouldReapplyBookingDiscountForProduct = shouldReapplyBookingDiscount(originProduct, selectedDiscount);
|
|
1003
|
+
if (applicableDiscounts.length && product.booking_id && typeof selectedDiscount.isManualSelect === "undefined" && !(options == null ? void 0 : options.scan) && !isEditModeAddNewProduct && !shouldReapplyBookingDiscountForProduct) {
|
|
959
1004
|
return;
|
|
960
1005
|
}
|
|
961
1006
|
const isNeedSplit = (selectedDiscount.tag || selectedDiscount.type) === "good_pass";
|
|
@@ -1011,10 +1056,16 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
1011
1056
|
let productDiscountDifference;
|
|
1012
1057
|
let discountedOptions = product.options;
|
|
1013
1058
|
let optionDiscountAmount = 0;
|
|
1059
|
+
let reapplyDiscountPercent;
|
|
1014
1060
|
if (isOrderLevel && productAllocation) {
|
|
1015
1061
|
amount = productAllocation.discountAmount;
|
|
1016
1062
|
productDiscountDifference = productAllocation.difference;
|
|
1017
1063
|
mainProductSellingPrice = Math.max(new import_decimal.default(product.price).minus(amount).toNumber(), 0);
|
|
1064
|
+
} else if (resolveReapplyEditModeDiscountPercent(originProduct, selectedDiscount2) !== void 0) {
|
|
1065
|
+
const percent = resolveReapplyEditModeDiscountPercent(originProduct, selectedDiscount2);
|
|
1066
|
+
reapplyDiscountPercent = new import_decimal.default(percent).toFixed(2);
|
|
1067
|
+
mainProductSellingPrice = new import_decimal.default(product.price || 0).mul(new import_decimal.default(100).minus(percent)).div(100).toDecimalPlaces(2).toNumber();
|
|
1068
|
+
amount = new import_decimal.default(product.price).minus(mainProductSellingPrice).toNumber();
|
|
1018
1069
|
} else {
|
|
1019
1070
|
mainProductSellingPrice = (0, import_utils.getDiscountAmount)(
|
|
1020
1071
|
selectedDiscount2,
|
|
@@ -1049,7 +1100,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
|
|
|
1049
1100
|
title: selectedDiscount2.format_title,
|
|
1050
1101
|
original_amount: product.price,
|
|
1051
1102
|
product_id: originProduct.id || originProduct.product_id,
|
|
1052
|
-
percent: selectedDiscount2.par_value,
|
|
1103
|
+
percent: reapplyDiscountPercent ?? selectedDiscount2.par_value,
|
|
1053
1104
|
discount_product_id: selectedDiscount2.product_id
|
|
1054
1105
|
},
|
|
1055
1106
|
// 前端使用的num数量,为了计算优惠金额
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Discount } from '../Discount/types';
|
|
2
|
+
import { SetDiscountSelectedParams } from '../../solution/ShopDiscount/types';
|
|
2
3
|
export declare enum UnavailableReason {
|
|
3
4
|
TimeLimit = "time_limit",
|
|
4
5
|
ProductNotApplicable = "product_not_applicable",
|
|
@@ -23,6 +24,14 @@ export interface DiscountResult {
|
|
|
23
24
|
discountList: any[];
|
|
24
25
|
}
|
|
25
26
|
export type RulesFormSubject = boolean | ((product: any) => boolean);
|
|
27
|
+
export interface RulesCalcDiscountOptions {
|
|
28
|
+
isSelected?: boolean;
|
|
29
|
+
discountId?: number;
|
|
30
|
+
selectedList?: SetDiscountSelectedParams[];
|
|
31
|
+
scan?: boolean;
|
|
32
|
+
/** Change time 重报价目标行:允许已选编辑态折扣卡重新应用到这些 booking 商品。 */
|
|
33
|
+
reapplyBookingDiscountProductUids?: string[];
|
|
34
|
+
}
|
|
26
35
|
export interface RulesModuleAPI {
|
|
27
36
|
setRulesList: (rulesList: Rules[]) => Promise<void>;
|
|
28
37
|
clear: () => Promise<void>;
|
|
@@ -34,7 +43,7 @@ export interface RulesModuleAPI {
|
|
|
34
43
|
}[];
|
|
35
44
|
isFormSubject: RulesFormSubject;
|
|
36
45
|
orderTotalAmount: number;
|
|
37
|
-
}) => DiscountResult;
|
|
46
|
+
}, options?: RulesCalcDiscountOptions) => DiscountResult;
|
|
38
47
|
}
|
|
39
48
|
type ProductDetail = {
|
|
40
49
|
isClient?: boolean;
|
|
@@ -308,12 +308,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
308
308
|
};
|
|
309
309
|
}
|
|
310
310
|
updateCreateStore() {
|
|
311
|
-
var _a;
|
|
312
311
|
const appPlugin = this.core.getPlugin("app");
|
|
313
312
|
const app = appPlugin == null ? void 0 : appPlugin.getApp();
|
|
314
313
|
if (app) {
|
|
315
314
|
const coreData = app.data.store.getStore().getDataByModel("core");
|
|
316
|
-
if (
|
|
315
|
+
if (coreData == null ? void 0 : coreData.core) {
|
|
317
316
|
const today = (0, import_dayjs.default)();
|
|
318
317
|
if (coreData == null ? void 0 : coreData.core.operating_day_boundary) {
|
|
319
318
|
const operatingDayBoundary = coreData.core.operating_day_boundary;
|
|
@@ -49,6 +49,9 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
49
49
|
private queuedAutoPaymentSync;
|
|
50
50
|
private autoPaymentSyncFlushing;
|
|
51
51
|
private autoPaymentSyncTimer;
|
|
52
|
+
private salesDetailLoadInFlight;
|
|
53
|
+
private serverOrderChangeUnsubscribe;
|
|
54
|
+
private serverOrderChangeHydrateInFlight;
|
|
52
55
|
constructor(name?: string, version?: string);
|
|
53
56
|
/**
|
|
54
57
|
* 子类可覆盖此方法以追加/收敛要注册的子模块。
|
|
@@ -69,6 +72,9 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
69
72
|
* 记录错误日志
|
|
70
73
|
*/
|
|
71
74
|
private logError;
|
|
75
|
+
private isCurrentSalesOrderRecord;
|
|
76
|
+
private syncCurrentSalesDetailFromServerOrderChange;
|
|
77
|
+
private registerServerOrderChangeSync;
|
|
72
78
|
private hydrateOrderPaymentNames;
|
|
73
79
|
get payment(): PaymentModule | undefined;
|
|
74
80
|
private getCurrentOrderCustomerId;
|
|
@@ -45,6 +45,7 @@ __reExport(BaseSales_exports, require("./types"), module.exports);
|
|
|
45
45
|
var import_Quotation = require("../../modules/Quotation");
|
|
46
46
|
var import_transformBaseProductToOrderProduct = require("./utils/transformBaseProductToOrderProduct");
|
|
47
47
|
var import_quotationPrice = require("./utils/quotationPrice");
|
|
48
|
+
var SERVER_ORDER_CHANGED_EVENT = "order:onOrdersChanged";
|
|
48
49
|
function isBaseSalesManualProductDiscountProduct(product) {
|
|
49
50
|
var _a, _b;
|
|
50
51
|
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");
|
|
@@ -82,6 +83,18 @@ function getBaseSalesUniqueArrayMetadataKey(key) {
|
|
|
82
83
|
return "unique_payment_number";
|
|
83
84
|
return null;
|
|
84
85
|
}
|
|
86
|
+
function isSameBaseSalesOrderRecord(left, right) {
|
|
87
|
+
if (!left || !right || typeof left !== "object" || typeof right !== "object")
|
|
88
|
+
return false;
|
|
89
|
+
const leftIdentities = new Set(
|
|
90
|
+
[left.order_id, left.id, left.external_sale_number, left.order_number].filter((value) => value !== void 0 && value !== null && value !== "").map(String)
|
|
91
|
+
);
|
|
92
|
+
if (leftIdentities.size === 0)
|
|
93
|
+
return false;
|
|
94
|
+
return [right.order_id, right.id, right.external_sale_number, right.order_number].some(
|
|
95
|
+
(value) => value !== void 0 && value !== null && value !== "" && leftIdentities.has(String(value))
|
|
96
|
+
);
|
|
97
|
+
}
|
|
85
98
|
function getBaseSalesMetadataUid(item, metadataKey) {
|
|
86
99
|
var _a;
|
|
87
100
|
const uid = ((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a[metadataKey]) ?? (item == null ? void 0 : item[metadataKey]);
|
|
@@ -159,6 +172,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
159
172
|
this.queuedAutoPaymentSync = false;
|
|
160
173
|
this.autoPaymentSyncFlushing = false;
|
|
161
174
|
this.autoPaymentSyncTimer = null;
|
|
175
|
+
this.salesDetailLoadInFlight = false;
|
|
176
|
+
this.serverOrderChangeUnsubscribe = null;
|
|
177
|
+
this.serverOrderChangeHydrateInFlight = null;
|
|
162
178
|
}
|
|
163
179
|
/**
|
|
164
180
|
* 子类可覆盖此方法以追加/收敛要注册的子模块。
|
|
@@ -223,6 +239,53 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
223
239
|
});
|
|
224
240
|
}
|
|
225
241
|
}
|
|
242
|
+
isCurrentSalesOrderRecord(order) {
|
|
243
|
+
var _a, _b;
|
|
244
|
+
const currentTempOrder = (_b = (_a = this.store.order) == null ? void 0 : _a.getTempOrder) == null ? void 0 : _b.call(_a);
|
|
245
|
+
const currentRecords = [
|
|
246
|
+
currentTempOrder,
|
|
247
|
+
this.currentSalesDetail
|
|
248
|
+
].filter(Boolean);
|
|
249
|
+
return currentRecords.some((record) => isSameBaseSalesOrderRecord(record, order));
|
|
250
|
+
}
|
|
251
|
+
async syncCurrentSalesDetailFromServerOrderChange(payload) {
|
|
252
|
+
const changedOrders = Array.isArray(payload) ? payload : Array.isArray(payload == null ? void 0 : payload.changedOrders) ? payload.changedOrders : (payload == null ? void 0 : payload.data) && typeof payload.data === "object" ? [payload.data] : [];
|
|
253
|
+
if (this.salesDetailLoadInFlight || this.serverOrderChangeHydrateInFlight)
|
|
254
|
+
return;
|
|
255
|
+
const changedOrder = changedOrders.find(
|
|
256
|
+
(order) => this.isCurrentSalesOrderRecord(order)
|
|
257
|
+
);
|
|
258
|
+
if (!changedOrder)
|
|
259
|
+
return;
|
|
260
|
+
if (!this.store.order)
|
|
261
|
+
return;
|
|
262
|
+
this.serverOrderChangeHydrateInFlight = (async () => {
|
|
263
|
+
const sales = await this.store.order.hydrateTempOrderFromRecord(changedOrder, {
|
|
264
|
+
recalcOnHydrate: false
|
|
265
|
+
});
|
|
266
|
+
this.currentSalesDetail = sales;
|
|
267
|
+
await this.core.effects.emit(`${this.name}:onSalesOrderLoaded`, { sales });
|
|
268
|
+
})();
|
|
269
|
+
try {
|
|
270
|
+
await this.serverOrderChangeHydrateInFlight;
|
|
271
|
+
} finally {
|
|
272
|
+
this.serverOrderChangeHydrateInFlight = null;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
registerServerOrderChangeSync() {
|
|
276
|
+
var _a, _b;
|
|
277
|
+
(_a = this.serverOrderChangeUnsubscribe) == null ? void 0 : _a.call(this);
|
|
278
|
+
const effects = (_b = this.core) == null ? void 0 : _b.effects;
|
|
279
|
+
if (!effects || typeof effects.on !== "function")
|
|
280
|
+
return;
|
|
281
|
+
this.serverOrderChangeUnsubscribe = effects.on(SERVER_ORDER_CHANGED_EVENT, (payload) => {
|
|
282
|
+
void this.syncCurrentSalesDetailFromServerOrderChange(payload).catch((error) => {
|
|
283
|
+
this.logError("sync sales detail from server order change failed", {
|
|
284
|
+
error: error instanceof Error ? error.message : String(error)
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
}
|
|
226
289
|
hydrateOrderPaymentNames(payments) {
|
|
227
290
|
if (!payments.length)
|
|
228
291
|
return [];
|
|
@@ -637,9 +700,13 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
637
700
|
);
|
|
638
701
|
}
|
|
639
702
|
await this.getPaymentMethodsAsync();
|
|
703
|
+
this.registerServerOrderChangeSync();
|
|
640
704
|
this.core.effects.emit(`${this.name}:onInited`, {});
|
|
641
705
|
}
|
|
642
706
|
async destroy() {
|
|
707
|
+
var _a;
|
|
708
|
+
(_a = this.serverOrderChangeUnsubscribe) == null ? void 0 : _a.call(this);
|
|
709
|
+
this.serverOrderChangeUnsubscribe = null;
|
|
643
710
|
Object.keys(this.store).forEach((key) => {
|
|
644
711
|
if (this.reusedSharedSubModuleNames.has(key))
|
|
645
712
|
return;
|
|
@@ -666,30 +733,35 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
666
733
|
async loadSalesDetail(orderIdOrParams) {
|
|
667
734
|
if (!this.store.order)
|
|
668
735
|
throw new Error("order 模块未初始化");
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
736
|
+
this.salesDetailLoadInFlight = true;
|
|
737
|
+
try {
|
|
738
|
+
const params = typeof orderIdOrParams === "object" ? orderIdOrParams : { orderId: orderIdOrParams };
|
|
739
|
+
const externalSaleNumber = params.externalSaleNumber || params.external_sale_number;
|
|
740
|
+
const preloadedSalesDetail = params.preloadedSalesDetail;
|
|
741
|
+
const lookup = params.orderId ?? externalSaleNumber ?? params.orderNumber ?? (preloadedSalesDetail == null ? void 0 : preloadedSalesDetail.order_id) ?? (preloadedSalesDetail == null ? void 0 : preloadedSalesDetail.external_sale_number) ?? (preloadedSalesDetail == null ? void 0 : preloadedSalesDetail.order_number);
|
|
742
|
+
if (!preloadedSalesDetail && (lookup === void 0 || lookup === null || lookup === "")) {
|
|
743
|
+
throw new Error("加载销售详情需要 orderId、externalSaleNumber 或 orderNumber");
|
|
744
|
+
}
|
|
745
|
+
const loadedRecord = preloadedSalesDetail ?? await this.store.order.getSalesOrderByLookup({
|
|
746
|
+
lookup,
|
|
747
|
+
forceRemote: params.forceRemote
|
|
748
|
+
});
|
|
749
|
+
if (!preloadedSalesDetail && (!loadedRecord || loadedRecord.code !== 200)) {
|
|
750
|
+
const message = loadedRecord && (loadedRecord.message || loadedRecord.msg) || `加载销售详情失败: ${lookup}`;
|
|
751
|
+
throw new Error(message);
|
|
752
|
+
}
|
|
753
|
+
const remoteRecord = preloadedSalesDetail ?? loadedRecord.data;
|
|
754
|
+
const currentTempOrder = params.merge ? this.store.order.getTempOrder() : null;
|
|
755
|
+
const record = params.merge ? mergeSalesDetailRecordWithTempOrder(currentTempOrder, remoteRecord) : remoteRecord;
|
|
756
|
+
const sales = await this.store.order.hydrateTempOrderFromRecord(record, {
|
|
757
|
+
recalcOnHydrate: false
|
|
758
|
+
});
|
|
759
|
+
this.currentSalesDetail = sales;
|
|
760
|
+
await this.core.effects.emit(`${this.name}:onSalesOrderLoaded`, { sales });
|
|
761
|
+
return sales;
|
|
762
|
+
} finally {
|
|
763
|
+
this.salesDetailLoadInFlight = false;
|
|
764
|
+
}
|
|
693
765
|
}
|
|
694
766
|
/** 获取当前已加载的销售详情(只读快照)。未加载过则返回 null。 */
|
|
695
767
|
getSalesOrder() {
|
|
@@ -441,7 +441,19 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
441
441
|
* 加车两阶段主决策(规格弹窗 / 资源编辑 / 直接加车)。
|
|
442
442
|
* 与 ticketBooking `handleSelectProduct` + `handleBooking4Service` 等价。
|
|
443
443
|
*/
|
|
444
|
-
decideAddProduct(item: any, options?: Partial<AddProductDecideContext>):
|
|
444
|
+
decideAddProduct(item: any, options?: Partial<AddProductDecideContext>): {
|
|
445
|
+
action: "reloadCatalog";
|
|
446
|
+
} | {
|
|
447
|
+
action: "add";
|
|
448
|
+
cacheItem: any;
|
|
449
|
+
} | {
|
|
450
|
+
action: "requiresDetail";
|
|
451
|
+
payload: AddProductRequiresDetailPayload;
|
|
452
|
+
} | {
|
|
453
|
+
action: "requiresBookingEdit";
|
|
454
|
+
cacheItem: any;
|
|
455
|
+
payload: import("./utils/addProductDecision").AddProductRequiresBookingEditPayload;
|
|
456
|
+
};
|
|
445
457
|
/** 规格弹窗 callback 后的第二段决策。 */
|
|
446
458
|
decideAfterDetail(cacheItem: any, options?: Partial<AddProductDecideContext>): import("./utils/addProductDecision").AddProductDecision;
|
|
447
459
|
/**
|