@pisell/pisellos 0.0.500 → 0.0.502

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.
Files changed (68) hide show
  1. package/dist/model/strategy/adapter/itemRule/adapter.d.ts +8 -0
  2. package/dist/model/strategy/adapter/itemRule/adapter.js +52 -8
  3. package/dist/model/strategy/adapter/itemRule/examples.d.ts +15 -0
  4. package/dist/model/strategy/adapter/itemRule/examples.js +68 -1
  5. package/dist/model/strategy/adapter/itemRule/index.d.ts +1 -1
  6. package/dist/model/strategy/adapter/itemRule/index.js +1 -1
  7. package/dist/model/strategy/adapter/itemRule/type.d.ts +20 -1
  8. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  9. package/dist/modules/Order/index.d.ts +10 -0
  10. package/dist/modules/Order/index.js +64 -40
  11. package/dist/modules/Order/types.d.ts +13 -1
  12. package/dist/modules/Order/utils.d.ts +36 -1
  13. package/dist/modules/Order/utils.js +120 -24
  14. package/dist/modules/ProductList/index.js +2 -2
  15. package/dist/modules/Quotation/index.js +6 -3
  16. package/dist/modules/SalesSummary/types.d.ts +2 -1
  17. package/dist/modules/SalesSummary/utils.js +10 -10
  18. package/dist/modules/Schedule/utils.d.ts +1 -1
  19. package/dist/solution/ScanOrder/index.d.ts +22 -0
  20. package/dist/solution/ScanOrder/index.js +863 -369
  21. package/dist/solution/ScanOrder/types.d.ts +31 -8
  22. package/dist/solution/ScanOrder/utils.d.ts +26 -0
  23. package/dist/solution/ScanOrder/utils.js +191 -44
  24. package/dist/solution/VenueBooking/index.d.ts +42 -5
  25. package/dist/solution/VenueBooking/index.js +692 -280
  26. package/dist/solution/VenueBooking/types.d.ts +23 -0
  27. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +2 -1
  28. package/dist/solution/VenueBooking/utils/dateSummary.js +7 -5
  29. package/dist/solution/VenueBooking/utils/resource.d.ts +11 -1
  30. package/dist/solution/VenueBooking/utils/resource.js +57 -21
  31. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
  32. package/dist/solution/VenueBooking/utils/slotMerge.js +33 -12
  33. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
  34. package/dist/solution/VenueBooking/utils/timeSlot.js +259 -62
  35. package/lib/model/strategy/adapter/itemRule/adapter.d.ts +8 -0
  36. package/lib/model/strategy/adapter/itemRule/adapter.js +41 -2
  37. package/lib/model/strategy/adapter/itemRule/examples.d.ts +15 -0
  38. package/lib/model/strategy/adapter/itemRule/examples.js +47 -0
  39. package/lib/model/strategy/adapter/itemRule/index.d.ts +1 -1
  40. package/lib/model/strategy/adapter/itemRule/index.js +2 -0
  41. package/lib/model/strategy/adapter/itemRule/type.d.ts +20 -1
  42. package/lib/modules/Order/index.d.ts +10 -0
  43. package/lib/modules/Order/index.js +40 -43
  44. package/lib/modules/Order/types.d.ts +13 -1
  45. package/lib/modules/Order/utils.d.ts +36 -1
  46. package/lib/modules/Order/utils.js +100 -21
  47. package/lib/modules/ProductList/index.js +3 -2
  48. package/lib/modules/Quotation/index.js +3 -0
  49. package/lib/modules/SalesSummary/types.d.ts +2 -1
  50. package/lib/modules/SalesSummary/utils.js +2 -2
  51. package/lib/modules/Schedule/utils.d.ts +1 -1
  52. package/lib/solution/ScanOrder/index.d.ts +22 -0
  53. package/lib/solution/ScanOrder/index.js +376 -21
  54. package/lib/solution/ScanOrder/types.d.ts +31 -8
  55. package/lib/solution/ScanOrder/utils.d.ts +26 -0
  56. package/lib/solution/ScanOrder/utils.js +128 -19
  57. package/lib/solution/VenueBooking/index.d.ts +42 -5
  58. package/lib/solution/VenueBooking/index.js +356 -84
  59. package/lib/solution/VenueBooking/types.d.ts +23 -0
  60. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +2 -1
  61. package/lib/solution/VenueBooking/utils/dateSummary.js +14 -5
  62. package/lib/solution/VenueBooking/utils/resource.d.ts +11 -1
  63. package/lib/solution/VenueBooking/utils/resource.js +15 -4
  64. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
  65. package/lib/solution/VenueBooking/utils/slotMerge.js +29 -12
  66. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
  67. package/lib/solution/VenueBooking/utils/timeSlot.js +182 -43
  68. package/package.json +1 -1
@@ -37,6 +37,10 @@ var import_BaseModule = require("../../modules/BaseModule");
37
37
  var import_types = require("./types");
38
38
  var import_utils = require("./utils");
39
39
  var import_types2 = require("../BookingByStep/types");
40
+ var import_ProductList = require("../../modules/ProductList");
41
+ var import_Schedule = require("../../modules/Schedule");
42
+ var import_getDateIsInSchedule = require("../../modules/Schedule/getDateIsInSchedule");
43
+ var import_utils2 = require("../../modules/Order/utils");
40
44
  var import_dayjs = __toESM(require("dayjs"));
41
45
  var import_itemRule = require("../../model/strategy/adapter/itemRule");
42
46
  __reExport(ScanOrder_exports, require("./types"), module.exports);
@@ -59,7 +63,8 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
59
63
  cartValidation: {
60
64
  passed: null,
61
65
  failures: []
62
- }
66
+ },
67
+ entryPaxNumber: 1
63
68
  };
64
69
  this.otherParams = {};
65
70
  this.itemRuleEvaluator = new import_itemRule.ItemRuleEvaluator();
@@ -67,6 +72,8 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
67
72
  this.itemRuleConfigsPromise = null;
68
73
  this.itemRulePrefillApplied = false;
69
74
  this.itemRuleRuntimeConfig = {};
75
+ /** 最近一次 checkResourceAvailable 从预约规则 link 拉取的商品快照 */
76
+ this.enabledReservationRuleProducts = [];
70
77
  }
71
78
  getScanOrderLoggerContext() {
72
79
  return {
@@ -221,11 +228,26 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
221
228
  if (this.store.scanOrderLogger) {
222
229
  this.store.scanOrderLogger.setContext(this.getScanOrderLoggerContext());
223
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
+ });
224
239
  console.log("[ScanOrder] 初始化开始");
225
240
  try {
226
241
  await ((_e = this.store.order) == null ? void 0 : _e.recalculateSummary({ createIfMissing: false }));
227
242
  (_f = this.store.order) == null ? void 0 : _f.persistTempOrder();
228
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
+ }
229
251
  await this.refreshItemRuleQuantityLimits();
230
252
  this.store.status = "ready";
231
253
  console.log("[ScanOrder] 初始化完成");
@@ -363,6 +385,50 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
363
385
  throw error;
364
386
  }
365
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
+ }
366
432
  ensureTempOrder() {
367
433
  if (!this.store.order)
368
434
  throw new Error("order 模块未初始化");
@@ -384,6 +450,25 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
384
450
  throw error;
385
451
  }
386
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
+ }
387
472
  getOrderProducts() {
388
473
  this.logMethodStart("getOrderProducts");
389
474
  if (!this.store.order)
@@ -409,20 +494,104 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
409
494
  throw error;
410
495
  }
411
496
  }
497
+ // 根据 enabledReservationRuleProducts / store.resource 构造 submit payload enhancer:
498
+ // - 给第一条 booking 补 resources 与 product_uid
499
+ // - 追加一条 is_rule=true 的 rule product,与 booking 互相关联
500
+ // 无 rule product 也无 resource 时返回 undefined,跳过增强
501
+ buildReservationRuleEnhancer() {
502
+ const ruleProduct = this.enabledReservationRuleProducts[0];
503
+ const resourceState = this.store.resource;
504
+ if (!ruleProduct && !resourceState)
505
+ return void 0;
506
+ return (payload, { bookingUuid, tempOrder }) => {
507
+ var _a;
508
+ const resourceId = tempOrder.resource_id ?? (resourceState == null ? void 0 : resourceState.relationId);
509
+ const pickOriginal = (value) => {
510
+ if (value && typeof value === "object" && !Array.isArray(value)) {
511
+ const original = value.original;
512
+ return typeof original === "string" && original.length > 0 ? original : void 0;
513
+ }
514
+ return void 0;
515
+ };
516
+ const mainField = pickOriginal(tempOrder.table_number) ?? pickOriginal((_a = resourceState == null ? void 0 : resourceState.table_form_record) == null ? void 0 : _a.name) ?? "";
517
+ const resourceEntry = resourceState && resourceId ? {
518
+ relation_type: "form",
519
+ like_status: "common",
520
+ id: Number(resourceId),
521
+ main_field: mainField,
522
+ form_id: resourceState.tableFormId,
523
+ relation_id: resourceState.relationId ?? resourceId,
524
+ capacity: 1,
525
+ metadata: {}
526
+ } : void 0;
527
+ const ruleProductUid = ruleProduct ? (0, import_utils2.createUuidV4)() : void 0;
528
+ const nextBookings = (payload.bookings || []).map(
529
+ (booking, idx) => idx === 0 ? {
530
+ ...booking,
531
+ ...resourceEntry ? { resources: [resourceEntry] } : {},
532
+ ...ruleProductUid ? { product_uid: ruleProductUid } : {}
533
+ } : booking
534
+ );
535
+ const nextProducts = [...payload.products || []];
536
+ if (ruleProduct && ruleProductUid) {
537
+ const sellingPrice = String(ruleProduct.price ?? "0.00");
538
+ const originalPrice = String(
539
+ ruleProduct.original_price ?? ruleProduct.price ?? "0.00"
540
+ );
541
+ nextProducts.push({
542
+ product_id: ruleProduct.id,
543
+ product_variant_id: 0,
544
+ num: 1,
545
+ selling_price: sellingPrice,
546
+ original_price: originalPrice,
547
+ payment_price: sellingPrice,
548
+ is_charge_tax: ruleProduct.is_gst ?? 0,
549
+ product_option_item: [],
550
+ discount_list: [],
551
+ product_bundle: [],
552
+ booking_uid: bookingUuid,
553
+ metadata: {
554
+ is_rule: true,
555
+ unique_identification_number: ruleProductUid,
556
+ booking_uid: bookingUuid
557
+ }
558
+ });
559
+ }
560
+ return { ...payload, bookings: nextBookings, products: nextProducts };
561
+ };
562
+ }
412
563
  async submitScanOrder() {
413
- var _a;
564
+ var _a, _b, _c, _d, _e, _f, _g;
414
565
  this.logMethodStart("submitScanOrder");
415
566
  try {
416
567
  await this.validateBeforeSubmitByItemRule();
417
568
  if (!this.store.order) {
418
569
  throw new Error("scanOrder解决方案需要 order 模块支持");
419
570
  }
571
+ const pax = (0, import_utils2.normalizeSubmitCollectPaxValue)(this.store.entryPaxNumber);
572
+ this.store.entryPaxNumber = pax;
573
+ const tempOrderForSubmit = this.store.order.ensureTempOrder();
574
+ tempOrderForSubmit.metadata = { ...tempOrderForSubmit.metadata, collect_pax: pax };
575
+ tempOrderForSubmit.delivery_type = "shop_service";
576
+ const resourceTableName = (_b = (_a = this.store.resource) == null ? void 0 : _a.table_form_record) == null ? void 0 : _b.name;
577
+ if (resourceTableName && typeof resourceTableName === "object") {
578
+ tempOrderForSubmit.table_number = resourceTableName;
579
+ } else {
580
+ delete tempOrderForSubmit.table_number;
581
+ }
582
+ this.store.order.persistTempOrder();
583
+ const enhancePayload = this.buildReservationRuleEnhancer();
420
584
  const result = await this.store.order.submitTempOrder({
421
- cacheId: this.cacheId
585
+ cacheId: this.cacheId,
586
+ platform: (_c = this.otherParams) == null ? void 0 : _c.platform,
587
+ businessCode: (_d = this.otherParams) == null ? void 0 : _d.businessCode,
588
+ channel: (_e = this.otherParams) == null ? void 0 : _e.channel,
589
+ type: (_f = this.otherParams) == null ? void 0 : _f.type,
590
+ enhancePayload
422
591
  });
423
592
  const tempOrder = this.store.order.getTempOrder();
424
593
  this.logMethodSuccess("submitScanOrder", {
425
- productCount: ((_a = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _a.length) || 0
594
+ productCount: ((_g = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _g.length) || 0
426
595
  });
427
596
  return result;
428
597
  } catch (error) {
@@ -691,22 +860,14 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
691
860
  (sourceItem == null ? void 0 : sourceItem.price) ?? (sourceItem == null ? void 0 : sourceItem.selling_price),
692
861
  "0.00"
693
862
  );
694
- const originalPrice = (0, import_utils.toPriceString)(
695
- (sourceItem == null ? void 0 : sourceItem.original_price) ?? (sourceItem == null ? void 0 : sourceItem.price) ?? sellingPrice,
696
- sellingPrice
697
- );
698
- const paymentPrice = (0, import_utils.toPriceString)(
699
- (sourceItem == null ? void 0 : sourceItem.payment_price) ?? (sourceItem == null ? void 0 : sourceItem.price) ?? sellingPrice,
700
- sellingPrice
701
- );
702
863
  tempOrder.products.push(
703
864
  (0, import_utils.normalizeOrderProduct)({
865
+ ...sourceItem,
704
866
  product_id: productId,
705
867
  product_variant_id: productVariantId,
706
868
  num: targetQuantity,
707
869
  selling_price: sellingPrice,
708
- original_price: originalPrice,
709
- payment_price: paymentPrice,
870
+ original_price: sellingPrice,
710
871
  metadata: {
711
872
  item_rule_prefill: true,
712
873
  item_rule_id: prefillItem.ruleId
@@ -747,6 +908,7 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
747
908
  }
748
909
  }
749
910
  if (hasChanges) {
911
+ this.store.order.applyDiscount();
750
912
  await this.store.order.recalculateSummary({ createIfMissing: true });
751
913
  this.store.order.persistTempOrder();
752
914
  }
@@ -758,6 +920,10 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
758
920
  });
759
921
  }
760
922
  async applyItemRulePrefill() {
923
+ var _a, _b;
924
+ if ((_b = (_a = this.store.order) == null ? void 0 : _a.getLastOrderInfo) == null ? void 0 : _b.call(_a)) {
925
+ return;
926
+ }
761
927
  this.logMethodStart("applyItemRulePrefill");
762
928
  await this.applyPrefillByItemRule();
763
929
  await this.refreshItemRuleQuantityLimits();
@@ -919,7 +1085,8 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
919
1085
  isExclusive,
920
1086
  isFull,
921
1087
  orderNumberPrefix,
922
- raw: config
1088
+ raw: config,
1089
+ table_form_record: (config == null ? void 0 : config.table_form_record) ?? null
923
1090
  };
924
1091
  }
925
1092
  async fetchTableConfigByResourceId(resourceId) {
@@ -943,7 +1110,7 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
943
1110
  // 通过 resource_id + 店铺配置
944
1111
  // hasOrderId 表示 url 上是否有 orderid,如果是的话,后续的流程会走加单
945
1112
  async checkResourceAvailable(resourceId, hasOrderId) {
946
- var _a, _b, _c, _d, _e, _f;
1113
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
947
1114
  this.logMethodStart("checkResourceAvailable", {
948
1115
  resourceId
949
1116
  });
@@ -959,19 +1126,39 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
959
1126
  const dineInConfig = (openData == null ? void 0 : openData.data) || {};
960
1127
  this.otherParams.dineInConfig = dineInConfig;
961
1128
  await this.syncItemRuleConfigsFromDineInConfig(dineInConfig);
962
- const shopClosedInfo = () => ({
1129
+ const closedBehaviorValue = dineInConfig == null ? void 0 : dineInConfig["availability.closed_behavior"];
1130
+ 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"]);
1131
+ const basicUnavailableMessage = (dineInConfig == null ? void 0 : dineInConfig["basic.unavailable_message"]) || closedMessage;
1132
+ const pauseMessage = (dineInConfig == null ? void 0 : dineInConfig["availability.pause_message"]) || closedMessage;
1133
+ const makeShopClosed = (errorTips, closed_behavior) => ({
963
1134
  mode: "shop_closed",
964
1135
  order_id: void 0,
965
1136
  relation_id: void 0,
966
1137
  table_form_id: void 0,
967
1138
  deskmate_valid: false,
968
- errorTips: (dineInConfig == null ? void 0 : dineInConfig["availability.pause_message"]) || (dineInConfig == null ? void 0 : dineInConfig["availability.closed_message"]) || (dineInConfig == null ? void 0 : dineInConfig["availability.message"]) || (dineInConfig == null ? void 0 : dineInConfig["basic.closed_message"])
1139
+ errorTips,
1140
+ closed_behavior
969
1141
  });
1142
+ if ((dineInConfig == null ? void 0 : dineInConfig["basic.enable"]) === false) {
1143
+ return makeShopClosed(basicUnavailableMessage);
1144
+ }
970
1145
  if ((0, import_utils.toBoolean)(dineInConfig == null ? void 0 : dineInConfig["availability.paused"])) {
971
1146
  if ((dineInConfig == null ? void 0 : dineInConfig["availability.pause_behavior"]) === "hide_all") {
972
- return shopClosedInfo();
1147
+ return makeShopClosed(pauseMessage);
973
1148
  }
974
1149
  }
1150
+ 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) : [];
1151
+ let outsideOperatingHours = false;
1152
+ if (operatingHourIds.length && this.store.schedule) {
1153
+ const scheduleList = this.store.schedule.getScheduleListByIds(operatingHourIds);
1154
+ if (scheduleList.length) {
1155
+ const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1156
+ outsideOperatingHours = !(0, import_getDateIsInSchedule.getDateIsInSchedule)(now, scheduleList);
1157
+ }
1158
+ }
1159
+ if (outsideOperatingHours && closedBehaviorValue !== "show_menu_disabled") {
1160
+ return makeShopClosed(closedMessage, closedBehaviorValue);
1161
+ }
975
1162
  const config = await this.fetchTableConfigByResourceId(resourceId);
976
1163
  const resourceState = this.normalizeResourceState(config, hasOrderId);
977
1164
  this.store.resource = resourceState;
@@ -981,6 +1168,7 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
981
1168
  relation_id: resourceState.relationId,
982
1169
  table_form_id: resourceState.tableFormId,
983
1170
  deskmate_valid: resourceState.deskmate_valid,
1171
+ table_form_record: resourceState.table_form_record,
984
1172
  policy: (_c = config == null ? void 0 : config.table_form_record) == null ? void 0 : _c.policy,
985
1173
  partyroom_booking: (_d = config == null ? void 0 : config.table_form_record) == null ? void 0 : _d.partyroom_booking
986
1174
  };
@@ -988,6 +1176,89 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
988
1176
  tempOrder.relation_id = resourceId || ((_e = this.otherParams) == null ? void 0 : _e.relation_id);
989
1177
  tempOrder.table_form_id = resourceState.tableFormId;
990
1178
  tempOrder.resource_id = resourceId;
1179
+ const reservationLinkIds = (0, import_utils.collectLinkProductIdsFromReservationRules)(
1180
+ dineInConfig["fulfillment.enabled_resource_rules"]
1181
+ );
1182
+ if (reservationLinkIds.length === 0) {
1183
+ this.enabledReservationRuleProducts = [];
1184
+ if (this.store.resource) {
1185
+ delete this.store.resource.requestEntryPax;
1186
+ delete this.store.resource.requestPaxMin;
1187
+ delete this.store.resource.requestPaxMax;
1188
+ }
1189
+ } else {
1190
+ tempOrder.metadata = { ...tempOrder.metadata || {} };
1191
+ delete tempOrder.metadata.table_occupancy_duration;
1192
+ const reservationProductList = new import_ProductList.ProductList(
1193
+ `${this.name}_reservationEnabledRules`,
1194
+ this.defaultVersion
1195
+ );
1196
+ await reservationProductList.initialize(this.core, {
1197
+ store: { list: [], selectProducts: [] },
1198
+ otherParams: {
1199
+ ...this.otherParams,
1200
+ fatherModule: this.name,
1201
+ openCache: Boolean(this.cacheId),
1202
+ cacheId: this.cacheId
1203
+ }
1204
+ });
1205
+ const scheduleDate = (0, import_dayjs.default)().format("YYYY-MM-DD");
1206
+ const scheduleDatetime = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1207
+ const loaded = await reservationProductList.loadProducts({
1208
+ product_ids: reservationLinkIds,
1209
+ schedule_date: scheduleDate,
1210
+ schedule_datetime: scheduleDatetime,
1211
+ cacheId: this.cacheId
1212
+ });
1213
+ if (Array.isArray(loaded)) {
1214
+ this.enabledReservationRuleProducts = loaded;
1215
+ const occupancyMinutes = (0, import_utils.pickFirstDurationMinutesFromProducts)(loaded);
1216
+ if (occupancyMinutes !== void 0) {
1217
+ tempOrder.metadata.table_occupancy_duration = occupancyMinutes;
1218
+ }
1219
+ if ((0, import_utils.hasCustomCapacityProduct)(loaded)) {
1220
+ availabilityInfo.requestEntryPax = 1;
1221
+ if (this.store.resource)
1222
+ this.store.resource.requestEntryPax = 1;
1223
+ delete availabilityInfo.requestPaxMin;
1224
+ delete availabilityInfo.requestPaxMax;
1225
+ if (this.store.resource) {
1226
+ delete this.store.resource.requestPaxMin;
1227
+ delete this.store.resource.requestPaxMax;
1228
+ }
1229
+ const paxBounds = (0, import_utils.pickFirstCustomCapacityPaxBounds)(loaded);
1230
+ if ((paxBounds == null ? void 0 : paxBounds.min) !== void 0) {
1231
+ availabilityInfo.requestPaxMin = paxBounds.min;
1232
+ if (this.store.resource)
1233
+ this.store.resource.requestPaxMin = paxBounds.min;
1234
+ }
1235
+ if ((paxBounds == null ? void 0 : paxBounds.max) !== void 0) {
1236
+ availabilityInfo.requestPaxMax = paxBounds.max;
1237
+ if (this.store.resource)
1238
+ this.store.resource.requestPaxMax = paxBounds.max;
1239
+ }
1240
+ } else if (this.store.resource) {
1241
+ delete this.store.resource.requestEntryPax;
1242
+ delete this.store.resource.requestPaxMin;
1243
+ delete this.store.resource.requestPaxMax;
1244
+ }
1245
+ } else {
1246
+ this.enabledReservationRuleProducts = [];
1247
+ if (this.store.resource) {
1248
+ delete this.store.resource.requestEntryPax;
1249
+ delete this.store.resource.requestPaxMin;
1250
+ delete this.store.resource.requestPaxMax;
1251
+ }
1252
+ void this.addScanOrderLog({
1253
+ level: "error",
1254
+ title: "[ScanOrder] enabled_reservation_rules product query failed",
1255
+ payload: {
1256
+ linkIds: reservationLinkIds,
1257
+ error: this.serializeError(loaded)
1258
+ }
1259
+ });
1260
+ }
1261
+ }
991
1262
  (_f = this.store.order) == null ? void 0 : _f.persistTempOrder();
992
1263
  if (availabilityInfo.mode === "idle") {
993
1264
  await this.addNewOrder();
@@ -995,8 +1266,37 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
995
1266
  if (availabilityInfo.mode === "additional_order" || availabilityInfo.mode === "additional_order_with_code") {
996
1267
  tempOrder.order_id = resourceState.lastOrderId;
997
1268
  }
998
- await this.refreshItemRuleQuantityLimits();
999
- await this.refreshCartValidationPassed();
1269
+ if (tempOrder.order_id) {
1270
+ const res = await ((_g = this.store.order) == null ? void 0 : _g.getOrderInfoByRemote(tempOrder.order_id));
1271
+ const entryPaxNumber = (_k = (_j = (_i = (_h = res == null ? void 0 : res.data) == null ? void 0 : _h.bookings) == null ? void 0 : _i.find((p) => {
1272
+ var _a2;
1273
+ return (_a2 = p.metadata) == null ? void 0 : _a2.collect_pax;
1274
+ })) == null ? void 0 : _j.metadata) == null ? void 0 : _k.collect_pax;
1275
+ if (entryPaxNumber) {
1276
+ await this.setEntryPaxNumber(entryPaxNumber);
1277
+ }
1278
+ }
1279
+ const lastOrderInfo = (_m = (_l = this.store.order) == null ? void 0 : _l.getLastOrderInfo) == null ? void 0 : _m.call(_l);
1280
+ const historicalItems = hasOrderId && Array.isArray(lastOrderInfo == null ? void 0 : lastOrderInfo.products) ? lastOrderInfo.products.reduce((acc, p) => {
1281
+ if (typeof (p == null ? void 0 : p.product_id) !== "number")
1282
+ return acc;
1283
+ acc.push({
1284
+ product_id: p.product_id,
1285
+ quantity: Number(p.product_quantity) || 0,
1286
+ ...typeof p.product_variant_id === "number" ? { product_variant_id: p.product_variant_id } : {}
1287
+ });
1288
+ return acc;
1289
+ }, []) : [];
1290
+ await this.setItemRuleRuntimeConfig({
1291
+ serviceType: (_n = this.otherParams) == null ? void 0 : _n.businessCode,
1292
+ submissionIndex: hasOrderId ? 1 : 0,
1293
+ historicalItems
1294
+ });
1295
+ if (outsideOperatingHours && closedBehaviorValue === "show_menu_disabled") {
1296
+ availabilityInfo.mode = "submit_disabled";
1297
+ availabilityInfo.errorTips = closedMessage;
1298
+ availabilityInfo.closed_behavior = closedBehaviorValue;
1299
+ }
1000
1300
  this.logMethodSuccess("checkResourceAvailable", {
1001
1301
  resourceId,
1002
1302
  mode: availabilityInfo.mode,
@@ -1063,6 +1363,61 @@ var ScanOrderImpl = class extends import_BaseModule.BaseModule {
1063
1363
  getOtherParams() {
1064
1364
  return this.otherParams;
1065
1365
  }
1366
+ async setOtherParams(params, { cover = false } = {}) {
1367
+ if (cover) {
1368
+ this.otherParams = params;
1369
+ } else {
1370
+ this.otherParams = { ...this.otherParams, ...params };
1371
+ }
1372
+ }
1373
+ async setEntryPaxNumber(number) {
1374
+ const pax = (0, import_utils2.normalizeSubmitCollectPaxValue)(number);
1375
+ this.store.entryPaxNumber = pax;
1376
+ if (this.store.order) {
1377
+ const t = this.store.order.ensureTempOrder();
1378
+ t.metadata = { ...t.metadata, collect_pax: pax };
1379
+ this.store.order.persistTempOrder();
1380
+ }
1381
+ this.itemRuleRuntimeConfig = {
1382
+ ...this.itemRuleRuntimeConfig,
1383
+ pax: { total: pax, adult: 0, child: 0 }
1384
+ };
1385
+ this.itemRulePrefillApplied = false;
1386
+ await this.refreshItemRuleQuantityLimits();
1387
+ await this.refreshCartValidationPassed();
1388
+ }
1389
+ getEntryPaxNumber() {
1390
+ return this.store.entryPaxNumber;
1391
+ }
1392
+ // 读取取餐/送餐开关
1393
+ // 依赖 checkResourceAvailable 已缓存的 dineInConfig
1394
+ getFulfillmentModes() {
1395
+ var _a;
1396
+ this.logMethodStart("getFulfillmentModes");
1397
+ const dineInConfig = ((_a = this.otherParams) == null ? void 0 : _a.dineInConfig) || {};
1398
+ const result = {
1399
+ enablePickup: Boolean(dineInConfig["fulfillment.enable_pickup"]),
1400
+ enableTableService: Boolean(dineInConfig["fulfillment.enable_table_service"])
1401
+ };
1402
+ this.logMethodSuccess("getFulfillmentModes", result);
1403
+ return result;
1404
+ }
1405
+ // 判定后台是否开启客户自定义取餐标识
1406
+ // 依赖 checkResourceAvailable 已缓存的 dineInConfig
1407
+ checkManualPickupRef() {
1408
+ var _a;
1409
+ this.logMethodStart("checkManualPickupRef");
1410
+ const dineInConfig = ((_a = this.otherParams) == null ? void 0 : _a.dineInConfig) || {};
1411
+ const refMode = dineInConfig["fulfillment.fulfillment_ref_mode"];
1412
+ const manualInputType = dineInConfig["fulfillment.manual_input_type"];
1413
+ const enabled = refMode === "manual_input";
1414
+ const result = enabled ? { enabled: true, manualInputType } : { enabled: false };
1415
+ this.logMethodSuccess("checkManualPickupRef", {
1416
+ enabled,
1417
+ manualInputType: enabled ? manualInputType : void 0
1418
+ });
1419
+ return result;
1420
+ }
1066
1421
  };
1067
1422
  // Annotate the CommonJS export names for ESM import in node:
1068
1423
  0 && (module.exports = {
@@ -1,4 +1,4 @@
1
- import { OrderModule, ProductList, SalesSummaryModule, ScanOrderLogInput, ScanOrderLoggerModule, ScanOrderLoggerProviderConfig, ScanOrderLoggerProviderType } from '../../modules';
1
+ import { OrderModule, ProductList, SalesSummaryModule, ScanOrderLogInput, ScanOrderLoggerModule, ScanOrderLoggerProviderConfig, ScanOrderLoggerProviderType, ScheduleModule } from '../../modules';
2
2
  import type { QuantityCheckResult, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
3
3
  /**
4
4
  * 扫码下单流程 hook
@@ -36,9 +36,10 @@ export interface ScanOrderOrderProduct extends ScanOrderOrderProductIdentity {
36
36
  order_detail_id: number | null;
37
37
  num: number;
38
38
  product_option_item: any[];
39
+ /** 券后单品单价(= 订单域实际成交单价)。未应用券时等同 original_price。 */
39
40
  selling_price: string;
41
+ /** 券前单品单价(= 店铺售价),不承载后台划线价语义。 */
40
42
  original_price: string;
41
- payment_price: string;
42
43
  tax_fee: string;
43
44
  is_charge_tax: number;
44
45
  discount_list: any[];
@@ -47,6 +48,11 @@ export interface ScanOrderOrderProduct extends ScanOrderOrderProductIdentity {
47
48
  _origin?: Record<string, any>;
48
49
  }
49
50
  export interface ScanOrderSubmitProduct extends Omit<ScanOrderOrderProduct, '_origin' | 'identity_key'> {
51
+ /**
52
+ * 出站兼容字段:SDK 内部不再消费 payment_price,
53
+ * 仅在提交后端时由 selling_price 派生,保持原有后端契约。
54
+ */
55
+ payment_price: string;
50
56
  }
51
57
  export interface ScanOrderSummary {
52
58
  product_quantity: number;
@@ -108,6 +114,9 @@ export interface ScanOrderTempOrder {
108
114
  shop_discount: string;
109
115
  surcharge_fee: string;
110
116
  note: string;
117
+ buzzer?: string;
118
+ delivery_type?: string;
119
+ table_number?: Record<string, any>;
111
120
  schedule_date: string;
112
121
  created_at: string;
113
122
  products: ScanOrderOrderProduct[];
@@ -121,17 +130,23 @@ export interface ScanOrderTempOrder {
121
130
  holder: Record<string, any> | null;
122
131
  summary: ScanOrderSummary;
123
132
  metadata: Record<string, any>;
133
+ lastOrderInfo?: Record<string, any>;
124
134
  }
125
135
  export interface ScanOrderSubmitPayload extends Omit<ScanOrderTempOrder, 'platform' | 'products' | 'created_at' | 'summary' | 'surcharges'> {
126
136
  platform: 'H5' | 'PC';
127
137
  request_unique_idempotency_token?: string;
128
138
  form_record_ids?: Array<{
129
139
  form_id: number | string;
130
- form_record_ids: Array<number | string>;
140
+ form_record_id: number | string;
131
141
  }>;
132
142
  products: ScanOrderSubmitProduct[];
133
143
  }
134
- export type ScanOrderAvailabilityMode = 'idle' | 'shop_closed' | 'resource_block' | 'resource_busy' | 'additional_order_with_code' | 'additional_order';
144
+ export type ScanOrderAvailabilityMode = 'idle' | 'shop_closed' | 'submit_disabled' | 'resource_block' | 'resource_busy' | 'additional_order_with_code' | 'additional_order';
145
+ export interface ScanOrderTableFormRecord {
146
+ policy?: string | null;
147
+ partyroom_booking?: string | null;
148
+ [key: string]: any;
149
+ }
135
150
  export interface ScanOrderAvailabilityInfo {
136
151
  mode: ScanOrderAvailabilityMode;
137
152
  order_id?: string;
@@ -139,8 +154,18 @@ export interface ScanOrderAvailabilityInfo {
139
154
  table_form_id?: string;
140
155
  deskmate_valid?: boolean;
141
156
  errorTips?: string;
157
+ /** 透传 `availability.closed_behavior`,便于 UI 识别拦截类型(如 show_menu_disabled) */
158
+ closed_behavior?: string;
159
+ /** `/order/dining/table/config` 返回的 `table_form_record` 原样透出 */
160
+ table_form_record?: ScanOrderTableFormRecord | null;
142
161
  policy?: string | null;
143
162
  partyroom_booking?: string | null;
163
+ /** 预约规则关联商品存在 custom 容量时,由 checkResourceAvailable 置为 1 */
164
+ requestEntryPax?: number;
165
+ /** 首个 `capacity.type === 'custom'` 商品里 `custom[0]` 的 min(人数下限) */
166
+ requestPaxMin?: number;
167
+ /** 首个 `capacity.type === 'custom'` 商品里 `custom[0]` 的 max(人数上限) */
168
+ requestPaxMax?: number;
144
169
  }
145
170
  export interface ScanOrderTableSnackConfig {
146
171
  snack?: boolean | number | string;
@@ -150,9 +175,6 @@ export interface ScanOrderOrderNumberPrefixConfig {
150
175
  table_order?: string;
151
176
  pos?: string;
152
177
  }
153
- export interface ScanOrderTableFormRecord {
154
- policy?: string | null;
155
- }
156
178
  export interface ScanOrderTableConfigApiData {
157
179
  table_max_number?: number | string | null;
158
180
  order_count?: number | string | null;
@@ -183,7 +205,6 @@ export interface ScanOrderResourceState extends ScanOrderAvailabilityInfo {
183
205
  isFull: boolean;
184
206
  orderNumberPrefix: ScanOrderOrderNumberPrefixConfig[];
185
207
  raw: ScanOrderTableConfigApiData | null;
186
- table_form_record?: ScanOrderTableFormRecord | null;
187
208
  }
188
209
  export interface ScanOrderState {
189
210
  entryContext: ScanOrderEntryContext | null;
@@ -196,11 +217,13 @@ export interface ScanOrderState {
196
217
  order?: OrderModule;
197
218
  salesSummary?: SalesSummaryModule;
198
219
  scanOrderLogger?: ScanOrderLoggerModule;
220
+ schedule?: ScheduleModule;
199
221
  itemRuleQuantityLimits: QuantityLimitResult[];
200
222
  cartValidation: {
201
223
  passed: boolean | null;
202
224
  failures: QuantityCheckResult[];
203
225
  };
226
+ entryPaxNumber: number | null;
204
227
  }
205
228
  export interface ScanOrderLoggerRuntimeConfig {
206
229
  provider?: ScanOrderLoggerProviderType;