@pisell/pisellos 0.0.504 → 0.0.505
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/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/ScanOrder/index.d.ts +12 -3
- package/dist/solution/ScanOrder/index.js +223 -131
- package/dist/solution/ScanOrder/types.d.ts +26 -22
- 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/lib/model/strategy/adapter/promotion/index.js +0 -49
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/ScanOrder/index.d.ts +12 -3
- package/lib/solution/ScanOrder/index.js +165 -86
- package/lib/solution/ScanOrder/types.d.ts +26 -22
- package/lib/solution/ScanOrder/utils.d.ts +13 -1
- package/lib/solution/ScanOrder/utils.js +37 -0
- package/package.json +1 -1
|
@@ -44,7 +44,7 @@ var import_utils2 = require("../../modules/Order/utils");
|
|
|
44
44
|
var import_dayjs = __toESM(require("dayjs"));
|
|
45
45
|
var import_itemRule = require("../../model/strategy/adapter/itemRule");
|
|
46
46
|
__reExport(ScanOrder_exports, require("./types"), module.exports);
|
|
47
|
-
var
|
|
47
|
+
var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
48
48
|
constructor(name, version) {
|
|
49
49
|
super(name, version);
|
|
50
50
|
this.defaultName = "scanOrder";
|
|
@@ -496,11 +496,13 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
496
496
|
}
|
|
497
497
|
// ScanOrder 提交 payload enhancer:
|
|
498
498
|
// - 给所有 booking 注入 appointment_status: 'started'(扫码点餐语义)
|
|
499
|
+
// - 给所有 booking 的 metadata 注入 resource_select_type(来自预约规则商品的 resource.type)
|
|
499
500
|
// - 给第一条 booking 补 resources 与 product_uid(仅当存在 resource / rule product)
|
|
500
501
|
// - 追加一条 is_rule=true 的 rule product,与 booking 互相关联
|
|
501
502
|
buildSubmitPayloadEnhancer() {
|
|
502
503
|
const ruleProduct = this.enabledReservationRuleProducts[0];
|
|
503
504
|
const resourceState = this.store.resource;
|
|
505
|
+
const resourceSelectType = resourceState == null ? void 0 : resourceState.resourceSelectType;
|
|
504
506
|
return (payload, { bookingUuid, tempOrder }) => {
|
|
505
507
|
var _a;
|
|
506
508
|
const resourceId = tempOrder.resource_id ?? (resourceState == null ? void 0 : resourceState.relationId);
|
|
@@ -526,6 +528,10 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
526
528
|
const nextBookings = (payload.bookings || []).map((booking, idx) => ({
|
|
527
529
|
...booking,
|
|
528
530
|
appointment_status: "started",
|
|
531
|
+
metadata: {
|
|
532
|
+
...booking.metadata || {},
|
|
533
|
+
...resourceSelectType ? { resource_select_type: resourceSelectType } : {}
|
|
534
|
+
},
|
|
529
535
|
...idx === 0 && resourceEntry ? { resources: [resourceEntry] } : {},
|
|
530
536
|
...idx === 0 && ruleProductUid ? { product_uid: ruleProductUid } : {}
|
|
531
537
|
}));
|
|
@@ -1009,20 +1015,22 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1009
1015
|
strategyCount: Array.isArray(this.itemRuleRuntimeConfig.strategyConfigs) ? this.itemRuleRuntimeConfig.strategyConfigs.length : 0
|
|
1010
1016
|
});
|
|
1011
1017
|
}
|
|
1012
|
-
normalizeResourceState(
|
|
1013
|
-
var _a, _b;
|
|
1014
|
-
const
|
|
1015
|
-
const
|
|
1016
|
-
const
|
|
1017
|
-
const
|
|
1018
|
-
const
|
|
1019
|
-
const relationId = (0, import_utils.toPositiveString)(config == null ? void 0 : config.relation_id);
|
|
1020
|
-
const tableFormId = (0, import_utils.toPositiveString)(config == null ? void 0 : config.table_form_id);
|
|
1018
|
+
normalizeResourceState(detail, resourceSelectType, hasOrderId) {
|
|
1019
|
+
var _a, _b, _c, _d;
|
|
1020
|
+
const currentOrderId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.order_id);
|
|
1021
|
+
const lastOrderId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.last_order_id);
|
|
1022
|
+
const relationId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.form_record_id);
|
|
1023
|
+
const tableFormId = (0, import_utils.toPositiveString)(detail == null ? void 0 : detail.form_id);
|
|
1024
|
+
const formRecord = (detail == null ? void 0 : detail.form_record) ?? null;
|
|
1021
1025
|
const allowSnack = ((_b = (_a = this.otherParams) == null ? void 0 : _a.dineInConfig) == null ? void 0 : _b["workflow.allow_add_items"]) || false;
|
|
1022
1026
|
const deskmateValid = false;
|
|
1023
|
-
const isExclusive =
|
|
1024
|
-
const isFull =
|
|
1025
|
-
|
|
1027
|
+
const isExclusive = resourceSelectType === "single";
|
|
1028
|
+
const isFull = (0, import_utils.computeResourceIsFull)({
|
|
1029
|
+
resourceSelectType,
|
|
1030
|
+
lastOrderId,
|
|
1031
|
+
capacityList: ((_d = (_c = detail == null ? void 0 : detail.resource_capacity) == null ? void 0 : _c[0]) == null ? void 0 : _d.capacity_list) ?? [],
|
|
1032
|
+
capacity: formRecord == null ? void 0 : formRecord.capacity
|
|
1033
|
+
});
|
|
1026
1034
|
let availabilityInfo = {
|
|
1027
1035
|
mode: "idle",
|
|
1028
1036
|
deskmate_valid: deskmateValid
|
|
@@ -1060,19 +1068,8 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1060
1068
|
deskmate_valid: deskmateValid
|
|
1061
1069
|
};
|
|
1062
1070
|
}
|
|
1063
|
-
if (isBlock) {
|
|
1064
|
-
availabilityInfo = {
|
|
1065
|
-
mode: "resource_block",
|
|
1066
|
-
order_id: lastOrderId,
|
|
1067
|
-
relation_id: relationId,
|
|
1068
|
-
table_form_id: tableFormId,
|
|
1069
|
-
deskmate_valid: deskmateValid
|
|
1070
|
-
};
|
|
1071
|
-
}
|
|
1072
1071
|
return {
|
|
1073
1072
|
...availabilityInfo,
|
|
1074
|
-
tableMaxNumber,
|
|
1075
|
-
orderCount,
|
|
1076
1073
|
currentOrderId,
|
|
1077
1074
|
lastOrderId,
|
|
1078
1075
|
relationId,
|
|
@@ -1081,27 +1078,46 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1081
1078
|
deskmateValid,
|
|
1082
1079
|
isExclusive,
|
|
1083
1080
|
isFull,
|
|
1084
|
-
|
|
1085
|
-
raw:
|
|
1086
|
-
table_form_record:
|
|
1081
|
+
resourceSelectType,
|
|
1082
|
+
raw: detail,
|
|
1083
|
+
table_form_record: formRecord
|
|
1087
1084
|
};
|
|
1088
1085
|
}
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1086
|
+
// 从首个预约规则商品的 product_resource.resources 中,按 form_id 匹配返回 type
|
|
1087
|
+
resolveResourceSelectType(formId) {
|
|
1088
|
+
var _a;
|
|
1089
|
+
const firstProduct = this.enabledReservationRuleProducts[0];
|
|
1090
|
+
const resources = ((_a = firstProduct == null ? void 0 : firstProduct.product_resource) == null ? void 0 : _a.resources) || [];
|
|
1091
|
+
const numericFormId = Number(formId);
|
|
1092
|
+
if (!Number.isFinite(numericFormId) || numericFormId <= 0)
|
|
1093
|
+
return void 0;
|
|
1094
|
+
const matched = resources.find((r) => Number(r == null ? void 0 : r.id) === numericFormId);
|
|
1095
|
+
return matched == null ? void 0 : matched.type;
|
|
1096
|
+
}
|
|
1097
|
+
async fetchResourceOccupyDetailByResourceId(resourceId) {
|
|
1098
|
+
var _a, _b, _c, _d;
|
|
1099
|
+
const formRecordId = Number(resourceId);
|
|
1100
|
+
if (!Number.isFinite(formRecordId) || formRecordId <= 0) {
|
|
1092
1101
|
throw new Error(`[ScanOrder] 非法桌台 resourceId: ${resourceId}`);
|
|
1093
1102
|
}
|
|
1103
|
+
const shopId = (_b = (_a = this.otherParams) == null ? void 0 : _a.getStateData) == null ? void 0 : _b.call(_a, "shop_id");
|
|
1104
|
+
if (!shopId) {
|
|
1105
|
+
throw new Error("[ScanOrder] 无法获取 shop_id");
|
|
1106
|
+
}
|
|
1094
1107
|
const response = await this.request.get(
|
|
1095
|
-
"/order/
|
|
1108
|
+
"/order/resource/occupy-detail",
|
|
1096
1109
|
{
|
|
1097
|
-
|
|
1098
|
-
|
|
1110
|
+
shop_id: shopId,
|
|
1111
|
+
"form_record_ids[]": formRecordId,
|
|
1112
|
+
with_resource_capacity_info: 1,
|
|
1113
|
+
with_resource_order_info: 1,
|
|
1114
|
+
with_resource_form_info: 1
|
|
1099
1115
|
}
|
|
1100
1116
|
);
|
|
1101
1117
|
if (!(response == null ? void 0 : response.status)) {
|
|
1102
|
-
throw new Error((response == null ? void 0 : response.message) || "
|
|
1118
|
+
throw new Error((response == null ? void 0 : response.message) || "获取资源占用详情失败");
|
|
1103
1119
|
}
|
|
1104
|
-
return (response == null ? void 0 : response.data)
|
|
1120
|
+
return ((_d = (_c = response == null ? void 0 : response.data) == null ? void 0 : _c.occupy_details) == null ? void 0 : _d[0]) ?? null;
|
|
1105
1121
|
}
|
|
1106
1122
|
// 检测当前链接是否可用
|
|
1107
1123
|
// 通过 resource_id + 店铺配置
|
|
@@ -1156,33 +1172,15 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1156
1172
|
if (outsideOperatingHours && closedBehaviorValue !== "show_menu_disabled") {
|
|
1157
1173
|
return makeShopClosed(closedMessage, closedBehaviorValue);
|
|
1158
1174
|
}
|
|
1159
|
-
const config = await this.fetchTableConfigByResourceId(resourceId);
|
|
1160
|
-
const resourceState = this.normalizeResourceState(config, hasOrderId);
|
|
1161
|
-
this.store.resource = resourceState;
|
|
1162
|
-
const availabilityInfo = {
|
|
1163
|
-
mode: resourceState.mode,
|
|
1164
|
-
order_id: resourceState.order_id,
|
|
1165
|
-
relation_id: resourceState.relationId,
|
|
1166
|
-
table_form_id: resourceState.tableFormId,
|
|
1167
|
-
deskmate_valid: resourceState.deskmate_valid,
|
|
1168
|
-
table_form_record: resourceState.table_form_record,
|
|
1169
|
-
policy: (_c = config == null ? void 0 : config.table_form_record) == null ? void 0 : _c.policy,
|
|
1170
|
-
partyroom_booking: (_d = config == null ? void 0 : config.table_form_record) == null ? void 0 : _d.partyroom_booking
|
|
1171
|
-
};
|
|
1172
1175
|
const tempOrder = this.ensureTempOrder();
|
|
1173
|
-
tempOrder.relation_id = resourceId || ((_e = this.otherParams) == null ? void 0 : _e.relation_id);
|
|
1174
|
-
tempOrder.table_form_id = resourceState.tableFormId;
|
|
1175
|
-
tempOrder.resource_id = resourceId;
|
|
1176
1176
|
const reservationLinkIds = (0, import_utils.collectLinkProductIdsFromReservationRules)(
|
|
1177
1177
|
dineInConfig["fulfillment.enabled_resource_rules"]
|
|
1178
1178
|
);
|
|
1179
|
+
let pendingRequestEntryPax;
|
|
1180
|
+
let pendingRequestPaxMin;
|
|
1181
|
+
let pendingRequestPaxMax;
|
|
1179
1182
|
if (reservationLinkIds.length === 0) {
|
|
1180
1183
|
this.enabledReservationRuleProducts = [];
|
|
1181
|
-
if (this.store.resource) {
|
|
1182
|
-
delete this.store.resource.requestEntryPax;
|
|
1183
|
-
delete this.store.resource.requestPaxMin;
|
|
1184
|
-
delete this.store.resource.requestPaxMax;
|
|
1185
|
-
}
|
|
1186
1184
|
} else {
|
|
1187
1185
|
tempOrder.metadata = { ...tempOrder.metadata || {} };
|
|
1188
1186
|
delete tempOrder.metadata.table_occupancy_duration;
|
|
@@ -1214,38 +1212,15 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1214
1212
|
tempOrder.metadata.table_occupancy_duration = occupancyMinutes;
|
|
1215
1213
|
}
|
|
1216
1214
|
if ((0, import_utils.hasCustomCapacityProduct)(loaded)) {
|
|
1217
|
-
|
|
1218
|
-
if (this.store.resource)
|
|
1219
|
-
this.store.resource.requestEntryPax = 1;
|
|
1220
|
-
delete availabilityInfo.requestPaxMin;
|
|
1221
|
-
delete availabilityInfo.requestPaxMax;
|
|
1222
|
-
if (this.store.resource) {
|
|
1223
|
-
delete this.store.resource.requestPaxMin;
|
|
1224
|
-
delete this.store.resource.requestPaxMax;
|
|
1225
|
-
}
|
|
1215
|
+
pendingRequestEntryPax = 1;
|
|
1226
1216
|
const paxBounds = (0, import_utils.pickFirstCustomCapacityPaxBounds)(loaded);
|
|
1227
|
-
if ((paxBounds == null ? void 0 : paxBounds.min) !== void 0)
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
}
|
|
1232
|
-
if ((paxBounds == null ? void 0 : paxBounds.max) !== void 0) {
|
|
1233
|
-
availabilityInfo.requestPaxMax = paxBounds.max;
|
|
1234
|
-
if (this.store.resource)
|
|
1235
|
-
this.store.resource.requestPaxMax = paxBounds.max;
|
|
1236
|
-
}
|
|
1237
|
-
} else if (this.store.resource) {
|
|
1238
|
-
delete this.store.resource.requestEntryPax;
|
|
1239
|
-
delete this.store.resource.requestPaxMin;
|
|
1240
|
-
delete this.store.resource.requestPaxMax;
|
|
1217
|
+
if ((paxBounds == null ? void 0 : paxBounds.min) !== void 0)
|
|
1218
|
+
pendingRequestPaxMin = paxBounds.min;
|
|
1219
|
+
if ((paxBounds == null ? void 0 : paxBounds.max) !== void 0)
|
|
1220
|
+
pendingRequestPaxMax = paxBounds.max;
|
|
1241
1221
|
}
|
|
1242
1222
|
} else {
|
|
1243
1223
|
this.enabledReservationRuleProducts = [];
|
|
1244
|
-
if (this.store.resource) {
|
|
1245
|
-
delete this.store.resource.requestEntryPax;
|
|
1246
|
-
delete this.store.resource.requestPaxMin;
|
|
1247
|
-
delete this.store.resource.requestPaxMax;
|
|
1248
|
-
}
|
|
1249
1224
|
void this.addScanOrderLog({
|
|
1250
1225
|
level: "error",
|
|
1251
1226
|
title: "[ScanOrder] enabled_reservation_rules product query failed",
|
|
@@ -1256,6 +1231,41 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1256
1231
|
});
|
|
1257
1232
|
}
|
|
1258
1233
|
}
|
|
1234
|
+
const occupyDetail = await this.fetchResourceOccupyDetailByResourceId(resourceId);
|
|
1235
|
+
const resourceSelectType = this.resolveResourceSelectType(
|
|
1236
|
+
(0, import_utils.toPositiveString)(occupyDetail == null ? void 0 : occupyDetail.form_id)
|
|
1237
|
+
);
|
|
1238
|
+
const resourceState = this.normalizeResourceState(
|
|
1239
|
+
occupyDetail,
|
|
1240
|
+
resourceSelectType,
|
|
1241
|
+
hasOrderId
|
|
1242
|
+
);
|
|
1243
|
+
this.store.resource = resourceState;
|
|
1244
|
+
if (pendingRequestEntryPax !== void 0) {
|
|
1245
|
+
this.store.resource.requestEntryPax = pendingRequestEntryPax;
|
|
1246
|
+
}
|
|
1247
|
+
if (pendingRequestPaxMin !== void 0) {
|
|
1248
|
+
this.store.resource.requestPaxMin = pendingRequestPaxMin;
|
|
1249
|
+
}
|
|
1250
|
+
if (pendingRequestPaxMax !== void 0) {
|
|
1251
|
+
this.store.resource.requestPaxMax = pendingRequestPaxMax;
|
|
1252
|
+
}
|
|
1253
|
+
const availabilityInfo = {
|
|
1254
|
+
mode: resourceState.mode,
|
|
1255
|
+
order_id: resourceState.order_id,
|
|
1256
|
+
relation_id: resourceState.relationId,
|
|
1257
|
+
table_form_id: resourceState.tableFormId,
|
|
1258
|
+
deskmate_valid: resourceState.deskmate_valid,
|
|
1259
|
+
table_form_record: resourceState.table_form_record,
|
|
1260
|
+
policy: (_c = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _c.policy,
|
|
1261
|
+
partyroom_booking: (_d = occupyDetail == null ? void 0 : occupyDetail.form_record) == null ? void 0 : _d.partyroom_booking,
|
|
1262
|
+
...this.store.resource.requestEntryPax !== void 0 ? { requestEntryPax: this.store.resource.requestEntryPax } : {},
|
|
1263
|
+
...this.store.resource.requestPaxMin !== void 0 ? { requestPaxMin: this.store.resource.requestPaxMin } : {},
|
|
1264
|
+
...this.store.resource.requestPaxMax !== void 0 ? { requestPaxMax: this.store.resource.requestPaxMax } : {}
|
|
1265
|
+
};
|
|
1266
|
+
tempOrder.relation_id = resourceId || ((_e = this.otherParams) == null ? void 0 : _e.relation_id);
|
|
1267
|
+
tempOrder.table_form_id = resourceState.tableFormId;
|
|
1268
|
+
tempOrder.resource_id = resourceId;
|
|
1259
1269
|
(_f = this.store.order) == null ? void 0 : _f.persistTempOrder();
|
|
1260
1270
|
if (availabilityInfo.mode === "idle") {
|
|
1261
1271
|
await this.addNewOrder();
|
|
@@ -1303,8 +1313,7 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1303
1313
|
persistedRelationId: tempOrder.relation_id,
|
|
1304
1314
|
persistedResourceId: tempOrder.resource_id,
|
|
1305
1315
|
deskmateValid: availabilityInfo.deskmate_valid,
|
|
1306
|
-
|
|
1307
|
-
tableMaxNumber: resourceState.tableMaxNumber,
|
|
1316
|
+
resourceSelectType: resourceState.resourceSelectType,
|
|
1308
1317
|
isExclusive: resourceState.isExclusive,
|
|
1309
1318
|
isFull: resourceState.isFull
|
|
1310
1319
|
});
|
|
@@ -1367,6 +1376,69 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1367
1376
|
this.otherParams = { ...this.otherParams, ...params };
|
|
1368
1377
|
}
|
|
1369
1378
|
}
|
|
1379
|
+
getUIStateBucketKey() {
|
|
1380
|
+
if (!this.cacheId)
|
|
1381
|
+
return null;
|
|
1382
|
+
return `${_ScanOrderImpl.UI_STATE_KEY_PREFIX}${this.cacheId}`;
|
|
1383
|
+
}
|
|
1384
|
+
readUIStateBucket() {
|
|
1385
|
+
var _a;
|
|
1386
|
+
const key = this.getUIStateBucketKey();
|
|
1387
|
+
if (!key || !((_a = this.window) == null ? void 0 : _a.sessionStorage))
|
|
1388
|
+
return {};
|
|
1389
|
+
try {
|
|
1390
|
+
const raw = this.window.sessionStorage.getItem(key) || "{}";
|
|
1391
|
+
const parsed = JSON.parse(raw);
|
|
1392
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
1393
|
+
} catch {
|
|
1394
|
+
return {};
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
writeUIStateBucket(bucket) {
|
|
1398
|
+
var _a;
|
|
1399
|
+
const key = this.getUIStateBucketKey();
|
|
1400
|
+
if (!key || !((_a = this.window) == null ? void 0 : _a.sessionStorage))
|
|
1401
|
+
return;
|
|
1402
|
+
try {
|
|
1403
|
+
this.window.sessionStorage.setItem(key, JSON.stringify(bucket));
|
|
1404
|
+
} catch (error) {
|
|
1405
|
+
console.warn("[ScanOrder] writeUIStateBucket failed", error);
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
setUIState(key, value) {
|
|
1409
|
+
if (!this.getUIStateBucketKey())
|
|
1410
|
+
return;
|
|
1411
|
+
const bucket = this.readUIStateBucket();
|
|
1412
|
+
bucket[key] = value;
|
|
1413
|
+
this.writeUIStateBucket(bucket);
|
|
1414
|
+
}
|
|
1415
|
+
getUIState(key) {
|
|
1416
|
+
if (!this.getUIStateBucketKey())
|
|
1417
|
+
return void 0;
|
|
1418
|
+
const bucket = this.readUIStateBucket();
|
|
1419
|
+
return bucket[key];
|
|
1420
|
+
}
|
|
1421
|
+
deleteUIState(key) {
|
|
1422
|
+
if (!this.getUIStateBucketKey())
|
|
1423
|
+
return;
|
|
1424
|
+
const bucket = this.readUIStateBucket();
|
|
1425
|
+
if (key in bucket) {
|
|
1426
|
+
delete bucket[key];
|
|
1427
|
+
this.writeUIStateBucket(bucket);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
// 整桶清空(用于扫新桌、提交成功、restoreOrder 等场景)
|
|
1431
|
+
clearUIState() {
|
|
1432
|
+
var _a;
|
|
1433
|
+
const key = this.getUIStateBucketKey();
|
|
1434
|
+
if (!key || !((_a = this.window) == null ? void 0 : _a.sessionStorage))
|
|
1435
|
+
return;
|
|
1436
|
+
try {
|
|
1437
|
+
this.window.sessionStorage.removeItem(key);
|
|
1438
|
+
} catch (error) {
|
|
1439
|
+
console.warn("[ScanOrder] clearUIState failed", error);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1370
1442
|
async setEntryPaxNumber(number) {
|
|
1371
1443
|
const pax = (0, import_utils2.normalizeSubmitCollectPaxValue)(number);
|
|
1372
1444
|
this.store.entryPaxNumber = pax;
|
|
@@ -1416,6 +1488,13 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
|
|
|
1416
1488
|
return result;
|
|
1417
1489
|
}
|
|
1418
1490
|
};
|
|
1491
|
+
var ScanOrderImpl = _ScanOrderImpl;
|
|
1492
|
+
// ─── UI 状态缓存(按 cacheId 分桶,sessionStorage) ───
|
|
1493
|
+
//
|
|
1494
|
+
// 用于物料层持久化 UI 层面的轻量状态(如当前步骤、gate 标记、登录回跳意图等)。
|
|
1495
|
+
// 桶键:pisell.scanOrder.uiState:<cacheId>;内部以 JSON object 形式存储多个字段。
|
|
1496
|
+
// 无 cacheId 时所有方法自动降级为 no-op,上层不用判空。
|
|
1497
|
+
ScanOrderImpl.UI_STATE_KEY_PREFIX = "pisell.scanOrder.uiState:";
|
|
1419
1498
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1420
1499
|
0 && (module.exports = {
|
|
1421
1500
|
ScanOrderImpl,
|
|
@@ -141,10 +141,11 @@ export interface ScanOrderSubmitPayload extends Omit<ScanOrderTempOrder, 'platfo
|
|
|
141
141
|
}>;
|
|
142
142
|
products: ScanOrderSubmitProduct[];
|
|
143
143
|
}
|
|
144
|
-
export type ScanOrderAvailabilityMode = 'idle' | 'shop_closed' | 'submit_disabled' | '
|
|
144
|
+
export type ScanOrderAvailabilityMode = 'idle' | 'shop_closed' | 'submit_disabled' | 'resource_busy' | 'additional_order_with_code' | 'additional_order';
|
|
145
145
|
export interface ScanOrderTableFormRecord {
|
|
146
146
|
policy?: string | null;
|
|
147
147
|
partyroom_booking?: string | null;
|
|
148
|
+
capacity?: number | string | null;
|
|
148
149
|
[key: string]: any;
|
|
149
150
|
}
|
|
150
151
|
export interface ScanOrderAvailabilityInfo {
|
|
@@ -156,7 +157,7 @@ export interface ScanOrderAvailabilityInfo {
|
|
|
156
157
|
errorTips?: string;
|
|
157
158
|
/** 透传 `availability.closed_behavior`,便于 UI 识别拦截类型(如 show_menu_disabled) */
|
|
158
159
|
closed_behavior?: string;
|
|
159
|
-
/** `/order/
|
|
160
|
+
/** `/order/resource/occupy-detail` 返回的 `form_record` 原样透出 */
|
|
160
161
|
table_form_record?: ScanOrderTableFormRecord | null;
|
|
161
162
|
policy?: string | null;
|
|
162
163
|
partyroom_booking?: string | null;
|
|
@@ -167,34 +168,36 @@ export interface ScanOrderAvailabilityInfo {
|
|
|
167
168
|
/** 首个 `capacity.type === 'custom'` 商品里 `custom[0]` 的 max(人数上限) */
|
|
168
169
|
requestPaxMax?: number;
|
|
169
170
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
/** `resource_capacity[i].capacity_list[j]` */
|
|
172
|
+
export interface ScanOrderResourceCapacitySlot {
|
|
173
|
+
start_at?: string;
|
|
174
|
+
end_at?: string;
|
|
175
|
+
pax?: number | string;
|
|
173
176
|
}
|
|
174
|
-
export interface
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
export interface ScanOrderResourceCapacity {
|
|
178
|
+
capacity?: number | string;
|
|
179
|
+
capacity_list?: ScanOrderResourceCapacitySlot[];
|
|
177
180
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
+
/** `/order/resource/occupy-detail` 单条 `occupy_details[i]` */
|
|
182
|
+
export interface ScanOrderResourceOccupyDetail {
|
|
183
|
+
form_record_id?: number | string | null;
|
|
184
|
+
form_id?: number | string | null;
|
|
181
185
|
order_id?: number | string | null;
|
|
182
186
|
last_order_id?: number | string | null;
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
table_snack?: ScanOrderTableSnackConfig[] | null;
|
|
186
|
-
order_number_prefix?: ScanOrderOrderNumberPrefixConfig[] | null;
|
|
187
|
+
resource_capacity?: ScanOrderResourceCapacity[] | null;
|
|
188
|
+
form_record?: ScanOrderTableFormRecord | null;
|
|
187
189
|
[key: string]: any;
|
|
188
190
|
}
|
|
189
|
-
export interface
|
|
191
|
+
export interface ScanOrderResourceOccupyDetailApiResponse {
|
|
190
192
|
status?: boolean;
|
|
191
193
|
code?: number;
|
|
192
194
|
message?: string;
|
|
193
|
-
data?:
|
|
195
|
+
data?: {
|
|
196
|
+
occupy_details?: ScanOrderResourceOccupyDetail[] | null;
|
|
197
|
+
} | null;
|
|
194
198
|
}
|
|
199
|
+
export type ScanOrderResourceSelectType = 'single' | 'multiple' | 'capacity';
|
|
195
200
|
export interface ScanOrderResourceState extends ScanOrderAvailabilityInfo {
|
|
196
|
-
tableMaxNumber: number;
|
|
197
|
-
orderCount: number;
|
|
198
201
|
relationId?: string;
|
|
199
202
|
tableFormId?: string;
|
|
200
203
|
currentOrderId?: string;
|
|
@@ -203,13 +206,14 @@ export interface ScanOrderResourceState extends ScanOrderAvailabilityInfo {
|
|
|
203
206
|
deskmateValid: boolean;
|
|
204
207
|
isExclusive: boolean;
|
|
205
208
|
isFull: boolean;
|
|
206
|
-
|
|
207
|
-
|
|
209
|
+
/** 来自首个预约规则商品 product_resource.resources 中与 form_id 匹配的 resource type */
|
|
210
|
+
resourceSelectType?: ScanOrderResourceSelectType;
|
|
211
|
+
raw: ScanOrderResourceOccupyDetail | null;
|
|
208
212
|
}
|
|
209
213
|
export interface ScanOrderState {
|
|
210
214
|
entryContext: ScanOrderEntryContext | null;
|
|
211
215
|
status: ScanOrderStatus;
|
|
212
|
-
config:
|
|
216
|
+
config: Record<string, any> | null;
|
|
213
217
|
resource: ScanOrderResourceState | null;
|
|
214
218
|
flow: Record<string, any>;
|
|
215
219
|
error: string | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ScanOrderOrderProduct, ScanOrderOrderProductIdentity, ScanOrderSummary, ScanOrderTempOrder } from './types';
|
|
1
|
+
import { ScanOrderOrderProduct, ScanOrderOrderProductIdentity, ScanOrderResourceCapacitySlot, ScanOrderResourceSelectType, ScanOrderSummary, ScanOrderTempOrder } from './types';
|
|
2
2
|
import type { CartItemSummary, ItemRuleBusinessData, PaxInfo, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
|
|
3
3
|
import type { StrategyConfig } from '../../model/strategy/type';
|
|
4
4
|
import type { ProductData } from '../../modules/Product/types';
|
|
@@ -109,6 +109,18 @@ export declare function collectLinkProductIdsFromReservationRules(rules: unknown
|
|
|
109
109
|
export declare function pickFirstDurationMinutesFromProducts(products: ProductData[]): number | undefined;
|
|
110
110
|
/** 是否存在 capacity.type === 'custom' 的商品 */
|
|
111
111
|
export declare function hasCustomCapacityProduct(products: ProductData[]): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* 根据预约规则商品的 resource.type 计算桌台是否已被"占满"。
|
|
114
|
+
* - single:只要有 `lastOrderId` 即视为占用
|
|
115
|
+
* - multiple:当前时间落在 `capacity_list[i]` 的 `[start_at, end_at]`(inclusive)内的 pax 之和 > 总容量
|
|
116
|
+
* - 其他('capacity' / undefined):返回 false,不施加限制
|
|
117
|
+
*/
|
|
118
|
+
export declare function computeResourceIsFull(params: {
|
|
119
|
+
resourceSelectType?: ScanOrderResourceSelectType;
|
|
120
|
+
lastOrderId?: string;
|
|
121
|
+
capacityList?: ScanOrderResourceCapacitySlot[];
|
|
122
|
+
capacity?: number | string | null;
|
|
123
|
+
}): boolean;
|
|
112
124
|
/**
|
|
113
125
|
* 在商品列表中找到第一个 `capacity.type === 'custom'` 的商品,取其 `custom` 数组第一项的 min/max。
|
|
114
126
|
* 仅返回有限数字字段;若均无法解析则返回 `undefined`。
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
7
|
var __export = (target, all) => {
|
|
6
8
|
for (var name in all)
|
|
@@ -14,6 +16,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
14
16
|
}
|
|
15
17
|
return to;
|
|
16
18
|
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
17
27
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
28
|
|
|
19
29
|
// src/solution/ScanOrder/utils.ts
|
|
@@ -25,6 +35,7 @@ __export(utils_exports, {
|
|
|
25
35
|
buildProductKey: () => buildProductKey,
|
|
26
36
|
buildQuantityLimitIndex: () => buildQuantityLimitIndex,
|
|
27
37
|
collectLinkProductIdsFromReservationRules: () => collectLinkProductIdsFromReservationRules,
|
|
38
|
+
computeResourceIsFull: () => computeResourceIsFull,
|
|
28
39
|
createEmptySummary: () => createEmptySummary,
|
|
29
40
|
extractStrategyModelIdsFromTableConfig: () => extractStrategyModelIdsFromTableConfig,
|
|
30
41
|
getProductIdentityIndex: () => getProductIdentityIndex,
|
|
@@ -46,6 +57,7 @@ __export(utils_exports, {
|
|
|
46
57
|
toPriceString: () => toPriceString
|
|
47
58
|
});
|
|
48
59
|
module.exports = __toCommonJS(utils_exports);
|
|
60
|
+
var import_dayjs = __toESM(require("dayjs"));
|
|
49
61
|
function createEmptySummary() {
|
|
50
62
|
return {
|
|
51
63
|
product_quantity: 0,
|
|
@@ -411,6 +423,30 @@ function hasCustomCapacityProduct(products) {
|
|
|
411
423
|
return ((_a = p == null ? void 0 : p.capacity) == null ? void 0 : _a.type) === "custom";
|
|
412
424
|
});
|
|
413
425
|
}
|
|
426
|
+
function computeResourceIsFull(params) {
|
|
427
|
+
const { resourceSelectType, lastOrderId, capacityList, capacity } = params;
|
|
428
|
+
if (resourceSelectType === "single")
|
|
429
|
+
return Boolean(lastOrderId);
|
|
430
|
+
if (resourceSelectType !== "multiple")
|
|
431
|
+
return false;
|
|
432
|
+
const totalCapacity = Number(capacity);
|
|
433
|
+
if (!Number.isFinite(totalCapacity) || totalCapacity <= 0)
|
|
434
|
+
return false;
|
|
435
|
+
const now = (0, import_dayjs.default)();
|
|
436
|
+
let occupied = 0;
|
|
437
|
+
for (const slot of capacityList || []) {
|
|
438
|
+
const start = (0, import_dayjs.default)(slot == null ? void 0 : slot.start_at);
|
|
439
|
+
const end = (0, import_dayjs.default)(slot == null ? void 0 : slot.end_at);
|
|
440
|
+
if (!start.isValid() || !end.isValid())
|
|
441
|
+
continue;
|
|
442
|
+
if ((now.isAfter(start) || now.isSame(start)) && (now.isBefore(end) || now.isSame(end))) {
|
|
443
|
+
const pax = Number(slot == null ? void 0 : slot.pax);
|
|
444
|
+
if (Number.isFinite(pax) && pax > 0)
|
|
445
|
+
occupied += pax;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return occupied > totalCapacity;
|
|
449
|
+
}
|
|
414
450
|
function pickFirstCustomCapacityPaxBounds(products) {
|
|
415
451
|
for (const p of products) {
|
|
416
452
|
const cap = p == null ? void 0 : p.capacity;
|
|
@@ -446,6 +482,7 @@ function pickFirstCustomCapacityPaxBounds(products) {
|
|
|
446
482
|
buildProductKey,
|
|
447
483
|
buildQuantityLimitIndex,
|
|
448
484
|
collectLinkProductIdsFromReservationRules,
|
|
485
|
+
computeResourceIsFull,
|
|
449
486
|
createEmptySummary,
|
|
450
487
|
extractStrategyModelIdsFromTableConfig,
|
|
451
488
|
getProductIdentityIndex,
|