@pisell/pisellos 2.1.129 → 2.1.131
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 +7 -6
- package/dist/modules/Order/index.js +137 -42
- package/dist/modules/Order/types.d.ts +32 -6
- package/dist/modules/Order/types.js +2 -0
- package/dist/modules/Order/utils.d.ts +73 -11
- package/dist/modules/Order/utils.js +304 -52
- package/dist/modules/SalesSummary/utils.js +33 -68
- package/dist/modules/ScanOrderLogger/providers/feishu.js +168 -60
- package/dist/modules/ScanOrderLogger/types.d.ts +6 -0
- package/dist/modules/Summary/utils.js +6 -21
- package/dist/solution/ScanOrder/index.d.ts +57 -8
- package/dist/solution/ScanOrder/index.js +1531 -583
- package/dist/solution/ScanOrder/types.d.ts +86 -26
- package/dist/solution/ScanOrder/types.js +20 -1
- package/dist/solution/ScanOrder/utils.d.ts +53 -5
- package/dist/solution/ScanOrder/utils.js +257 -37
- package/dist/solution/VenueBooking/index.d.ts +30 -10
- package/dist/solution/VenueBooking/index.js +460 -217
- package/dist/solution/VenueBooking/types.d.ts +23 -0
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -1
- package/dist/solution/VenueBooking/utils/dateSummary.js +1 -1
- package/dist/solution/VenueBooking/utils/resource.d.ts +11 -1
- package/dist/solution/VenueBooking/utils/resource.js +57 -21
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
- package/dist/solution/VenueBooking/utils/slotMerge.js +33 -12
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
- package/dist/solution/VenueBooking/utils/timeSlot.js +259 -62
- package/lib/modules/Order/index.d.ts +7 -6
- package/lib/modules/Order/index.js +123 -31
- package/lib/modules/Order/types.d.ts +32 -6
- package/lib/modules/Order/utils.d.ts +73 -11
- package/lib/modules/Order/utils.js +203 -28
- package/lib/modules/SalesSummary/utils.js +13 -47
- package/lib/modules/ScanOrderLogger/providers/feishu.js +100 -34
- package/lib/modules/ScanOrderLogger/types.d.ts +6 -0
- package/lib/modules/Summary/utils.js +4 -18
- package/lib/solution/ScanOrder/index.d.ts +57 -8
- package/lib/solution/ScanOrder/index.js +713 -117
- package/lib/solution/ScanOrder/types.d.ts +86 -26
- package/lib/solution/ScanOrder/utils.d.ts +53 -5
- package/lib/solution/ScanOrder/utils.js +186 -19
- package/lib/solution/VenueBooking/index.d.ts +30 -10
- package/lib/solution/VenueBooking/index.js +206 -51
- package/lib/solution/VenueBooking/types.d.ts +23 -0
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -1
- package/lib/solution/VenueBooking/utils/dateSummary.js +1 -1
- package/lib/solution/VenueBooking/utils/resource.d.ts +11 -1
- package/lib/solution/VenueBooking/utils/resource.js +15 -4
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
- package/lib/solution/VenueBooking/utils/slotMerge.js +29 -12
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
- package/lib/solution/VenueBooking/utils/timeSlot.js +182 -43
- package/package.json +1 -1
|
@@ -35,14 +35,20 @@ __export(ScanOrder_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(ScanOrder_exports);
|
|
36
36
|
var import_BaseModule = require("../../modules/BaseModule");
|
|
37
37
|
var import_types = require("./types");
|
|
38
|
+
var import_Order = require("../../modules/Order");
|
|
39
|
+
var import_types2 = require("../../modules/Account/types");
|
|
40
|
+
var import_types3 = require("../RegisterAndLogin/types");
|
|
41
|
+
var import_decimal = __toESM(require("decimal.js"));
|
|
38
42
|
var import_utils = require("./utils");
|
|
39
|
-
var
|
|
43
|
+
var import_types4 = require("../BookingByStep/types");
|
|
40
44
|
var import_ProductList = require("../../modules/ProductList");
|
|
45
|
+
var import_Schedule = require("../../modules/Schedule");
|
|
46
|
+
var import_getDateIsInSchedule = require("../../modules/Schedule/getDateIsInSchedule");
|
|
41
47
|
var import_utils2 = require("../../modules/Order/utils");
|
|
42
48
|
var import_dayjs = __toESM(require("dayjs"));
|
|
43
49
|
var import_itemRule = require("../../model/strategy/adapter/itemRule");
|
|
44
50
|
__reExport(ScanOrder_exports, require("./types"), module.exports);
|
|
45
|
-
var
|
|
51
|
+
var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
46
52
|
constructor(name, version) {
|
|
47
53
|
super(name, version);
|
|
48
54
|
this.defaultName = "scanOrder";
|
|
@@ -72,6 +78,9 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
72
78
|
this.itemRuleRuntimeConfig = {};
|
|
73
79
|
/** 最近一次 checkResourceAvailable 从预约规则 link 拉取的商品快照 */
|
|
74
80
|
this.enabledReservationRuleProducts = [];
|
|
81
|
+
this.loginEffectDisposers = [];
|
|
82
|
+
this.customerLoginRefreshInFlight = null;
|
|
83
|
+
this.customerLoginRefreshIdInFlight = null;
|
|
75
84
|
}
|
|
76
85
|
getScanOrderLoggerContext() {
|
|
77
86
|
return {
|
|
@@ -82,11 +91,11 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
82
91
|
}
|
|
83
92
|
serializeError(error) {
|
|
84
93
|
if (error instanceof Error) {
|
|
85
|
-
return {
|
|
94
|
+
return JSON.stringify({
|
|
86
95
|
name: error.name,
|
|
87
96
|
message: error.message,
|
|
88
97
|
stack: error.stack
|
|
89
|
-
};
|
|
98
|
+
});
|
|
90
99
|
}
|
|
91
100
|
return {
|
|
92
101
|
message: String(error)
|
|
@@ -155,6 +164,119 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
155
164
|
}
|
|
156
165
|
});
|
|
157
166
|
}
|
|
167
|
+
normalizeCustomerId(value) {
|
|
168
|
+
const customerId = Number(value);
|
|
169
|
+
if (!Number.isFinite(customerId) || customerId <= 0)
|
|
170
|
+
return null;
|
|
171
|
+
return customerId;
|
|
172
|
+
}
|
|
173
|
+
resolveCustomerIdFromLoginPayload(payload) {
|
|
174
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
175
|
+
const candidates = [
|
|
176
|
+
payload == null ? void 0 : payload.customerId,
|
|
177
|
+
payload == null ? void 0 : payload.customer_id,
|
|
178
|
+
payload == null ? void 0 : payload.id,
|
|
179
|
+
(_a = payload == null ? void 0 : payload.user) == null ? void 0 : _a.customerId,
|
|
180
|
+
(_b = payload == null ? void 0 : payload.user) == null ? void 0 : _b.customer_id,
|
|
181
|
+
(_c = payload == null ? void 0 : payload.user) == null ? void 0 : _c.id,
|
|
182
|
+
(_e = (_d = payload == null ? void 0 : payload.user) == null ? void 0 : _d._origin) == null ? void 0 : _e.customer_id,
|
|
183
|
+
(_f = payload == null ? void 0 : payload.account) == null ? void 0 : _f.customerId,
|
|
184
|
+
(_g = payload == null ? void 0 : payload.account) == null ? void 0 : _g.customer_id,
|
|
185
|
+
(_h = payload == null ? void 0 : payload.account) == null ? void 0 : _h.id,
|
|
186
|
+
(_i = payload == null ? void 0 : payload._origin) == null ? void 0 : _i.customer_id
|
|
187
|
+
];
|
|
188
|
+
for (const candidate of candidates) {
|
|
189
|
+
const customerId = this.normalizeCustomerId(candidate);
|
|
190
|
+
if (customerId)
|
|
191
|
+
return customerId;
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
clearLoginEffectListeners() {
|
|
196
|
+
for (const dispose of this.loginEffectDisposers) {
|
|
197
|
+
dispose();
|
|
198
|
+
}
|
|
199
|
+
this.loginEffectDisposers = [];
|
|
200
|
+
}
|
|
201
|
+
registerLoginEffect(event, callback) {
|
|
202
|
+
var _a;
|
|
203
|
+
const effects = (_a = this.core) == null ? void 0 : _a.effects;
|
|
204
|
+
if (!(effects == null ? void 0 : effects.on))
|
|
205
|
+
return;
|
|
206
|
+
effects.on(event, callback);
|
|
207
|
+
this.loginEffectDisposers.push(() => {
|
|
208
|
+
if (typeof effects.off === "function") {
|
|
209
|
+
effects.off(event, callback);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
registerCustomerLoginListeners() {
|
|
214
|
+
this.clearLoginEffectListeners();
|
|
215
|
+
const createHandleLogin = () => async (payload) => {
|
|
216
|
+
const customerId = this.resolveCustomerIdFromLoginPayload(payload);
|
|
217
|
+
if (!customerId)
|
|
218
|
+
return;
|
|
219
|
+
await this.refreshOrderMarketingAfterLogin({ customerId });
|
|
220
|
+
};
|
|
221
|
+
this.registerLoginEffect(
|
|
222
|
+
_ScanOrderImpl.PISELL1_LOGIN_SUCCESS,
|
|
223
|
+
createHandleLogin()
|
|
224
|
+
);
|
|
225
|
+
this.registerLoginEffect(import_types2.AccountHooks.OnLogin, createHandleLogin());
|
|
226
|
+
this.registerLoginEffect(
|
|
227
|
+
import_types3.RegisterAndLoginHooks.onLoginSuccess,
|
|
228
|
+
createHandleLogin()
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
async refreshOrderMarketingAfterLogin(params) {
|
|
232
|
+
if (!this.store.order)
|
|
233
|
+
throw new Error("order 模块未初始化");
|
|
234
|
+
if (this.customerLoginRefreshInFlight) {
|
|
235
|
+
if (this.customerLoginRefreshIdInFlight === params.customerId) {
|
|
236
|
+
await this.customerLoginRefreshInFlight;
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
await this.customerLoginRefreshInFlight;
|
|
240
|
+
}
|
|
241
|
+
this.customerLoginRefreshIdInFlight = params.customerId;
|
|
242
|
+
const refreshTask = (async () => {
|
|
243
|
+
await this.store.order.loadDiscountConfig({
|
|
244
|
+
customerId: params.customerId
|
|
245
|
+
});
|
|
246
|
+
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
247
|
+
this.store.order.persistTempOrder();
|
|
248
|
+
await this.refreshItemRuleQuantityLimits();
|
|
249
|
+
await this.refreshCartValidationPassed();
|
|
250
|
+
})();
|
|
251
|
+
this.customerLoginRefreshInFlight = refreshTask;
|
|
252
|
+
try {
|
|
253
|
+
await refreshTask;
|
|
254
|
+
} catch (error) {
|
|
255
|
+
throw error;
|
|
256
|
+
} finally {
|
|
257
|
+
if (this.customerLoginRefreshInFlight === refreshTask) {
|
|
258
|
+
this.customerLoginRefreshInFlight = null;
|
|
259
|
+
this.customerLoginRefreshIdInFlight = null;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/** 与 `otherParams.cacheId` 一致,供宿主在 URL 变化时判断是否需要重新注册模块 */
|
|
264
|
+
getCacheId() {
|
|
265
|
+
return this.cacheId;
|
|
266
|
+
}
|
|
267
|
+
async destroyRegisteredChildModules() {
|
|
268
|
+
const modules = [
|
|
269
|
+
this.store.schedule,
|
|
270
|
+
this.store.salesSummary,
|
|
271
|
+
this.store.order,
|
|
272
|
+
this.store.products,
|
|
273
|
+
this.store.scanOrderLogger
|
|
274
|
+
];
|
|
275
|
+
for (const mod of modules) {
|
|
276
|
+
if (mod && typeof mod.destroy === "function")
|
|
277
|
+
await Promise.resolve(mod.destroy());
|
|
278
|
+
}
|
|
279
|
+
}
|
|
158
280
|
async initialize(core, options = {}) {
|
|
159
281
|
var _a, _b, _c, _d, _e, _f;
|
|
160
282
|
this.logMethodStart("initialize");
|
|
@@ -193,7 +315,7 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
193
315
|
];
|
|
194
316
|
moduleArr.forEach((step) => {
|
|
195
317
|
var _a2, _b2, _c2, _d2, _e2, _f2;
|
|
196
|
-
const targetModule = (0,
|
|
318
|
+
const targetModule = (0, import_types4.createModule)(step, this.name);
|
|
197
319
|
if (targetModule) {
|
|
198
320
|
this.store[step] = targetModule;
|
|
199
321
|
const initialState = step === "salesSummary" ? {
|
|
@@ -202,7 +324,7 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
202
324
|
const loggerProvider = ((_c2 = this.otherParams) == null ? void 0 : _c2.scanOrderLoggerProvider) || "feishu";
|
|
203
325
|
const loggerConfig = ((_d2 = this.otherParams) == null ? void 0 : _d2.scanOrderLoggerConfig) || {
|
|
204
326
|
feishu: {
|
|
205
|
-
|
|
327
|
+
webhook: "https://open.feishu.cn/open-apis/bot/v2/hook/216b3fe6-af98-424e-8706-f0471241a7ed"
|
|
206
328
|
}
|
|
207
329
|
};
|
|
208
330
|
this.core.registerModule(targetModule, {
|
|
@@ -226,11 +348,27 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
226
348
|
if (this.store.scanOrderLogger) {
|
|
227
349
|
this.store.scanOrderLogger.setContext(this.getScanOrderLoggerContext());
|
|
228
350
|
}
|
|
351
|
+
const scheduleModule = new import_Schedule.ScheduleModule(`${this.name}_schedule`);
|
|
352
|
+
this.store.schedule = scheduleModule;
|
|
353
|
+
this.core.registerModule(scheduleModule, {
|
|
354
|
+
otherParams: {
|
|
355
|
+
...this.otherParams,
|
|
356
|
+
fatherModule: this.name
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
this.registerCustomerLoginListeners();
|
|
229
360
|
console.log("[ScanOrder] 初始化开始");
|
|
230
361
|
try {
|
|
231
362
|
await ((_e = this.store.order) == null ? void 0 : _e.recalculateSummary({ createIfMissing: false }));
|
|
232
363
|
(_f = this.store.order) == null ? void 0 : _f.persistTempOrder();
|
|
233
364
|
await this.loadRuntimeConfigs();
|
|
365
|
+
if (this.store.schedule) {
|
|
366
|
+
try {
|
|
367
|
+
await this.store.schedule.loadAllSchedule();
|
|
368
|
+
} catch (scheduleError) {
|
|
369
|
+
console.warn("[ScanOrder] loadAllSchedule 失败,operating_hours 判定将跳过", scheduleError);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
234
372
|
await this.refreshItemRuleQuantityLimits();
|
|
235
373
|
this.store.status = "ready";
|
|
236
374
|
console.log("[ScanOrder] 初始化完成");
|
|
@@ -252,7 +390,10 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
252
390
|
}
|
|
253
391
|
async destroy() {
|
|
254
392
|
this.logMethodStart("destroy");
|
|
393
|
+
this.clearLoginEffectListeners();
|
|
255
394
|
await this.core.effects.emit(import_types.ScanOrderHooks.onDestroy, {});
|
|
395
|
+
await this.destroyRegisteredChildModules();
|
|
396
|
+
super.destroy();
|
|
256
397
|
console.log("[ScanOrder] 已销毁");
|
|
257
398
|
this.logMethodSuccess("destroy");
|
|
258
399
|
}
|
|
@@ -368,6 +509,50 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
368
509
|
throw error;
|
|
369
510
|
}
|
|
370
511
|
}
|
|
512
|
+
// 存储 UI 层选择的取餐方式到 tempOrder.metadata.shop_service_data
|
|
513
|
+
// service_type 在扫码点餐场景固定为 dine_in
|
|
514
|
+
setPickupReferenceMode(mode) {
|
|
515
|
+
this.logMethodStart("setPickupReferenceMode", { mode });
|
|
516
|
+
try {
|
|
517
|
+
if (!this.store.order)
|
|
518
|
+
throw new Error("order 模块未初始化");
|
|
519
|
+
const tempOrder = this.store.order.ensureTempOrder();
|
|
520
|
+
tempOrder.metadata = {
|
|
521
|
+
...tempOrder.metadata || {},
|
|
522
|
+
shop_service_data: {
|
|
523
|
+
...(tempOrder.metadata || {}).shop_service_data || {},
|
|
524
|
+
service_type: "dine_in",
|
|
525
|
+
pickup_reference_mode: mode
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
this.store.order.persistTempOrder();
|
|
529
|
+
this.logMethodSuccess("setPickupReferenceMode", {
|
|
530
|
+
mode
|
|
531
|
+
});
|
|
532
|
+
return tempOrder.metadata.shop_service_data;
|
|
533
|
+
} catch (error) {
|
|
534
|
+
this.logMethodError("setPickupReferenceMode", error, { mode });
|
|
535
|
+
throw error;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
// 存储用户自定义取餐标识到 tempOrder.buzzer
|
|
539
|
+
setPickupRef(buzzer) {
|
|
540
|
+
this.logMethodStart("setPickupRef", {
|
|
541
|
+
buzzerLength: String(buzzer || "").length
|
|
542
|
+
});
|
|
543
|
+
try {
|
|
544
|
+
if (!this.store.order)
|
|
545
|
+
throw new Error("order 模块未初始化");
|
|
546
|
+
const result = this.store.order.updateTempOrderBuzzer(buzzer);
|
|
547
|
+
this.logMethodSuccess("setPickupRef", {
|
|
548
|
+
buzzerLength: result.length
|
|
549
|
+
});
|
|
550
|
+
return result;
|
|
551
|
+
} catch (error) {
|
|
552
|
+
this.logMethodError("setPickupRef", error);
|
|
553
|
+
throw error;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
371
556
|
ensureTempOrder() {
|
|
372
557
|
if (!this.store.order)
|
|
373
558
|
throw new Error("order 模块未初始化");
|
|
@@ -389,6 +574,25 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
389
574
|
throw error;
|
|
390
575
|
}
|
|
391
576
|
}
|
|
577
|
+
// 重置 tempOrder 与与上一单强相关的运行态(resource/entryPaxNumber/enabledReservationRuleProducts),
|
|
578
|
+
// 适用于从支付页通过 react-router 跳回继续下单时清理残留数据
|
|
579
|
+
async restoreOrder() {
|
|
580
|
+
this.logMethodStart("restoreOrder");
|
|
581
|
+
try {
|
|
582
|
+
if (!this.store.order) {
|
|
583
|
+
throw new Error("scanOrder 解决方案需要 order 模块支持");
|
|
584
|
+
}
|
|
585
|
+
this.store.resource = null;
|
|
586
|
+
this.store.entryPaxNumber = 1;
|
|
587
|
+
this.enabledReservationRuleProducts = [];
|
|
588
|
+
const tempOrder = this.store.order.restoreOrder();
|
|
589
|
+
this.logMethodSuccess("restoreOrder");
|
|
590
|
+
return tempOrder;
|
|
591
|
+
} catch (error) {
|
|
592
|
+
this.logMethodError("restoreOrder", error);
|
|
593
|
+
throw error;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
392
596
|
getOrderProducts() {
|
|
393
597
|
this.logMethodStart("getOrderProducts");
|
|
394
598
|
if (!this.store.order)
|
|
@@ -414,8 +618,229 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
414
618
|
throw error;
|
|
415
619
|
}
|
|
416
620
|
}
|
|
417
|
-
|
|
621
|
+
getDiscountList() {
|
|
622
|
+
if (!this.store.order)
|
|
623
|
+
return [];
|
|
624
|
+
return this.store.order.getDiscountList();
|
|
625
|
+
}
|
|
626
|
+
async scanCode(code, customerId) {
|
|
627
|
+
this.logMethodStart("scanCode", { code });
|
|
628
|
+
try {
|
|
629
|
+
if (!this.store.order)
|
|
630
|
+
throw new Error("order 模块未初始化");
|
|
631
|
+
const raw = await this.store.order.scanCode(code, customerId);
|
|
632
|
+
if (raw.isAvailable) {
|
|
633
|
+
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
634
|
+
this.store.order.persistTempOrder();
|
|
635
|
+
}
|
|
636
|
+
this.logMethodSuccess("scanCode", { isAvailable: raw.isAvailable });
|
|
637
|
+
return {
|
|
638
|
+
isAvailable: raw.isAvailable,
|
|
639
|
+
type: raw.type,
|
|
640
|
+
unavailableReason: raw.unavailableReason
|
|
641
|
+
};
|
|
642
|
+
} catch (error) {
|
|
643
|
+
this.logMethodError("scanCode", error);
|
|
644
|
+
throw error;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
async setDiscountSelected(params) {
|
|
418
648
|
var _a, _b, _c, _d, _e;
|
|
649
|
+
this.logMethodStart("setDiscountSelected", params);
|
|
650
|
+
try {
|
|
651
|
+
if (!this.store.order)
|
|
652
|
+
throw new Error("order 模块未初始化");
|
|
653
|
+
const list = this.store.order.getDiscountList();
|
|
654
|
+
const updated = list.map(
|
|
655
|
+
(d) => d.id === params.discountId ? {
|
|
656
|
+
...d,
|
|
657
|
+
isSelected: params.isSelected,
|
|
658
|
+
isManualSelect: !params.isSelected
|
|
659
|
+
} : d
|
|
660
|
+
);
|
|
661
|
+
const tempOrder = this.store.order.ensureTempOrder();
|
|
662
|
+
const orderStore = this.store.order.store || {};
|
|
663
|
+
const discountModule = orderStore.discount;
|
|
664
|
+
const rulesModule = orderStore.rules;
|
|
665
|
+
const holders = ((_a = tempOrder.holder) == null ? void 0 : _a.form_record_id) ? [{ form_record_id: tempOrder.holder.form_record_id }] : [];
|
|
666
|
+
let nextDiscountList = updated;
|
|
667
|
+
await (discountModule == null ? void 0 : discountModule.setDiscountList(updated));
|
|
668
|
+
if (rulesModule) {
|
|
669
|
+
const result = rulesModule.calcDiscount(
|
|
670
|
+
{
|
|
671
|
+
productList: tempOrder.products,
|
|
672
|
+
discountList: updated,
|
|
673
|
+
holders,
|
|
674
|
+
isFormSubject: !!((_b = tempOrder.holder) == null ? void 0 : _b.type) && tempOrder.holder.type === "form"
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
discountId: params.discountId,
|
|
678
|
+
isSelected: params.isSelected
|
|
679
|
+
}
|
|
680
|
+
) || { productList: tempOrder.products, discountList: updated };
|
|
681
|
+
if (result == null ? void 0 : result.productList) {
|
|
682
|
+
tempOrder.products = result.productList;
|
|
683
|
+
}
|
|
684
|
+
if (result == null ? void 0 : result.discountList) {
|
|
685
|
+
nextDiscountList = result.discountList;
|
|
686
|
+
if (!params.isSelected) {
|
|
687
|
+
const beforeSelectedIds = new Set(
|
|
688
|
+
updated.filter((d) => d.isSelected).map((d) => d.id)
|
|
689
|
+
);
|
|
690
|
+
for (const d of nextDiscountList) {
|
|
691
|
+
if (d.isSelected && !beforeSelectedIds.has(d.id)) {
|
|
692
|
+
d.isSelected = false;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
const selectedResourceIds = new Set(
|
|
699
|
+
nextDiscountList.filter((d) => d.isSelected).map((d) => d.id)
|
|
700
|
+
);
|
|
701
|
+
for (const product of tempOrder.products) {
|
|
702
|
+
if ((_c = product._origin) == null ? void 0 : _c.isManualDiscount)
|
|
703
|
+
continue;
|
|
704
|
+
product.discount_list = (product.discount_list || []).filter((pd) => {
|
|
705
|
+
var _a2;
|
|
706
|
+
const rid = ((_a2 = pd.discount) == null ? void 0 : _a2.resource_id) ?? pd.id;
|
|
707
|
+
return rid != null && selectedResourceIds.has(rid);
|
|
708
|
+
});
|
|
709
|
+
const totalPerUnitDiscount = (product.discount_list || []).reduce(
|
|
710
|
+
(sum, pd) => sum + (pd.amount || 0),
|
|
711
|
+
0
|
|
712
|
+
);
|
|
713
|
+
const optionSum = (0, import_utils2.sumOptionUnitPrice)(product.product_option_item);
|
|
714
|
+
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");
|
|
715
|
+
const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
|
|
716
|
+
const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
717
|
+
if (product.metadata) {
|
|
718
|
+
product.metadata.main_product_selling_price = newMainSellingPrice;
|
|
719
|
+
product.metadata.price_schema_version = 2;
|
|
720
|
+
}
|
|
721
|
+
product.selling_price = (0, import_utils2.composeLinePrice)({
|
|
722
|
+
mainPrice: newMainSellingPrice,
|
|
723
|
+
bundle: product.product_bundle
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
import_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
|
|
727
|
+
await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
|
|
728
|
+
tempOrder.discount_list = (nextDiscountList || []).filter((d) => d.isSelected);
|
|
729
|
+
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
730
|
+
this.store.order.persistTempOrder();
|
|
731
|
+
this.logMethodSuccess("setDiscountSelected", params);
|
|
732
|
+
} catch (error) {
|
|
733
|
+
this.logMethodError("setDiscountSelected", error);
|
|
734
|
+
throw error;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
async onCustomerLogin(params) {
|
|
738
|
+
this.logMethodStart("onCustomerLogin", { customerId: params.customerId });
|
|
739
|
+
try {
|
|
740
|
+
await this.refreshOrderMarketingAfterLogin({
|
|
741
|
+
customerId: params.customerId
|
|
742
|
+
});
|
|
743
|
+
this.logMethodSuccess("onCustomerLogin", { customerId: params.customerId });
|
|
744
|
+
} catch (error) {
|
|
745
|
+
this.logMethodError("onCustomerLogin", error);
|
|
746
|
+
throw error;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
// ScanOrder 提交 payload enhancer:
|
|
750
|
+
// - 给所有 booking 注入 appointment_status: 'started'(扫码点餐语义)
|
|
751
|
+
// - 给所有 booking 的 metadata 注入 resource_select_type(来自预约规则商品的 resource.type)
|
|
752
|
+
// - 给第一条 booking 补 resources 与 product_uid(仅当存在 resource / rule product)
|
|
753
|
+
// - 追加一条 is_rule=true 的 rule product,与 booking 互相关联
|
|
754
|
+
buildSubmitPayloadEnhancer() {
|
|
755
|
+
const ruleProduct = this.enabledReservationRuleProducts[0];
|
|
756
|
+
const resourceState = this.store.resource;
|
|
757
|
+
const resourceSelectType = resourceState == null ? void 0 : resourceState.resourceSelectType;
|
|
758
|
+
const resolveResourceCapacity = () => {
|
|
759
|
+
var _a;
|
|
760
|
+
if (resourceSelectType === "single") {
|
|
761
|
+
const raw = (_a = resourceState == null ? void 0 : resourceState.table_form_record) == null ? void 0 : _a.capacity;
|
|
762
|
+
const num = Number(raw);
|
|
763
|
+
if (Number.isFinite(num) && num > 0)
|
|
764
|
+
return num;
|
|
765
|
+
return 1;
|
|
766
|
+
}
|
|
767
|
+
return 1;
|
|
768
|
+
};
|
|
769
|
+
return (payload, { bookingUuid, tempOrder }) => {
|
|
770
|
+
var _a, _b;
|
|
771
|
+
const resourceId = tempOrder.resource_id ?? (resourceState == null ? void 0 : resourceState.relationId);
|
|
772
|
+
const pickOriginal = (value) => {
|
|
773
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
774
|
+
const original = value.original;
|
|
775
|
+
return typeof original === "string" && original.length > 0 ? original : void 0;
|
|
776
|
+
}
|
|
777
|
+
return void 0;
|
|
778
|
+
};
|
|
779
|
+
const mainField = pickOriginal(tempOrder.table_number) ?? pickOriginal((_a = resourceState == null ? void 0 : resourceState.table_form_record) == null ? void 0 : _a.name) ?? "";
|
|
780
|
+
const resourceEntry = resourceState && resourceId ? {
|
|
781
|
+
relation_type: "form",
|
|
782
|
+
like_status: "common",
|
|
783
|
+
id: Number(resourceId),
|
|
784
|
+
main_field: mainField,
|
|
785
|
+
form_id: resourceState.tableFormId,
|
|
786
|
+
relation_id: resourceState.relationId ?? resourceId,
|
|
787
|
+
capacity: resolveResourceCapacity(),
|
|
788
|
+
metadata: {}
|
|
789
|
+
} : void 0;
|
|
790
|
+
const ruleProductUid = ruleProduct ? (0, import_utils2.createUuidV4)() : void 0;
|
|
791
|
+
const rawCollectPax = (_b = tempOrder.metadata) == null ? void 0 : _b.collect_pax;
|
|
792
|
+
const hasCollectPaxForCapacity = rawCollectPax !== null && rawCollectPax !== void 0 && rawCollectPax !== "";
|
|
793
|
+
const bookingCapacityValue = hasCollectPaxForCapacity ? (0, import_utils2.normalizeSubmitCollectPaxValue)(rawCollectPax) : resolveResourceCapacity();
|
|
794
|
+
const bookingCapacityDimensionId = (0, import_utils.pickFirstCustomCapacityDimensionId)(this.enabledReservationRuleProducts) ?? 0;
|
|
795
|
+
const nextBookings = (payload.bookings || []).map((booking, idx) => ({
|
|
796
|
+
...booking,
|
|
797
|
+
appointment_status: "started",
|
|
798
|
+
metadata: {
|
|
799
|
+
...booking.metadata || {},
|
|
800
|
+
...resourceSelectType ? { resource_select_type: resourceSelectType } : {},
|
|
801
|
+
...resourceSelectType ? {
|
|
802
|
+
capacity: [
|
|
803
|
+
{
|
|
804
|
+
id: bookingCapacityDimensionId,
|
|
805
|
+
value: bookingCapacityValue,
|
|
806
|
+
name: ""
|
|
807
|
+
}
|
|
808
|
+
]
|
|
809
|
+
} : {}
|
|
810
|
+
},
|
|
811
|
+
...idx === 0 && resourceEntry ? { resources: [resourceEntry] } : {},
|
|
812
|
+
...idx === 0 && ruleProductUid ? { product_uid: ruleProductUid } : {}
|
|
813
|
+
}));
|
|
814
|
+
const nextProducts = [...payload.products || []];
|
|
815
|
+
if (ruleProduct && ruleProductUid && !tempOrder.order_id) {
|
|
816
|
+
const sellingPrice = String(ruleProduct.price ?? "0.00");
|
|
817
|
+
const originalPrice = String(
|
|
818
|
+
ruleProduct.original_price ?? ruleProduct.price ?? "0.00"
|
|
819
|
+
);
|
|
820
|
+
nextProducts.push({
|
|
821
|
+
product_id: ruleProduct.id,
|
|
822
|
+
product_variant_id: 0,
|
|
823
|
+
num: 1,
|
|
824
|
+
selling_price: sellingPrice,
|
|
825
|
+
original_price: originalPrice,
|
|
826
|
+
payment_price: sellingPrice,
|
|
827
|
+
is_charge_tax: ruleProduct.is_gst ?? 0,
|
|
828
|
+
product_option_item: [],
|
|
829
|
+
discount_list: [],
|
|
830
|
+
product_bundle: [],
|
|
831
|
+
booking_uid: bookingUuid,
|
|
832
|
+
metadata: {
|
|
833
|
+
is_rule: true,
|
|
834
|
+
unique_identification_number: ruleProductUid,
|
|
835
|
+
booking_uid: bookingUuid
|
|
836
|
+
}
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
return { ...payload, bookings: nextBookings, products: nextProducts };
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
async submitScanOrder() {
|
|
843
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
419
844
|
this.logMethodStart("submitScanOrder");
|
|
420
845
|
try {
|
|
421
846
|
await this.validateBeforeSubmitByItemRule();
|
|
@@ -426,17 +851,26 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
426
851
|
this.store.entryPaxNumber = pax;
|
|
427
852
|
const tempOrderForSubmit = this.store.order.ensureTempOrder();
|
|
428
853
|
tempOrderForSubmit.metadata = { ...tempOrderForSubmit.metadata, collect_pax: pax };
|
|
854
|
+
tempOrderForSubmit.delivery_type = "shop_service";
|
|
855
|
+
const resourceTableName = (_b = (_a = this.store.resource) == null ? void 0 : _a.table_form_record) == null ? void 0 : _b.name;
|
|
856
|
+
if (resourceTableName && typeof resourceTableName === "object") {
|
|
857
|
+
tempOrderForSubmit.table_number = resourceTableName;
|
|
858
|
+
} else {
|
|
859
|
+
delete tempOrderForSubmit.table_number;
|
|
860
|
+
}
|
|
429
861
|
this.store.order.persistTempOrder();
|
|
862
|
+
const enhancePayload = this.buildSubmitPayloadEnhancer();
|
|
430
863
|
const result = await this.store.order.submitTempOrder({
|
|
431
864
|
cacheId: this.cacheId,
|
|
432
|
-
platform: (
|
|
433
|
-
businessCode: (
|
|
434
|
-
channel: (
|
|
435
|
-
type: (
|
|
865
|
+
platform: (_c = this.otherParams) == null ? void 0 : _c.platform,
|
|
866
|
+
businessCode: (_d = this.otherParams) == null ? void 0 : _d.businessCode,
|
|
867
|
+
channel: (_e = this.otherParams) == null ? void 0 : _e.channel,
|
|
868
|
+
type: (_f = this.otherParams) == null ? void 0 : _f.type,
|
|
869
|
+
enhancePayload
|
|
436
870
|
});
|
|
437
871
|
const tempOrder = this.store.order.getTempOrder();
|
|
438
872
|
this.logMethodSuccess("submitScanOrder", {
|
|
439
|
-
productCount: ((
|
|
873
|
+
productCount: ((_g = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _g.length) || 0
|
|
440
874
|
});
|
|
441
875
|
return result;
|
|
442
876
|
} catch (error) {
|
|
@@ -484,6 +918,36 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
484
918
|
throw error;
|
|
485
919
|
}
|
|
486
920
|
}
|
|
921
|
+
/**
|
|
922
|
+
* 设置单行商品备注(与整单 `updateTempOrderNote` 区分)。
|
|
923
|
+
* 多行同 SKU 时必须传入与删除/更新一致的 identity(如 `identity_key`)。
|
|
924
|
+
*/
|
|
925
|
+
async setOrderProductLineNote(identity, note) {
|
|
926
|
+
this.logMethodStart("setOrderProductLineNote", {
|
|
927
|
+
product_id: identity.product_id,
|
|
928
|
+
product_variant_id: identity.product_variant_id
|
|
929
|
+
});
|
|
930
|
+
try {
|
|
931
|
+
const params = {
|
|
932
|
+
product_id: identity.product_id,
|
|
933
|
+
product_variant_id: identity.product_variant_id,
|
|
934
|
+
updates: { note: String(note || "") }
|
|
935
|
+
};
|
|
936
|
+
if (identity.identity_key !== void 0)
|
|
937
|
+
params.identity_key = identity.identity_key;
|
|
938
|
+
if (identity.product_option_item !== void 0) {
|
|
939
|
+
params.product_option_item = identity.product_option_item;
|
|
940
|
+
}
|
|
941
|
+
if (identity.product_bundle !== void 0)
|
|
942
|
+
params.product_bundle = identity.product_bundle;
|
|
943
|
+
const products = await this.updateProductInOrder(params);
|
|
944
|
+
this.logMethodSuccess("setOrderProductLineNote", { productCount: products.length });
|
|
945
|
+
return products;
|
|
946
|
+
} catch (error) {
|
|
947
|
+
this.logMethodError("setOrderProductLineNote", error);
|
|
948
|
+
throw error;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
487
951
|
async removeProductFromOrder(identity) {
|
|
488
952
|
this.logMethodStart("removeProductFromOrder", {
|
|
489
953
|
product_id: identity.product_id,
|
|
@@ -857,20 +1321,22 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
857
1321
|
strategyCount: Array.isArray(this.itemRuleRuntimeConfig.strategyConfigs) ? this.itemRuleRuntimeConfig.strategyConfigs.length : 0
|
|
858
1322
|
});
|
|
859
1323
|
}
|
|
860
|
-
normalizeResourceState(
|
|
861
|
-
var _a, _b;
|
|
862
|
-
const
|
|
863
|
-
const
|
|
864
|
-
const
|
|
865
|
-
const
|
|
866
|
-
const
|
|
867
|
-
const
|
|
868
|
-
const tableFormId = (0, import_utils.toPositiveString)(config == null ? void 0 : config.table_form_id);
|
|
869
|
-
const allowSnack = ((_b = (_a = this.otherParams) == null ? void 0 : _a.dineInConfig) == null ? void 0 : _b["workflow.allow_add_items"]) || false;
|
|
1324
|
+
normalizeResourceState(detail, resourceSelectType, hasOrderId) {
|
|
1325
|
+
var _a, _b, _c, _d;
|
|
1326
|
+
const currentOrderId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.order_id);
|
|
1327
|
+
const lastOrderId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.last_order_id);
|
|
1328
|
+
const relationId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.form_record_id);
|
|
1329
|
+
const tableFormId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.form_id);
|
|
1330
|
+
const formRecord = (detail == null ? void 0 : detail.form_record) ?? null;
|
|
1331
|
+
const allowSnack = ((_b = (_a = this.otherParams) == null ? void 0 : _a.dineInConfig) == null ? void 0 : _b["sale.allow_add_items"]) || false;
|
|
870
1332
|
const deskmateValid = false;
|
|
871
|
-
const isExclusive =
|
|
872
|
-
const isFull =
|
|
873
|
-
|
|
1333
|
+
const isExclusive = resourceSelectType === "single";
|
|
1334
|
+
const isFull = (0, import_utils.computeResourceIsFull)({
|
|
1335
|
+
resourceSelectType,
|
|
1336
|
+
lastOrderId,
|
|
1337
|
+
capacityList: ((_d = (_c = detail == null ? void 0 : detail.resource_capacity) == null ? void 0 : _c[0]) == null ? void 0 : _d.capacity_list) ?? [],
|
|
1338
|
+
capacity: formRecord == null ? void 0 : formRecord.capacity
|
|
1339
|
+
});
|
|
874
1340
|
let availabilityInfo = {
|
|
875
1341
|
mode: "idle",
|
|
876
1342
|
deskmate_valid: deskmateValid
|
|
@@ -894,33 +1360,19 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
894
1360
|
};
|
|
895
1361
|
}
|
|
896
1362
|
} else if (lastOrderId) {
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
table_form_id: tableFormId,
|
|
908
|
-
deskmate_valid: deskmateValid
|
|
909
|
-
};
|
|
910
|
-
}
|
|
911
|
-
if (isBlock) {
|
|
912
|
-
availabilityInfo = {
|
|
913
|
-
mode: "resource_block",
|
|
914
|
-
order_id: lastOrderId,
|
|
915
|
-
relation_id: relationId,
|
|
916
|
-
table_form_id: tableFormId,
|
|
917
|
-
deskmate_valid: deskmateValid
|
|
918
|
-
};
|
|
1363
|
+
const canFallthroughToIdle = resourceSelectType === "multiple" && !isFull;
|
|
1364
|
+
if (!canFallthroughToIdle) {
|
|
1365
|
+
availabilityInfo = {
|
|
1366
|
+
mode: "resource_busy",
|
|
1367
|
+
order_id: "0",
|
|
1368
|
+
relation_id: relationId,
|
|
1369
|
+
table_form_id: tableFormId,
|
|
1370
|
+
deskmate_valid: deskmateValid
|
|
1371
|
+
};
|
|
1372
|
+
}
|
|
919
1373
|
}
|
|
920
1374
|
return {
|
|
921
1375
|
...availabilityInfo,
|
|
922
|
-
tableMaxNumber,
|
|
923
|
-
orderCount,
|
|
924
1376
|
currentOrderId,
|
|
925
1377
|
lastOrderId,
|
|
926
1378
|
relationId,
|
|
@@ -929,27 +1381,46 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
929
1381
|
deskmateValid,
|
|
930
1382
|
isExclusive,
|
|
931
1383
|
isFull,
|
|
932
|
-
|
|
933
|
-
raw:
|
|
934
|
-
table_form_record:
|
|
1384
|
+
resourceSelectType,
|
|
1385
|
+
raw: detail,
|
|
1386
|
+
table_form_record: formRecord
|
|
935
1387
|
};
|
|
936
1388
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1389
|
+
// 从首个预约规则商品的 product_resource.resources 中,按 form_id 匹配返回 type
|
|
1390
|
+
resolveResourceSelectType(formId) {
|
|
1391
|
+
var _a;
|
|
1392
|
+
const firstProduct = this.enabledReservationRuleProducts[0];
|
|
1393
|
+
const resources = ((_a = firstProduct == null ? void 0 : firstProduct.product_resource) == null ? void 0 : _a.resources) || [];
|
|
1394
|
+
const numericFormId = Number(formId);
|
|
1395
|
+
if (!Number.isFinite(numericFormId) || numericFormId <= 0)
|
|
1396
|
+
return void 0;
|
|
1397
|
+
const matched = resources.find((r) => Number(r == null ? void 0 : r.id) === numericFormId);
|
|
1398
|
+
return matched == null ? void 0 : matched.type;
|
|
1399
|
+
}
|
|
1400
|
+
async fetchResourceOccupyDetailByResourceId(resourceId) {
|
|
1401
|
+
var _a, _b, _c, _d;
|
|
1402
|
+
const formRecordId = Number(resourceId);
|
|
1403
|
+
if (!Number.isFinite(formRecordId) || formRecordId <= 0) {
|
|
940
1404
|
throw new Error(`[ScanOrder] 非法桌台 resourceId: ${resourceId}`);
|
|
941
1405
|
}
|
|
1406
|
+
const shopId = (_b = (_a = this.otherParams) == null ? void 0 : _a.getStateData) == null ? void 0 : _b.call(_a, "shop_id");
|
|
1407
|
+
if (!shopId) {
|
|
1408
|
+
throw new Error("[ScanOrder] 无法获取 shop_id");
|
|
1409
|
+
}
|
|
942
1410
|
const response = await this.request.get(
|
|
943
|
-
"/order/
|
|
1411
|
+
"/order/resource/occupy-detail",
|
|
944
1412
|
{
|
|
945
|
-
|
|
946
|
-
|
|
1413
|
+
shop_id: shopId,
|
|
1414
|
+
"form_record_ids[]": formRecordId,
|
|
1415
|
+
with_resource_capacity_info: 1,
|
|
1416
|
+
with_resource_order_info: 1,
|
|
1417
|
+
with_resource_form_info: 1
|
|
947
1418
|
}
|
|
948
1419
|
);
|
|
949
1420
|
if (!(response == null ? void 0 : response.status)) {
|
|
950
|
-
throw new Error((response == null ? void 0 : response.message) || "
|
|
1421
|
+
throw new Error((response == null ? void 0 : response.message) || "获取资源占用详情失败");
|
|
951
1422
|
}
|
|
952
|
-
return (response == null ? void 0 : response.data)
|
|
1423
|
+
return ((_d = (_c = response == null ? void 0 : response.data) == null ? void 0 : _c.occupy_details) == null ? void 0 : _d[0]) ?? null;
|
|
953
1424
|
}
|
|
954
1425
|
// 检测当前链接是否可用
|
|
955
1426
|
// 通过 resource_id + 店铺配置
|
|
@@ -971,46 +1442,48 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
971
1442
|
const dineInConfig = (openData == null ? void 0 : openData.data) || {};
|
|
972
1443
|
this.otherParams.dineInConfig = dineInConfig;
|
|
973
1444
|
await this.syncItemRuleConfigsFromDineInConfig(dineInConfig);
|
|
974
|
-
const
|
|
1445
|
+
const closedBehaviorValue = dineInConfig == null ? void 0 : dineInConfig["availability.closed_behavior"];
|
|
1446
|
+
const closedMessage = (dineInConfig == null ? void 0 : dineInConfig["availability.closed_message"]) || (dineInConfig == null ? void 0 : dineInConfig["availability.message"]) || (dineInConfig == null ? void 0 : dineInConfig["basic.closed_message"]);
|
|
1447
|
+
const basicUnavailableMessage = (dineInConfig == null ? void 0 : dineInConfig["basic.unavailable_message"]) || closedMessage;
|
|
1448
|
+
const pauseMessage = (dineInConfig == null ? void 0 : dineInConfig["availability.pause_message"]) || closedMessage;
|
|
1449
|
+
const makeShopClosed = (errorTips, closed_behavior) => ({
|
|
975
1450
|
mode: "shop_closed",
|
|
976
1451
|
order_id: void 0,
|
|
977
1452
|
relation_id: void 0,
|
|
978
1453
|
table_form_id: void 0,
|
|
979
1454
|
deskmate_valid: false,
|
|
980
|
-
errorTips
|
|
1455
|
+
errorTips,
|
|
1456
|
+
closed_behavior
|
|
981
1457
|
});
|
|
1458
|
+
if ((dineInConfig == null ? void 0 : dineInConfig["basic.enable"]) === false) {
|
|
1459
|
+
return makeShopClosed(basicUnavailableMessage);
|
|
1460
|
+
}
|
|
982
1461
|
if ((0, import_utils.toBoolean)(dineInConfig == null ? void 0 : dineInConfig["availability.paused"])) {
|
|
983
1462
|
if ((dineInConfig == null ? void 0 : dineInConfig["availability.pause_behavior"]) === "hide_all") {
|
|
984
|
-
return
|
|
1463
|
+
return makeShopClosed(pauseMessage);
|
|
985
1464
|
}
|
|
986
1465
|
}
|
|
987
|
-
const
|
|
988
|
-
|
|
989
|
-
this.store.
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
};
|
|
1466
|
+
const operatingHourIds = Array.isArray(dineInConfig == null ? void 0 : dineInConfig["availability.operating_hours"]) ? dineInConfig["availability.operating_hours"].map((id) => Number(id)).filter((id) => Number.isFinite(id) && id > 0) : [];
|
|
1467
|
+
let outsideOperatingHours = false;
|
|
1468
|
+
if (operatingHourIds.length && this.store.schedule) {
|
|
1469
|
+
const scheduleList = this.store.schedule.getScheduleListByIds(operatingHourIds);
|
|
1470
|
+
if (scheduleList.length) {
|
|
1471
|
+
const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
|
|
1472
|
+
outsideOperatingHours = !(0, import_getDateIsInSchedule.getDateIsInSchedule)(now, scheduleList);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
if (outsideOperatingHours && closedBehaviorValue !== "show_menu_disabled") {
|
|
1476
|
+
return makeShopClosed(closedMessage, closedBehaviorValue);
|
|
1477
|
+
}
|
|
1000
1478
|
const tempOrder = this.ensureTempOrder();
|
|
1001
|
-
tempOrder.relation_id = resourceId || ((_e = this.otherParams) == null ? void 0 : _e.relation_id);
|
|
1002
|
-
tempOrder.table_form_id = resourceState.tableFormId;
|
|
1003
|
-
tempOrder.resource_id = resourceId;
|
|
1004
1479
|
const reservationLinkIds = (0, import_utils.collectLinkProductIdsFromReservationRules)(
|
|
1005
|
-
dineInConfig["
|
|
1480
|
+
dineInConfig["fulfillment.enabled_resource_rules"]
|
|
1006
1481
|
);
|
|
1482
|
+
let pendingRequestEntryPax;
|
|
1483
|
+
let pendingRequestPaxMin;
|
|
1484
|
+
let pendingRequestPaxMax;
|
|
1007
1485
|
if (reservationLinkIds.length === 0) {
|
|
1008
1486
|
this.enabledReservationRuleProducts = [];
|
|
1009
|
-
if (this.store.resource) {
|
|
1010
|
-
delete this.store.resource.requestEntryPax;
|
|
1011
|
-
delete this.store.resource.requestPaxMin;
|
|
1012
|
-
delete this.store.resource.requestPaxMax;
|
|
1013
|
-
}
|
|
1014
1487
|
} else {
|
|
1015
1488
|
tempOrder.metadata = { ...tempOrder.metadata || {} };
|
|
1016
1489
|
delete tempOrder.metadata.table_occupancy_duration;
|
|
@@ -1042,38 +1515,15 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1042
1515
|
tempOrder.metadata.table_occupancy_duration = occupancyMinutes;
|
|
1043
1516
|
}
|
|
1044
1517
|
if ((0, import_utils.hasCustomCapacityProduct)(loaded)) {
|
|
1045
|
-
|
|
1046
|
-
if (this.store.resource)
|
|
1047
|
-
this.store.resource.requestEntryPax = 1;
|
|
1048
|
-
delete availabilityInfo.requestPaxMin;
|
|
1049
|
-
delete availabilityInfo.requestPaxMax;
|
|
1050
|
-
if (this.store.resource) {
|
|
1051
|
-
delete this.store.resource.requestPaxMin;
|
|
1052
|
-
delete this.store.resource.requestPaxMax;
|
|
1053
|
-
}
|
|
1518
|
+
pendingRequestEntryPax = 1;
|
|
1054
1519
|
const paxBounds = (0, import_utils.pickFirstCustomCapacityPaxBounds)(loaded);
|
|
1055
|
-
if ((paxBounds == null ? void 0 : paxBounds.min) !== void 0)
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
}
|
|
1060
|
-
if ((paxBounds == null ? void 0 : paxBounds.max) !== void 0) {
|
|
1061
|
-
availabilityInfo.requestPaxMax = paxBounds.max;
|
|
1062
|
-
if (this.store.resource)
|
|
1063
|
-
this.store.resource.requestPaxMax = paxBounds.max;
|
|
1064
|
-
}
|
|
1065
|
-
} else if (this.store.resource) {
|
|
1066
|
-
delete this.store.resource.requestEntryPax;
|
|
1067
|
-
delete this.store.resource.requestPaxMin;
|
|
1068
|
-
delete this.store.resource.requestPaxMax;
|
|
1520
|
+
if ((paxBounds == null ? void 0 : paxBounds.min) !== void 0)
|
|
1521
|
+
pendingRequestPaxMin = paxBounds.min;
|
|
1522
|
+
if ((paxBounds == null ? void 0 : paxBounds.max) !== void 0)
|
|
1523
|
+
pendingRequestPaxMax = paxBounds.max;
|
|
1069
1524
|
}
|
|
1070
1525
|
} else {
|
|
1071
1526
|
this.enabledReservationRuleProducts = [];
|
|
1072
|
-
if (this.store.resource) {
|
|
1073
|
-
delete this.store.resource.requestEntryPax;
|
|
1074
|
-
delete this.store.resource.requestPaxMin;
|
|
1075
|
-
delete this.store.resource.requestPaxMax;
|
|
1076
|
-
}
|
|
1077
1527
|
void this.addScanOrderLog({
|
|
1078
1528
|
level: "error",
|
|
1079
1529
|
title: "[ScanOrder] enabled_reservation_rules product query failed",
|
|
@@ -1084,6 +1534,41 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1084
1534
|
});
|
|
1085
1535
|
}
|
|
1086
1536
|
}
|
|
1537
|
+
const occupyDetail = await this.fetchResourceOccupyDetailByResourceId(resourceId);
|
|
1538
|
+
const resourceSelectType = this.resolveResourceSelectType(
|
|
1539
|
+
(0, import_utils.toPositiveString)(occupyDetail == null ? void 0 : occupyDetail.form_id)
|
|
1540
|
+
);
|
|
1541
|
+
const resourceState = this.normalizeResourceState(
|
|
1542
|
+
occupyDetail,
|
|
1543
|
+
resourceSelectType,
|
|
1544
|
+
hasOrderId
|
|
1545
|
+
);
|
|
1546
|
+
this.store.resource = resourceState;
|
|
1547
|
+
if (pendingRequestEntryPax !== void 0) {
|
|
1548
|
+
this.store.resource.requestEntryPax = pendingRequestEntryPax;
|
|
1549
|
+
}
|
|
1550
|
+
if (pendingRequestPaxMin !== void 0) {
|
|
1551
|
+
this.store.resource.requestPaxMin = pendingRequestPaxMin;
|
|
1552
|
+
}
|
|
1553
|
+
if (pendingRequestPaxMax !== void 0) {
|
|
1554
|
+
this.store.resource.requestPaxMax = pendingRequestPaxMax;
|
|
1555
|
+
}
|
|
1556
|
+
const availabilityInfo = {
|
|
1557
|
+
mode: resourceState.mode,
|
|
1558
|
+
order_id: resourceState.order_id,
|
|
1559
|
+
relation_id: resourceState.relationId,
|
|
1560
|
+
table_form_id: resourceState.tableFormId,
|
|
1561
|
+
deskmate_valid: resourceState.deskmate_valid,
|
|
1562
|
+
table_form_record: resourceState.table_form_record,
|
|
1563
|
+
policy: (_c = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _c.policy,
|
|
1564
|
+
partyroom_booking: (_d = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _d.partyroom_booking,
|
|
1565
|
+
...this.store.resource.requestEntryPax !== void 0 ? { requestEntryPax: this.store.resource.requestEntryPax } : {},
|
|
1566
|
+
...this.store.resource.requestPaxMin !== void 0 ? { requestPaxMin: this.store.resource.requestPaxMin } : {},
|
|
1567
|
+
...this.store.resource.requestPaxMax !== void 0 ? { requestPaxMax: this.store.resource.requestPaxMax } : {}
|
|
1568
|
+
};
|
|
1569
|
+
tempOrder.relation_id = resourceId || ((_e = this.otherParams) == null ? void 0 : _e.relation_id);
|
|
1570
|
+
tempOrder.table_form_id = resourceState.tableFormId;
|
|
1571
|
+
tempOrder.resource_id = resourceId;
|
|
1087
1572
|
(_f = this.store.order) == null ? void 0 : _f.persistTempOrder();
|
|
1088
1573
|
if (availabilityInfo.mode === "idle") {
|
|
1089
1574
|
await this.addNewOrder();
|
|
@@ -1117,6 +1602,11 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1117
1602
|
submissionIndex: hasOrderId ? 1 : 0,
|
|
1118
1603
|
historicalItems
|
|
1119
1604
|
});
|
|
1605
|
+
if (outsideOperatingHours && closedBehaviorValue === "show_menu_disabled") {
|
|
1606
|
+
availabilityInfo.mode = "submit_disabled";
|
|
1607
|
+
availabilityInfo.errorTips = closedMessage;
|
|
1608
|
+
availabilityInfo.closed_behavior = closedBehaviorValue;
|
|
1609
|
+
}
|
|
1120
1610
|
this.logMethodSuccess("checkResourceAvailable", {
|
|
1121
1611
|
resourceId,
|
|
1122
1612
|
mode: availabilityInfo.mode,
|
|
@@ -1126,14 +1616,13 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1126
1616
|
persistedRelationId: tempOrder.relation_id,
|
|
1127
1617
|
persistedResourceId: tempOrder.resource_id,
|
|
1128
1618
|
deskmateValid: availabilityInfo.deskmate_valid,
|
|
1129
|
-
|
|
1130
|
-
tableMaxNumber: resourceState.tableMaxNumber,
|
|
1619
|
+
resourceSelectType: resourceState.resourceSelectType,
|
|
1131
1620
|
isExclusive: resourceState.isExclusive,
|
|
1132
1621
|
isFull: resourceState.isFull
|
|
1133
1622
|
});
|
|
1134
1623
|
return availabilityInfo;
|
|
1135
1624
|
} catch (error) {
|
|
1136
|
-
this.logMethodError("checkResourceAvailable", error, {
|
|
1625
|
+
this.logMethodError("checkResourceAvailable", error.message, {
|
|
1137
1626
|
resourceId
|
|
1138
1627
|
});
|
|
1139
1628
|
throw error;
|
|
@@ -1176,7 +1665,7 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1176
1665
|
});
|
|
1177
1666
|
return formattedRes;
|
|
1178
1667
|
} catch (error) {
|
|
1179
|
-
this.logMethodError("getProductList", error);
|
|
1668
|
+
this.logMethodError("getProductList", error.message);
|
|
1180
1669
|
throw error;
|
|
1181
1670
|
}
|
|
1182
1671
|
}
|
|
@@ -1190,6 +1679,69 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1190
1679
|
this.otherParams = { ...this.otherParams, ...params };
|
|
1191
1680
|
}
|
|
1192
1681
|
}
|
|
1682
|
+
getUIStateBucketKey() {
|
|
1683
|
+
if (!this.cacheId)
|
|
1684
|
+
return null;
|
|
1685
|
+
return `${_ScanOrderImpl.UI_STATE_KEY_PREFIX}${this.cacheId}`;
|
|
1686
|
+
}
|
|
1687
|
+
readUIStateBucket() {
|
|
1688
|
+
var _a;
|
|
1689
|
+
const key = this.getUIStateBucketKey();
|
|
1690
|
+
if (!key || !((_a = this.window) == null ? void 0 : _a.localStorage))
|
|
1691
|
+
return {};
|
|
1692
|
+
try {
|
|
1693
|
+
const raw = this.window.localStorage.getItem(key) || "{}";
|
|
1694
|
+
const parsed = JSON.parse(raw);
|
|
1695
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
1696
|
+
} catch {
|
|
1697
|
+
return {};
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
writeUIStateBucket(bucket) {
|
|
1701
|
+
var _a;
|
|
1702
|
+
const key = this.getUIStateBucketKey();
|
|
1703
|
+
if (!key || !((_a = this.window) == null ? void 0 : _a.localStorage))
|
|
1704
|
+
return;
|
|
1705
|
+
try {
|
|
1706
|
+
this.window.localStorage.setItem(key, JSON.stringify(bucket));
|
|
1707
|
+
} catch (error) {
|
|
1708
|
+
console.warn("[ScanOrder] writeUIStateBucket failed", error);
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
setUIState(key, value) {
|
|
1712
|
+
if (!this.getUIStateBucketKey())
|
|
1713
|
+
return;
|
|
1714
|
+
const bucket = this.readUIStateBucket();
|
|
1715
|
+
bucket[key] = value;
|
|
1716
|
+
this.writeUIStateBucket(bucket);
|
|
1717
|
+
}
|
|
1718
|
+
getUIState(key) {
|
|
1719
|
+
if (!this.getUIStateBucketKey())
|
|
1720
|
+
return void 0;
|
|
1721
|
+
const bucket = this.readUIStateBucket();
|
|
1722
|
+
return bucket[key];
|
|
1723
|
+
}
|
|
1724
|
+
deleteUIState(key) {
|
|
1725
|
+
if (!this.getUIStateBucketKey())
|
|
1726
|
+
return;
|
|
1727
|
+
const bucket = this.readUIStateBucket();
|
|
1728
|
+
if (key in bucket) {
|
|
1729
|
+
delete bucket[key];
|
|
1730
|
+
this.writeUIStateBucket(bucket);
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
// 整桶清空(用于扫新桌、提交成功、restoreOrder 等场景)
|
|
1734
|
+
clearUIState() {
|
|
1735
|
+
var _a;
|
|
1736
|
+
const key = this.getUIStateBucketKey();
|
|
1737
|
+
if (!key || !((_a = this.window) == null ? void 0 : _a.localStorage))
|
|
1738
|
+
return;
|
|
1739
|
+
try {
|
|
1740
|
+
this.window.localStorage.removeItem(key);
|
|
1741
|
+
} catch (error) {
|
|
1742
|
+
console.warn("[ScanOrder] clearUIState failed", error);
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1193
1745
|
async setEntryPaxNumber(number) {
|
|
1194
1746
|
const pax = (0, import_utils2.normalizeSubmitCollectPaxValue)(number);
|
|
1195
1747
|
this.store.entryPaxNumber = pax;
|
|
@@ -1209,7 +1761,51 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1209
1761
|
getEntryPaxNumber() {
|
|
1210
1762
|
return this.store.entryPaxNumber;
|
|
1211
1763
|
}
|
|
1764
|
+
// 读取取餐/送餐开关
|
|
1765
|
+
// 依赖 checkResourceAvailable 已缓存的 dineInConfig
|
|
1766
|
+
getFulfillmentModes() {
|
|
1767
|
+
var _a;
|
|
1768
|
+
this.logMethodStart("getFulfillmentModes");
|
|
1769
|
+
const dineInConfig = ((_a = this.otherParams) == null ? void 0 : _a.dineInConfig) || {};
|
|
1770
|
+
const result = {
|
|
1771
|
+
enablePickup: Boolean(dineInConfig["fulfillment.enable_pickup"]),
|
|
1772
|
+
enableTableService: Boolean(dineInConfig["fulfillment.enable_table_service"])
|
|
1773
|
+
};
|
|
1774
|
+
this.logMethodSuccess("getFulfillmentModes", result);
|
|
1775
|
+
return result;
|
|
1776
|
+
}
|
|
1777
|
+
// 判定后台是否开启客户自定义取餐标识
|
|
1778
|
+
// 依赖 checkResourceAvailable 已缓存的 dineInConfig
|
|
1779
|
+
checkManualPickupRef() {
|
|
1780
|
+
var _a;
|
|
1781
|
+
this.logMethodStart("checkManualPickupRef");
|
|
1782
|
+
const dineInConfig = ((_a = this.otherParams) == null ? void 0 : _a.dineInConfig) || {};
|
|
1783
|
+
const refMode = dineInConfig["fulfillment.fulfillment_ref_mode"];
|
|
1784
|
+
const manualInputType = dineInConfig["fulfillment.manual_input_type"];
|
|
1785
|
+
const enabled = refMode === "manual_input";
|
|
1786
|
+
const result = enabled ? { enabled: true, manualInputType } : { enabled: false };
|
|
1787
|
+
this.logMethodSuccess("checkManualPickupRef", {
|
|
1788
|
+
enabled,
|
|
1789
|
+
manualInputType: enabled ? manualInputType : void 0
|
|
1790
|
+
});
|
|
1791
|
+
return result;
|
|
1792
|
+
}
|
|
1212
1793
|
};
|
|
1794
|
+
var ScanOrderImpl = _ScanOrderImpl;
|
|
1795
|
+
ScanOrderImpl.PISELL1_LOGIN_SUCCESS = "pisell1.login.success";
|
|
1796
|
+
// ─── UI 状态缓存(按 cacheId 分桶,localStorage) ───
|
|
1797
|
+
//
|
|
1798
|
+
// 用于物料层持久化 UI 层面的轻量状态(如当前步骤、gate 标记、登录回跳意图等)。
|
|
1799
|
+
// 桶键:pisell.scanOrder.uiState:<cacheId>;内部以 JSON object 形式存储多个字段。
|
|
1800
|
+
// 无 cacheId 时所有方法自动降级为 no-op,上层不用判空。
|
|
1801
|
+
//
|
|
1802
|
+
// 之所以用 localStorage 而不是 sessionStorage:
|
|
1803
|
+
// 1. 与 Order 模块 openCache 下的 tempOrder 同栈,购物车在 / UIState 在,行为对齐;
|
|
1804
|
+
// 2. pisell1.login 整页 OAuth 跳转在 H5 壳 / iOS Safari 场景下可能丢 sessionStorage,
|
|
1805
|
+
// 导致登录回跳后 gate 标记失效、pax 弹窗重开、落点错误;localStorage 稳定不受影响。
|
|
1806
|
+
// 3. 失效由上层显式控制:提交成功 clearStepCache / entryContext 不一致 clearUIState /
|
|
1807
|
+
// pendingStep 登录回调 deleteUIState,足够约束生命周期。
|
|
1808
|
+
ScanOrderImpl.UI_STATE_KEY_PREFIX = "pisell.scanOrder.uiState:";
|
|
1213
1809
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1214
1810
|
0 && (module.exports = {
|
|
1215
1811
|
ScanOrderImpl,
|