@pisell/pisellos 2.1.165 → 2.1.166
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/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
- package/dist/model/strategy/adapter/dataVariant/adapter.js +167 -0
- package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
- package/dist/model/strategy/adapter/dataVariant/evaluator.js +780 -0
- package/dist/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
- package/dist/model/strategy/adapter/dataVariant/examples.js +277 -0
- package/dist/model/strategy/adapter/dataVariant/index.d.ts +4 -0
- package/dist/model/strategy/adapter/dataVariant/index.js +4 -0
- package/dist/model/strategy/adapter/dataVariant/type.d.ts +148 -0
- package/dist/model/strategy/adapter/dataVariant/type.js +54 -0
- package/dist/model/strategy/adapter/index.d.ts +4 -0
- package/dist/model/strategy/adapter/index.js +5 -1
- package/dist/model/strategy/adapter/promotion/index.js +0 -9
- package/dist/modules/Discount/index.d.ts +5 -2
- package/dist/modules/Discount/index.js +21 -1
- package/dist/modules/Discount/types.d.ts +4 -0
- package/dist/modules/Order/index.d.ts +1 -0
- package/dist/modules/Order/index.js +18 -6
- package/dist/modules/Order/types.d.ts +2 -0
- package/dist/modules/ProductList/index.d.ts +3 -1
- package/dist/modules/ProductList/index.js +22 -11
- package/dist/modules/Schedule/getDateIsInSchedule.js +5 -0
- package/dist/solution/BookingByStep/index.d.ts +2 -2
- package/dist/solution/ScanOrder/index.js +1 -1
- package/dist/solution/ShopDiscount/index.js +16 -15
- package/dist/solution/VenueBooking/index.d.ts +40 -3
- package/dist/solution/VenueBooking/index.js +394 -261
- package/dist/solution/VenueBooking/types.d.ts +3 -1
- package/dist/solution/VenueBooking/types.js +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
- package/dist/solution/VenueBooking/utils/dateSummary.js +12 -25
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +0 -6
- package/dist/solution/VenueBooking/utils/slotMerge.js +3 -9
- package/dist/solution/VenueBooking/utils/smartPricing.d.ts +70 -0
- package/dist/solution/VenueBooking/utils/smartPricing.js +233 -0
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +2 -0
- package/dist/solution/VenueBooking/utils/timeSlot.js +9 -4
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -0
- package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
- package/lib/model/strategy/adapter/dataVariant/adapter.js +149 -0
- package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +583 -0
- package/lib/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
- package/lib/model/strategy/adapter/dataVariant/examples.js +293 -0
- package/lib/model/strategy/adapter/dataVariant/index.d.ts +4 -0
- package/lib/model/strategy/adapter/dataVariant/index.js +38 -0
- package/lib/model/strategy/adapter/dataVariant/type.d.ts +148 -0
- package/lib/model/strategy/adapter/dataVariant/type.js +31 -0
- package/lib/model/strategy/adapter/index.d.ts +4 -0
- package/lib/model/strategy/adapter/index.js +13 -2
- package/lib/modules/Discount/index.d.ts +5 -2
- package/lib/modules/Discount/index.js +11 -1
- package/lib/modules/Discount/types.d.ts +4 -0
- package/lib/modules/Order/index.d.ts +1 -0
- package/lib/modules/Order/index.js +11 -1
- package/lib/modules/Order/types.d.ts +2 -0
- package/lib/modules/ProductList/index.d.ts +3 -1
- package/lib/modules/ProductList/index.js +45 -39
- package/lib/modules/Schedule/getDateIsInSchedule.js +4 -0
- package/lib/solution/BookingByStep/index.d.ts +2 -2
- package/lib/solution/ScanOrder/index.js +1 -1
- package/lib/solution/ShopDiscount/index.js +3 -2
- package/lib/solution/VenueBooking/index.d.ts +40 -3
- package/lib/solution/VenueBooking/index.js +257 -111
- package/lib/solution/VenueBooking/types.d.ts +3 -1
- package/lib/solution/VenueBooking/types.js +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +2 -2
- package/lib/solution/VenueBooking/utils/dateSummary.js +5 -10
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +0 -6
- package/lib/solution/VenueBooking/utils/slotMerge.js +3 -4
- package/lib/solution/VenueBooking/utils/smartPricing.d.ts +70 -0
- package/lib/solution/VenueBooking/utils/smartPricing.js +180 -0
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +2 -0
- package/lib/solution/VenueBooking/utils/timeSlot.js +7 -3
- package/package.json +1 -1
|
@@ -50,6 +50,7 @@ var import_resource = require("./utils/resource");
|
|
|
50
50
|
var import_timeSlot = require("./utils/timeSlot");
|
|
51
51
|
var import_dateSummary = require("./utils/dateSummary");
|
|
52
52
|
var import_slotMerge = require("./utils/slotMerge");
|
|
53
|
+
var import_smartPricing = require("./utils/smartPricing");
|
|
53
54
|
var import_utils3 = require("../../modules/Order/utils");
|
|
54
55
|
var import_Order = require("../../modules/Order");
|
|
55
56
|
var import_types4 = require("../RegisterAndLogin/types");
|
|
@@ -110,6 +111,10 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
110
111
|
this.loadAllProductsInFlight = null;
|
|
111
112
|
this.productsLoaded = false;
|
|
112
113
|
this.loadOpenDataConfigInFlight = null;
|
|
114
|
+
/** 按日期缓存 slot 智能定价 Map,避免同周重复 resolveProducts */
|
|
115
|
+
this.slotPriceMapCache = /* @__PURE__ */ new Map();
|
|
116
|
+
/** loadProducts 后缓存的全量商品(venue + addon),供分段算价复用 */
|
|
117
|
+
this.smartPricingProductCatalog = [];
|
|
113
118
|
}
|
|
114
119
|
getLoggerContext() {
|
|
115
120
|
return {
|
|
@@ -272,19 +277,16 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
272
277
|
});
|
|
273
278
|
}
|
|
274
279
|
registerCustomerLoginListeners() {
|
|
275
|
-
var _a, _b, _c, _d;
|
|
276
280
|
this.clearLoginEffectListeners();
|
|
277
|
-
const
|
|
278
|
-
const registerAndLoginModule = (_b = this.core) == null ? void 0 : _b.getModule("registerAndLogin");
|
|
279
|
-
const currentAccount = ((_c = accountModule == null ? void 0 : accountModule.getCurrentAccount) == null ? void 0 : _c.call(accountModule)) || ((_d = accountModule == null ? void 0 : accountModule.getAccount) == null ? void 0 : _d.call(accountModule)) || null;
|
|
280
|
-
const createHandleLogin = (eventName) => async (payload) => {
|
|
281
|
+
const createHandleLogin = () => async (payload) => {
|
|
281
282
|
const customerId = this.resolveCustomerIdFromLoginPayload(payload);
|
|
282
283
|
if (!customerId)
|
|
283
284
|
return;
|
|
284
285
|
await this.refreshOrderMarketingAfterLogin({ customerId });
|
|
285
286
|
};
|
|
286
|
-
this.registerLoginEffect(
|
|
287
|
-
this.registerLoginEffect(
|
|
287
|
+
this.registerLoginEffect(_VenueBookingImpl.PISELL1_LOGIN_SUCCESS, createHandleLogin());
|
|
288
|
+
this.registerLoginEffect(import_types3.AccountHooks.OnLogin, createHandleLogin());
|
|
289
|
+
this.registerLoginEffect(import_types4.RegisterAndLoginHooks.onLoginSuccess, createHandleLogin());
|
|
288
290
|
}
|
|
289
291
|
async refreshOrderMarketingAfterLogin(params) {
|
|
290
292
|
if (!this.store.order)
|
|
@@ -298,20 +300,24 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
298
300
|
}
|
|
299
301
|
this.customerLoginRefreshIdInFlight = params.customerId;
|
|
300
302
|
const refreshTask = (async () => {
|
|
301
|
-
var _a;
|
|
302
|
-
|
|
303
|
-
await this.store.quotation.loadQuotations({
|
|
304
|
-
channel: (_a = this.otherParams) == null ? void 0 : _a.channel
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
this.recalculateOrderPricesFromQuotation();
|
|
303
|
+
var _a, _b, _c;
|
|
304
|
+
this.smartPricingCustomerId = params.customerId;
|
|
308
305
|
await this.store.order.loadDiscountConfig({
|
|
309
306
|
customerId: params.customerId
|
|
310
307
|
});
|
|
308
|
+
this.clearSlotPriceMapCache();
|
|
309
|
+
this.recalculateOrderPricesFromSmartPricing();
|
|
310
|
+
this.store.order.applyDiscount();
|
|
311
|
+
this.normalizeDiscountedOrderPrices(
|
|
312
|
+
this.store.order.getDiscountList()
|
|
313
|
+
);
|
|
311
314
|
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
312
315
|
this.store.order.persistTempOrder();
|
|
313
316
|
await this.refreshItemRuleQuantityLimits();
|
|
314
317
|
await this.refreshCartValidationPassed();
|
|
318
|
+
await ((_c = (_b = (_a = this.core) == null ? void 0 : _a.effects) == null ? void 0 : _b.emit) == null ? void 0 : _c.call(_b, import_types.VenueBookingHooks.onSmartPricingUpdated, {
|
|
319
|
+
customerId: params.customerId
|
|
320
|
+
}));
|
|
315
321
|
})();
|
|
316
322
|
this.customerLoginRefreshInFlight = refreshTask;
|
|
317
323
|
try {
|
|
@@ -326,11 +332,12 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
326
332
|
}
|
|
327
333
|
}
|
|
328
334
|
async initialize(core, options = {}) {
|
|
329
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i
|
|
335
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
330
336
|
this.logMethodStart("initialize");
|
|
331
337
|
this.core = core;
|
|
332
338
|
this.initializeOptions = options || {};
|
|
333
339
|
this.store = { ...this.store, ...options.store };
|
|
340
|
+
this.smartPricingCustomerId = void 0;
|
|
334
341
|
this.store.entryContext = ((_a = options.otherParams) == null ? void 0 : _a.entryContext) || this.store.entryContext;
|
|
335
342
|
this.store.status = "initializing";
|
|
336
343
|
this.store.error = null;
|
|
@@ -462,10 +469,6 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
462
469
|
await this.loadRuntimeConfigs();
|
|
463
470
|
if (this.store.schedule) {
|
|
464
471
|
await this.store.schedule.loadAllSchedule();
|
|
465
|
-
this.injectScheduleResolverToQuotation();
|
|
466
|
-
(_k = this.store.quotation) == null ? void 0 : _k.loadQuotations({
|
|
467
|
-
channel: (_j = this.otherParams) == null ? void 0 : _j.channel
|
|
468
|
-
});
|
|
469
472
|
}
|
|
470
473
|
await this.refreshItemRuleQuantityLimits();
|
|
471
474
|
this.store.status = "ready";
|
|
@@ -541,6 +544,95 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
541
544
|
getCartValidation() {
|
|
542
545
|
return this.store.cartValidation || { passed: null, failures: [] };
|
|
543
546
|
}
|
|
547
|
+
/** 清除 slot 价格分段缓存(商品重载 / 登录后 customerId 变化时调用) */
|
|
548
|
+
clearSlotPriceMapCache() {
|
|
549
|
+
this.slotPriceMapCache.clear();
|
|
550
|
+
}
|
|
551
|
+
/** 读取当前登录 customerId */
|
|
552
|
+
resolveCustomerIdForSmartPricing() {
|
|
553
|
+
var _a, _b, _c;
|
|
554
|
+
if (this.smartPricingCustomerId)
|
|
555
|
+
return this.smartPricingCustomerId;
|
|
556
|
+
try {
|
|
557
|
+
const userPlugin = (_a = this.core) == null ? void 0 : _a.getPlugin("user");
|
|
558
|
+
const customerId = Number((_c = (_b = userPlugin == null ? void 0 : userPlugin.get) == null ? void 0 : _b.call(userPlugin)) == null ? void 0 : _c.id);
|
|
559
|
+
return Number.isFinite(customerId) && customerId > 0 ? customerId : void 0;
|
|
560
|
+
} catch {
|
|
561
|
+
return void 0;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
resolveAvailableWalletIdsForSmartPricing() {
|
|
565
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
566
|
+
const orderWalletIds = (_b = (_a = this.store.order) == null ? void 0 : _a.getAvailableWalletIds) == null ? void 0 : _b.call(_a);
|
|
567
|
+
const fallbackWalletIds = ((_c = this.otherParams) == null ? void 0 : _c.available_wallet_ids) || ((_d = this.otherParams) == null ? void 0 : _d.availableWalletIds) || ((_f = (_e = this.otherParams) == null ? void 0 : _e.strategy_context) == null ? void 0 : _f.available_wallet_ids) || ((_h = (_g = this.otherParams) == null ? void 0 : _g.strategy_context) == null ? void 0 : _h.availableWalletIds);
|
|
568
|
+
const source = Array.isArray(orderWalletIds) && orderWalletIds.length ? orderWalletIds : fallbackWalletIds;
|
|
569
|
+
if (!Array.isArray(source))
|
|
570
|
+
return [];
|
|
571
|
+
const ids = source.map((item) => Number(item)).filter((item) => Number.isFinite(item) && item > 0);
|
|
572
|
+
return Array.from(new Set(ids));
|
|
573
|
+
}
|
|
574
|
+
/** 读取 schedule 全量列表,供智能定价 schedule_match 使用 */
|
|
575
|
+
getScheduleListForSmartPricing() {
|
|
576
|
+
var _a;
|
|
577
|
+
const scheduleModule = this.store.schedule;
|
|
578
|
+
const list = (_a = scheduleModule == null ? void 0 : scheduleModule.store) == null ? void 0 : _a.scheduleList;
|
|
579
|
+
return Array.isArray(list) ? list : [];
|
|
580
|
+
}
|
|
581
|
+
/** 构建智能定价上下文,对齐 OS Server buildProductFormatterContext */
|
|
582
|
+
buildSmartPricingContext(customerId) {
|
|
583
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
584
|
+
const evaluator = (_b = (_a = this.core) == null ? void 0 : _a.context) == null ? void 0 : _b.dataVariantEvaluator;
|
|
585
|
+
return {
|
|
586
|
+
evaluator,
|
|
587
|
+
scheduleList: this.getScheduleListForSmartPricing(),
|
|
588
|
+
menuList: ((_c = this.otherParams) == null ? void 0 : _c.menuList) || ((_e = (_d = this.otherParams) == null ? void 0 : _d.openData) == null ? void 0 : _e.menuList) || [],
|
|
589
|
+
customerId: customerId ?? this.resolveCustomerIdForSmartPricing(),
|
|
590
|
+
availableWalletIds: this.resolveAvailableWalletIdsForSmartPricing(),
|
|
591
|
+
channel: (_f = this.otherParams) == null ? void 0 : _f.channel,
|
|
592
|
+
businessCode: (_g = this.otherParams) == null ? void 0 : _g.businessCode,
|
|
593
|
+
orderType: ((_h = this.otherParams) == null ? void 0 : _h.orderType) || ((_i = this.otherParams) == null ? void 0 : _i.type),
|
|
594
|
+
strategy_context: (_j = this.otherParams) == null ? void 0 : _j.strategy_context
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
/** venue + addon 全量商品,供智能定价评估 */
|
|
598
|
+
getAllProductsForSmartPricing() {
|
|
599
|
+
if (this.smartPricingProductCatalog.length) {
|
|
600
|
+
return this.smartPricingProductCatalog;
|
|
601
|
+
}
|
|
602
|
+
const venueList = this.getVenueProducts();
|
|
603
|
+
const addonList = this.getAddonProductsList();
|
|
604
|
+
return [...venueList, ...addonList];
|
|
605
|
+
}
|
|
606
|
+
getSlotPriceMapCacheKey(date, context) {
|
|
607
|
+
return [
|
|
608
|
+
date,
|
|
609
|
+
context.customerId ?? "",
|
|
610
|
+
(context.availableWalletIds || []).join(","),
|
|
611
|
+
context.channel ?? "",
|
|
612
|
+
context.businessCode ?? ""
|
|
613
|
+
].join("|");
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* 按 schedule 分段构建 slot 价格 Map,带实例级缓存。
|
|
617
|
+
*/
|
|
618
|
+
buildSlotPriceMapForDate(date, config, productIds) {
|
|
619
|
+
const context = this.buildSmartPricingContext();
|
|
620
|
+
const cacheKey = this.getSlotPriceMapCacheKey(date, context);
|
|
621
|
+
const cached = this.slotPriceMapCache.get(cacheKey);
|
|
622
|
+
if (cached)
|
|
623
|
+
return cached;
|
|
624
|
+
const timeLabels = (0, import_timeSlot.generateTimeLabels)(config);
|
|
625
|
+
const slotPriceMap = (0, import_smartPricing.buildSlotPriceMapByScheduleSegments)({
|
|
626
|
+
products: this.getAllProductsForSmartPricing(),
|
|
627
|
+
productIds,
|
|
628
|
+
date,
|
|
629
|
+
timeLabels,
|
|
630
|
+
config,
|
|
631
|
+
context
|
|
632
|
+
});
|
|
633
|
+
this.slotPriceMapCache.set(cacheKey, slotPriceMap);
|
|
634
|
+
return slotPriceMap;
|
|
635
|
+
}
|
|
544
636
|
// ─── 场地商品 & 附加商品 ───
|
|
545
637
|
async loadAllProducts() {
|
|
546
638
|
if (this.loadAllProductsInFlight)
|
|
@@ -569,9 +661,18 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
569
661
|
menu_list_ids: menuListIds,
|
|
570
662
|
cacheId: this.cacheId,
|
|
571
663
|
schedule_date: (0, import_dayjs.default)().format("YYYY-MM-DD"),
|
|
572
|
-
schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
|
|
664
|
+
schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"),
|
|
665
|
+
with_extra: ["dataVariants"]
|
|
573
666
|
});
|
|
574
|
-
const
|
|
667
|
+
const rawList = Array.isArray(allProducts) ? allProducts : [];
|
|
668
|
+
let list = rawList;
|
|
669
|
+
this.smartPricingProductCatalog = rawList.slice();
|
|
670
|
+
list = (0, import_smartPricing.formatProductsWithDataVariant)(
|
|
671
|
+
list,
|
|
672
|
+
this.buildSmartPricingContext(),
|
|
673
|
+
(0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
|
|
674
|
+
);
|
|
675
|
+
this.clearSlotPriceMapCache();
|
|
575
676
|
const venueList = list.filter((p) => p.duration != null);
|
|
576
677
|
const addonList = list.filter((p) => p.duration == null);
|
|
577
678
|
const venueStore = (_c = this.store.venueProducts) == null ? void 0 : _c.store;
|
|
@@ -752,29 +853,24 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
752
853
|
config: this.baseSlotConfig,
|
|
753
854
|
rawResources: this.store.rawResourceData,
|
|
754
855
|
resourceProductMap: this.resourceProductMap,
|
|
755
|
-
|
|
756
|
-
|
|
856
|
+
resolveConfig: (date) => this.resolveSlotConfigForDate(date),
|
|
857
|
+
buildSlotPriceMap: (date, config, productIds) => this.buildSlotPriceMapForDate(date, config, productIds)
|
|
757
858
|
});
|
|
758
859
|
}
|
|
759
860
|
getTimeSlotGrid(date) {
|
|
760
861
|
const resolvedSlotConfig = this.syncOperatingHoursToSlotConfig(date);
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
];
|
|
768
|
-
const timeLabels = (0, import_timeSlot.generateTimeLabels)(resolvedSlotConfig);
|
|
769
|
-
const timePoints = timeLabels.map((label) => `${date} ${label}`);
|
|
770
|
-
quotationPriceMap = this.store.quotation.buildProductPriceMap({ productIds, timePoints });
|
|
771
|
-
}
|
|
862
|
+
const productIds = [
|
|
863
|
+
...new Set(
|
|
864
|
+
[...this.resourceProductMap.values()].flat().map((m) => m.productId)
|
|
865
|
+
)
|
|
866
|
+
];
|
|
867
|
+
const slotPriceMap = productIds.length ? this.buildSlotPriceMapForDate(date, resolvedSlotConfig, productIds) : void 0;
|
|
772
868
|
return (0, import_timeSlot.buildTimeSlotGrid)({
|
|
773
869
|
date,
|
|
774
870
|
config: resolvedSlotConfig,
|
|
775
871
|
rawResources: this.store.rawResourceData,
|
|
776
872
|
resourceProductMap: this.resourceProductMap,
|
|
777
|
-
|
|
873
|
+
slotPriceMap
|
|
778
874
|
});
|
|
779
875
|
}
|
|
780
876
|
// ─── 时间槽订单操作 ───
|
|
@@ -1059,8 +1155,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1059
1155
|
booking_uid: bookingUuid,
|
|
1060
1156
|
price_breakdown: (0, import_slotMerge.buildPriceBreakdown)({
|
|
1061
1157
|
group,
|
|
1062
|
-
productId: mapping.productId
|
|
1063
|
-
quotation: this.store.quotation
|
|
1158
|
+
productId: mapping.productId
|
|
1064
1159
|
})
|
|
1065
1160
|
},
|
|
1066
1161
|
_origin: {
|
|
@@ -1153,20 +1248,12 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1153
1248
|
if (!this.store.schedule)
|
|
1154
1249
|
throw new Error("schedule 模块未初始化");
|
|
1155
1250
|
await this.store.schedule.loadAllSchedule();
|
|
1156
|
-
this.injectScheduleResolverToQuotation();
|
|
1157
1251
|
this.logMethodSuccess("loadSchedules");
|
|
1158
1252
|
} catch (error) {
|
|
1159
1253
|
this.logMethodError("loadSchedules", error);
|
|
1160
1254
|
throw error;
|
|
1161
1255
|
}
|
|
1162
1256
|
}
|
|
1163
|
-
injectScheduleResolverToQuotation() {
|
|
1164
|
-
if (this.store.quotation && this.store.schedule) {
|
|
1165
|
-
this.store.quotation.setScheduleResolver(
|
|
1166
|
-
(id) => this.store.schedule.getScheduleListByIds([id])[0]
|
|
1167
|
-
);
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
1257
|
getScheduleListByIds(ids) {
|
|
1171
1258
|
if (!this.store.schedule)
|
|
1172
1259
|
return [];
|
|
@@ -1205,14 +1292,16 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1205
1292
|
throw error;
|
|
1206
1293
|
}
|
|
1207
1294
|
}
|
|
1208
|
-
|
|
1295
|
+
recalculateOrderPricesFromSmartPricing() {
|
|
1209
1296
|
var _a, _b;
|
|
1210
|
-
if (!this.store.order
|
|
1297
|
+
if (!this.store.order)
|
|
1211
1298
|
return;
|
|
1212
1299
|
const tempOrder = this.store.order.getTempOrder();
|
|
1213
1300
|
if (!((_a = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _a.length))
|
|
1214
1301
|
return;
|
|
1215
1302
|
const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
|
|
1303
|
+
const catalog = this.getAllProductsForSmartPricing();
|
|
1304
|
+
const context = this.buildSmartPricingContext();
|
|
1216
1305
|
for (const product of tempOrder.products) {
|
|
1217
1306
|
if ((_b = product.metadata) == null ? void 0 : _b.venue_booking) {
|
|
1218
1307
|
const mappings = this.resourceProductMap.get(product.metadata.resource_id);
|
|
@@ -1225,37 +1314,75 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1225
1314
|
product,
|
|
1226
1315
|
this.store.slotConfig.slotDurationMinutes
|
|
1227
1316
|
);
|
|
1228
|
-
const
|
|
1229
|
-
...slot,
|
|
1230
|
-
|
|
1231
|
-
|
|
1317
|
+
const uniqueDates = [
|
|
1318
|
+
...new Set(slots.map((slot) => (0, import_dayjs.default)(slot.startTime).format("YYYY-MM-DD")))
|
|
1319
|
+
];
|
|
1320
|
+
const slotPriceMaps = /* @__PURE__ */ new Map();
|
|
1321
|
+
for (const slotDate of uniqueDates) {
|
|
1322
|
+
slotPriceMaps.set(
|
|
1323
|
+
slotDate,
|
|
1324
|
+
this.buildSlotPriceMapForDate(slotDate, this.store.slotConfig, [mapping.productId])
|
|
1325
|
+
);
|
|
1326
|
+
}
|
|
1327
|
+
const updatedSlots = slots.map((slot) => {
|
|
1328
|
+
const slotDate = (0, import_dayjs.default)(slot.startTime).format("YYYY-MM-DD");
|
|
1329
|
+
const slotPriceMap = slotPriceMaps.get(slotDate);
|
|
1330
|
+
return {
|
|
1331
|
+
...slot,
|
|
1232
1332
|
productId: mapping.productId,
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1333
|
+
price: slotPriceMap ? (0, import_smartPricing.getSlotPriceFromMap)({
|
|
1334
|
+
slotPriceMap,
|
|
1335
|
+
productId: mapping.productId,
|
|
1336
|
+
slotStartTime: slot.startTime,
|
|
1337
|
+
fallbackPrice: mapping.price
|
|
1338
|
+
}) : mapping.price
|
|
1339
|
+
};
|
|
1340
|
+
});
|
|
1236
1341
|
const merged = (0, import_slotMerge.mergeConsecutiveSlots)(updatedSlots);
|
|
1237
1342
|
if (merged.length === 1) {
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1343
|
+
this.resetProductPriceForSmartPricing({
|
|
1344
|
+
product,
|
|
1345
|
+
price: merged[0].totalPrice,
|
|
1346
|
+
priceBreakdown: (0, import_slotMerge.buildPriceBreakdown)({
|
|
1347
|
+
group: merged[0],
|
|
1348
|
+
productId: mapping.productId
|
|
1349
|
+
})
|
|
1244
1350
|
});
|
|
1245
1351
|
}
|
|
1246
1352
|
} else if (product.product_id != null) {
|
|
1247
|
-
const
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1353
|
+
const smartPrice = (0, import_smartPricing.getPriceForProductAtDatetime)({
|
|
1354
|
+
products: catalog,
|
|
1355
|
+
context,
|
|
1356
|
+
productId: Number(product.product_id),
|
|
1357
|
+
datetime: now,
|
|
1358
|
+
fallbackPrice: product.selling_price
|
|
1359
|
+
});
|
|
1360
|
+
this.resetProductPriceForSmartPricing({
|
|
1361
|
+
product,
|
|
1362
|
+
price: smartPrice
|
|
1251
1363
|
});
|
|
1252
|
-
if (quotationPrice !== null) {
|
|
1253
|
-
product.selling_price = quotationPrice;
|
|
1254
|
-
product.original_price = quotationPrice;
|
|
1255
|
-
}
|
|
1256
1364
|
}
|
|
1257
1365
|
}
|
|
1258
1366
|
}
|
|
1367
|
+
/**
|
|
1368
|
+
* DataVariant 重算价格后,同步刷新订单展示、Rules 与 Summary 共用的价格口径。
|
|
1369
|
+
* Rules 会在本轮结束后根据当前客户的 discountList 重新写入实际折扣。
|
|
1370
|
+
*/
|
|
1371
|
+
resetProductPriceForSmartPricing(params) {
|
|
1372
|
+
const { product, price, priceBreakdown } = params;
|
|
1373
|
+
const metadata = product.metadata || {};
|
|
1374
|
+
product.selling_price = price;
|
|
1375
|
+
product.original_price = price;
|
|
1376
|
+
product.discount_list = [];
|
|
1377
|
+
product.metadata = {
|
|
1378
|
+
...metadata,
|
|
1379
|
+
...priceBreakdown ? { price_breakdown: priceBreakdown } : {},
|
|
1380
|
+
source_product_price: price,
|
|
1381
|
+
main_product_original_price: price,
|
|
1382
|
+
main_product_selling_price: price,
|
|
1383
|
+
price_schema_version: 2
|
|
1384
|
+
};
|
|
1385
|
+
}
|
|
1259
1386
|
async scanCode(code, customerId) {
|
|
1260
1387
|
this.logMethodStart("scanCode", { code });
|
|
1261
1388
|
try {
|
|
@@ -1281,7 +1408,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1281
1408
|
}
|
|
1282
1409
|
/** 勾选/取消勾选某张折扣券,重新计算折扣并持久化 */
|
|
1283
1410
|
async setDiscountSelected(params) {
|
|
1284
|
-
var _a, _b, _c, _d, _e
|
|
1411
|
+
var _a, _b, _c, _d, _e;
|
|
1285
1412
|
this.logMethodStart("setDiscountSelected", params);
|
|
1286
1413
|
try {
|
|
1287
1414
|
if (!this.store.order)
|
|
@@ -1333,42 +1460,15 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1333
1460
|
}
|
|
1334
1461
|
}
|
|
1335
1462
|
}
|
|
1336
|
-
|
|
1337
|
-
nextDiscountList.filter((d) => d.isSelected).map((d) => d.id)
|
|
1338
|
-
);
|
|
1339
|
-
for (const product of tempOrder.products) {
|
|
1340
|
-
if ((_c = product._origin) == null ? void 0 : _c.isManualDiscount)
|
|
1341
|
-
continue;
|
|
1342
|
-
product.discount_list = (product.discount_list || []).filter((pd) => {
|
|
1343
|
-
var _a2;
|
|
1344
|
-
const rid = ((_a2 = pd.discount) == null ? void 0 : _a2.resource_id) ?? pd.id;
|
|
1345
|
-
return rid != null && selectedResourceIds.has(rid);
|
|
1346
|
-
});
|
|
1347
|
-
const totalPerUnitDiscount = (product.discount_list || []).reduce(
|
|
1348
|
-
(sum, pd) => sum + (pd.amount || 0),
|
|
1349
|
-
0
|
|
1350
|
-
);
|
|
1351
|
-
const optionSum = (0, import_utils3.sumOptionUnitPrice)(product.product_option_item);
|
|
1352
|
-
const sourcePrice = ((_d = product.metadata) == null ? void 0 : _d.source_product_price) ?? (((_e = product.metadata) == null ? void 0 : _e.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");
|
|
1353
|
-
const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
|
|
1354
|
-
const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
1355
|
-
if (product.metadata) {
|
|
1356
|
-
product.metadata.main_product_selling_price = newMainSellingPrice;
|
|
1357
|
-
product.metadata.price_schema_version = 2;
|
|
1358
|
-
}
|
|
1359
|
-
product.selling_price = (0, import_utils3.composeLinePrice)({
|
|
1360
|
-
mainPrice: newMainSellingPrice,
|
|
1361
|
-
bundle: product.product_bundle
|
|
1362
|
-
});
|
|
1363
|
-
}
|
|
1463
|
+
this.normalizeDiscountedOrderPrices(nextDiscountList);
|
|
1364
1464
|
import_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
|
|
1365
1465
|
await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
|
|
1366
1466
|
tempOrder.discount_list = (nextDiscountList || []).filter((d) => d.isSelected);
|
|
1367
1467
|
const afterApplyTarget = this.store.order.getDiscountList().find((d) => d.id === params.discountId) || null;
|
|
1368
1468
|
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
1369
1469
|
this.store.order.persistTempOrder();
|
|
1370
|
-
const finalSummary = ((
|
|
1371
|
-
const finalProduct = ((
|
|
1470
|
+
const finalSummary = ((_c = this.store.order.getTempOrder()) == null ? void 0 : _c.summary) || null;
|
|
1471
|
+
const finalProduct = ((_e = (_d = this.store.order.getTempOrder()) == null ? void 0 : _d.products) == null ? void 0 : _e[0]) || null;
|
|
1372
1472
|
this.logMethodSuccess("setDiscountSelected", params);
|
|
1373
1473
|
const finalTarget = this.store.order.getDiscountList().find((d) => d.id === params.discountId) || null;
|
|
1374
1474
|
return this.store.order.getDiscountList();
|
|
@@ -1377,6 +1477,51 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1377
1477
|
throw error;
|
|
1378
1478
|
}
|
|
1379
1479
|
}
|
|
1480
|
+
/**
|
|
1481
|
+
* 统一 VenueBooking 折扣后的订单行价。
|
|
1482
|
+
*
|
|
1483
|
+
* Rules 的 `discount_list.amount` 是已经按适用规则计算出的每件优惠额;它是这里唯一
|
|
1484
|
+
* 的折扣金额来源。使用智能定价写入的 source_product_price 减去该金额,再同步
|
|
1485
|
+
* selling_price 与 Summary 使用的 main_product_selling_price,避免 UI 的购物车行价、
|
|
1486
|
+
* 小计和提交订单各自读取到不同的价格字段。
|
|
1487
|
+
*/
|
|
1488
|
+
normalizeDiscountedOrderPrices(discountList) {
|
|
1489
|
+
var _a;
|
|
1490
|
+
const order = this.store.order;
|
|
1491
|
+
if (!order)
|
|
1492
|
+
return;
|
|
1493
|
+
const tempOrder = order.ensureTempOrder();
|
|
1494
|
+
const selectedResourceIds = new Set(
|
|
1495
|
+
(discountList || []).filter((discount) => discount.isSelected).map((discount) => discount.id)
|
|
1496
|
+
);
|
|
1497
|
+
for (const product of tempOrder.products) {
|
|
1498
|
+
if ((_a = product._origin) == null ? void 0 : _a.isManualDiscount)
|
|
1499
|
+
continue;
|
|
1500
|
+
product.discount_list = (product.discount_list || []).filter((detail) => {
|
|
1501
|
+
var _a2;
|
|
1502
|
+
const resourceId = ((_a2 = detail.discount) == null ? void 0 : _a2.resource_id) ?? detail.id;
|
|
1503
|
+
return resourceId != null && selectedResourceIds.has(resourceId);
|
|
1504
|
+
});
|
|
1505
|
+
const totalPerUnitDiscount = (product.discount_list || []).reduce(
|
|
1506
|
+
(total, detail) => total.plus(detail.amount || 0),
|
|
1507
|
+
new import_decimal.default(0)
|
|
1508
|
+
);
|
|
1509
|
+
const metadata = product.metadata || (product.metadata = {});
|
|
1510
|
+
const optionSum = (0, import_utils3.sumOptionUnitPrice)(product.product_option_item);
|
|
1511
|
+
const sourcePrice = metadata.source_product_price ?? (metadata.main_product_original_price != null ? new import_decimal.default(Number(metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
|
|
1512
|
+
const nextSourceSellingPrice = import_decimal.default.max(
|
|
1513
|
+
0,
|
|
1514
|
+
new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount)
|
|
1515
|
+
).toDecimalPlaces(2).toString();
|
|
1516
|
+
const nextMainSellingPrice = new import_decimal.default(Number(nextSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
1517
|
+
metadata.main_product_selling_price = nextMainSellingPrice;
|
|
1518
|
+
metadata.price_schema_version = 2;
|
|
1519
|
+
product.selling_price = (0, import_utils3.composeLinePrice)({
|
|
1520
|
+
mainPrice: nextMainSellingPrice,
|
|
1521
|
+
bundle: product.product_bundle
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1380
1525
|
async addNewOrder() {
|
|
1381
1526
|
this.logMethodStart("addNewOrder");
|
|
1382
1527
|
try {
|
|
@@ -1456,7 +1601,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1456
1601
|
}
|
|
1457
1602
|
}
|
|
1458
1603
|
async addProductToOrder(product) {
|
|
1459
|
-
var _a;
|
|
1604
|
+
var _a, _b;
|
|
1460
1605
|
this.logMethodStart("addProductToOrder", {
|
|
1461
1606
|
product_id: product.product_id,
|
|
1462
1607
|
product_variant_id: product.product_variant_id
|
|
@@ -1464,18 +1609,18 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1464
1609
|
try {
|
|
1465
1610
|
if (!this.store.order)
|
|
1466
1611
|
throw new Error("order 模块未初始化");
|
|
1467
|
-
if (!((_a = product.metadata) == null ? void 0 : _a.venue_booking) &&
|
|
1468
|
-
const
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1612
|
+
if (!((_a = product.metadata) == null ? void 0 : _a.venue_booking) && product.product_id != null) {
|
|
1613
|
+
const smartPrice = (0, import_smartPricing.getPriceForProductAtDatetime)({
|
|
1614
|
+
products: this.getAllProductsForSmartPricing(),
|
|
1615
|
+
context: this.buildSmartPricingContext(),
|
|
1616
|
+
productId: Number(product.product_id),
|
|
1617
|
+
datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"),
|
|
1618
|
+
fallbackPrice: product.selling_price
|
|
1472
1619
|
});
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
product.original_price = product.selling_price;
|
|
1478
|
-
}
|
|
1620
|
+
product.selling_price = smartPrice;
|
|
1621
|
+
product.original_price = smartPrice;
|
|
1622
|
+
} else if (product.selling_price != null && !((_b = product.metadata) == null ? void 0 : _b.venue_booking)) {
|
|
1623
|
+
product.original_price = product.selling_price;
|
|
1479
1624
|
}
|
|
1480
1625
|
const products = await this.store.order.addProductToOrder(product);
|
|
1481
1626
|
await this.refreshItemRuleQuantityLimits();
|
|
@@ -1942,6 +2087,7 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
|
|
|
1942
2087
|
};
|
|
1943
2088
|
var VenueBookingImpl = _VenueBookingImpl;
|
|
1944
2089
|
VenueBookingImpl.OPEN_DATA_CACHE_TTL = 5 * 60 * 1e3;
|
|
2090
|
+
VenueBookingImpl.PISELL1_LOGIN_SUCCESS = "pisell1.login.success";
|
|
1945
2091
|
// ─── UI 状态缓存(按 cacheId 分桶,sessionStorage) ───
|
|
1946
2092
|
//
|
|
1947
2093
|
// 用于物料层持久化 UI 层面的轻量状态(如当前步骤、登录回跳意图等)。
|
|
@@ -6,7 +6,9 @@ export declare enum VenueBookingHooks {
|
|
|
6
6
|
onDestroy = "venueBooking:onDestroy",
|
|
7
7
|
onRetryInit = "venueBooking:onRetryInit",
|
|
8
8
|
onRefresh = "venueBooking:onRefresh",
|
|
9
|
-
onCartValidationChanged = "venueBooking:onCartValidationChanged"
|
|
9
|
+
onCartValidationChanged = "venueBooking:onCartValidationChanged",
|
|
10
|
+
/** 登录客户的智能定价、营销配置与订单汇总已完成刷新 */
|
|
11
|
+
onSmartPricingUpdated = "venueBooking:onSmartPricingUpdated"
|
|
10
12
|
}
|
|
11
13
|
export type VenueBookingStatus = 'idle' | 'initializing' | 'ready' | 'error';
|
|
12
14
|
export interface VenueBookingEntryContext {
|
|
@@ -29,6 +29,7 @@ var VenueBookingHooks = /* @__PURE__ */ ((VenueBookingHooks2) => {
|
|
|
29
29
|
VenueBookingHooks2["onRetryInit"] = "venueBooking:onRetryInit";
|
|
30
30
|
VenueBookingHooks2["onRefresh"] = "venueBooking:onRefresh";
|
|
31
31
|
VenueBookingHooks2["onCartValidationChanged"] = "venueBooking:onCartValidationChanged";
|
|
32
|
+
VenueBookingHooks2["onSmartPricingUpdated"] = "venueBooking:onSmartPricingUpdated";
|
|
32
33
|
return VenueBookingHooks2;
|
|
33
34
|
})(VenueBookingHooks || {});
|
|
34
35
|
var DEFAULT_SLOT_CONFIG = {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { VenueBookingSlotConfig, VenueResourceRawData, VenueDateSummaryItem, ResourceProductMapping } from '../types';
|
|
2
|
-
import type { QuotationModule } from '../../../modules/Quotation';
|
|
3
2
|
export declare function buildDateRangeSummary(params: {
|
|
4
3
|
startDate: string;
|
|
5
4
|
endDate: string;
|
|
6
5
|
config: VenueBookingSlotConfig;
|
|
7
6
|
rawResources: VenueResourceRawData[];
|
|
8
7
|
resourceProductMap: Map<number | string, ResourceProductMapping[]>;
|
|
9
|
-
quotationModule?: QuotationModule;
|
|
10
8
|
resolveConfig?: (date: string) => VenueBookingSlotConfig;
|
|
9
|
+
/** 按日期构建 slot 智能定价 Map */
|
|
10
|
+
buildSlotPriceMap?: (date: string, config: VenueBookingSlotConfig, productIds: number[]) => Map<string, string | null>;
|
|
11
11
|
}): VenueDateSummaryItem[];
|
|
@@ -41,28 +41,23 @@ function buildDateRangeSummary(params) {
|
|
|
41
41
|
config,
|
|
42
42
|
rawResources,
|
|
43
43
|
resourceProductMap,
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
resolveConfig,
|
|
45
|
+
buildSlotPriceMap
|
|
46
46
|
} = params;
|
|
47
47
|
const result = [];
|
|
48
|
-
const productIds =
|
|
48
|
+
const productIds = buildSlotPriceMap ? [...new Set([...resourceProductMap.values()].flat().map((m) => m.productId))] : [];
|
|
49
49
|
let cursor = (0, import_dayjs.default)(startDate);
|
|
50
50
|
const end = (0, import_dayjs.default)(endDate);
|
|
51
51
|
while (!cursor.isAfter(end)) {
|
|
52
52
|
const date = cursor.format("YYYY-MM-DD");
|
|
53
53
|
const effectiveConfig = (resolveConfig == null ? void 0 : resolveConfig(date)) || config;
|
|
54
|
-
|
|
55
|
-
if (quotationModule && productIds.length) {
|
|
56
|
-
const timeLabels = (0, import_timeSlot.generateTimeLabels)(effectiveConfig);
|
|
57
|
-
const timePoints = timeLabels.map((label) => `${date} ${label}`);
|
|
58
|
-
quotationPriceMap = quotationModule.buildProductPriceMap({ productIds, timePoints });
|
|
59
|
-
}
|
|
54
|
+
const slotPriceMap = buildSlotPriceMap && productIds.length ? buildSlotPriceMap(date, effectiveConfig, productIds) : void 0;
|
|
60
55
|
const grid = (0, import_timeSlot.buildTimeSlotGrid)({
|
|
61
56
|
date,
|
|
62
57
|
config: effectiveConfig,
|
|
63
58
|
rawResources,
|
|
64
59
|
resourceProductMap,
|
|
65
|
-
|
|
60
|
+
slotPriceMap
|
|
66
61
|
});
|
|
67
62
|
let totalSlots = 0;
|
|
68
63
|
let availableSlots = 0;
|
|
@@ -5,12 +5,6 @@ export declare function mergeConsecutiveSlots(slots: VenueSlotSelection[]): Merg
|
|
|
5
5
|
export declare function buildPriceBreakdown(params: {
|
|
6
6
|
group: MergedSlotGroup;
|
|
7
7
|
productId: number;
|
|
8
|
-
quotation?: {
|
|
9
|
-
getQuotationShelfId: (p: {
|
|
10
|
-
productId: number;
|
|
11
|
-
datetime: string;
|
|
12
|
-
}) => number;
|
|
13
|
-
};
|
|
14
8
|
}): PriceBreakdownEntry[];
|
|
15
9
|
export interface BuildVenueBookingParams {
|
|
16
10
|
group: MergedSlotGroup;
|
|
@@ -82,17 +82,16 @@ function mergeConsecutiveSlots(slots) {
|
|
|
82
82
|
return groups;
|
|
83
83
|
}
|
|
84
84
|
function buildPriceBreakdown(params) {
|
|
85
|
-
const { group
|
|
85
|
+
const { group } = params;
|
|
86
86
|
if (!group.slots.length)
|
|
87
87
|
return [];
|
|
88
88
|
const entries = [];
|
|
89
89
|
for (const slot of group.slots) {
|
|
90
90
|
const unitPrice = Number(slot.price || "0");
|
|
91
|
-
const shelfId = quotation ? quotation.getQuotationShelfId({ productId, datetime: slot.startTime }) : 0;
|
|
92
91
|
const startHm = (0, import_dayjs.default)(slot.startTime, "YYYY-MM-DD HH:mm").format("YYYY-MM-DD HH:mm");
|
|
93
92
|
const endHm = (0, import_dayjs.default)(slot.endTime, "YYYY-MM-DD HH:mm").format("YYYY-MM-DD HH:mm");
|
|
94
93
|
const last = entries[entries.length - 1];
|
|
95
|
-
if (last && last.unit_price === unitPrice && last.quotation_shelf_id ===
|
|
94
|
+
if (last && last.unit_price === unitPrice && last.quotation_shelf_id === 0 && last.end_time === startHm) {
|
|
96
95
|
last.end_time = endHm;
|
|
97
96
|
last.quantity += 1;
|
|
98
97
|
} else {
|
|
@@ -100,7 +99,7 @@ function buildPriceBreakdown(params) {
|
|
|
100
99
|
start_time: startHm,
|
|
101
100
|
end_time: endHm,
|
|
102
101
|
unit_price: unitPrice,
|
|
103
|
-
quotation_shelf_id:
|
|
102
|
+
quotation_shelf_id: 0,
|
|
104
103
|
quantity: 1
|
|
105
104
|
});
|
|
106
105
|
}
|