@pisell/pisellos 2.2.313 → 2.2.315
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 +2 -0
- package/dist/index.js +3 -1
- package/dist/model/strategy/adapter/itemRule/adapter.d.ts +3 -1
- package/dist/model/strategy/adapter/itemRule/adapter.js +74 -7
- package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +3 -1
- package/dist/model/strategy/adapter/itemRule/evaluator.js +13 -0
- package/dist/model/strategy/adapter/itemRule/type.d.ts +40 -1
- package/dist/model/strategy/adapter/itemRule/type.js +10 -0
- package/dist/modules/BookingContext/utils/productExtend.d.ts +7 -0
- package/dist/modules/BookingContext/utils/productExtend.js +62 -18
- package/dist/modules/BookingContext/utils/resources.js +1 -1
- package/dist/modules/BusinessAvailability/index.d.ts +30 -0
- package/dist/modules/BusinessAvailability/index.js +204 -0
- package/dist/modules/Cart/index.js +4 -3
- package/dist/modules/Cart/types.d.ts +2 -0
- package/dist/modules/Cart/utils/cartProduct.d.ts +3 -1
- package/dist/modules/Cart/utils/cartProduct.js +59 -32
- package/dist/modules/FulfillmentTiming/index.d.ts +11 -0
- package/dist/modules/FulfillmentTiming/index.js +407 -0
- package/dist/modules/FulfillmentTiming/types.d.ts +67 -0
- package/dist/modules/FulfillmentTiming/types.js +1 -0
- package/dist/modules/OpenData/types.d.ts +14 -0
- package/dist/modules/Order/index.d.ts +14 -2
- package/dist/modules/Order/index.js +856 -486
- package/dist/modules/Order/localEftposState.d.ts +13 -0
- package/dist/modules/Order/localEftposState.js +39 -0
- package/dist/modules/Order/pickupTiming.d.ts +46 -0
- package/dist/modules/Order/pickupTiming.js +53 -0
- package/dist/modules/Order/types.d.ts +30 -2
- package/dist/modules/Order/utils.js +25 -7
- package/dist/modules/Payment/index.js +9 -10
- package/dist/modules/Product/types.d.ts +11 -0
- package/dist/modules/ProductList/index.js +1 -1
- package/dist/modules/ResourcePlanner/planner.d.ts +2 -0
- package/dist/modules/ResourcePlanner/planner.js +332 -23
- package/dist/modules/ResourcePlanner/types.d.ts +29 -0
- package/dist/modules/Schedule/index.d.ts +8 -0
- package/dist/modules/Schedule/index.js +141 -39
- package/dist/modules/index.d.ts +1 -0
- package/dist/modules/index.js +1 -0
- package/dist/plugins/request.d.ts +7 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1536 -1309
- package/dist/server/modules/form/index.d.ts +19 -0
- package/dist/server/modules/form/index.js +205 -0
- package/dist/server/modules/form/types.d.ts +13 -0
- package/dist/server/modules/form/types.js +3 -0
- package/dist/server/modules/index.d.ts +3 -0
- package/dist/server/modules/index.js +4 -0
- package/dist/server/modules/order/index.d.ts +15 -0
- package/dist/server/modules/order/index.js +920 -688
- package/dist/server/modules/order/types.d.ts +1 -0
- package/dist/server/test.json +1 -1
- package/dist/server/utils/small-ticket.d.ts +1 -85
- package/dist/server/utils/small-ticket.js +2 -2542
- package/dist/shared/payment/loadPaymentMethods.d.ts +9 -0
- package/dist/shared/payment/loadPaymentMethods.js +66 -0
- package/dist/shared/receipt/customerInvoiceLanguages.d.ts +8 -0
- package/dist/shared/receipt/customerInvoiceLanguages.js +60 -0
- package/dist/shared/receipt/loadCustomerInvoiceLayout.d.ts +27 -0
- package/dist/shared/receipt/loadCustomerInvoiceLayout.js +184 -0
- package/dist/shared/receipt/small-ticket.d.ts +96 -0
- package/dist/shared/receipt/small-ticket.js +2751 -0
- package/dist/shared/receipt/templateVisibility.d.ts +23 -0
- package/dist/shared/receipt/templateVisibility.js +64 -0
- package/dist/shared/sales/loadSalesOrderSnapshot.d.ts +9 -0
- package/dist/shared/sales/loadSalesOrderSnapshot.js +21 -0
- package/dist/solution/BaseSales/fulfillmentItemRules.d.ts +27 -0
- package/dist/solution/BaseSales/fulfillmentItemRules.js +750 -0
- package/dist/solution/BaseSales/index.d.ts +39 -16
- package/dist/solution/BaseSales/index.js +1754 -1154
- package/dist/solution/BaseSales/pickupTiming.d.ts +47 -0
- package/dist/solution/BaseSales/pickupTiming.js +616 -0
- package/dist/solution/BaseSales/types.d.ts +11 -0
- package/dist/solution/BaseSales/utils/parseSalesResponse.js +3 -0
- package/dist/solution/BookingByStep/index.d.ts +4 -2
- package/dist/solution/BookingByStep/index.js +8 -3
- package/dist/solution/BookingTicket/index.d.ts +8 -2
- package/dist/solution/BookingTicket/index.js +513 -436
- package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +0 -1
- package/dist/solution/BookingTicket/utils/addProductDecision.js +1 -1
- package/dist/solution/BookingTicket/utils/cartView.js +3 -1
- package/dist/solution/OrderInvoicePreview/index.d.ts +66 -0
- package/dist/solution/OrderInvoicePreview/index.js +340 -0
- package/dist/solution/RegisterAndLogin/config.js +54 -11
- package/dist/solution/RegisterAndLogin/index.d.ts +2 -0
- package/dist/solution/RegisterAndLogin/index.js +1 -1
- package/dist/solution/RegisterAndLogin/utils.d.ts +12 -4
- package/dist/solution/RegisterAndLogin/utils.js +36 -16
- package/dist/solution/Sales/index.js +1 -1
- package/dist/solution/UnifiedBookingSales/businessAvailability.d.ts +27 -0
- package/dist/solution/UnifiedBookingSales/businessAvailability.js +292 -0
- package/dist/solution/UnifiedBookingSales/index.d.ts +36 -4
- package/dist/solution/UnifiedBookingSales/index.js +1714 -905
- package/dist/solution/UnifiedBookingSales/types.d.ts +16 -2
- package/dist/solution/VenueBooking/index.d.ts +15 -2
- package/dist/solution/VenueBooking/index.js +1062 -785
- package/dist/solution/VenueBooking/types.d.ts +2 -1
- package/dist/solution/VenueBooking/types.js +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.js +7 -4
- package/dist/solution/VenueBooking/utils/smartPricing.d.ts +71 -0
- package/dist/solution/VenueBooking/utils/smartPricing.js +273 -0
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/timeSlot.js +6 -3
- package/dist/solution/index.d.ts +1 -0
- package/dist/solution/index.js +2 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +21 -1
- package/lib/model/strategy/adapter/itemRule/adapter.d.ts +3 -1
- package/lib/model/strategy/adapter/itemRule/adapter.js +54 -4
- package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +3 -1
- package/lib/model/strategy/adapter/itemRule/evaluator.js +9 -0
- package/lib/model/strategy/adapter/itemRule/type.d.ts +40 -1
- package/lib/model/strategy/adapter/itemRule/type.js +10 -0
- package/lib/modules/BookingContext/utils/productExtend.d.ts +7 -0
- package/lib/modules/BookingContext/utils/productExtend.js +45 -2
- package/lib/modules/BookingContext/utils/resources.js +1 -1
- package/lib/modules/BusinessAvailability/index.d.ts +30 -0
- package/lib/modules/BusinessAvailability/index.js +146 -0
- package/lib/modules/Cart/index.js +4 -2
- package/lib/modules/Cart/types.d.ts +2 -0
- package/lib/modules/Cart/utils/cartProduct.d.ts +3 -1
- package/lib/modules/Cart/utils/cartProduct.js +39 -20
- package/lib/modules/FulfillmentTiming/index.d.ts +11 -0
- package/lib/modules/FulfillmentTiming/index.js +359 -0
- package/lib/modules/FulfillmentTiming/types.d.ts +67 -0
- package/lib/modules/FulfillmentTiming/types.js +5 -0
- package/lib/modules/OpenData/types.d.ts +14 -0
- package/lib/modules/Order/index.d.ts +14 -2
- package/lib/modules/Order/index.js +240 -38
- package/lib/modules/Order/localEftposState.d.ts +13 -0
- package/lib/modules/Order/localEftposState.js +44 -0
- package/lib/modules/Order/pickupTiming.d.ts +46 -0
- package/lib/modules/Order/pickupTiming.js +61 -0
- package/lib/modules/Order/types.d.ts +30 -2
- package/lib/modules/Order/utils.js +21 -5
- package/lib/modules/Payment/index.js +3 -4
- package/lib/modules/Product/types.d.ts +11 -0
- package/lib/modules/ProductList/index.js +1 -1
- package/lib/modules/ResourcePlanner/planner.d.ts +2 -0
- package/lib/modules/ResourcePlanner/planner.js +252 -8
- package/lib/modules/ResourcePlanner/types.d.ts +29 -0
- package/lib/modules/Schedule/index.d.ts +8 -0
- package/lib/modules/Schedule/index.js +68 -12
- package/lib/modules/index.d.ts +1 -0
- package/lib/modules/index.js +11 -0
- package/lib/plugins/request.d.ts +7 -0
- package/lib/server/index.d.ts +1 -0
- package/lib/server/index.js +158 -37
- package/lib/server/modules/form/index.d.ts +19 -0
- package/lib/server/modules/form/index.js +73 -0
- package/lib/server/modules/form/types.d.ts +13 -0
- package/lib/server/modules/form/types.js +9 -0
- package/lib/server/modules/index.d.ts +3 -0
- package/lib/server/modules/index.js +15 -1
- package/lib/server/modules/order/index.d.ts +15 -0
- package/lib/server/modules/order/index.js +114 -3
- package/lib/server/modules/order/types.d.ts +1 -0
- package/lib/server/test.json +1 -1
- package/lib/server/utils/small-ticket.d.ts +1 -85
- package/lib/server/utils/small-ticket.js +9 -2305
- package/lib/shared/payment/loadPaymentMethods.d.ts +9 -0
- package/lib/shared/payment/loadPaymentMethods.js +40 -0
- package/lib/shared/receipt/customerInvoiceLanguages.d.ts +8 -0
- package/lib/shared/receipt/customerInvoiceLanguages.js +58 -0
- package/lib/shared/receipt/loadCustomerInvoiceLayout.d.ts +27 -0
- package/lib/shared/receipt/loadCustomerInvoiceLayout.js +124 -0
- package/lib/shared/receipt/small-ticket.d.ts +96 -0
- package/lib/shared/receipt/small-ticket.js +2546 -0
- package/lib/shared/receipt/templateVisibility.d.ts +23 -0
- package/lib/shared/receipt/templateVisibility.js +63 -0
- package/lib/shared/sales/loadSalesOrderSnapshot.d.ts +9 -0
- package/lib/shared/sales/loadSalesOrderSnapshot.js +22 -0
- package/lib/solution/BaseSales/fulfillmentItemRules.d.ts +27 -0
- package/lib/solution/BaseSales/fulfillmentItemRules.js +259 -0
- package/lib/solution/BaseSales/index.d.ts +39 -16
- package/lib/solution/BaseSales/index.js +333 -31
- package/lib/solution/BaseSales/pickupTiming.d.ts +47 -0
- package/lib/solution/BaseSales/pickupTiming.js +290 -0
- package/lib/solution/BaseSales/types.d.ts +11 -0
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +3 -0
- package/lib/solution/BookingByStep/index.d.ts +4 -2
- package/lib/solution/BookingByStep/index.js +7 -3
- package/lib/solution/BookingTicket/index.d.ts +8 -2
- package/lib/solution/BookingTicket/index.js +65 -6
- package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +0 -1
- package/lib/solution/BookingTicket/utils/addProductDecision.js +1 -1
- package/lib/solution/BookingTicket/utils/cartView.js +3 -1
- package/lib/solution/OrderInvoicePreview/index.d.ts +66 -0
- package/lib/solution/OrderInvoicePreview/index.js +246 -0
- package/lib/solution/RegisterAndLogin/config.js +57 -11
- package/lib/solution/RegisterAndLogin/index.d.ts +2 -0
- package/lib/solution/RegisterAndLogin/index.js +9 -1
- package/lib/solution/RegisterAndLogin/utils.d.ts +12 -4
- package/lib/solution/RegisterAndLogin/utils.js +24 -17
- package/lib/solution/Sales/index.js +1 -1
- package/lib/solution/UnifiedBookingSales/businessAvailability.d.ts +27 -0
- package/lib/solution/UnifiedBookingSales/businessAvailability.js +138 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +36 -4
- package/lib/solution/UnifiedBookingSales/index.js +561 -74
- package/lib/solution/UnifiedBookingSales/types.d.ts +16 -2
- package/lib/solution/VenueBooking/index.d.ts +15 -2
- package/lib/solution/VenueBooking/index.js +243 -96
- package/lib/solution/VenueBooking/types.d.ts +2 -1
- package/lib/solution/VenueBooking/types.js +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.js +7 -4
- package/lib/solution/VenueBooking/utils/smartPricing.d.ts +71 -0
- package/lib/solution/VenueBooking/utils/smartPricing.js +224 -0
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/timeSlot.js +5 -2
- package/lib/solution/index.d.ts +1 -0
- package/lib/solution/index.js +11 -0
- package/package.json +1 -1
|
@@ -72,6 +72,11 @@ export interface UnifiedBookingSalesPrepareAvailabilityProjectionParams {
|
|
|
72
72
|
}
|
|
73
73
|
export interface AvailabilityContextRef {
|
|
74
74
|
contextId: string;
|
|
75
|
+
/** POS/Kiosk duration protocol capability and business-day default. */
|
|
76
|
+
durationTimeSelection?: {
|
|
77
|
+
version: 1;
|
|
78
|
+
currentBusinessDate: string;
|
|
79
|
+
};
|
|
75
80
|
}
|
|
76
81
|
export interface ContextualProductTimeRange extends ProductTimeRange {
|
|
77
82
|
availabilityContextId: string;
|
|
@@ -80,7 +85,7 @@ export interface ContextualProductTimeRange extends ProductTimeRange {
|
|
|
80
85
|
export interface ContextualProductTimeRangeGroup extends Omit<ProductTimeRangeGroup, 'ranges'> {
|
|
81
86
|
ranges: ContextualProductTimeRange[];
|
|
82
87
|
}
|
|
83
|
-
export type ContextualAvailabilityQuery = Omit<Extract<AvailabilityQuery, {
|
|
88
|
+
export type ContextualAvailabilityQuery = (Omit<Extract<AvailabilityQuery, {
|
|
84
89
|
target: 'product';
|
|
85
90
|
}>, never> | Omit<Extract<AvailabilityQuery, {
|
|
86
91
|
target: 'date';
|
|
@@ -92,7 +97,10 @@ export type ContextualAvailabilityQuery = Omit<Extract<AvailabilityQuery, {
|
|
|
92
97
|
target: 'resource';
|
|
93
98
|
}>, 'selectedRanges'> & {
|
|
94
99
|
selectedRanges: ContextualProductTimeRange[];
|
|
95
|
-
})
|
|
100
|
+
})) & {
|
|
101
|
+
/** Automatic remembered selection must not inherit POS manual exceptions. */
|
|
102
|
+
selectionIntent?: 'remembered' | 'manual';
|
|
103
|
+
};
|
|
96
104
|
export type ContextualTimeAvailabilityItem = Omit<TimeAvailabilityItem, keyof ProductTimeRange> & ContextualProductTimeRange;
|
|
97
105
|
export interface ContextualTimeAvailabilityGroup extends Omit<TimeAvailabilityGroup, 'times'> {
|
|
98
106
|
times: ContextualTimeAvailabilityItem[];
|
|
@@ -155,6 +163,10 @@ export interface UnifiedBookingSalesAddRetailProductParams {
|
|
|
155
163
|
}
|
|
156
164
|
export interface ContextualCommitAvailabilitySelectionParams {
|
|
157
165
|
mode: 'add' | 'edit';
|
|
166
|
+
/** Only POS duration add supports automatic remembered-time commits. */
|
|
167
|
+
selectionIntent?: 'remembered' | 'manual';
|
|
168
|
+
/** Local UI intent guard, checked again immediately before the Order mutation. */
|
|
169
|
+
availabilityCommitGuard?: () => void;
|
|
158
170
|
productLineUid?: string;
|
|
159
171
|
orderProduct: Record<string, any>;
|
|
160
172
|
candidate: ContextualProductTimeRange;
|
|
@@ -216,6 +228,8 @@ export interface UnifiedBookingSalesDiscountResult {
|
|
|
216
228
|
summaryAfter?: unknown;
|
|
217
229
|
}
|
|
218
230
|
export interface UnifiedBookingSalesApi {
|
|
231
|
+
/** Uses cached business settings and evaluates the current store-local clock. */
|
|
232
|
+
getBusinessAvailability: () => Promise<import('../../modules/BusinessAvailability').BusinessAvailability>;
|
|
219
233
|
loadOpenData: (params: UnifiedBookingSalesLoadOpenDataParams) => Promise<OpenDataConfig>;
|
|
220
234
|
/** Returns the latest OpenData payload cached by this solution instance. */
|
|
221
235
|
getOpenData: () => Promise<OpenDataConfig | null>;
|
|
@@ -41,6 +41,11 @@ export declare class VenueBookingImpl extends BaseSalesImpl implements Module {
|
|
|
41
41
|
private customerLoginRefreshIdInFlight;
|
|
42
42
|
private loadAllProductsInFlight;
|
|
43
43
|
private productsLoaded;
|
|
44
|
+
private smartPricingCustomerId;
|
|
45
|
+
private smartPricingProductCatalog;
|
|
46
|
+
private slotPriceMapCache;
|
|
47
|
+
private slotPriceStrategyConfigs;
|
|
48
|
+
private slotPriceScheduleList;
|
|
44
49
|
private loadOpenDataConfigInFlight;
|
|
45
50
|
private static readonly OPEN_DATA_CACHE_TTL;
|
|
46
51
|
private getLoggerContext;
|
|
@@ -69,7 +74,7 @@ export declare class VenueBookingImpl extends BaseSalesImpl implements Module {
|
|
|
69
74
|
private clearLoginEffectListeners;
|
|
70
75
|
private registerLoginEffect;
|
|
71
76
|
private registerCustomerLoginListeners;
|
|
72
|
-
private
|
|
77
|
+
private refreshOrderMarketingForCustomer;
|
|
73
78
|
initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
|
|
74
79
|
destroy(): Promise<void>;
|
|
75
80
|
retryInit(): Promise<void>;
|
|
@@ -82,6 +87,11 @@ export declare class VenueBookingImpl extends BaseSalesImpl implements Module {
|
|
|
82
87
|
passed: boolean | null;
|
|
83
88
|
failures: QuantityCheckResult[];
|
|
84
89
|
};
|
|
90
|
+
private resolveCustomerIdForSmartPricing;
|
|
91
|
+
private buildSmartPricingContext;
|
|
92
|
+
private buildSlotPriceMapForDate;
|
|
93
|
+
/** 规则或客户上下文更新后,同步商品展示、已选时段和订单汇总。 */
|
|
94
|
+
refreshSmartPricing(): Promise<void>;
|
|
85
95
|
loadAllProducts(): Promise<{
|
|
86
96
|
venueProducts: ProductData[];
|
|
87
97
|
addonProducts: ProductData[];
|
|
@@ -167,7 +177,10 @@ export declare class VenueBookingImpl extends BaseSalesImpl implements Module {
|
|
|
167
177
|
onCustomerLogin(params: {
|
|
168
178
|
customerId: number;
|
|
169
179
|
}): Promise<void>;
|
|
170
|
-
|
|
180
|
+
/** 宿主退出登录或以匿名身份重新进入时,清理客户资产并恢复匿名价格。 */
|
|
181
|
+
onCustomerLogout(): Promise<void>;
|
|
182
|
+
private recalculateOrderPricesFromSmartPricing;
|
|
183
|
+
private resetProductPriceForSmartPricing;
|
|
171
184
|
scanCode(code: string, customerId?: number): Promise<{
|
|
172
185
|
isAvailable: boolean;
|
|
173
186
|
isAccepted?: boolean | undefined;
|
|
@@ -34,6 +34,7 @@ var _itemRule = require("../../model/strategy/adapter/itemRule");
|
|
|
34
34
|
var _resource = require("./utils/resource");
|
|
35
35
|
var _timeSlot = require("./utils/timeSlot");
|
|
36
36
|
var _dateSummary = require("./utils/dateSummary");
|
|
37
|
+
var _smartPricing = require("./utils/smartPricing");
|
|
37
38
|
var _slotMerge = require("./utils/slotMerge");
|
|
38
39
|
var _utils3 = require("../../modules/Order/utils");
|
|
39
40
|
var _Order = require("../../modules/Order");
|
|
@@ -94,6 +95,12 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
94
95
|
customerLoginRefreshIdInFlight = null;
|
|
95
96
|
loadAllProductsInFlight = null;
|
|
96
97
|
productsLoaded = false;
|
|
98
|
+
// undefined 尚未同步宿主身份;null 表示已明确退出,禁止回退到旧用户插件。
|
|
99
|
+
smartPricingCustomerId;
|
|
100
|
+
smartPricingProductCatalog = [];
|
|
101
|
+
slotPriceMapCache = new Map();
|
|
102
|
+
slotPriceStrategyConfigs;
|
|
103
|
+
slotPriceScheduleList = undefined;
|
|
97
104
|
loadOpenDataConfigInFlight = null;
|
|
98
105
|
static OPEN_DATA_CACHE_TTL = 5 * 60 * 1000;
|
|
99
106
|
getLoggerContext() {
|
|
@@ -248,7 +255,7 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
248
255
|
};
|
|
249
256
|
}
|
|
250
257
|
readProductOriginFromTempOrder(tempOrder, product) {
|
|
251
|
-
const uid =
|
|
258
|
+
const uid = (0, _utils3.getOrderProductLineUid)(product);
|
|
252
259
|
if (uid && tempOrder._extend?.productsByUid?.[uid]?.origin) {
|
|
253
260
|
return tempOrder._extend.productsByUid[uid].origin;
|
|
254
261
|
}
|
|
@@ -287,6 +294,9 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
287
294
|
return null;
|
|
288
295
|
}
|
|
289
296
|
resolveHolderCustomerId() {
|
|
297
|
+
if (this.smartPricingCustomerId !== undefined) {
|
|
298
|
+
return this.smartPricingCustomerId ?? undefined;
|
|
299
|
+
}
|
|
290
300
|
const customer = JSON.parse(this.window?.getLocalStorage?.('customer') || '{}');
|
|
291
301
|
if (customer?.id) return Number(customer.id);
|
|
292
302
|
return undefined;
|
|
@@ -338,52 +348,65 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
338
348
|
}
|
|
339
349
|
registerCustomerLoginListeners() {
|
|
340
350
|
this.clearLoginEffectListeners();
|
|
341
|
-
const
|
|
342
|
-
const registerAndLoginModule = this.core?.getModule('registerAndLogin');
|
|
343
|
-
const currentAccount = accountModule?.getCurrentAccount?.() || accountModule?.getAccount?.() || null;
|
|
344
|
-
const createHandleLogin = eventName => async payload => {
|
|
351
|
+
const handleLogin = async payload => {
|
|
345
352
|
const customerId = this.resolveCustomerIdFromLoginPayload(payload);
|
|
346
353
|
if (!customerId) return;
|
|
347
|
-
await this.
|
|
354
|
+
await this.refreshOrderMarketingForCustomer({
|
|
348
355
|
customerId
|
|
349
356
|
});
|
|
350
357
|
};
|
|
351
|
-
this.registerLoginEffect(_types3.AccountHooks.OnLogin,
|
|
352
|
-
this.registerLoginEffect(_types4.RegisterAndLoginHooks.onLoginSuccess,
|
|
358
|
+
this.registerLoginEffect(_types3.AccountHooks.OnLogin, handleLogin);
|
|
359
|
+
this.registerLoginEffect(_types4.RegisterAndLoginHooks.onLoginSuccess, handleLogin);
|
|
360
|
+
this.registerLoginEffect(_types3.AccountHooks.OnLogout, () => this.onCustomerLogout());
|
|
353
361
|
}
|
|
354
|
-
async
|
|
362
|
+
async refreshOrderMarketingForCustomer(params) {
|
|
355
363
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
356
|
-
if (this.customerLoginRefreshInFlight) {
|
|
357
|
-
if (this.customerLoginRefreshIdInFlight === params.customerId) {
|
|
358
|
-
await this.customerLoginRefreshInFlight;
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
364
|
+
if (this.customerLoginRefreshInFlight && this.customerLoginRefreshIdInFlight === params.customerId) {
|
|
361
365
|
await this.customerLoginRefreshInFlight;
|
|
366
|
+
return;
|
|
362
367
|
}
|
|
368
|
+
const previousRefresh = this.customerLoginRefreshInFlight;
|
|
363
369
|
this.customerLoginRefreshIdInFlight = params.customerId;
|
|
364
370
|
const refreshTask = (async () => {
|
|
365
|
-
//
|
|
366
|
-
if (
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
371
|
+
// 身份切换按调用顺序执行;上一请求失败也不能阻止退出清理。
|
|
372
|
+
if (previousRefresh) await previousRefresh.catch(() => undefined);
|
|
373
|
+
this.smartPricingCustomerId = params.customerId;
|
|
374
|
+
const order = this.store.order;
|
|
375
|
+
if (params.customerId === null) {
|
|
376
|
+
order.clearOrderCustomer();
|
|
377
|
+
// 清除客户记录,保留表单定义供下次登录刷新。
|
|
378
|
+
const holder = this.store.holder;
|
|
379
|
+
for (const formId of Object.keys(holder?.getHolderFormMap() || {})) {
|
|
380
|
+
holder?.setFormData(formId, {
|
|
381
|
+
records: []
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
} else {
|
|
385
|
+
const tempOrder = order.ensureTempOrder();
|
|
386
|
+
if (Number(tempOrder.customer_id) !== params.customerId) {
|
|
387
|
+
const user = this.core.getPlugin('user')?.get?.();
|
|
388
|
+
order.updateTempOrderCustomer({
|
|
389
|
+
...(Number(user?.id) === params.customerId ? user : {}),
|
|
390
|
+
customer_id: params.customerId
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
// 先获取新客户的钱包/优惠资产,再按该上下文计算智能价。
|
|
394
|
+
await order.loadDiscountConfig({
|
|
395
|
+
customerId: params.customerId,
|
|
396
|
+
apply: false
|
|
375
397
|
});
|
|
398
|
+
if (this.store.holder) {
|
|
399
|
+
await this.store.holder.refreshAllFormRecords({
|
|
400
|
+
customer_id: params.customerId,
|
|
401
|
+
useCache: false
|
|
402
|
+
});
|
|
403
|
+
}
|
|
376
404
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
await this.
|
|
382
|
-
createIfMissing: true
|
|
383
|
-
});
|
|
384
|
-
this.store.order.persistTempOrder();
|
|
385
|
-
await this.refreshItemRuleQuantityLimits();
|
|
386
|
-
await this.refreshCartValidationPassed();
|
|
405
|
+
|
|
406
|
+
// 不复用身份切换前尚未返回的商品请求,避免旧客户的结果覆盖新价格。
|
|
407
|
+
if (this.loadAllProductsInFlight) await this.loadAllProductsInFlight;
|
|
408
|
+
if (this.productsLoaded) await this.loadAllProducts();
|
|
409
|
+
await this.refreshSmartPricing();
|
|
387
410
|
})();
|
|
388
411
|
this.customerLoginRefreshInFlight = refreshTask;
|
|
389
412
|
try {
|
|
@@ -407,6 +430,12 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
407
430
|
this.store.status = 'initializing';
|
|
408
431
|
this.store.error = null;
|
|
409
432
|
this.store.rawResourceData = [];
|
|
433
|
+
this.smartPricingCustomerId = undefined;
|
|
434
|
+
this.smartPricingProductCatalog = [];
|
|
435
|
+
this.productsLoaded = false;
|
|
436
|
+
this.slotPriceStrategyConfigs = undefined;
|
|
437
|
+
this.slotPriceScheduleList = undefined;
|
|
438
|
+
this.slotPriceMapCache.clear();
|
|
410
439
|
this.baseSlotConfig = {
|
|
411
440
|
..._types.DEFAULT_SLOT_CONFIG,
|
|
412
441
|
...(options.otherParams?.slotConfig || {})
|
|
@@ -644,6 +673,80 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
644
673
|
failures: []
|
|
645
674
|
};
|
|
646
675
|
}
|
|
676
|
+
resolveCustomerIdForSmartPricing() {
|
|
677
|
+
if (this.smartPricingCustomerId !== undefined) return this.smartPricingCustomerId ?? undefined;
|
|
678
|
+
try {
|
|
679
|
+
const user = this.core?.getPlugin('user');
|
|
680
|
+
const customerId = Number(user?.get?.()?.id);
|
|
681
|
+
return Number.isFinite(customerId) && customerId > 0 ? customerId : undefined;
|
|
682
|
+
} catch {
|
|
683
|
+
return undefined;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
buildSmartPricingContext() {
|
|
687
|
+
const strategyContext = this.otherParams?.strategy_context || {};
|
|
688
|
+
const orderWalletIds = this.store.order?.getAvailableWalletIds?.();
|
|
689
|
+
const fallbackWalletIds = this.otherParams?.available_wallet_ids ?? this.otherParams?.availableWalletIds ?? strategyContext.available_wallet_ids ?? strategyContext.availableWalletIds;
|
|
690
|
+
const walletIds = this.smartPricingCustomerId === null ? [] : orderWalletIds?.length ? orderWalletIds : fallbackWalletIds;
|
|
691
|
+
return {
|
|
692
|
+
evaluator: this.core?.context?.dataVariantEvaluator,
|
|
693
|
+
scheduleList: this.store.schedule?.getScheduleList?.() || [],
|
|
694
|
+
menuList: this.otherParams?.menuList || this.otherParams?.openData?.menuList || this.core?.context?.menuList || [],
|
|
695
|
+
customerId: this.resolveCustomerIdForSmartPricing(),
|
|
696
|
+
availableWalletIds: Array.isArray(walletIds) ? walletIds : [],
|
|
697
|
+
channel: this.otherParams?.channel ?? strategyContext.channel,
|
|
698
|
+
businessCode: this.otherParams?.businessCode ?? strategyContext.business_code ?? strategyContext.businessCode,
|
|
699
|
+
orderType: this.otherParams?.orderType || this.otherParams?.type || strategyContext.orderType || strategyContext.order_type,
|
|
700
|
+
strategy_context: strategyContext
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
buildSlotPriceMapForDate(date, config, productIds) {
|
|
704
|
+
const context = this.buildSmartPricingContext();
|
|
705
|
+
const strategyConfigs = context.evaluator?.getStrategyConfigs?.();
|
|
706
|
+
if (strategyConfigs !== this.slotPriceStrategyConfigs) {
|
|
707
|
+
this.slotPriceMapCache.clear();
|
|
708
|
+
this.slotPriceStrategyConfigs = strategyConfigs;
|
|
709
|
+
}
|
|
710
|
+
if (context.scheduleList !== this.slotPriceScheduleList) {
|
|
711
|
+
this.slotPriceMapCache.clear();
|
|
712
|
+
this.slotPriceScheduleList = context.scheduleList;
|
|
713
|
+
}
|
|
714
|
+
const cacheKey = JSON.stringify([date, config, productIds, context.customerId, context.availableWalletIds, context.channel, context.businessCode, context.orderType]);
|
|
715
|
+
const cached = this.slotPriceMapCache.get(cacheKey);
|
|
716
|
+
if (cached) return cached;
|
|
717
|
+
const priceMap = (0, _smartPricing.buildSlotPriceMapByScheduleSegments)({
|
|
718
|
+
products: this.smartPricingProductCatalog,
|
|
719
|
+
productIds,
|
|
720
|
+
date,
|
|
721
|
+
timeLabels: (0, _timeSlot.generateTimeLabels)(config),
|
|
722
|
+
config,
|
|
723
|
+
context
|
|
724
|
+
});
|
|
725
|
+
this.slotPriceMapCache.set(cacheKey, priceMap);
|
|
726
|
+
return priceMap;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/** 规则或客户上下文更新后,同步商品展示、已选时段和订单汇总。 */
|
|
730
|
+
async refreshSmartPricing() {
|
|
731
|
+
if (this.loadAllProductsInFlight) await this.loadAllProductsInFlight;
|
|
732
|
+
this.slotPriceMapCache.clear();
|
|
733
|
+
if (!this.productsLoaded || !this.store.order) return;
|
|
734
|
+
await this.store.schedule?.loadAllSchedule();
|
|
735
|
+
const products = (0, _smartPricing.formatProductsWithDataVariant)(this.smartPricingProductCatalog, this.buildSmartPricingContext());
|
|
736
|
+
this.store.venueProducts?.addProduct(products.filter(product => product.duration != null));
|
|
737
|
+
this.store.addonProducts?.addProduct(products.filter(product => product.duration == null));
|
|
738
|
+
this.recalculateOrderPricesFromSmartPricing();
|
|
739
|
+
this.store.order.applyDiscount();
|
|
740
|
+
await this.store.order.recalculateSummary({
|
|
741
|
+
createIfMissing: false
|
|
742
|
+
});
|
|
743
|
+
this.store.order.persistTempOrder();
|
|
744
|
+
await this.refreshItemRuleQuantityLimits();
|
|
745
|
+
await this.refreshCartValidationPassed();
|
|
746
|
+
await this.core.effects.emit(_types.VenueBookingHooks.onSmartPricingUpdated, {
|
|
747
|
+
customerId: this.resolveCustomerIdForSmartPricing()
|
|
748
|
+
});
|
|
749
|
+
}
|
|
647
750
|
|
|
648
751
|
// ─── 场地商品 & 附加商品 ───
|
|
649
752
|
|
|
@@ -660,19 +763,34 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
660
763
|
if (!this.store.venueProducts) throw new Error('venueProducts 模块未初始化');
|
|
661
764
|
if (!this.store.addonProducts) throw new Error('addonProducts 模块未初始化');
|
|
662
765
|
await this.loadOpenDataConfig();
|
|
766
|
+
if (!this.store.schedule) throw new Error('schedule 模块未初始化');
|
|
767
|
+
await this.store.schedule.loadAllSchedule();
|
|
663
768
|
const associatedMenus = this.otherParams?.openData?.['menu.associated_menus'] || [];
|
|
664
769
|
if (!associatedMenus.length) {
|
|
665
770
|
this.logMethodError('loadAllProducts', new Error('未获取到餐牌配置(menu.associated_menus),请检查 OpenData 配置'));
|
|
666
771
|
throw new Error('未获取到餐牌配置(menu.associated_menus),请检查 OpenData 配置');
|
|
667
772
|
}
|
|
668
773
|
const menuListIds = associatedMenus.map(n => Number(n.value));
|
|
774
|
+
const pricingContext = this.buildSmartPricingContext();
|
|
669
775
|
const allProducts = await this.store.venueProducts.loadProducts({
|
|
670
776
|
menu_list_ids: menuListIds,
|
|
671
777
|
cacheId: this.cacheId,
|
|
672
778
|
schedule_date: (0, _dayjs.default)().format('YYYY-MM-DD'),
|
|
673
|
-
schedule_datetime: (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss')
|
|
779
|
+
schedule_datetime: (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss'),
|
|
780
|
+
customer_id: this.resolveCustomerIdForSmartPricing(),
|
|
781
|
+
strategy_context: {
|
|
782
|
+
...pricingContext.strategy_context,
|
|
783
|
+
channel: pricingContext.channel,
|
|
784
|
+
business_code: pricingContext.businessCode,
|
|
785
|
+
order_type: pricingContext.orderType,
|
|
786
|
+
available_wallet_ids: pricingContext.availableWalletIds
|
|
787
|
+
}
|
|
674
788
|
});
|
|
675
|
-
const
|
|
789
|
+
const loadedList = Array.isArray(allProducts) ? allProducts : [];
|
|
790
|
+
const rawProducts = this.store.venueProducts.getRawProductPriceSources(loadedList.map(product => product.id));
|
|
791
|
+
this.smartPricingProductCatalog = await Promise.all(loadedList.map(async product => rawProducts.get(product.id) ?? (await this.core.server?.getProducts?.()?.getProductById(product.id)) ?? product));
|
|
792
|
+
const list = (0, _smartPricing.formatProductsWithDataVariant)(this.smartPricingProductCatalog, this.buildSmartPricingContext());
|
|
793
|
+
this.slotPriceMapCache.clear();
|
|
676
794
|
const venueList = list.filter(p => p.duration != null);
|
|
677
795
|
const addonList = list.filter(p => p.duration == null);
|
|
678
796
|
const venueStore = this.store.venueProducts?.store;
|
|
@@ -680,7 +798,9 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
680
798
|
venueStore.list = venueList.slice().sort((a, b) => Number(b.sort) - Number(a.sort));
|
|
681
799
|
}
|
|
682
800
|
this.store.addonProducts.addProduct(addonList);
|
|
683
|
-
|
|
801
|
+
|
|
802
|
+
// 无规则命中时仍应回到原始商品价,不能回退到加载时刻的智能价。
|
|
803
|
+
this.resourceProductMap = (0, _resource.buildResourceProductMap)(this.smartPricingProductCatalog.filter(product => product.duration != null));
|
|
684
804
|
|
|
685
805
|
// 加载 holder 表单
|
|
686
806
|
if (this.store.order) {
|
|
@@ -704,8 +824,10 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
704
824
|
}
|
|
705
825
|
}
|
|
706
826
|
async loadVenueProducts() {
|
|
707
|
-
|
|
708
|
-
|
|
827
|
+
await this.loadAllProducts();
|
|
828
|
+
// 同步会话中已选的时段,避免新网格价格与恢复的购物车价格不一致。
|
|
829
|
+
await this.refreshSmartPricing();
|
|
830
|
+
return this.getVenueProducts();
|
|
709
831
|
}
|
|
710
832
|
async loadAddonProducts() {
|
|
711
833
|
const result = await this.loadAllProducts();
|
|
@@ -866,31 +988,22 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
866
988
|
config: this.baseSlotConfig,
|
|
867
989
|
rawResources: this.store.rawResourceData,
|
|
868
990
|
resourceProductMap: this.resourceProductMap,
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
resolveConfig: date => this.resolveSlotConfigForDate(date)
|
|
991
|
+
resolveConfig: date => this.resolveSlotConfigForDate(date),
|
|
992
|
+
buildSlotPriceMap: (date, config, productIds) => this.buildSlotPriceMapForDate(date, config, productIds)
|
|
872
993
|
});
|
|
873
994
|
}
|
|
874
995
|
getTimeSlotGrid(date) {
|
|
875
996
|
const resolvedSlotConfig = this.syncOperatingHoursToSlotConfig(date);
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
const timeLabels = (0, _timeSlot.generateTimeLabels)(resolvedSlotConfig);
|
|
880
|
-
const timePoints = timeLabels.map(label => `${date} ${label}`);
|
|
881
|
-
quotationPriceMap = this.store.quotation.buildProductPriceMap({
|
|
882
|
-
productIds,
|
|
883
|
-
timePoints,
|
|
884
|
-
channel: this.otherParams?.channel
|
|
885
|
-
});
|
|
886
|
-
}
|
|
887
|
-
return (0, _timeSlot.buildTimeSlotGrid)({
|
|
997
|
+
const productIds = [...new Set([...this.resourceProductMap.values()].flat().map(mapping => mapping.productId))];
|
|
998
|
+
const slotPriceMap = this.buildSlotPriceMapForDate(date, resolvedSlotConfig, productIds);
|
|
999
|
+
const grid = (0, _timeSlot.buildTimeSlotGrid)({
|
|
888
1000
|
date,
|
|
889
1001
|
config: resolvedSlotConfig,
|
|
890
1002
|
rawResources: this.store.rawResourceData,
|
|
891
1003
|
resourceProductMap: this.resourceProductMap,
|
|
892
|
-
|
|
1004
|
+
slotPriceMap
|
|
893
1005
|
});
|
|
1006
|
+
return grid;
|
|
894
1007
|
}
|
|
895
1008
|
|
|
896
1009
|
// ─── 时间槽订单操作 ───
|
|
@@ -1107,7 +1220,7 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1107
1220
|
tempOrder.bookings = tempOrder.bookings || [];
|
|
1108
1221
|
for (let i = 0; i < merged.length; i++) {
|
|
1109
1222
|
const group = merged[i];
|
|
1110
|
-
const
|
|
1223
|
+
const productUid = (0, _slotMerge.buildVenueIdentityKey)(resourceId, i);
|
|
1111
1224
|
const bookingUuid = (0, _utils3.createUuidV4)();
|
|
1112
1225
|
const startMoment = (0, _dayjs.default)(group.startTime, 'YYYY-MM-DD HH:mm');
|
|
1113
1226
|
const endMoment = (0, _dayjs.default)(group.endTime, 'YYYY-MM-DD HH:mm');
|
|
@@ -1180,12 +1293,12 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1180
1293
|
const normalizedVenueOrderProduct = (0, _utils.normalizeOrderProduct)({
|
|
1181
1294
|
product_id: mapping.productId,
|
|
1182
1295
|
product_variant_id: 0,
|
|
1183
|
-
identity_key: identityKey,
|
|
1184
1296
|
num: 1,
|
|
1185
1297
|
selling_price: group.totalPrice,
|
|
1186
1298
|
original_price: group.totalPrice,
|
|
1187
1299
|
is_charge_tax: venueProduct?.is_charge_tax ?? 0,
|
|
1188
1300
|
metadata: {
|
|
1301
|
+
unique_identification_number: productUid,
|
|
1189
1302
|
venue_booking: true,
|
|
1190
1303
|
...(productTitle ? {
|
|
1191
1304
|
product_title: productTitle
|
|
@@ -1199,9 +1312,7 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1199
1312
|
booking_uid: bookingUuid,
|
|
1200
1313
|
price_breakdown: (0, _slotMerge.buildPriceBreakdown)({
|
|
1201
1314
|
group,
|
|
1202
|
-
productId: mapping.productId
|
|
1203
|
-
quotation: this.store.quotation,
|
|
1204
|
-
channel: this.otherParams?.channel
|
|
1315
|
+
productId: mapping.productId
|
|
1205
1316
|
})
|
|
1206
1317
|
},
|
|
1207
1318
|
_origin: venueProductOrigin
|
|
@@ -1210,7 +1321,7 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1210
1321
|
...normalizedVenueOrderProduct,
|
|
1211
1322
|
product_title: productTitle
|
|
1212
1323
|
} : normalizedVenueOrderProduct;
|
|
1213
|
-
this.attachProductOriginToTempOrder(tempOrder,
|
|
1324
|
+
this.attachProductOriginToTempOrder(tempOrder, productUid, venueProductOrigin);
|
|
1214
1325
|
tempOrder.products.push(venueOrderProduct);
|
|
1215
1326
|
const booking = (0, _slotMerge.buildVenueBookingEntry)({
|
|
1216
1327
|
group,
|
|
@@ -1218,7 +1329,7 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1218
1329
|
mapping,
|
|
1219
1330
|
rawResource,
|
|
1220
1331
|
bookingUuid,
|
|
1221
|
-
productUid
|
|
1332
|
+
productUid,
|
|
1222
1333
|
childResources: childRawResources
|
|
1223
1334
|
});
|
|
1224
1335
|
tempOrder.bookings.push(booking);
|
|
@@ -1252,6 +1363,7 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1252
1363
|
// ─── 配置 ───
|
|
1253
1364
|
|
|
1254
1365
|
setSlotConfig(config) {
|
|
1366
|
+
this.slotPriceMapCache.clear();
|
|
1255
1367
|
this.baseSlotConfig = {
|
|
1256
1368
|
...this.baseSlotConfig,
|
|
1257
1369
|
...config
|
|
@@ -1274,6 +1386,8 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1274
1386
|
if (!this.store.schedule) throw new Error('schedule 模块未初始化');
|
|
1275
1387
|
await this.store.schedule.loadAllSchedule();
|
|
1276
1388
|
this.injectScheduleResolverToQuotation();
|
|
1389
|
+
this.slotPriceMapCache.clear();
|
|
1390
|
+
await this.refreshSmartPricing();
|
|
1277
1391
|
this.logMethodSuccess('loadSchedules');
|
|
1278
1392
|
} catch (error) {
|
|
1279
1393
|
this.logMethodError('loadSchedules', error);
|
|
@@ -1313,7 +1427,7 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1313
1427
|
customerId: params.customerId
|
|
1314
1428
|
});
|
|
1315
1429
|
try {
|
|
1316
|
-
await this.
|
|
1430
|
+
await this.refreshOrderMarketingForCustomer({
|
|
1317
1431
|
customerId: params.customerId
|
|
1318
1432
|
});
|
|
1319
1433
|
this.logMethodSuccess('onCustomerLogin', {
|
|
@@ -1324,8 +1438,15 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1324
1438
|
throw error;
|
|
1325
1439
|
}
|
|
1326
1440
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1441
|
+
|
|
1442
|
+
/** 宿主退出登录或以匿名身份重新进入时,清理客户资产并恢复匿名价格。 */
|
|
1443
|
+
async onCustomerLogout() {
|
|
1444
|
+
await this.refreshOrderMarketingForCustomer({
|
|
1445
|
+
customerId: null
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
recalculateOrderPricesFromSmartPricing() {
|
|
1449
|
+
if (!this.store.order) return;
|
|
1329
1450
|
const tempOrder = this.store.order.getTempOrder();
|
|
1330
1451
|
if (!tempOrder?.products?.length) return;
|
|
1331
1452
|
const now = (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss');
|
|
@@ -1336,40 +1457,67 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1336
1457
|
const mapping = mappings.find(m => Number(m.productId) === Number(product.product_id)) || mappings[0];
|
|
1337
1458
|
if (!mapping) continue;
|
|
1338
1459
|
const slots = (0, _slotMerge.expandMergedSlotToIndividual)(product, this.store.slotConfig.slotDurationMinutes);
|
|
1339
|
-
const updatedSlots = slots.map(slot =>
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1460
|
+
const updatedSlots = slots.map(slot => {
|
|
1461
|
+
const slotStart = (0, _dayjs.default)(slot.startTime);
|
|
1462
|
+
let date = slotStart.format('YYYY-MM-DD');
|
|
1463
|
+
const previousDate = slotStart.subtract(1, 'day').format('YYYY-MM-DD');
|
|
1464
|
+
const previousConfig = this.resolveSlotConfigForDate(previousDate);
|
|
1465
|
+
if ((0, _timeSlot.isBusinessHoursCrossDay)(previousConfig) && slotStart.format('HH:mm') < previousConfig.businessStartTime) {
|
|
1466
|
+
date = previousDate;
|
|
1467
|
+
}
|
|
1468
|
+
const slotPriceMap = this.buildSlotPriceMapForDate(date, this.resolveSlotConfigForDate(date), [mapping.productId]);
|
|
1469
|
+
return {
|
|
1470
|
+
...slot,
|
|
1343
1471
|
productId: mapping.productId,
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1472
|
+
price: (0, _smartPricing.getSlotPriceFromMap)({
|
|
1473
|
+
slotPriceMap,
|
|
1474
|
+
productId: mapping.productId,
|
|
1475
|
+
slotStartTime: slot.startTime,
|
|
1476
|
+
fallbackPrice: mapping.price
|
|
1477
|
+
})
|
|
1478
|
+
};
|
|
1479
|
+
});
|
|
1348
1480
|
const merged = (0, _slotMerge.mergeConsecutiveSlots)(updatedSlots);
|
|
1349
1481
|
if (merged.length === 1) {
|
|
1350
|
-
product
|
|
1351
|
-
product.original_price = merged[0].totalPrice;
|
|
1482
|
+
this.resetProductPriceForSmartPricing(product, merged[0].totalPrice);
|
|
1352
1483
|
product.metadata.price_breakdown = (0, _slotMerge.buildPriceBreakdown)({
|
|
1353
1484
|
group: merged[0],
|
|
1354
|
-
productId: mapping.productId
|
|
1355
|
-
quotation: this.store.quotation,
|
|
1356
|
-
channel: this.otherParams?.channel
|
|
1485
|
+
productId: mapping.productId
|
|
1357
1486
|
});
|
|
1358
1487
|
}
|
|
1359
1488
|
} else if (product.product_id != null) {
|
|
1360
|
-
const
|
|
1489
|
+
const price = (0, _smartPricing.getPriceForProductAtDatetime)({
|
|
1490
|
+
products: this.smartPricingProductCatalog,
|
|
1491
|
+
context: this.buildSmartPricingContext(),
|
|
1361
1492
|
productId: product.product_id,
|
|
1362
1493
|
variantId: product.product_variant_id ?? undefined,
|
|
1363
1494
|
datetime: now,
|
|
1364
|
-
|
|
1495
|
+
fallbackPrice: product.metadata?.source_product_price ?? product.original_price
|
|
1365
1496
|
});
|
|
1366
|
-
|
|
1367
|
-
product.selling_price = quotationPrice;
|
|
1368
|
-
product.original_price = quotationPrice;
|
|
1369
|
-
}
|
|
1497
|
+
this.resetProductPriceForSmartPricing(product, price);
|
|
1370
1498
|
}
|
|
1371
1499
|
}
|
|
1372
1500
|
}
|
|
1501
|
+
resetProductPriceForSmartPricing(product, price) {
|
|
1502
|
+
const mainPrice = new _decimal.default(price).plus((0, _utils3.sumOptionUnitPrice)((0, _utils3.getProductSkuOptions)(product))).toFixed(2);
|
|
1503
|
+
product.metadata = {
|
|
1504
|
+
...product.metadata,
|
|
1505
|
+
source_product_price: price,
|
|
1506
|
+
main_product_original_price: mainPrice,
|
|
1507
|
+
main_product_selling_price: mainPrice,
|
|
1508
|
+
price_schema_version: 2
|
|
1509
|
+
};
|
|
1510
|
+
product.discount_list = [];
|
|
1511
|
+
product.selling_price = (0, _utils3.composeLinePrice)({
|
|
1512
|
+
mainPrice,
|
|
1513
|
+
bundle: product.product_bundle
|
|
1514
|
+
});
|
|
1515
|
+
product.original_price = (0, _utils3.composeLinePrice)({
|
|
1516
|
+
mainPrice,
|
|
1517
|
+
bundle: product.product_bundle,
|
|
1518
|
+
useOriginalBundle: true
|
|
1519
|
+
});
|
|
1520
|
+
}
|
|
1373
1521
|
async scanCode(code, customerId) {
|
|
1374
1522
|
this.logMethodStart('scanCode', {
|
|
1375
1523
|
code
|
|
@@ -1565,19 +1713,16 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1565
1713
|
});
|
|
1566
1714
|
try {
|
|
1567
1715
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1568
|
-
if (!product.metadata?.venue_booking &&
|
|
1569
|
-
const
|
|
1716
|
+
if (!product.metadata?.venue_booking && product.product_id != null) {
|
|
1717
|
+
const price = (0, _smartPricing.getPriceForProductAtDatetime)({
|
|
1718
|
+
products: this.smartPricingProductCatalog,
|
|
1719
|
+
context: this.buildSmartPricingContext(),
|
|
1570
1720
|
productId: product.product_id,
|
|
1571
1721
|
variantId: product.product_variant_id ?? undefined,
|
|
1572
1722
|
datetime: (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss'),
|
|
1573
|
-
|
|
1723
|
+
fallbackPrice: product.metadata?.source_product_price ?? product.selling_price
|
|
1574
1724
|
});
|
|
1575
|
-
|
|
1576
|
-
product.selling_price = quotationPrice;
|
|
1577
|
-
product.original_price = quotationPrice;
|
|
1578
|
-
} else if (product.selling_price != null) {
|
|
1579
|
-
product.original_price = product.selling_price;
|
|
1580
|
-
}
|
|
1725
|
+
this.resetProductPriceForSmartPricing(product, price);
|
|
1581
1726
|
}
|
|
1582
1727
|
const products = await this.store.order.addProductToOrder(product);
|
|
1583
1728
|
await this.refreshItemRuleQuantityLimits();
|
|
@@ -1624,7 +1769,8 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1624
1769
|
const venueBookingUids = new Set();
|
|
1625
1770
|
for (const product of tempOrder.products || []) {
|
|
1626
1771
|
if (!product?.metadata?.venue_booking) continue;
|
|
1627
|
-
|
|
1772
|
+
const productUid = (0, _utils3.getOrderProductLineUid)(product);
|
|
1773
|
+
if (productUid) venueProductUids.add(productUid);
|
|
1628
1774
|
if (product.metadata?.booking_uid) {
|
|
1629
1775
|
venueBookingUids.add(String(product.metadata.booking_uid));
|
|
1630
1776
|
}
|
|
@@ -1853,7 +1999,7 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1853
1999
|
},
|
|
1854
2000
|
_origin: origin
|
|
1855
2001
|
});
|
|
1856
|
-
const productUid =
|
|
2002
|
+
const productUid = (0, _utils3.getOrderProductLineUid)(product) || '';
|
|
1857
2003
|
this.attachProductOriginToTempOrder(tempOrder, productUid, origin);
|
|
1858
2004
|
tempOrder.products.push(product);
|
|
1859
2005
|
hasChanges = true;
|
|
@@ -1879,7 +2025,7 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
1879
2025
|
}
|
|
1880
2026
|
};
|
|
1881
2027
|
if (delta > 0 || Boolean(sourceItem && (!previousOrigin || previousOrigin?.price !== sourceItem?.price))) {
|
|
1882
|
-
const productUid =
|
|
2028
|
+
const productUid = (0, _utils3.getOrderProductLineUid)(nextProduct) || '';
|
|
1883
2029
|
this.attachProductOriginToTempOrder(tempOrder, productUid, nextOrigin);
|
|
1884
2030
|
tempOrder.products[productIndex] = nextProduct;
|
|
1885
2031
|
hasChanges = true;
|
|
@@ -2092,6 +2238,7 @@ class VenueBookingImpl extends _BaseSales.BaseSalesImpl {
|
|
|
2092
2238
|
async setOtherParams(params, {
|
|
2093
2239
|
cover = false
|
|
2094
2240
|
} = {}) {
|
|
2241
|
+
this.slotPriceMapCache.clear();
|
|
2095
2242
|
if (cover) {
|
|
2096
2243
|
this.otherParams = params;
|
|
2097
2244
|
} else {
|