@pisell/pisellos 2.1.128 → 2.1.130
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 +0 -9
- package/dist/modules/Order/index.d.ts +4 -0
- package/dist/modules/Order/index.js +18 -1
- package/dist/modules/Order/types.d.ts +9 -1
- package/dist/modules/Order/utils.d.ts +7 -0
- package/dist/modules/Order/utils.js +27 -11
- package/dist/solution/ScanOrder/index.d.ts +27 -3
- package/dist/solution/ScanOrder/index.js +865 -481
- package/dist/solution/ScanOrder/types.d.ts +34 -24
- package/dist/solution/ScanOrder/types.js +5 -1
- package/dist/solution/ScanOrder/utils.d.ts +13 -1
- package/dist/solution/ScanOrder/utils.js +45 -6
- package/dist/solution/VenueBooking/index.d.ts +28 -5
- package/dist/solution/VenueBooking/index.js +463 -227
- 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/model/strategy/adapter/promotion/index.js +49 -0
- package/lib/modules/Order/index.d.ts +4 -0
- package/lib/modules/Order/index.js +14 -1
- package/lib/modules/Order/types.d.ts +9 -1
- package/lib/modules/Order/utils.d.ts +7 -0
- package/lib/modules/Order/utils.js +22 -12
- package/lib/solution/ScanOrder/index.d.ts +27 -3
- package/lib/solution/ScanOrder/index.js +409 -114
- package/lib/solution/ScanOrder/types.d.ts +34 -24
- package/lib/solution/ScanOrder/utils.d.ts +13 -1
- package/lib/solution/ScanOrder/utils.js +37 -0
- package/lib/solution/VenueBooking/index.d.ts +28 -5
- package/lib/solution/VenueBooking/index.js +203 -58
- 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
|
@@ -38,11 +38,13 @@ var import_types = require("./types");
|
|
|
38
38
|
var import_utils = require("./utils");
|
|
39
39
|
var import_types2 = require("../BookingByStep/types");
|
|
40
40
|
var import_ProductList = require("../../modules/ProductList");
|
|
41
|
+
var import_Schedule = require("../../modules/Schedule");
|
|
42
|
+
var import_getDateIsInSchedule = require("../../modules/Schedule/getDateIsInSchedule");
|
|
41
43
|
var import_utils2 = require("../../modules/Order/utils");
|
|
42
44
|
var import_dayjs = __toESM(require("dayjs"));
|
|
43
45
|
var import_itemRule = require("../../model/strategy/adapter/itemRule");
|
|
44
46
|
__reExport(ScanOrder_exports, require("./types"), module.exports);
|
|
45
|
-
var
|
|
47
|
+
var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
46
48
|
constructor(name, version) {
|
|
47
49
|
super(name, version);
|
|
48
50
|
this.defaultName = "scanOrder";
|
|
@@ -82,11 +84,11 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
82
84
|
}
|
|
83
85
|
serializeError(error) {
|
|
84
86
|
if (error instanceof Error) {
|
|
85
|
-
return {
|
|
87
|
+
return JSON.stringify({
|
|
86
88
|
name: error.name,
|
|
87
89
|
message: error.message,
|
|
88
90
|
stack: error.stack
|
|
89
|
-
};
|
|
91
|
+
});
|
|
90
92
|
}
|
|
91
93
|
return {
|
|
92
94
|
message: String(error)
|
|
@@ -202,7 +204,7 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
202
204
|
const loggerProvider = ((_c2 = this.otherParams) == null ? void 0 : _c2.scanOrderLoggerProvider) || "feishu";
|
|
203
205
|
const loggerConfig = ((_d2 = this.otherParams) == null ? void 0 : _d2.scanOrderLoggerConfig) || {
|
|
204
206
|
feishu: {
|
|
205
|
-
|
|
207
|
+
webhook: "https://open.feishu.cn/open-apis/bot/v2/hook/216b3fe6-af98-424e-8706-f0471241a7ed"
|
|
206
208
|
}
|
|
207
209
|
};
|
|
208
210
|
this.core.registerModule(targetModule, {
|
|
@@ -226,11 +228,26 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
226
228
|
if (this.store.scanOrderLogger) {
|
|
227
229
|
this.store.scanOrderLogger.setContext(this.getScanOrderLoggerContext());
|
|
228
230
|
}
|
|
231
|
+
const scheduleModule = new import_Schedule.ScheduleModule(`${this.name}_schedule`);
|
|
232
|
+
this.store.schedule = scheduleModule;
|
|
233
|
+
this.core.registerModule(scheduleModule, {
|
|
234
|
+
otherParams: {
|
|
235
|
+
...this.otherParams,
|
|
236
|
+
fatherModule: this.name
|
|
237
|
+
}
|
|
238
|
+
});
|
|
229
239
|
console.log("[ScanOrder] 初始化开始");
|
|
230
240
|
try {
|
|
231
241
|
await ((_e = this.store.order) == null ? void 0 : _e.recalculateSummary({ createIfMissing: false }));
|
|
232
242
|
(_f = this.store.order) == null ? void 0 : _f.persistTempOrder();
|
|
233
243
|
await this.loadRuntimeConfigs();
|
|
244
|
+
if (this.store.schedule) {
|
|
245
|
+
try {
|
|
246
|
+
await this.store.schedule.loadAllSchedule();
|
|
247
|
+
} catch (scheduleError) {
|
|
248
|
+
console.warn("[ScanOrder] loadAllSchedule 失败,operating_hours 判定将跳过", scheduleError);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
234
251
|
await this.refreshItemRuleQuantityLimits();
|
|
235
252
|
this.store.status = "ready";
|
|
236
253
|
console.log("[ScanOrder] 初始化完成");
|
|
@@ -368,6 +385,50 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
368
385
|
throw error;
|
|
369
386
|
}
|
|
370
387
|
}
|
|
388
|
+
// 存储 UI 层选择的取餐方式到 tempOrder.metadata.shop_service_data
|
|
389
|
+
// service_type 在扫码点餐场景固定为 dine_in
|
|
390
|
+
setPickupReferenceMode(mode) {
|
|
391
|
+
this.logMethodStart("setPickupReferenceMode", { mode });
|
|
392
|
+
try {
|
|
393
|
+
if (!this.store.order)
|
|
394
|
+
throw new Error("order 模块未初始化");
|
|
395
|
+
const tempOrder = this.store.order.ensureTempOrder();
|
|
396
|
+
tempOrder.metadata = {
|
|
397
|
+
...tempOrder.metadata || {},
|
|
398
|
+
shop_service_data: {
|
|
399
|
+
...(tempOrder.metadata || {}).shop_service_data || {},
|
|
400
|
+
service_type: "dine_in",
|
|
401
|
+
pickup_reference_mode: mode
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
this.store.order.persistTempOrder();
|
|
405
|
+
this.logMethodSuccess("setPickupReferenceMode", {
|
|
406
|
+
mode
|
|
407
|
+
});
|
|
408
|
+
return tempOrder.metadata.shop_service_data;
|
|
409
|
+
} catch (error) {
|
|
410
|
+
this.logMethodError("setPickupReferenceMode", error, { mode });
|
|
411
|
+
throw error;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// 存储用户自定义取餐标识到 tempOrder.buzzer
|
|
415
|
+
setPickupRef(buzzer) {
|
|
416
|
+
this.logMethodStart("setPickupRef", {
|
|
417
|
+
buzzerLength: String(buzzer || "").length
|
|
418
|
+
});
|
|
419
|
+
try {
|
|
420
|
+
if (!this.store.order)
|
|
421
|
+
throw new Error("order 模块未初始化");
|
|
422
|
+
const result = this.store.order.updateTempOrderBuzzer(buzzer);
|
|
423
|
+
this.logMethodSuccess("setPickupRef", {
|
|
424
|
+
buzzerLength: result.length
|
|
425
|
+
});
|
|
426
|
+
return result;
|
|
427
|
+
} catch (error) {
|
|
428
|
+
this.logMethodError("setPickupRef", error);
|
|
429
|
+
throw error;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
371
432
|
ensureTempOrder() {
|
|
372
433
|
if (!this.store.order)
|
|
373
434
|
throw new Error("order 模块未初始化");
|
|
@@ -389,6 +450,25 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
389
450
|
throw error;
|
|
390
451
|
}
|
|
391
452
|
}
|
|
453
|
+
// 重置 tempOrder 与与上一单强相关的运行态(resource/entryPaxNumber/enabledReservationRuleProducts),
|
|
454
|
+
// 适用于从支付页通过 react-router 跳回继续下单时清理残留数据
|
|
455
|
+
async restoreOrder() {
|
|
456
|
+
this.logMethodStart("restoreOrder");
|
|
457
|
+
try {
|
|
458
|
+
if (!this.store.order) {
|
|
459
|
+
throw new Error("scanOrder 解决方案需要 order 模块支持");
|
|
460
|
+
}
|
|
461
|
+
this.store.resource = null;
|
|
462
|
+
this.store.entryPaxNumber = 1;
|
|
463
|
+
this.enabledReservationRuleProducts = [];
|
|
464
|
+
const tempOrder = this.store.order.restoreOrder();
|
|
465
|
+
this.logMethodSuccess("restoreOrder");
|
|
466
|
+
return tempOrder;
|
|
467
|
+
} catch (error) {
|
|
468
|
+
this.logMethodError("restoreOrder", error);
|
|
469
|
+
throw error;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
392
472
|
getOrderProducts() {
|
|
393
473
|
this.logMethodStart("getOrderProducts");
|
|
394
474
|
if (!this.store.order)
|
|
@@ -414,8 +494,90 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
414
494
|
throw error;
|
|
415
495
|
}
|
|
416
496
|
}
|
|
497
|
+
// ScanOrder 提交 payload enhancer:
|
|
498
|
+
// - 给所有 booking 注入 appointment_status: 'started'(扫码点餐语义)
|
|
499
|
+
// - 给所有 booking 的 metadata 注入 resource_select_type(来自预约规则商品的 resource.type)
|
|
500
|
+
// - 给第一条 booking 补 resources 与 product_uid(仅当存在 resource / rule product)
|
|
501
|
+
// - 追加一条 is_rule=true 的 rule product,与 booking 互相关联
|
|
502
|
+
buildSubmitPayloadEnhancer() {
|
|
503
|
+
const ruleProduct = this.enabledReservationRuleProducts[0];
|
|
504
|
+
const resourceState = this.store.resource;
|
|
505
|
+
const resourceSelectType = resourceState == null ? void 0 : resourceState.resourceSelectType;
|
|
506
|
+
const resolveResourceCapacity = () => {
|
|
507
|
+
var _a;
|
|
508
|
+
if (resourceSelectType === "single") {
|
|
509
|
+
const raw = (_a = resourceState == null ? void 0 : resourceState.table_form_record) == null ? void 0 : _a.capacity;
|
|
510
|
+
const num = Number(raw);
|
|
511
|
+
if (Number.isFinite(num) && num > 0)
|
|
512
|
+
return num;
|
|
513
|
+
return 1;
|
|
514
|
+
}
|
|
515
|
+
return 1;
|
|
516
|
+
};
|
|
517
|
+
return (payload, { bookingUuid, tempOrder }) => {
|
|
518
|
+
var _a;
|
|
519
|
+
const resourceId = tempOrder.resource_id ?? (resourceState == null ? void 0 : resourceState.relationId);
|
|
520
|
+
const pickOriginal = (value) => {
|
|
521
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
522
|
+
const original = value.original;
|
|
523
|
+
return typeof original === "string" && original.length > 0 ? original : void 0;
|
|
524
|
+
}
|
|
525
|
+
return void 0;
|
|
526
|
+
};
|
|
527
|
+
const mainField = pickOriginal(tempOrder.table_number) ?? pickOriginal((_a = resourceState == null ? void 0 : resourceState.table_form_record) == null ? void 0 : _a.name) ?? "";
|
|
528
|
+
const resourceEntry = resourceState && resourceId ? {
|
|
529
|
+
relation_type: "form",
|
|
530
|
+
like_status: "common",
|
|
531
|
+
id: Number(resourceId),
|
|
532
|
+
main_field: mainField,
|
|
533
|
+
form_id: resourceState.tableFormId,
|
|
534
|
+
relation_id: resourceState.relationId ?? resourceId,
|
|
535
|
+
capacity: resolveResourceCapacity(),
|
|
536
|
+
metadata: {}
|
|
537
|
+
} : void 0;
|
|
538
|
+
const ruleProductUid = ruleProduct ? (0, import_utils2.createUuidV4)() : void 0;
|
|
539
|
+
const bookingCapacityValue = resolveResourceCapacity();
|
|
540
|
+
const nextBookings = (payload.bookings || []).map((booking, idx) => ({
|
|
541
|
+
...booking,
|
|
542
|
+
appointment_status: "started",
|
|
543
|
+
metadata: {
|
|
544
|
+
...booking.metadata || {},
|
|
545
|
+
...resourceSelectType ? { resource_select_type: resourceSelectType } : {},
|
|
546
|
+
...resourceSelectType ? { capacity: [{ id: 0, value: bookingCapacityValue, name: "" }] } : {}
|
|
547
|
+
},
|
|
548
|
+
...idx === 0 && resourceEntry ? { resources: [resourceEntry] } : {},
|
|
549
|
+
...idx === 0 && ruleProductUid ? { product_uid: ruleProductUid } : {}
|
|
550
|
+
}));
|
|
551
|
+
const nextProducts = [...payload.products || []];
|
|
552
|
+
if (ruleProduct && ruleProductUid) {
|
|
553
|
+
const sellingPrice = String(ruleProduct.price ?? "0.00");
|
|
554
|
+
const originalPrice = String(
|
|
555
|
+
ruleProduct.original_price ?? ruleProduct.price ?? "0.00"
|
|
556
|
+
);
|
|
557
|
+
nextProducts.push({
|
|
558
|
+
product_id: ruleProduct.id,
|
|
559
|
+
product_variant_id: 0,
|
|
560
|
+
num: 1,
|
|
561
|
+
selling_price: sellingPrice,
|
|
562
|
+
original_price: originalPrice,
|
|
563
|
+
payment_price: sellingPrice,
|
|
564
|
+
is_charge_tax: ruleProduct.is_gst ?? 0,
|
|
565
|
+
product_option_item: [],
|
|
566
|
+
discount_list: [],
|
|
567
|
+
product_bundle: [],
|
|
568
|
+
booking_uid: bookingUuid,
|
|
569
|
+
metadata: {
|
|
570
|
+
is_rule: true,
|
|
571
|
+
unique_identification_number: ruleProductUid,
|
|
572
|
+
booking_uid: bookingUuid
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
return { ...payload, bookings: nextBookings, products: nextProducts };
|
|
577
|
+
};
|
|
578
|
+
}
|
|
417
579
|
async submitScanOrder() {
|
|
418
|
-
var _a, _b, _c, _d, _e;
|
|
580
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
419
581
|
this.logMethodStart("submitScanOrder");
|
|
420
582
|
try {
|
|
421
583
|
await this.validateBeforeSubmitByItemRule();
|
|
@@ -426,17 +588,26 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
426
588
|
this.store.entryPaxNumber = pax;
|
|
427
589
|
const tempOrderForSubmit = this.store.order.ensureTempOrder();
|
|
428
590
|
tempOrderForSubmit.metadata = { ...tempOrderForSubmit.metadata, collect_pax: pax };
|
|
591
|
+
tempOrderForSubmit.delivery_type = "shop_service";
|
|
592
|
+
const resourceTableName = (_b = (_a = this.store.resource) == null ? void 0 : _a.table_form_record) == null ? void 0 : _b.name;
|
|
593
|
+
if (resourceTableName && typeof resourceTableName === "object") {
|
|
594
|
+
tempOrderForSubmit.table_number = resourceTableName;
|
|
595
|
+
} else {
|
|
596
|
+
delete tempOrderForSubmit.table_number;
|
|
597
|
+
}
|
|
429
598
|
this.store.order.persistTempOrder();
|
|
599
|
+
const enhancePayload = this.buildSubmitPayloadEnhancer();
|
|
430
600
|
const result = await this.store.order.submitTempOrder({
|
|
431
601
|
cacheId: this.cacheId,
|
|
432
|
-
platform: (
|
|
433
|
-
businessCode: (
|
|
434
|
-
channel: (
|
|
435
|
-
type: (
|
|
602
|
+
platform: (_c = this.otherParams) == null ? void 0 : _c.platform,
|
|
603
|
+
businessCode: (_d = this.otherParams) == null ? void 0 : _d.businessCode,
|
|
604
|
+
channel: (_e = this.otherParams) == null ? void 0 : _e.channel,
|
|
605
|
+
type: (_f = this.otherParams) == null ? void 0 : _f.type,
|
|
606
|
+
enhancePayload
|
|
436
607
|
});
|
|
437
608
|
const tempOrder = this.store.order.getTempOrder();
|
|
438
609
|
this.logMethodSuccess("submitScanOrder", {
|
|
439
|
-
productCount: ((
|
|
610
|
+
productCount: ((_g = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _g.length) || 0
|
|
440
611
|
});
|
|
441
612
|
return result;
|
|
442
613
|
} catch (error) {
|
|
@@ -857,20 +1028,22 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
857
1028
|
strategyCount: Array.isArray(this.itemRuleRuntimeConfig.strategyConfigs) ? this.itemRuleRuntimeConfig.strategyConfigs.length : 0
|
|
858
1029
|
});
|
|
859
1030
|
}
|
|
860
|
-
normalizeResourceState(
|
|
861
|
-
var _a, _b;
|
|
862
|
-
const
|
|
863
|
-
const
|
|
864
|
-
const
|
|
865
|
-
const
|
|
866
|
-
const
|
|
867
|
-
const relationId = (0, import_utils.toPositiveString)(config == null ? void 0 : config.relation_id);
|
|
868
|
-
const tableFormId = (0, import_utils.toPositiveString)(config == null ? void 0 : config.table_form_id);
|
|
1031
|
+
normalizeResourceState(detail, resourceSelectType, hasOrderId) {
|
|
1032
|
+
var _a, _b, _c, _d;
|
|
1033
|
+
const currentOrderId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.order_id);
|
|
1034
|
+
const lastOrderId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.last_order_id);
|
|
1035
|
+
const relationId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.form_record_id);
|
|
1036
|
+
const tableFormId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.form_id);
|
|
1037
|
+
const formRecord = (detail == null ? void 0 : detail.form_record) ?? null;
|
|
869
1038
|
const allowSnack = ((_b = (_a = this.otherParams) == null ? void 0 : _a.dineInConfig) == null ? void 0 : _b["workflow.allow_add_items"]) || false;
|
|
870
1039
|
const deskmateValid = false;
|
|
871
|
-
const isExclusive =
|
|
872
|
-
const isFull =
|
|
873
|
-
|
|
1040
|
+
const isExclusive = resourceSelectType === "single";
|
|
1041
|
+
const isFull = (0, import_utils.computeResourceIsFull)({
|
|
1042
|
+
resourceSelectType,
|
|
1043
|
+
lastOrderId,
|
|
1044
|
+
capacityList: ((_d = (_c = detail == null ? void 0 : detail.resource_capacity) == null ? void 0 : _c[0]) == null ? void 0 : _d.capacity_list) ?? [],
|
|
1045
|
+
capacity: formRecord == null ? void 0 : formRecord.capacity
|
|
1046
|
+
});
|
|
874
1047
|
let availabilityInfo = {
|
|
875
1048
|
mode: "idle",
|
|
876
1049
|
deskmate_valid: deskmateValid
|
|
@@ -894,33 +1067,19 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
894
1067
|
};
|
|
895
1068
|
}
|
|
896
1069
|
} 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
|
-
};
|
|
1070
|
+
const canFallthroughToIdle = resourceSelectType === "multiple" && !isFull;
|
|
1071
|
+
if (!canFallthroughToIdle) {
|
|
1072
|
+
availabilityInfo = {
|
|
1073
|
+
mode: "resource_busy",
|
|
1074
|
+
order_id: "0",
|
|
1075
|
+
relation_id: relationId,
|
|
1076
|
+
table_form_id: tableFormId,
|
|
1077
|
+
deskmate_valid: deskmateValid
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
919
1080
|
}
|
|
920
1081
|
return {
|
|
921
1082
|
...availabilityInfo,
|
|
922
|
-
tableMaxNumber,
|
|
923
|
-
orderCount,
|
|
924
1083
|
currentOrderId,
|
|
925
1084
|
lastOrderId,
|
|
926
1085
|
relationId,
|
|
@@ -929,27 +1088,46 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
929
1088
|
deskmateValid,
|
|
930
1089
|
isExclusive,
|
|
931
1090
|
isFull,
|
|
932
|
-
|
|
933
|
-
raw:
|
|
934
|
-
table_form_record:
|
|
1091
|
+
resourceSelectType,
|
|
1092
|
+
raw: detail,
|
|
1093
|
+
table_form_record: formRecord
|
|
935
1094
|
};
|
|
936
1095
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1096
|
+
// 从首个预约规则商品的 product_resource.resources 中,按 form_id 匹配返回 type
|
|
1097
|
+
resolveResourceSelectType(formId) {
|
|
1098
|
+
var _a;
|
|
1099
|
+
const firstProduct = this.enabledReservationRuleProducts[0];
|
|
1100
|
+
const resources = ((_a = firstProduct == null ? void 0 : firstProduct.product_resource) == null ? void 0 : _a.resources) || [];
|
|
1101
|
+
const numericFormId = Number(formId);
|
|
1102
|
+
if (!Number.isFinite(numericFormId) || numericFormId <= 0)
|
|
1103
|
+
return void 0;
|
|
1104
|
+
const matched = resources.find((r) => Number(r == null ? void 0 : r.id) === numericFormId);
|
|
1105
|
+
return matched == null ? void 0 : matched.type;
|
|
1106
|
+
}
|
|
1107
|
+
async fetchResourceOccupyDetailByResourceId(resourceId) {
|
|
1108
|
+
var _a, _b, _c, _d;
|
|
1109
|
+
const formRecordId = Number(resourceId);
|
|
1110
|
+
if (!Number.isFinite(formRecordId) || formRecordId <= 0) {
|
|
940
1111
|
throw new Error(`[ScanOrder] 非法桌台 resourceId: ${resourceId}`);
|
|
941
1112
|
}
|
|
1113
|
+
const shopId = (_b = (_a = this.otherParams) == null ? void 0 : _a.getStateData) == null ? void 0 : _b.call(_a, "shop_id");
|
|
1114
|
+
if (!shopId) {
|
|
1115
|
+
throw new Error("[ScanOrder] 无法获取 shop_id");
|
|
1116
|
+
}
|
|
942
1117
|
const response = await this.request.get(
|
|
943
|
-
"/order/
|
|
1118
|
+
"/order/resource/occupy-detail",
|
|
944
1119
|
{
|
|
945
|
-
|
|
946
|
-
|
|
1120
|
+
shop_id: shopId,
|
|
1121
|
+
"form_record_ids[]": formRecordId,
|
|
1122
|
+
with_resource_capacity_info: 1,
|
|
1123
|
+
with_resource_order_info: 1,
|
|
1124
|
+
with_resource_form_info: 1
|
|
947
1125
|
}
|
|
948
1126
|
);
|
|
949
1127
|
if (!(response == null ? void 0 : response.status)) {
|
|
950
|
-
throw new Error((response == null ? void 0 : response.message) || "
|
|
1128
|
+
throw new Error((response == null ? void 0 : response.message) || "获取资源占用详情失败");
|
|
951
1129
|
}
|
|
952
|
-
return (response == null ? void 0 : response.data)
|
|
1130
|
+
return ((_d = (_c = response == null ? void 0 : response.data) == null ? void 0 : _c.occupy_details) == null ? void 0 : _d[0]) ?? null;
|
|
953
1131
|
}
|
|
954
1132
|
// 检测当前链接是否可用
|
|
955
1133
|
// 通过 resource_id + 店铺配置
|
|
@@ -971,46 +1149,48 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
971
1149
|
const dineInConfig = (openData == null ? void 0 : openData.data) || {};
|
|
972
1150
|
this.otherParams.dineInConfig = dineInConfig;
|
|
973
1151
|
await this.syncItemRuleConfigsFromDineInConfig(dineInConfig);
|
|
974
|
-
const
|
|
1152
|
+
const closedBehaviorValue = dineInConfig == null ? void 0 : dineInConfig["availability.closed_behavior"];
|
|
1153
|
+
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"]);
|
|
1154
|
+
const basicUnavailableMessage = (dineInConfig == null ? void 0 : dineInConfig["basic.unavailable_message"]) || closedMessage;
|
|
1155
|
+
const pauseMessage = (dineInConfig == null ? void 0 : dineInConfig["availability.pause_message"]) || closedMessage;
|
|
1156
|
+
const makeShopClosed = (errorTips, closed_behavior) => ({
|
|
975
1157
|
mode: "shop_closed",
|
|
976
1158
|
order_id: void 0,
|
|
977
1159
|
relation_id: void 0,
|
|
978
1160
|
table_form_id: void 0,
|
|
979
1161
|
deskmate_valid: false,
|
|
980
|
-
errorTips
|
|
1162
|
+
errorTips,
|
|
1163
|
+
closed_behavior
|
|
981
1164
|
});
|
|
1165
|
+
if ((dineInConfig == null ? void 0 : dineInConfig["basic.enable"]) === false) {
|
|
1166
|
+
return makeShopClosed(basicUnavailableMessage);
|
|
1167
|
+
}
|
|
982
1168
|
if ((0, import_utils.toBoolean)(dineInConfig == null ? void 0 : dineInConfig["availability.paused"])) {
|
|
983
1169
|
if ((dineInConfig == null ? void 0 : dineInConfig["availability.pause_behavior"]) === "hide_all") {
|
|
984
|
-
return
|
|
1170
|
+
return makeShopClosed(pauseMessage);
|
|
985
1171
|
}
|
|
986
1172
|
}
|
|
987
|
-
const
|
|
988
|
-
|
|
989
|
-
this.store.
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
};
|
|
1173
|
+
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) : [];
|
|
1174
|
+
let outsideOperatingHours = false;
|
|
1175
|
+
if (operatingHourIds.length && this.store.schedule) {
|
|
1176
|
+
const scheduleList = this.store.schedule.getScheduleListByIds(operatingHourIds);
|
|
1177
|
+
if (scheduleList.length) {
|
|
1178
|
+
const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
|
|
1179
|
+
outsideOperatingHours = !(0, import_getDateIsInSchedule.getDateIsInSchedule)(now, scheduleList);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
if (outsideOperatingHours && closedBehaviorValue !== "show_menu_disabled") {
|
|
1183
|
+
return makeShopClosed(closedMessage, closedBehaviorValue);
|
|
1184
|
+
}
|
|
1000
1185
|
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
1186
|
const reservationLinkIds = (0, import_utils.collectLinkProductIdsFromReservationRules)(
|
|
1005
|
-
dineInConfig["
|
|
1187
|
+
dineInConfig["fulfillment.enabled_resource_rules"]
|
|
1006
1188
|
);
|
|
1189
|
+
let pendingRequestEntryPax;
|
|
1190
|
+
let pendingRequestPaxMin;
|
|
1191
|
+
let pendingRequestPaxMax;
|
|
1007
1192
|
if (reservationLinkIds.length === 0) {
|
|
1008
1193
|
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
1194
|
} else {
|
|
1015
1195
|
tempOrder.metadata = { ...tempOrder.metadata || {} };
|
|
1016
1196
|
delete tempOrder.metadata.table_occupancy_duration;
|
|
@@ -1042,38 +1222,15 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1042
1222
|
tempOrder.metadata.table_occupancy_duration = occupancyMinutes;
|
|
1043
1223
|
}
|
|
1044
1224
|
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
|
-
}
|
|
1225
|
+
pendingRequestEntryPax = 1;
|
|
1054
1226
|
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;
|
|
1227
|
+
if ((paxBounds == null ? void 0 : paxBounds.min) !== void 0)
|
|
1228
|
+
pendingRequestPaxMin = paxBounds.min;
|
|
1229
|
+
if ((paxBounds == null ? void 0 : paxBounds.max) !== void 0)
|
|
1230
|
+
pendingRequestPaxMax = paxBounds.max;
|
|
1069
1231
|
}
|
|
1070
1232
|
} else {
|
|
1071
1233
|
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
1234
|
void this.addScanOrderLog({
|
|
1078
1235
|
level: "error",
|
|
1079
1236
|
title: "[ScanOrder] enabled_reservation_rules product query failed",
|
|
@@ -1084,6 +1241,41 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1084
1241
|
});
|
|
1085
1242
|
}
|
|
1086
1243
|
}
|
|
1244
|
+
const occupyDetail = await this.fetchResourceOccupyDetailByResourceId(resourceId);
|
|
1245
|
+
const resourceSelectType = this.resolveResourceSelectType(
|
|
1246
|
+
(0, import_utils.toPositiveString)(occupyDetail == null ? void 0 : occupyDetail.form_id)
|
|
1247
|
+
);
|
|
1248
|
+
const resourceState = this.normalizeResourceState(
|
|
1249
|
+
occupyDetail,
|
|
1250
|
+
resourceSelectType,
|
|
1251
|
+
hasOrderId
|
|
1252
|
+
);
|
|
1253
|
+
this.store.resource = resourceState;
|
|
1254
|
+
if (pendingRequestEntryPax !== void 0) {
|
|
1255
|
+
this.store.resource.requestEntryPax = pendingRequestEntryPax;
|
|
1256
|
+
}
|
|
1257
|
+
if (pendingRequestPaxMin !== void 0) {
|
|
1258
|
+
this.store.resource.requestPaxMin = pendingRequestPaxMin;
|
|
1259
|
+
}
|
|
1260
|
+
if (pendingRequestPaxMax !== void 0) {
|
|
1261
|
+
this.store.resource.requestPaxMax = pendingRequestPaxMax;
|
|
1262
|
+
}
|
|
1263
|
+
const availabilityInfo = {
|
|
1264
|
+
mode: resourceState.mode,
|
|
1265
|
+
order_id: resourceState.order_id,
|
|
1266
|
+
relation_id: resourceState.relationId,
|
|
1267
|
+
table_form_id: resourceState.tableFormId,
|
|
1268
|
+
deskmate_valid: resourceState.deskmate_valid,
|
|
1269
|
+
table_form_record: resourceState.table_form_record,
|
|
1270
|
+
policy: (_c = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _c.policy,
|
|
1271
|
+
partyroom_booking: (_d = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _d.partyroom_booking,
|
|
1272
|
+
...this.store.resource.requestEntryPax !== void 0 ? { requestEntryPax: this.store.resource.requestEntryPax } : {},
|
|
1273
|
+
...this.store.resource.requestPaxMin !== void 0 ? { requestPaxMin: this.store.resource.requestPaxMin } : {},
|
|
1274
|
+
...this.store.resource.requestPaxMax !== void 0 ? { requestPaxMax: this.store.resource.requestPaxMax } : {}
|
|
1275
|
+
};
|
|
1276
|
+
tempOrder.relation_id = resourceId || ((_e = this.otherParams) == null ? void 0 : _e.relation_id);
|
|
1277
|
+
tempOrder.table_form_id = resourceState.tableFormId;
|
|
1278
|
+
tempOrder.resource_id = resourceId;
|
|
1087
1279
|
(_f = this.store.order) == null ? void 0 : _f.persistTempOrder();
|
|
1088
1280
|
if (availabilityInfo.mode === "idle") {
|
|
1089
1281
|
await this.addNewOrder();
|
|
@@ -1117,6 +1309,11 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1117
1309
|
submissionIndex: hasOrderId ? 1 : 0,
|
|
1118
1310
|
historicalItems
|
|
1119
1311
|
});
|
|
1312
|
+
if (outsideOperatingHours && closedBehaviorValue === "show_menu_disabled") {
|
|
1313
|
+
availabilityInfo.mode = "submit_disabled";
|
|
1314
|
+
availabilityInfo.errorTips = closedMessage;
|
|
1315
|
+
availabilityInfo.closed_behavior = closedBehaviorValue;
|
|
1316
|
+
}
|
|
1120
1317
|
this.logMethodSuccess("checkResourceAvailable", {
|
|
1121
1318
|
resourceId,
|
|
1122
1319
|
mode: availabilityInfo.mode,
|
|
@@ -1126,14 +1323,13 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1126
1323
|
persistedRelationId: tempOrder.relation_id,
|
|
1127
1324
|
persistedResourceId: tempOrder.resource_id,
|
|
1128
1325
|
deskmateValid: availabilityInfo.deskmate_valid,
|
|
1129
|
-
|
|
1130
|
-
tableMaxNumber: resourceState.tableMaxNumber,
|
|
1326
|
+
resourceSelectType: resourceState.resourceSelectType,
|
|
1131
1327
|
isExclusive: resourceState.isExclusive,
|
|
1132
1328
|
isFull: resourceState.isFull
|
|
1133
1329
|
});
|
|
1134
1330
|
return availabilityInfo;
|
|
1135
1331
|
} catch (error) {
|
|
1136
|
-
this.logMethodError("checkResourceAvailable", error, {
|
|
1332
|
+
this.logMethodError("checkResourceAvailable", error.message, {
|
|
1137
1333
|
resourceId
|
|
1138
1334
|
});
|
|
1139
1335
|
throw error;
|
|
@@ -1176,7 +1372,7 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1176
1372
|
});
|
|
1177
1373
|
return formattedRes;
|
|
1178
1374
|
} catch (error) {
|
|
1179
|
-
this.logMethodError("getProductList", error);
|
|
1375
|
+
this.logMethodError("getProductList", error.message);
|
|
1180
1376
|
throw error;
|
|
1181
1377
|
}
|
|
1182
1378
|
}
|
|
@@ -1190,6 +1386,69 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1190
1386
|
this.otherParams = { ...this.otherParams, ...params };
|
|
1191
1387
|
}
|
|
1192
1388
|
}
|
|
1389
|
+
getUIStateBucketKey() {
|
|
1390
|
+
if (!this.cacheId)
|
|
1391
|
+
return null;
|
|
1392
|
+
return `${_ScanOrderImpl.UI_STATE_KEY_PREFIX}${this.cacheId}`;
|
|
1393
|
+
}
|
|
1394
|
+
readUIStateBucket() {
|
|
1395
|
+
var _a;
|
|
1396
|
+
const key = this.getUIStateBucketKey();
|
|
1397
|
+
if (!key || !((_a = this.window) == null ? void 0 : _a.sessionStorage))
|
|
1398
|
+
return {};
|
|
1399
|
+
try {
|
|
1400
|
+
const raw = this.window.sessionStorage.getItem(key) || "{}";
|
|
1401
|
+
const parsed = JSON.parse(raw);
|
|
1402
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
1403
|
+
} catch {
|
|
1404
|
+
return {};
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
writeUIStateBucket(bucket) {
|
|
1408
|
+
var _a;
|
|
1409
|
+
const key = this.getUIStateBucketKey();
|
|
1410
|
+
if (!key || !((_a = this.window) == null ? void 0 : _a.sessionStorage))
|
|
1411
|
+
return;
|
|
1412
|
+
try {
|
|
1413
|
+
this.window.sessionStorage.setItem(key, JSON.stringify(bucket));
|
|
1414
|
+
} catch (error) {
|
|
1415
|
+
console.warn("[ScanOrder] writeUIStateBucket failed", error);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
setUIState(key, value) {
|
|
1419
|
+
if (!this.getUIStateBucketKey())
|
|
1420
|
+
return;
|
|
1421
|
+
const bucket = this.readUIStateBucket();
|
|
1422
|
+
bucket[key] = value;
|
|
1423
|
+
this.writeUIStateBucket(bucket);
|
|
1424
|
+
}
|
|
1425
|
+
getUIState(key) {
|
|
1426
|
+
if (!this.getUIStateBucketKey())
|
|
1427
|
+
return void 0;
|
|
1428
|
+
const bucket = this.readUIStateBucket();
|
|
1429
|
+
return bucket[key];
|
|
1430
|
+
}
|
|
1431
|
+
deleteUIState(key) {
|
|
1432
|
+
if (!this.getUIStateBucketKey())
|
|
1433
|
+
return;
|
|
1434
|
+
const bucket = this.readUIStateBucket();
|
|
1435
|
+
if (key in bucket) {
|
|
1436
|
+
delete bucket[key];
|
|
1437
|
+
this.writeUIStateBucket(bucket);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
// 整桶清空(用于扫新桌、提交成功、restoreOrder 等场景)
|
|
1441
|
+
clearUIState() {
|
|
1442
|
+
var _a;
|
|
1443
|
+
const key = this.getUIStateBucketKey();
|
|
1444
|
+
if (!key || !((_a = this.window) == null ? void 0 : _a.sessionStorage))
|
|
1445
|
+
return;
|
|
1446
|
+
try {
|
|
1447
|
+
this.window.sessionStorage.removeItem(key);
|
|
1448
|
+
} catch (error) {
|
|
1449
|
+
console.warn("[ScanOrder] clearUIState failed", error);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1193
1452
|
async setEntryPaxNumber(number) {
|
|
1194
1453
|
const pax = (0, import_utils2.normalizeSubmitCollectPaxValue)(number);
|
|
1195
1454
|
this.store.entryPaxNumber = pax;
|
|
@@ -1209,7 +1468,43 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1209
1468
|
getEntryPaxNumber() {
|
|
1210
1469
|
return this.store.entryPaxNumber;
|
|
1211
1470
|
}
|
|
1471
|
+
// 读取取餐/送餐开关
|
|
1472
|
+
// 依赖 checkResourceAvailable 已缓存的 dineInConfig
|
|
1473
|
+
getFulfillmentModes() {
|
|
1474
|
+
var _a;
|
|
1475
|
+
this.logMethodStart("getFulfillmentModes");
|
|
1476
|
+
const dineInConfig = ((_a = this.otherParams) == null ? void 0 : _a.dineInConfig) || {};
|
|
1477
|
+
const result = {
|
|
1478
|
+
enablePickup: Boolean(dineInConfig["fulfillment.enable_pickup"]),
|
|
1479
|
+
enableTableService: Boolean(dineInConfig["fulfillment.enable_table_service"])
|
|
1480
|
+
};
|
|
1481
|
+
this.logMethodSuccess("getFulfillmentModes", result);
|
|
1482
|
+
return result;
|
|
1483
|
+
}
|
|
1484
|
+
// 判定后台是否开启客户自定义取餐标识
|
|
1485
|
+
// 依赖 checkResourceAvailable 已缓存的 dineInConfig
|
|
1486
|
+
checkManualPickupRef() {
|
|
1487
|
+
var _a;
|
|
1488
|
+
this.logMethodStart("checkManualPickupRef");
|
|
1489
|
+
const dineInConfig = ((_a = this.otherParams) == null ? void 0 : _a.dineInConfig) || {};
|
|
1490
|
+
const refMode = dineInConfig["fulfillment.fulfillment_ref_mode"];
|
|
1491
|
+
const manualInputType = dineInConfig["fulfillment.manual_input_type"];
|
|
1492
|
+
const enabled = refMode === "manual_input";
|
|
1493
|
+
const result = enabled ? { enabled: true, manualInputType } : { enabled: false };
|
|
1494
|
+
this.logMethodSuccess("checkManualPickupRef", {
|
|
1495
|
+
enabled,
|
|
1496
|
+
manualInputType: enabled ? manualInputType : void 0
|
|
1497
|
+
});
|
|
1498
|
+
return result;
|
|
1499
|
+
}
|
|
1212
1500
|
};
|
|
1501
|
+
var ScanOrderImpl = _ScanOrderImpl;
|
|
1502
|
+
// ─── UI 状态缓存(按 cacheId 分桶,sessionStorage) ───
|
|
1503
|
+
//
|
|
1504
|
+
// 用于物料层持久化 UI 层面的轻量状态(如当前步骤、gate 标记、登录回跳意图等)。
|
|
1505
|
+
// 桶键:pisell.scanOrder.uiState:<cacheId>;内部以 JSON object 形式存储多个字段。
|
|
1506
|
+
// 无 cacheId 时所有方法自动降级为 no-op,上层不用判空。
|
|
1507
|
+
ScanOrderImpl.UI_STATE_KEY_PREFIX = "pisell.scanOrder.uiState:";
|
|
1213
1508
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1214
1509
|
0 && (module.exports = {
|
|
1215
1510
|
ScanOrderImpl,
|