@pisell/pisellos 2.2.172 → 2.2.173
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/Order/index.d.ts +6 -21
- package/dist/modules/Order/index.js +56 -103
- package/dist/modules/Order/types.d.ts +3 -2
- package/dist/modules/Order/utils.d.ts +16 -0
- package/dist/modules/Order/utils.js +80 -1
- package/dist/server/modules/products/index.js +111 -93
- package/dist/solution/BaseSales/index.d.ts +4 -16
- package/dist/solution/BaseSales/index.js +172 -102
- package/dist/solution/BaseSales/types.d.ts +14 -0
- package/dist/solution/BaseSales/utils/quotationPrice.js +95 -17
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +10 -2
- package/lib/model/strategy/adapter/promotion/index.js +49 -0
- package/lib/modules/Order/index.d.ts +6 -21
- package/lib/modules/Order/index.js +55 -100
- package/lib/modules/Order/types.d.ts +3 -2
- package/lib/modules/Order/utils.d.ts +16 -0
- package/lib/modules/Order/utils.js +52 -1
- package/lib/server/modules/products/index.js +19 -7
- package/lib/solution/BaseSales/index.d.ts +4 -16
- package/lib/solution/BaseSales/index.js +68 -33
- package/lib/solution/BaseSales/types.d.ts +14 -0
- package/lib/solution/BaseSales/utils/quotationPrice.js +90 -14
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +8 -0
- package/package.json +1 -1
|
@@ -190,14 +190,25 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
190
190
|
this.quotationPriceBridge = quotation;
|
|
191
191
|
}
|
|
192
192
|
if (params.scheduleModule) {
|
|
193
|
+
const scheduleCache = /* @__PURE__ */ new Map();
|
|
194
|
+
let hasLoadedScheduleList = false;
|
|
193
195
|
this.quotationPriceBridge.setScheduleResolver((id) => {
|
|
194
196
|
var _a2, _b, _c, _d, _e, _f;
|
|
195
197
|
const scheduleId = String(id);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (
|
|
199
|
-
|
|
198
|
+
if (scheduleCache.has(scheduleId))
|
|
199
|
+
return scheduleCache.get(scheduleId);
|
|
200
|
+
if (!hasLoadedScheduleList) {
|
|
201
|
+
const scheduleList = ((_b = (_a2 = params.scheduleModule).getScheduleList) == null ? void 0 : _b.call(_a2)) || [];
|
|
202
|
+
for (const schedule of scheduleList) {
|
|
203
|
+
scheduleCache.set(String(schedule.id), schedule);
|
|
204
|
+
}
|
|
205
|
+
hasLoadedScheduleList = true;
|
|
206
|
+
}
|
|
207
|
+
if (scheduleCache.has(scheduleId))
|
|
208
|
+
return scheduleCache.get(scheduleId);
|
|
200
209
|
const schedules = ((_d = (_c = params.scheduleModule).getScheduleListByIds) == null ? void 0 : _d.call(_c, [id])) || ((_f = (_e = params.scheduleModule).getScheduleByIds) == null ? void 0 : _f.call(_e, [id])) || [];
|
|
210
|
+
if (schedules[0])
|
|
211
|
+
scheduleCache.set(scheduleId, schedules[0]);
|
|
201
212
|
return schedules[0];
|
|
202
213
|
});
|
|
203
214
|
}
|
|
@@ -257,10 +268,11 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
257
268
|
customer_id: customerId
|
|
258
269
|
});
|
|
259
270
|
const productPrice = quotedPrice ?? product.price;
|
|
271
|
+
const productBasePrice = quotedPrice ?? product.base_price ?? product.price ?? 0;
|
|
260
272
|
return {
|
|
261
273
|
id: product.id,
|
|
262
274
|
price: String(productPrice ?? 0),
|
|
263
|
-
base_price: String(
|
|
275
|
+
base_price: String(productBasePrice),
|
|
264
276
|
variant: this.buildVariantPriceData(product, datetime, customerId),
|
|
265
277
|
bundle_group: this.buildBundleGroupPriceData(product, datetime, customerId)
|
|
266
278
|
};
|
|
@@ -277,7 +289,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
277
289
|
customer_id: customerId
|
|
278
290
|
});
|
|
279
291
|
const price = quotedPrice ?? variant.price ?? product.price ?? 0;
|
|
280
|
-
const basePrice = variant.base_price ?? variant.price ?? product.base_price ?? product.price ?? 0;
|
|
292
|
+
const basePrice = quotedPrice ?? variant.base_price ?? variant.price ?? product.base_price ?? product.price ?? 0;
|
|
281
293
|
return {
|
|
282
294
|
id: Number(variant.id),
|
|
283
295
|
product_id: Number(variant.product_id ?? product.id),
|
|
@@ -302,7 +314,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
302
314
|
customer_id: customerId
|
|
303
315
|
});
|
|
304
316
|
const price = quotedPrice ?? item.price ?? 0;
|
|
305
|
-
const basePrice = item.base_price ?? item.price ?? 0;
|
|
317
|
+
const basePrice = quotedPrice ?? item.base_price ?? item.price ?? 0;
|
|
306
318
|
return {
|
|
307
319
|
id: Number(item.id),
|
|
308
320
|
product_id: Number(item.product_id ?? product.id),
|
|
@@ -39,6 +39,8 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
39
39
|
window: WindowPlugin;
|
|
40
40
|
request: RequestPlugin;
|
|
41
41
|
protected currentSalesDetail: ISalesDetail | null;
|
|
42
|
+
protected discountConfigCacheKey: string | null;
|
|
43
|
+
protected hasManualDiscountSelection: boolean;
|
|
42
44
|
constructor(name?: string, version?: string);
|
|
43
45
|
/**
|
|
44
46
|
* 子类可覆盖此方法以追加/收敛要注册的子模块。
|
|
@@ -113,23 +115,9 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
113
115
|
updateRemoteOrderNote(orderId: number | string, note: string): void;
|
|
114
116
|
updateTempOrderShopDiscount(amount: string | number): string;
|
|
115
117
|
updateTempOrderContactsInfo(contactsInfo: Record<string, any> | null): Record<string, any> | null;
|
|
116
|
-
/**
|
|
117
|
-
* 运行时切换 tempOrder 是否写入 localStorage(委托 OrderModule)。
|
|
118
|
-
* SalesSdk 等内存态场景可在挂载后设为 false,避免污染本地缓存。
|
|
119
|
-
*
|
|
120
|
-
* @example
|
|
121
|
-
* bookingTicket.setEnableTempOrderPersist(false);
|
|
122
|
-
* await bookingTicket.addProductToOrder(product);
|
|
123
|
-
*/
|
|
118
|
+
/** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化。 */
|
|
124
119
|
setEnableTempOrderPersist(enabled: boolean): void;
|
|
125
|
-
/**
|
|
126
|
-
* 读取当前 tempOrder localStorage 持久化开关(委托 OrderModule)。
|
|
127
|
-
*
|
|
128
|
-
* @example
|
|
129
|
-
* if (bookingTicket.isTempOrderPersistEnabled()) {
|
|
130
|
-
* bookingTicket.restoreOrder();
|
|
131
|
-
* }
|
|
132
|
-
*/
|
|
120
|
+
/** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化。 */
|
|
133
121
|
isTempOrderPersistEnabled(): boolean;
|
|
134
122
|
private ensureTempOrder;
|
|
135
123
|
addNewOrder(): Promise<OrderTempOrder>;
|
|
@@ -57,6 +57,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
57
57
|
this.otherParams = {};
|
|
58
58
|
// 当前缓存中已加载的最新 SalesDetail;只读 getter 走它对外暴露详情数据。
|
|
59
59
|
this.currentSalesDetail = null;
|
|
60
|
+
this.discountConfigCacheKey = null;
|
|
61
|
+
this.hasManualDiscountSelection = false;
|
|
60
62
|
}
|
|
61
63
|
/**
|
|
62
64
|
* 子类可覆盖此方法以追加/收敛要注册的子模块。
|
|
@@ -417,30 +419,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
417
419
|
throw new Error("order 模块未初始化");
|
|
418
420
|
return this.store.order.updateTempOrderContactsInfo(contactsInfo);
|
|
419
421
|
}
|
|
420
|
-
/**
|
|
421
|
-
* 运行时切换 tempOrder 是否写入 localStorage(委托 OrderModule)。
|
|
422
|
-
* SalesSdk 等内存态场景可在挂载后设为 false,避免污染本地缓存。
|
|
423
|
-
*
|
|
424
|
-
* @example
|
|
425
|
-
* bookingTicket.setEnableTempOrderPersist(false);
|
|
426
|
-
* await bookingTicket.addProductToOrder(product);
|
|
427
|
-
*/
|
|
422
|
+
/** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化。 */
|
|
428
423
|
setEnableTempOrderPersist(enabled) {
|
|
429
424
|
if (!this.store.order)
|
|
430
425
|
throw new Error("order 模块未初始化");
|
|
431
426
|
this.store.order.setEnableTempOrderPersist(enabled);
|
|
432
427
|
}
|
|
433
|
-
/**
|
|
434
|
-
* 读取当前 tempOrder localStorage 持久化开关(委托 OrderModule)。
|
|
435
|
-
*
|
|
436
|
-
* @example
|
|
437
|
-
* if (bookingTicket.isTempOrderPersistEnabled()) {
|
|
438
|
-
* bookingTicket.restoreOrder();
|
|
439
|
-
* }
|
|
440
|
-
*/
|
|
428
|
+
/** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化。 */
|
|
441
429
|
isTempOrderPersistEnabled() {
|
|
442
430
|
if (!this.store.order)
|
|
443
|
-
return
|
|
431
|
+
return false;
|
|
444
432
|
return this.store.order.isTempOrderPersistEnabled();
|
|
445
433
|
}
|
|
446
434
|
ensureTempOrder() {
|
|
@@ -477,6 +465,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
477
465
|
}
|
|
478
466
|
const tempOrder = this.store.order.restoreOrder();
|
|
479
467
|
this.currentSalesDetail = null;
|
|
468
|
+
this.discountConfigCacheKey = null;
|
|
469
|
+
this.hasManualDiscountSelection = false;
|
|
480
470
|
await this.effectsEmit("onTempOrderReplaced", { tempOrder });
|
|
481
471
|
if (this.syncAppDataToTempOrder(tempOrder)) {
|
|
482
472
|
this.store.order.persistTempOrder();
|
|
@@ -615,7 +605,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
615
605
|
});
|
|
616
606
|
}
|
|
617
607
|
async loadDiscountConfig(params) {
|
|
618
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
608
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
|
|
619
609
|
if (!this.store.order)
|
|
620
610
|
throw new Error("order 模块未初始化");
|
|
621
611
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
@@ -627,18 +617,37 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
627
617
|
(params == null ? void 0 : params.customerId) || tempOrder.customer_id || ((_c = tempOrder.customer) == null ? void 0 : _c.id) || ((_e = (_d = tempOrder._extend) == null ? void 0 : _d.customerSnapshot) == null ? void 0 : _e.id) || ((_g = (_f = tempOrder._extend) == null ? void 0 : _f.customerSnapshot) == null ? void 0 : _g.customer_id) || 0
|
|
628
618
|
);
|
|
629
619
|
const currentDiscountList = ((_h = discountModule == null ? void 0 : discountModule.getDiscountList) == null ? void 0 : _h.call(discountModule)) || [];
|
|
620
|
+
const originalDiscountList = ((_i = discountModule == null ? void 0 : discountModule.getOriginalDiscountList) == null ? void 0 : _i.call(discountModule)) || [];
|
|
621
|
+
const hasManualDiscountSelection = this.hasManualDiscountSelection || currentDiscountList.some((discount) => discount.isManualSelect);
|
|
622
|
+
const discountAction = (params == null ? void 0 : params.action) || (orderId ? "edit" : "create");
|
|
623
|
+
const discountConfigCacheKey = [
|
|
624
|
+
customerId,
|
|
625
|
+
discountAction,
|
|
626
|
+
Number(orderId) || 0
|
|
627
|
+
].join(":");
|
|
630
628
|
let preparedDiscountList = [];
|
|
631
629
|
if (customerId && customerId !== 1) {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
630
|
+
if (this.discountConfigCacheKey === discountConfigCacheKey) {
|
|
631
|
+
preparedDiscountList = originalDiscountList;
|
|
632
|
+
} else {
|
|
633
|
+
preparedDiscountList = await this.store.order.loadDiscountConfig({
|
|
634
|
+
customerId,
|
|
635
|
+
action: discountAction,
|
|
636
|
+
orderId: Number(orderId) || void 0,
|
|
637
|
+
apply: false
|
|
638
|
+
});
|
|
639
|
+
this.discountConfigCacheKey = discountConfigCacheKey;
|
|
640
|
+
await ((_j = discountModule == null ? void 0 : discountModule.setOriginalDiscountList) == null ? void 0 : _j.call(discountModule, preparedDiscountList));
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
if (hasManualDiscountSelection && currentDiscountList.length) {
|
|
644
|
+
return {
|
|
645
|
+
productList: tempOrder.products || [],
|
|
646
|
+
discountList: currentDiscountList
|
|
647
|
+
};
|
|
639
648
|
}
|
|
640
649
|
let nextDiscountList = this.mergeHistoricalDiscountList(
|
|
641
|
-
preparedDiscountList || ((
|
|
650
|
+
preparedDiscountList || ((_k = discountModule == null ? void 0 : discountModule.getDiscountList) == null ? void 0 : _k.call(discountModule)) || [],
|
|
642
651
|
tempOrder.products || []
|
|
643
652
|
);
|
|
644
653
|
nextDiscountList = this.mergeCurrentDiscountSelectionState(
|
|
@@ -647,17 +656,39 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
647
656
|
);
|
|
648
657
|
await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
|
|
649
658
|
if (rulesModule) {
|
|
650
|
-
const holders = ((
|
|
659
|
+
const holders = ((_l = tempOrder.holder) == null ? void 0 : _l.form_record_id) ? [{ form_record_id: tempOrder.holder.form_record_id }] : [];
|
|
651
660
|
const result = rulesModule.calcDiscount({
|
|
652
661
|
productList: tempOrder.products,
|
|
653
662
|
discountList: nextDiscountList,
|
|
654
663
|
holders,
|
|
655
|
-
isFormSubject: !!((
|
|
656
|
-
orderTotalAmount: Number(((
|
|
664
|
+
isFormSubject: !!((_m = tempOrder.holder) == null ? void 0 : _m.type) && tempOrder.holder.type === "form",
|
|
665
|
+
orderTotalAmount: Number(((_n = orderStore.summary) == null ? void 0 : _n.total_amount) || 0)
|
|
657
666
|
}) || { productList: tempOrder.products, discountList: nextDiscountList };
|
|
658
667
|
if (result.productList) {
|
|
659
668
|
tempOrder.products = result.productList;
|
|
660
669
|
}
|
|
670
|
+
for (const product of tempOrder.products || []) {
|
|
671
|
+
const productUid = (_o = product.metadata) == null ? void 0 : _o.unique_identification_number;
|
|
672
|
+
const runtimeOrigin = productUid ? (_r = (_q = (_p = tempOrder._extend) == null ? void 0 : _p.productsByUid) == null ? void 0 : _q[productUid]) == null ? void 0 : _r.origin : void 0;
|
|
673
|
+
if ((runtimeOrigin == null ? void 0 : runtimeOrigin.isManualDiscount) || ((_s = product.metadata) == null ? void 0 : _s.is_manual_discount))
|
|
674
|
+
continue;
|
|
675
|
+
const totalPerUnitDiscount = (product.discount_list || []).reduce(
|
|
676
|
+
(sum, pd) => sum + Number(pd.amount || 0),
|
|
677
|
+
0
|
|
678
|
+
);
|
|
679
|
+
const optionSum = (0, import_utils.sumOptionUnitPrice)(product.product_option_item);
|
|
680
|
+
const sourcePrice = ((_t = product.metadata) == null ? void 0 : _t.source_product_price) ?? (((_u = product.metadata) == null ? void 0 : _u.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
|
|
681
|
+
const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
|
|
682
|
+
const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
683
|
+
if (product.metadata) {
|
|
684
|
+
product.metadata.main_product_selling_price = newMainSellingPrice;
|
|
685
|
+
product.metadata.price_schema_version = 2;
|
|
686
|
+
}
|
|
687
|
+
product.selling_price = (0, import_utils.composeLinePrice)({
|
|
688
|
+
mainPrice: newMainSellingPrice,
|
|
689
|
+
bundle: product.product_bundle
|
|
690
|
+
});
|
|
691
|
+
}
|
|
661
692
|
if (result.discountList) {
|
|
662
693
|
nextDiscountList = this.mergeHistoricalDiscountList(
|
|
663
694
|
result.discountList,
|
|
@@ -668,6 +699,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
668
699
|
tempOrder.discount_list = nextDiscountList.filter((discount) => discount.isSelected);
|
|
669
700
|
}
|
|
670
701
|
}
|
|
702
|
+
const summary = await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
671
703
|
this.store.order.persistTempOrder();
|
|
672
704
|
await this.effectsEmit("onDiscountApplied", {
|
|
673
705
|
productList: tempOrder.products || [],
|
|
@@ -681,7 +713,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
681
713
|
};
|
|
682
714
|
}
|
|
683
715
|
async bestDiscount(cb) {
|
|
684
|
-
var _a, _b, _c, _d;
|
|
716
|
+
var _a, _b, _c, _d, _e;
|
|
685
717
|
if (!this.store.order)
|
|
686
718
|
throw new Error("order 模块未初始化");
|
|
687
719
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
@@ -689,6 +721,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
689
721
|
const discountModule = orderStore.discount;
|
|
690
722
|
const rulesModule = orderStore.rules;
|
|
691
723
|
const originalDiscountList = ((_a = discountModule == null ? void 0 : discountModule.getOriginalDiscountList) == null ? void 0 : _a.call(discountModule)) || this.getDiscountList();
|
|
724
|
+
const currentDiscountList = ((_b = discountModule == null ? void 0 : discountModule.getDiscountList) == null ? void 0 : _b.call(discountModule)) || [];
|
|
692
725
|
let nextDiscountList = this.mergeHistoricalDiscountList(
|
|
693
726
|
originalDiscountList || [],
|
|
694
727
|
tempOrder.products || []
|
|
@@ -699,13 +732,13 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
699
732
|
};
|
|
700
733
|
await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
|
|
701
734
|
if (rulesModule) {
|
|
702
|
-
const holders = ((
|
|
735
|
+
const holders = ((_c = tempOrder.holder) == null ? void 0 : _c.form_record_id) ? [{ form_record_id: tempOrder.holder.form_record_id }] : [];
|
|
703
736
|
result = rulesModule.calcDiscount({
|
|
704
737
|
productList: tempOrder.products,
|
|
705
738
|
discountList: nextDiscountList,
|
|
706
739
|
holders,
|
|
707
|
-
isFormSubject: !!((
|
|
708
|
-
orderTotalAmount: Number(((
|
|
740
|
+
isFormSubject: !!((_d = tempOrder.holder) == null ? void 0 : _d.type) && tempOrder.holder.type === "form",
|
|
741
|
+
orderTotalAmount: Number(((_e = orderStore.summary) == null ? void 0 : _e.total_amount) || 0)
|
|
709
742
|
}) || result;
|
|
710
743
|
if (result.productList) {
|
|
711
744
|
tempOrder.products = result.productList;
|
|
@@ -766,6 +799,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
766
799
|
isManualSelect: !params.isSelected
|
|
767
800
|
} : d
|
|
768
801
|
);
|
|
802
|
+
this.hasManualDiscountSelection = true;
|
|
769
803
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
770
804
|
const orderStore = this.store.order.store || {};
|
|
771
805
|
const discountModule = orderStore.discount;
|
|
@@ -798,6 +832,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
798
832
|
for (const d of nextDiscountList) {
|
|
799
833
|
if (d.isSelected && !beforeSelectedIds.has(d.id)) {
|
|
800
834
|
d.isSelected = false;
|
|
835
|
+
d.isManualSelect = true;
|
|
801
836
|
}
|
|
802
837
|
}
|
|
803
838
|
}
|
|
@@ -243,6 +243,19 @@ export interface BaseSalesProductBookingPriceSegment {
|
|
|
243
243
|
quotation_shelf_id: number;
|
|
244
244
|
source: BaseSalesProductBookingPriceSegmentSource;
|
|
245
245
|
}
|
|
246
|
+
export interface BaseSalesBundleProductBookingPriceResult {
|
|
247
|
+
bundle_id?: number;
|
|
248
|
+
group_id?: number;
|
|
249
|
+
bundle_group_id?: number;
|
|
250
|
+
bundle_product_id: number | null;
|
|
251
|
+
bundle_variant_id: number;
|
|
252
|
+
unit_price: string;
|
|
253
|
+
total_price: string;
|
|
254
|
+
quantity: number;
|
|
255
|
+
quotation_shelf_id: number;
|
|
256
|
+
source: BaseSalesProductBookingPriceSegmentSource;
|
|
257
|
+
segments: BaseSalesProductBookingPriceSegment[];
|
|
258
|
+
}
|
|
246
259
|
export interface BaseSalesProductBookingPriceResult {
|
|
247
260
|
product_id: number | null;
|
|
248
261
|
product_variant_id: number;
|
|
@@ -253,6 +266,7 @@ export interface BaseSalesProductBookingPriceResult {
|
|
|
253
266
|
duration?: BaseSalesQuotationDurationConfig;
|
|
254
267
|
quotation_shelf_id: number;
|
|
255
268
|
segments: BaseSalesProductBookingPriceSegment[];
|
|
269
|
+
product_bundle?: BaseSalesBundleProductBookingPriceResult[];
|
|
256
270
|
}
|
|
257
271
|
export type BaseSalesAvailabilityMode = 'idle' | 'shop_closed' | 'submit_disabled' | 'resource_busy' | 'additional_order_with_code' | 'additional_order';
|
|
258
272
|
export interface BaseSalesTableFormRecord {
|
|
@@ -99,6 +99,29 @@ function getFallbackPrice(params) {
|
|
|
99
99
|
function getProductQuantity(product) {
|
|
100
100
|
return toPositiveInt(product.num ?? product.quantity, 1);
|
|
101
101
|
}
|
|
102
|
+
function getBundleProductId(bundle) {
|
|
103
|
+
const productId = toFiniteNumber(
|
|
104
|
+
bundle.bundle_product_id ?? bundle._bundle_product_id,
|
|
105
|
+
NaN
|
|
106
|
+
);
|
|
107
|
+
if (!Number.isFinite(productId))
|
|
108
|
+
return null;
|
|
109
|
+
return productId;
|
|
110
|
+
}
|
|
111
|
+
function getBundleVariantId(bundle) {
|
|
112
|
+
const variantId = toFiniteNumber(
|
|
113
|
+
bundle.bundle_variant_id ?? bundle.variant_id,
|
|
114
|
+
0
|
|
115
|
+
);
|
|
116
|
+
if (!Number.isFinite(variantId) || variantId <= 0)
|
|
117
|
+
return void 0;
|
|
118
|
+
return variantId;
|
|
119
|
+
}
|
|
120
|
+
function getBundleFallbackPrice(bundle) {
|
|
121
|
+
return toPriceString(
|
|
122
|
+
bundle.bundle_selling_price ?? bundle.price ?? bundle.original_price ?? bundle.base_price ?? 0
|
|
123
|
+
);
|
|
124
|
+
}
|
|
102
125
|
function shouldSplitByDuration(duration, start, end) {
|
|
103
126
|
if (!duration)
|
|
104
127
|
return false;
|
|
@@ -162,37 +185,90 @@ function buildPriceSegment(params) {
|
|
|
162
185
|
source: quotedPrice !== null ? "quotation" : "fallback"
|
|
163
186
|
};
|
|
164
187
|
}
|
|
165
|
-
function
|
|
188
|
+
function calculatePriceForProduct(params) {
|
|
166
189
|
var _a;
|
|
190
|
+
const segments = params.segments.map((segment) => buildPriceSegment({
|
|
191
|
+
quotation: params.quotation,
|
|
192
|
+
productId: params.productId,
|
|
193
|
+
variantId: params.variantId,
|
|
194
|
+
customerId: params.customerId,
|
|
195
|
+
fallbackPrice: params.fallbackPrice,
|
|
196
|
+
segment
|
|
197
|
+
}));
|
|
198
|
+
const unitPrice = segments.reduce(
|
|
199
|
+
(total, segment) => total.plus(segment.total_price),
|
|
200
|
+
new import_decimal.default(0)
|
|
201
|
+
);
|
|
202
|
+
const totalPrice = unitPrice.times(params.quantity);
|
|
203
|
+
const quotationShelfId = ((_a = segments.find((segment) => segment.quotation_shelf_id)) == null ? void 0 : _a.quotation_shelf_id) || 0;
|
|
204
|
+
return {
|
|
205
|
+
unitPrice,
|
|
206
|
+
totalPrice,
|
|
207
|
+
quotationShelfId,
|
|
208
|
+
segments
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function calculateBundlePrices(params, segments) {
|
|
212
|
+
var _a;
|
|
213
|
+
const bundleList = ((_a = params.product) == null ? void 0 : _a.product_bundle) || [];
|
|
214
|
+
if (!bundleList.length)
|
|
215
|
+
return void 0;
|
|
216
|
+
return bundleList.map((bundle) => {
|
|
217
|
+
const productId = getBundleProductId(bundle);
|
|
218
|
+
const variantId = getBundleVariantId(bundle);
|
|
219
|
+
const quantity = getProductQuantity(bundle);
|
|
220
|
+
const price = calculatePriceForProduct({
|
|
221
|
+
quotation: params.quotation,
|
|
222
|
+
productId,
|
|
223
|
+
variantId,
|
|
224
|
+
customerId: params.customer_id,
|
|
225
|
+
quantity,
|
|
226
|
+
fallbackPrice: getBundleFallbackPrice(bundle),
|
|
227
|
+
segments
|
|
228
|
+
});
|
|
229
|
+
return {
|
|
230
|
+
bundle_id: bundle.bundle_id ?? bundle.id,
|
|
231
|
+
group_id: bundle.group_id,
|
|
232
|
+
bundle_group_id: bundle.bundle_group_id,
|
|
233
|
+
bundle_product_id: productId,
|
|
234
|
+
bundle_variant_id: variantId ?? 0,
|
|
235
|
+
unit_price: price.unitPrice.toDecimalPlaces(2).toFixed(2),
|
|
236
|
+
total_price: price.totalPrice.toDecimalPlaces(2).toFixed(2),
|
|
237
|
+
quantity,
|
|
238
|
+
quotation_shelf_id: price.quotationShelfId,
|
|
239
|
+
source: price.segments.some((segment) => segment.source === "quotation") ? "quotation" : "fallback",
|
|
240
|
+
segments: price.segments
|
|
241
|
+
};
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
function calculateBaseSalesProductBookingPrice(params) {
|
|
167
245
|
const product = params.product || {};
|
|
168
246
|
const productId = getProductId(product);
|
|
169
247
|
const variantId = getProductVariantId(product);
|
|
170
248
|
const productQuantity = getProductQuantity(product);
|
|
171
249
|
const fallbackPrice = getFallbackPrice(params);
|
|
172
|
-
const
|
|
250
|
+
const timeSegments = buildTimeSegments(params);
|
|
251
|
+
const price = calculatePriceForProduct({
|
|
173
252
|
quotation: params.quotation,
|
|
174
253
|
productId,
|
|
175
254
|
variantId,
|
|
176
255
|
customerId: params.customer_id,
|
|
256
|
+
quantity: productQuantity,
|
|
177
257
|
fallbackPrice,
|
|
178
|
-
|
|
179
|
-
})
|
|
180
|
-
const
|
|
181
|
-
(total, segment) => total.plus(segment.total_price),
|
|
182
|
-
new import_decimal.default(0)
|
|
183
|
-
);
|
|
184
|
-
const totalPrice = unitPrice.times(productQuantity);
|
|
185
|
-
const quotationShelfId = ((_a = segments.find((segment) => segment.quotation_shelf_id)) == null ? void 0 : _a.quotation_shelf_id) || 0;
|
|
258
|
+
segments: timeSegments
|
|
259
|
+
});
|
|
260
|
+
const bundlePrices = calculateBundlePrices(params, timeSegments);
|
|
186
261
|
return {
|
|
187
262
|
product_id: productId,
|
|
188
263
|
product_variant_id: variantId ?? 0,
|
|
189
264
|
customer_id: params.customer_id,
|
|
190
|
-
unit_price: unitPrice.toDecimalPlaces(2).toFixed(2),
|
|
191
|
-
total_price: totalPrice.toDecimalPlaces(2).toFixed(2),
|
|
265
|
+
unit_price: price.unitPrice.toDecimalPlaces(2).toFixed(2),
|
|
266
|
+
total_price: price.totalPrice.toDecimalPlaces(2).toFixed(2),
|
|
192
267
|
quantity: productQuantity,
|
|
193
268
|
duration: params.duration,
|
|
194
|
-
quotation_shelf_id: quotationShelfId,
|
|
195
|
-
segments
|
|
269
|
+
quotation_shelf_id: price.quotationShelfId,
|
|
270
|
+
segments: price.segments,
|
|
271
|
+
...bundlePrices ? { product_bundle: bundlePrices } : {}
|
|
196
272
|
};
|
|
197
273
|
}
|
|
198
274
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
311
311
|
date: string;
|
|
312
312
|
status: string;
|
|
313
313
|
week: string;
|
|
314
|
-
weekNum: 0 |
|
|
314
|
+
weekNum: 0 | 1 | 2 | 6 | 3 | 5 | 4;
|
|
315
315
|
}[]>;
|
|
316
316
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
317
317
|
private getScheduleDataByIds;
|
|
@@ -482,11 +482,17 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
|
|
|
482
482
|
* 在 BookingTicket 命名空间也 emit 一次,方便上层统一从 Solution 订阅。
|
|
483
483
|
*/
|
|
484
484
|
setOrderCustomer(customer) {
|
|
485
|
+
var _a;
|
|
485
486
|
if (!customer) {
|
|
486
487
|
this.clearOrderCustomer();
|
|
487
488
|
return;
|
|
488
489
|
}
|
|
490
|
+
const previousCustomerId = (_a = this.store.order.getOrderCustomer()) == null ? void 0 : _a.customer_id;
|
|
489
491
|
const patch = (0, import_orderCustomer.formatOrderCustomerPatch)(customer);
|
|
492
|
+
if (Number(previousCustomerId || 0) !== Number(patch.customer_id || 0)) {
|
|
493
|
+
this.discountConfigCacheKey = null;
|
|
494
|
+
this.hasManualDiscountSelection = false;
|
|
495
|
+
}
|
|
490
496
|
this.store.order.setOrderCustomer(patch, customer);
|
|
491
497
|
const next = this.buildOrderCustomerPayload();
|
|
492
498
|
this.core.effects.emit(`${this.name}:onOrderCustomerChange`, next);
|
|
@@ -510,6 +516,8 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
|
|
|
510
516
|
clearOrderCustomer() {
|
|
511
517
|
var _a, _b;
|
|
512
518
|
this.store.order.clearOrderCustomer();
|
|
519
|
+
this.discountConfigCacheKey = null;
|
|
520
|
+
this.hasManualDiscountSelection = false;
|
|
513
521
|
const orderStore = this.store.order.store || {};
|
|
514
522
|
const discountModule = orderStore.discount;
|
|
515
523
|
void ((_a = discountModule == null ? void 0 : discountModule.setOriginalDiscountList) == null ? void 0 : _a.call(discountModule, []));
|