@pisell/pisellos 2.1.173 → 2.1.174

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 (93) hide show
  1. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  2. package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  3. package/dist/model/strategy/adapter/walletPass/evaluator.js +4 -2
  4. package/dist/modules/Discount/availability.d.ts +7 -0
  5. package/dist/modules/Discount/availability.js +52 -0
  6. package/dist/modules/Discount/entitlementPass.d.ts +34 -0
  7. package/dist/modules/Discount/entitlementPass.js +147 -0
  8. package/dist/modules/Discount/entitlementState.d.ts +8 -0
  9. package/dist/modules/Discount/entitlementState.js +205 -0
  10. package/dist/modules/Discount/index.d.ts +6 -3
  11. package/dist/modules/Discount/index.js +125 -23
  12. package/dist/modules/Discount/types.d.ts +34 -5
  13. package/dist/modules/Holder/index.d.ts +48 -0
  14. package/dist/modules/Holder/index.js +640 -0
  15. package/dist/modules/Holder/types.d.ts +123 -0
  16. package/dist/modules/Holder/types.js +1 -0
  17. package/dist/modules/Holder/utils.d.ts +13 -0
  18. package/dist/modules/Holder/utils.js +34 -0
  19. package/dist/modules/Order/index.d.ts +1 -0
  20. package/dist/modules/Order/index.js +18 -1
  21. package/dist/modules/Order/types.d.ts +2 -0
  22. package/dist/modules/Order/utils.d.ts +10 -0
  23. package/dist/modules/Order/utils.js +35 -3
  24. package/dist/modules/Product/types.d.ts +7 -0
  25. package/dist/modules/Rules/entitlementLines.d.ts +8 -0
  26. package/dist/modules/Rules/entitlementLines.js +157 -0
  27. package/dist/modules/Rules/index.d.ts +12 -2
  28. package/dist/modules/Rules/index.js +377 -112
  29. package/dist/modules/Rules/types.d.ts +2 -2
  30. package/dist/modules/index.d.ts +1 -0
  31. package/dist/modules/index.js +2 -1
  32. package/dist/plugins/window.d.ts +3 -0
  33. package/dist/solution/BookingByStep/index.d.ts +17 -2
  34. package/dist/solution/BookingByStep/index.js +276 -204
  35. package/dist/solution/BookingByStep/types.d.ts +2 -1
  36. package/dist/solution/BookingByStep/types.js +3 -1
  37. package/dist/solution/ScanOrder/index.js +1 -1
  38. package/dist/solution/ScanOrder/types.d.ts +1 -0
  39. package/dist/solution/ShopDiscount/index.d.ts +3 -0
  40. package/dist/solution/ShopDiscount/index.js +161 -78
  41. package/dist/solution/ShopDiscount/utils.d.ts +1 -0
  42. package/dist/solution/ShopDiscount/utils.js +40 -1
  43. package/dist/solution/VenueBooking/index.d.ts +19 -0
  44. package/dist/solution/VenueBooking/index.js +978 -748
  45. package/dist/solution/VenueBooking/types.d.ts +2 -0
  46. package/dist/types/index.d.ts +1 -0
  47. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  48. package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  49. package/lib/model/strategy/adapter/walletPass/evaluator.js +4 -2
  50. package/lib/modules/Discount/availability.d.ts +7 -0
  51. package/lib/modules/Discount/availability.js +91 -0
  52. package/lib/modules/Discount/entitlementPass.d.ts +34 -0
  53. package/lib/modules/Discount/entitlementPass.js +184 -0
  54. package/lib/modules/Discount/entitlementState.d.ts +8 -0
  55. package/lib/modules/Discount/entitlementState.js +206 -0
  56. package/lib/modules/Discount/index.d.ts +6 -3
  57. package/lib/modules/Discount/index.js +66 -16
  58. package/lib/modules/Discount/types.d.ts +34 -5
  59. package/lib/modules/Holder/index.d.ts +48 -0
  60. package/lib/modules/Holder/index.js +402 -0
  61. package/lib/modules/Holder/types.d.ts +123 -0
  62. package/lib/modules/Holder/types.js +17 -0
  63. package/lib/modules/Holder/utils.d.ts +13 -0
  64. package/lib/modules/Holder/utils.js +71 -0
  65. package/lib/modules/Order/index.d.ts +1 -0
  66. package/lib/modules/Order/index.js +14 -0
  67. package/lib/modules/Order/types.d.ts +2 -0
  68. package/lib/modules/Order/utils.d.ts +10 -0
  69. package/lib/modules/Order/utils.js +36 -5
  70. package/lib/modules/Product/types.d.ts +7 -0
  71. package/lib/modules/Rules/entitlementLines.d.ts +8 -0
  72. package/lib/modules/Rules/entitlementLines.js +158 -0
  73. package/lib/modules/Rules/index.d.ts +12 -2
  74. package/lib/modules/Rules/index.js +304 -70
  75. package/lib/modules/Rules/types.d.ts +2 -2
  76. package/lib/modules/index.d.ts +1 -0
  77. package/lib/modules/index.js +3 -1
  78. package/lib/plugins/window.d.ts +3 -0
  79. package/lib/solution/BookingByStep/index.d.ts +17 -2
  80. package/lib/solution/BookingByStep/index.js +39 -0
  81. package/lib/solution/BookingByStep/types.d.ts +2 -1
  82. package/lib/solution/BookingByStep/types.js +5 -0
  83. package/lib/solution/ScanOrder/index.js +1 -1
  84. package/lib/solution/ScanOrder/types.d.ts +1 -0
  85. package/lib/solution/ShopDiscount/index.d.ts +3 -0
  86. package/lib/solution/ShopDiscount/index.js +78 -28
  87. package/lib/solution/ShopDiscount/utils.d.ts +1 -0
  88. package/lib/solution/ShopDiscount/utils.js +42 -1
  89. package/lib/solution/VenueBooking/index.d.ts +19 -0
  90. package/lib/solution/VenueBooking/index.js +134 -16
  91. package/lib/solution/VenueBooking/types.d.ts +2 -0
  92. package/lib/types/index.d.ts +1 -0
  93. package/package.json +1 -1
@@ -29,7 +29,7 @@ export interface RulesModuleAPI {
29
29
  discountList: any[];
30
30
  productList: any[];
31
31
  holders: {
32
- form_record_id: number;
32
+ form_record_id: number | string;
33
33
  }[];
34
34
  isFormSubject: boolean;
35
35
  }) => DiscountResult;
@@ -49,7 +49,7 @@ type ProductDetail = {
49
49
  original_price?: number | string;
50
50
  num?: number;
51
51
  quantity: number;
52
- holder_id?: number | string;
52
+ holder_id?: number | string | Array<number | string>;
53
53
  vouchersApplicable?: boolean;
54
54
  startDate?: any;
55
55
  };
@@ -16,3 +16,4 @@ export * from './Schedule';
16
16
  export * from './Quotation';
17
17
  export * from './ScanOrderLogger';
18
18
  export * from './OpenData';
19
+ export * from './Holder';
@@ -34,6 +34,7 @@ __reExport(modules_exports, require("./Schedule"), module.exports);
34
34
  __reExport(modules_exports, require("./Quotation"), module.exports);
35
35
  __reExport(modules_exports, require("./ScanOrderLogger"), module.exports);
36
36
  __reExport(modules_exports, require("./OpenData"), module.exports);
37
+ __reExport(modules_exports, require("./Holder"), module.exports);
37
38
  // Annotate the CommonJS export names for ESM import in node:
38
39
  0 && (module.exports = {
39
40
  ...require("./Product"),
@@ -53,5 +54,6 @@ __reExport(modules_exports, require("./OpenData"), module.exports);
53
54
  ...require("./Schedule"),
54
55
  ...require("./Quotation"),
55
56
  ...require("./ScanOrderLogger"),
56
- ...require("./OpenData")
57
+ ...require("./OpenData"),
58
+ ...require("./Holder")
57
59
  });
@@ -1,4 +1,5 @@
1
1
  import { Plugin } from '../types';
2
+ import type { WalletPassEvaluator } from '../model/strategy/adapter/walletPass/evaluator';
2
3
  /**
3
4
  * WindowPlugin 接口定义
4
5
  */
@@ -14,6 +15,8 @@ export interface WindowPlugin extends Plugin {
14
15
  document: Partial<Document>;
15
16
  history: History;
16
17
  interaction?: any;
18
+ getWalletPassEvaluator?: () => WalletPassEvaluator | undefined;
19
+ getLocalStorage?: (key: string) => string | null;
17
20
  }
18
21
  /**
19
22
  * 简单的 Storage 接口实现
@@ -10,6 +10,7 @@ import { ITime } from '../../modules/Date/types';
10
10
  import dayjs from 'dayjs';
11
11
  import { LoadScheduleAvailableDateParams } from '../../modules/Schedule/types';
12
12
  import { IHolder, IFetchHolderAccountsParams } from '../../modules/AccountList/types';
13
+ import { IAppendFormRecordParams } from '../../modules/Holder/types';
13
14
  export declare class BookingByStepImpl extends BaseModule implements Module {
14
15
  protected defaultName: string;
15
16
  protected defaultVersion: string;
@@ -126,6 +127,20 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
126
127
  * @param params
127
128
  */
128
129
  fetchHolderAccountsAsync(params: IFetchHolderAccountsParams): Promise<void>;
130
+ /**
131
+ * 获取 holder 表单 map
132
+ */
133
+ getHolderFormMap(): import("../../modules").HolderFormMap;
134
+ /**
135
+ * 登录后或外部触发时,按当前 holderMap 批量刷新所有表单的 records
136
+ */
137
+ refreshAllHolderFormRecords(params?: {
138
+ customer_id?: number;
139
+ }): Promise<import("../../modules").HolderFormMap>;
140
+ /**
141
+ * 添加表单记录
142
+ */
143
+ appendFormRecord(params: IAppendFormRecordParams): import("../../modules").IFormRecord;
129
144
  setDateRange(dateRange: ITime[]): Promise<void>;
130
145
  clearDateRange(): void;
131
146
  getDateRange(): Promise<ITime[]>;
@@ -310,7 +325,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
310
325
  date: string;
311
326
  status: string;
312
327
  week: string;
313
- weekNum: 0 | 1 | 2 | 5 | 4 | 3 | 6;
328
+ weekNum: 0 | 2 | 1 | 5 | 3 | 4 | 6;
314
329
  }[]>;
315
330
  submitTimeSlot(timeSlots: TimeSliceItem): void;
316
331
  private getScheduleDataByIds;
@@ -329,7 +344,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
329
344
  count: number;
330
345
  left: number;
331
346
  summaryCount: number;
332
- status: "sold_out" | "lots_of_space" | "filling_up_fast";
347
+ status: "lots_of_space" | "filling_up_fast" | "sold_out";
333
348
  }[];
334
349
  /**
335
350
  * 找到多个资源的公共可用时间段
@@ -89,6 +89,7 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
89
89
  }
90
90
  const moduleArr = [
91
91
  "accountList",
92
+ "holder",
92
93
  "cart",
93
94
  "schedule",
94
95
  "summary",
@@ -379,6 +380,27 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
379
380
  }
380
381
  return this.store.accountList.fetchHolderAccounts(params);
381
382
  }
383
+ /**
384
+ * 获取 holder 表单 map
385
+ */
386
+ getHolderFormMap() {
387
+ return this.store.holder.getHolderFormMap();
388
+ }
389
+ /**
390
+ * 登录后或外部触发时,按当前 holderMap 批量刷新所有表单的 records
391
+ */
392
+ async refreshAllHolderFormRecords(params) {
393
+ return this.store.holder.refreshAllFormRecords({
394
+ customer_id: params == null ? void 0 : params.customer_id,
395
+ useCache: false
396
+ });
397
+ }
398
+ /**
399
+ * 添加表单记录
400
+ */
401
+ appendFormRecord(params) {
402
+ return this.store.holder.appendFormRecord(params);
403
+ }
382
404
  // 设置日期范围,注入到日期模块中
383
405
  async setDateRange(dateRange) {
384
406
  this.store.date.setDateRange(dateRange);
@@ -486,6 +508,14 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
486
508
  date = (normalProductCartItem == null ? void 0 : normalProductCartItem.start_date) || "";
487
509
  }
488
510
  this.updateQuotationPriceAndCart(date);
511
+ try {
512
+ const customerId = Number(accountInfo.id);
513
+ await this.refreshAllHolderFormRecords({
514
+ customer_id: customerId
515
+ });
516
+ } catch (error) {
517
+ console.error("[BookingByStep] 登录后刷新 holder 表单失败", error);
518
+ }
489
519
  }
490
520
  } else {
491
521
  throw new Error(`没有找到${accountId}账户`);
@@ -631,6 +661,15 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
631
661
  account = activeAccount;
632
662
  }
633
663
  }
664
+ try {
665
+ this.store.holder.ensureFormByProduct({
666
+ product: productData,
667
+ shop_id: (productData == null ? void 0 : productData.shop_id) || "",
668
+ useCache: true
669
+ });
670
+ } catch (error) {
671
+ console.error("[BookingByStep] 加载 holder 表单失败", error);
672
+ }
634
673
  const flag = this.store.cart.mergeCartItemByRowKey({
635
674
  rowKey,
636
675
  quantity,
@@ -1,4 +1,4 @@
1
- import { ProductList, CartModule, ProductData, AccountModule, AccountListModule, DateModule, GuestListModule, OrderModule, PaymentModule, ResourceListModule, StepModule, SummaryModule, SalesSummaryModule, ScheduleModule, ScanOrderLoggerModule } from '../../modules';
1
+ import { ProductList, CartModule, ProductData, AccountModule, AccountListModule, DateModule, GuestListModule, OrderModule, PaymentModule, ResourceListModule, StepModule, SummaryModule, SalesSummaryModule, ScheduleModule, ScanOrderLoggerModule, HolderModule } from '../../modules';
2
2
  export interface BookingByStepState {
3
3
  cart: CartModule;
4
4
  summary: SummaryModule;
@@ -16,6 +16,7 @@ export interface BookingByStepState {
16
16
  schedule: ScheduleModule;
17
17
  salesSummary?: SalesSummaryModule;
18
18
  scanOrderLogger?: ScanOrderLoggerModule;
19
+ holder: HolderModule;
19
20
  }
20
21
  export declare function createModule<T extends keyof BookingByStepState>(moduleName: T, solutionName: string, name?: string, version?: string): BookingByStepState[T];
21
22
  export declare enum BookingByStepHooks {
@@ -81,6 +81,11 @@ function createModule(moduleName, solutionName, name, version) {
81
81
  `${solutionName}_${name || moduleName}`,
82
82
  version
83
83
  );
84
+ case "holder":
85
+ return new import_modules.HolderModule(
86
+ `${solutionName}_${name || moduleName}`,
87
+ version
88
+ );
84
89
  default:
85
90
  throw new Error(`Unknown module type: ${moduleName}`);
86
91
  }
@@ -563,7 +563,7 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
563
563
  ...tempOrder.metadata || {},
564
564
  shop_service_data: {
565
565
  ...(tempOrder.metadata || {}).shop_service_data || {},
566
- service_type: ((_a = this.otherParams) == null ? void 0 : _a.businessCode) === "dine_in" ? "dine_in" : "take_away",
566
+ service_type: ((_a = this.otherParams) == null ? void 0 : _a.businessCode) === "dine_in" ? "dine_in" : "",
567
567
  pickup_reference_mode: mode
568
568
  }
569
569
  };
@@ -34,6 +34,7 @@ export interface ScanOrderOrderProductIdentity {
34
34
  /** 参与合并/匹配;与 remove 通配语义见 isSkuOnlyDeleteIdentity */
35
35
  product_option_item?: any[];
36
36
  product_bundle?: any[];
37
+ shop_id?: number | string;
37
38
  }
38
39
  export interface ScanOrderOrderProduct extends ScanOrderOrderProductIdentity {
39
40
  order_detail_id: number | null;
@@ -12,6 +12,8 @@ export declare class ShopDiscountImpl extends BaseModule implements Module {
12
12
  private store;
13
13
  private options;
14
14
  private hooks?;
15
+ private entitlementPassEnabled;
16
+ setEntitlementPassEnabled(enabled: boolean): void;
15
17
  constructor(name?: string, version?: string);
16
18
  initialize(core: PisellCore, options: any): Promise<void>;
17
19
  destroy(): Promise<void>;
@@ -42,6 +44,7 @@ export declare class ShopDiscountImpl extends BaseModule implements Module {
42
44
  batchSearchByProductIds(productIds: number[]): Promise<Discount[]>;
43
45
  scanCode(code: string, customerId?: number): Promise<{
44
46
  isAvailable: boolean;
47
+ isAccepted?: boolean;
45
48
  productList: Record<string, any>[];
46
49
  discountList: Discount[];
47
50
  type: "server" | "clientCalc";
@@ -40,6 +40,9 @@ var import_utils = require("./utils");
40
40
  var import_types = require("../../modules/Rules/types");
41
41
  var import_decimal = __toESM(require("decimal.js"));
42
42
  var import_lodash_es = require("lodash-es");
43
+ var import_entitlementPass = require("../../modules/Discount/entitlementPass");
44
+ var import_availability = require("../../modules/Discount/availability");
45
+ var import_entitlementState = require("../../modules/Discount/entitlementState");
43
46
  var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
44
47
  constructor(name, version) {
45
48
  super(name, version);
@@ -47,6 +50,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
47
50
  this.defaultVersion = "1.0.0";
48
51
  this.isSolution = true;
49
52
  this.options = {};
53
+ this.entitlementPassEnabled = false;
50
54
  this.store = {
51
55
  customer: null,
52
56
  productList: [],
@@ -60,6 +64,15 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
60
64
  orderId: void 0
61
65
  };
62
66
  }
67
+ // 由使用多次卡的预约组件显式开启,其他入口沿用原券流程。
68
+ setEntitlementPassEnabled(enabled) {
69
+ var _a, _b;
70
+ this.entitlementPassEnabled = enabled;
71
+ (_a = this.store.rules) == null ? void 0 : _a.setEntitlementPassEnabled(enabled);
72
+ if (!enabled) {
73
+ (_b = this.store.discount) == null ? void 0 : _b.setDiscountList(this.getDiscountList().filter((item) => !(0, import_entitlementPass.isEntitlementPass)(item)));
74
+ }
75
+ }
63
76
  // =========== 生命周期方法 ===========
64
77
  async initialize(core, options) {
65
78
  var _a, _b;
@@ -133,9 +146,8 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
133
146
  `${this.name}:onCustomerChange`,
134
147
  (customer) => {
135
148
  var _a;
136
- if (((_a = this.options.otherParams) == null ? void 0 : _a.cacheId) && this.getDiscountList().length) {
149
+ if (!this.entitlementPassEnabled && ((_a = this.options.otherParams) == null ? void 0 : _a.cacheId) && this.getDiscountList().length)
137
150
  return;
138
- }
139
151
  this.loadPrepareConfig({
140
152
  customerId: customer.id,
141
153
  action: "create",
@@ -186,9 +198,13 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
186
198
  // }
187
199
  // 设置客户
188
200
  async setCustomer(customer) {
189
- var _a;
201
+ var _a, _b;
190
202
  if (((_a = this.store.customer) == null ? void 0 : _a.id) !== customer.id) {
191
203
  this.store.customer = customer;
204
+ if (this.entitlementPassEnabled) {
205
+ const retained = this.getDiscountList().filter((item) => !(0, import_entitlementPass.isEntitlementPass)(item) || item.isEditMode || item.isScan && String(item.customer_id) === String(customer.id));
206
+ await ((_b = this.store.discount) == null ? void 0 : _b.setDiscountList(retained));
207
+ }
192
208
  await this.core.effects.emit(
193
209
  `${this.name}:onCustomerChange`,
194
210
  customer
@@ -222,6 +238,8 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
222
238
  },
223
239
  options
224
240
  ) || { productList, discountList: this.getDiscountList() };
241
+ if (this.entitlementPassEnabled)
242
+ this.store.productList = newProductList || productList;
225
243
  if (newDiscountList) {
226
244
  newDiscountList = this.setDiscountList(newDiscountList);
227
245
  }
@@ -279,9 +297,13 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
279
297
  }
280
298
  // 扫码输入code
281
299
  async scanCode(code, customerId) {
282
- var _a, _b, _c;
300
+ var _a, _b, _c, _d, _e;
283
301
  try {
284
- const resultDiscountWithReason = await ((_a = this.store.discount) == null ? void 0 : _a.batchSearch(code, { customerId, orderId: this.store.orderId })) || { discountList: [], unavailableReasonKey: null };
302
+ const resultDiscountWithReason = await ((_a = this.store.discount) == null ? void 0 : _a.batchSearch(code, {
303
+ customerId,
304
+ orderId: this.store.orderId,
305
+ withEntitlementPass: this.entitlementPassEnabled
306
+ })) || { discountList: [], unavailableReasonKey: null };
285
307
  const { discountList: resultDiscountList, unavailableReasonKey } = resultDiscountWithReason;
286
308
  const rulesModule = this.store.rules;
287
309
  if (!rulesModule) {
@@ -309,7 +331,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
309
331
  };
310
332
  });
311
333
  const currentSelectedDiscountList = this.getDiscountList().filter((n) => n.isSelected);
312
- if (currentSelectedDiscountList.length && currentSelectedDiscountList.some((n) => withScanList.some((m) => m.id === n.id))) {
334
+ if (!withScanList.some(import_entitlementPass.isEntitlementPass) && currentSelectedDiscountList.length && currentSelectedDiscountList.some((n) => withScanList.some((m) => m.id === n.id))) {
313
335
  return {
314
336
  type: "clientCalc",
315
337
  isAvailable: true,
@@ -320,6 +342,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
320
342
  const {
321
343
  productList: newProductList,
322
344
  discountList: newDiscountList,
345
+ evaluatedDiscountList,
323
346
  isAvailable,
324
347
  unavailableReason
325
348
  } = rulesModule.isDiscountListAvailable({
@@ -333,22 +356,42 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
333
356
  productList: this.store.productList || [],
334
357
  discountList: this.getDiscountList()
335
358
  };
359
+ let isAccepted = isAvailable;
336
360
  if (isAvailable) {
361
+ if (this.entitlementPassEnabled)
362
+ this.setProductList(newProductList || []);
337
363
  this.setDiscountList(newDiscountList || []);
338
364
  this.store.originalDiscountList = newDiscountList || [];
339
- this.setProductList(newProductList || []);
365
+ if (!this.entitlementPassEnabled)
366
+ this.setProductList(newProductList || []);
340
367
  if (this.isWalkIn() && resultDiscountList.length && ((_c = this.options.otherParams) == null ? void 0 : _c.platform) === "shop") {
341
368
  await this.getCustomerWallet(
342
369
  resultDiscountList[0].customer_id
343
370
  );
344
371
  }
345
372
  }
373
+ if (!isAvailable) {
374
+ const ids = new Set(withScanList.map((item) => String(item.id)));
375
+ const retainable = (evaluatedDiscountList || []).filter((item) => ids.has(String(item.id)) && (0, import_entitlementPass.isEntitlementPass)(item) && !(0, import_availability.getDiscountLifecycleReason)(item));
376
+ if (retainable.length) {
377
+ this.setDiscountList((0, import_entitlementState.retainScannedEntitlements)(this.getDiscountList(), retainable));
378
+ isAccepted = true;
379
+ }
380
+ }
381
+ if (this.entitlementPassEnabled) {
382
+ this.store.originalDiscountList = this.getDiscountList();
383
+ await ((_d = this.store.discount) == null ? void 0 : _d.setOriginalDiscountList(this.getDiscountList()));
384
+ }
346
385
  return {
347
386
  type: "clientCalc",
348
387
  isAvailable: isAvailable || false,
349
- productList: newProductList || this.store.productList || [],
350
- discountList: newDiscountList || this.getDiscountList(),
351
- unavailableReason
388
+ isAccepted,
389
+ productList: isAvailable ? newProductList : this.store.productList || [],
390
+ discountList: this.getDiscountList(),
391
+ unavailableReason,
392
+ unavailableReasonKey: ((_e = (evaluatedDiscountList || []).find(
393
+ (item) => withScanList.some((scanned) => String(scanned.id) === String(item.id)) && item.reasonCode
394
+ )) == null ? void 0 : _e.reasonCode) || unavailableReasonKey
352
395
  };
353
396
  } catch (error) {
354
397
  console.error("[ShopDiscount] 扫码出错:", error);
@@ -386,7 +429,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
386
429
  }
387
430
  // 设置优惠券列表
388
431
  setDiscountList(discountList) {
389
- var _a;
432
+ var _a, _b;
390
433
  const productList = this.store.productList || [];
391
434
  const editModeDiscountList = [];
392
435
  productList.forEach((item) => {
@@ -394,7 +437,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
394
437
  if (item.booking_id) {
395
438
  const product = (_a2 = this.hooks) == null ? void 0 : _a2.getProduct(item);
396
439
  (item.discount_list || []).forEach((discount) => {
397
- var _a3, _b, _c, _d, _e;
440
+ var _a3, _b2, _c, _d, _e;
398
441
  if (discount.id && ["good_pass", "discount_card"].includes(discount.type)) {
399
442
  const index = editModeDiscountList.findIndex((n) => {
400
443
  var _a4;
@@ -415,7 +458,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
415
458
  name: discount.name || discount.discount.title.auto,
416
459
  isEditMode: true,
417
460
  limited_relation_product_data: {},
418
- savedAmount: new import_decimal.default(discount.amount || 0).times((product == null ? void 0 : product.quantity) || (product == null ? void 0 : product.num) || 1).plus(((_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.product_discount_difference) || 0).toNumber(),
461
+ savedAmount: new import_decimal.default(discount.amount || 0).times((product == null ? void 0 : product.quantity) || (product == null ? void 0 : product.num) || 1).plus(((_b2 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b2.product_discount_difference) || 0).toNumber(),
419
462
  isAvailable: true,
420
463
  id: ((_c = discount.discount) == null ? void 0 : _c.resource_id) || discount.id,
421
464
  format_title: ((_d = discount.discount) == null ? void 0 : _d.title) || discount.format_title,
@@ -428,10 +471,10 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
428
471
  });
429
472
  }
430
473
  });
431
- const newDiscountList = [
432
- ...editModeDiscountList,
433
- ...discountList.filter((item) => !item.isDisabled)
434
- ];
474
+ const newDiscountList = this.entitlementPassEnabled ? (0, import_entitlementState.withCommittedEntitlementDetails)([
475
+ ...editModeDiscountList.filter((item) => !(0, import_entitlementPass.isEntitlementPass)(item)),
476
+ ...discountList.filter((item) => (0, import_entitlementPass.isEntitlementPass)(item) || !item.isDisabled)
477
+ ], productList, ((_a = this.hooks) == null ? void 0 : _a.getProduct) || ((item) => item)) : [...editModeDiscountList, ...discountList.filter((item) => !item.isDisabled && !(0, import_entitlementPass.isEntitlementPass)(item))];
435
478
  const isProductFree = (id) => {
436
479
  var _a2;
437
480
  const targetProduct = productList.find((n) => n.id === id);
@@ -461,7 +504,7 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
461
504
  item.isDisabledForProductUsed = false;
462
505
  }
463
506
  });
464
- (_a = this.store.discount) == null ? void 0 : _a.setDiscountList(newDiscountList);
507
+ (_b = this.store.discount) == null ? void 0 : _b.setDiscountList(newDiscountList);
465
508
  this.emitDiscountListChange(newDiscountList);
466
509
  return newDiscountList;
467
510
  }
@@ -478,7 +521,9 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
478
521
  });
479
522
  if (result == null ? void 0 : result.data) {
480
523
  const { ...customer } = result.data;
481
- this.setCustomer(customer);
524
+ const customerUpdate = this.setCustomer(customer);
525
+ if (this.entitlementPassEnabled)
526
+ await customerUpdate;
482
527
  await this.core.effects.emit(
483
528
  `${this.name}:onScanCustomerChange`,
484
529
  customer
@@ -507,8 +552,9 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
507
552
  }
508
553
  // 加载准备配置
509
554
  async loadPrepareConfig(params) {
510
- var _a, _b, _c, _d, _e;
555
+ var _a, _b, _c, _d, _e, _f;
511
556
  try {
557
+ const entitlementPassEnabled = this.entitlementPassEnabled;
512
558
  const orderId = this.store.orderId;
513
559
  const customerId = params.customerId || ((_a = this.getCustomer()) == null ? void 0 : _a.id);
514
560
  const goodPassList = await ((_b = this.store.discount) == null ? void 0 : _b.loadPrepareConfig({
@@ -517,21 +563,25 @@ var ShopDiscountImpl = class extends import_BaseModule.BaseModule {
517
563
  with_good_pass: 1,
518
564
  with_discount_card: 1,
519
565
  with_wallet_pass_holder: 1,
566
+ ...this.entitlementPassEnabled ? { with_entitlement_pass: 1, filter_order_wallet_pass_usage: 0 } : {},
520
567
  request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
521
568
  ...orderId ? { order_id: orderId } : {}
522
569
  }));
523
- const scanDiscount = (_c = this.getDiscountList()) == null ? void 0 : _c.filter(
524
- (item) => item.isScan
570
+ if (entitlementPassEnabled !== this.entitlementPassEnabled)
571
+ return;
572
+ if (entitlementPassEnabled && (String(customerId) !== String((_c = this.getCustomer()) == null ? void 0 : _c.id) || String(orderId) !== String(this.store.orderId)))
573
+ return;
574
+ const newDiscountList = (0, import_entitlementState.mergeEntitlementDiscountLists)(
575
+ this.getDiscountList(),
576
+ goodPassList || [],
577
+ (_d = this.store.discount) == null ? void 0 : _d.getOriginalDiscountList()
525
578
  );
526
- const scanDiscountIds = scanDiscount.map((n) => n.id);
527
- const newGoodPassList = goodPassList == null ? void 0 : goodPassList.filter((n) => !scanDiscountIds.includes(n.id));
528
- const newDiscountList = [...scanDiscount, ...newGoodPassList || []];
529
579
  this.store.originalDiscountList = newDiscountList;
530
- await ((_d = this.store.discount) == null ? void 0 : _d.setOriginalDiscountList(newDiscountList));
531
- const filteredDiscountList = this.filterDiscountListByBookingTime(newDiscountList, this.store.currentBookingTime);
580
+ await ((_e = this.store.discount) == null ? void 0 : _e.setOriginalDiscountList(newDiscountList));
581
+ const filteredDiscountList = newDiscountList.filter((item) => (0, import_entitlementPass.isEntitlementPass)(item) || this.filterDiscountListByBookingTime([item], this.store.currentBookingTime).length > 0);
532
582
  this.store.filteredDiscountList = filteredDiscountList;
533
583
  this.setDiscountList(filteredDiscountList || []);
534
- if ((_e = this.store.productList) == null ? void 0 : _e.length) {
584
+ if ((_f = this.store.productList) == null ? void 0 : _f.length) {
535
585
  const result = this.calcDiscount(this.store.productList);
536
586
  await this.core.effects.emit(
537
587
  `${this.name}:onLoadPrepareCalcResult`,
@@ -89,3 +89,4 @@ export declare const calculateOrderLevelDiscountAllocation: (discount: Discount,
89
89
  discountAmount: number;
90
90
  difference: number;
91
91
  }>;
92
+ export declare const getDiscountTimeUnavailableReason: (discount: Discount, useTime: string) => 'not_started' | 'time_limit' | 'outside_schedule' | undefined;
@@ -35,6 +35,7 @@ __export(utils_exports, {
35
35
  getDiscountAmount: () => getDiscountAmount,
36
36
  getDiscountListAmount: () => getDiscountListAmount,
37
37
  getDiscountListAmountTotal: () => getDiscountListAmountTotal,
38
+ getDiscountTimeUnavailableReason: () => getDiscountTimeUnavailableReason,
38
39
  isAllNormalProduct: () => isAllNormalProduct,
39
40
  isNormalProductByDurationSchedule: () => isNormalProductByDurationSchedule,
40
41
  isOrderLevelFixedAmountDiscount: () => isOrderLevelFixedAmountDiscount,
@@ -43,6 +44,11 @@ __export(utils_exports, {
43
44
  module.exports = __toCommonJS(utils_exports);
44
45
  var import_decimal = __toESM(require("decimal.js"));
45
46
  var import_dayjs = __toESM(require("dayjs"));
47
+ var import_isSameOrAfter = __toESM(require("dayjs/plugin/isSameOrAfter"));
48
+ var import_isSameOrBefore = __toESM(require("dayjs/plugin/isSameOrBefore"));
49
+ var import_entitlementPass = require("../../modules/Discount/entitlementPass");
50
+ import_dayjs.default.extend(import_isSameOrAfter.default);
51
+ import_dayjs.default.extend(import_isSameOrBefore.default);
46
52
  var uniqueById = (arr, key = "id") => {
47
53
  const seen = /* @__PURE__ */ new Set();
48
54
  return arr.filter((item) => !seen.has(item[key]) && seen.add(item[key]));
@@ -56,7 +62,7 @@ var isAllNormalProduct = (items) => {
56
62
  };
57
63
  var getDiscountAmount = (discount, total, price) => {
58
64
  var _a;
59
- if (discount.tag === "good_pass") {
65
+ if ((0, import_entitlementPass.isFullCoveragePass)(discount)) {
60
66
  return new import_decimal.default(price).minus(new import_decimal.default(price || 0)).toNumber();
61
67
  }
62
68
  const isFixedAmount = ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.discount_card_type) === "fixed_amount";
@@ -293,6 +299,8 @@ var filterDiscountListByBookingTime = (discountList, bookingTime) => {
293
299
  }
294
300
  return discountList.filter((discount) => {
295
301
  var _a, _b;
302
+ if ((0, import_entitlementPass.isEntitlementPass)(discount))
303
+ return !getDiscountTimeUnavailableReason(discount, bookingTime);
296
304
  if (((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.validity_type) === "custom_schedule_validity") {
297
305
  return getDateIsInSchedule(bookingTime, ((_b = discount.custom_schedule_snapshot) == null ? void 0 : _b.data) || []);
298
306
  }
@@ -391,6 +399,38 @@ var calculateOrderLevelDiscountAllocation = (discount, applicableProducts) => {
391
399
  }
392
400
  return result;
393
401
  };
402
+ var getDiscountTimeUnavailableReason = (discount, useTime) => {
403
+ var _a, _b, _c, _d, _e;
404
+ const useTimeDayjs = (0, import_dayjs.default)(useTime);
405
+ if (!useTimeDayjs.isValid())
406
+ return "time_limit";
407
+ try {
408
+ if (((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.validity_type) === "custom_schedule_validity") {
409
+ return getDateIsInSchedule(useTime, ((_b = discount.custom_schedule_snapshot) == null ? void 0 : _b.data) || []) ? void 0 : "outside_schedule";
410
+ }
411
+ const isHasStart = !!discount.start_date && !!discount.start_time;
412
+ const startDate = (0, import_dayjs.default)(`${discount.start_date} ${discount.start_time}`);
413
+ if (isHasStart) {
414
+ if (!startDate.isValid())
415
+ return "time_limit";
416
+ if (useTimeDayjs.isBefore(startDate))
417
+ return "not_started";
418
+ }
419
+ const expireTime = discount.expire_time ? (0, import_dayjs.default)(discount.expire_time) : null;
420
+ const isBeforeExpire = expireTime ? expireTime.isValid() && useTimeDayjs.isBefore(expireTime) : true;
421
+ if (!isBeforeExpire)
422
+ return "time_limit";
423
+ const validity = (_d = (_c = discount.extension_data) == null ? void 0 : _c.find(
424
+ (field) => field.field_key === "valid_times"
425
+ )) == null ? void 0 : _d.value;
426
+ if ((validity == null ? void 0 : validity.restrict_use_by_schedule) === true && !getDateIsInSchedule(useTime, ((_e = discount.custom_schedule_snapshot) == null ? void 0 : _e.data) || [])) {
427
+ return "outside_schedule";
428
+ }
429
+ return void 0;
430
+ } catch (error) {
431
+ return "time_limit";
432
+ }
433
+ };
394
434
  // Annotate the CommonJS export names for ESM import in node:
395
435
  0 && (module.exports = {
396
436
  calculateOrderLevelDiscountAllocation,
@@ -399,6 +439,7 @@ var calculateOrderLevelDiscountAllocation = (discount, applicableProducts) => {
399
439
  getDiscountAmount,
400
440
  getDiscountListAmount,
401
441
  getDiscountListAmountTotal,
442
+ getDiscountTimeUnavailableReason,
402
443
  isAllNormalProduct,
403
444
  isNormalProductByDurationSchedule,
404
445
  isOrderLevelFixedAmountDiscount,
@@ -7,6 +7,7 @@ import type { OpenDataAvailabilityResult } from '../../modules/OpenData';
7
7
  import type { ProductData } from '../../modules/Product/types';
8
8
  import { type CartItemSummary, type PaxInfo, type QuantityCheckResult, type QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
9
9
  import type { StrategyConfig } from '../../model/strategy/type';
10
+ import type { IAppendFormRecordParams, IRefreshAllFormRecordsParams } from '../../modules/Holder/types';
10
11
  export * from './types';
11
12
  interface VenueBookingItemRuleRuntimeConfig {
12
13
  strategyConfigs?: StrategyConfig[];
@@ -52,6 +53,12 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
52
53
  constructor(name?: string, version?: string);
53
54
  private normalizeCustomerId;
54
55
  private resolveCustomerIdFromLoginPayload;
56
+ private resolveHolderCustomerId;
57
+ /**
58
+ * 按商品 holder_config 预加载表单数据到 holderMap。
59
+ * appointment_booking 在加购时触发;venueBooking 在商品加载后预加载,避免 getHolderFormMap 为空。
60
+ */
61
+ private preloadHolderForms;
55
62
  private clearLoginEffectListeners;
56
63
  private registerLoginEffect;
57
64
  private registerCustomerLoginListeners;
@@ -199,6 +206,18 @@ export declare class VenueBookingImpl extends BaseModule implements Module {
199
206
  getUIState<T = any>(key: string): T | undefined;
200
207
  deleteUIState(key: string): void;
201
208
  setBookingHolder(bookingUid: string, holder: any): void;
209
+ /**
210
+ * 获取 holder 表单 map
211
+ */
212
+ getHolderFormMap(): import("../../modules/Holder").HolderFormMap;
213
+ /**
214
+ * UI 层触发:按当前 holderMap 批量刷新所有表单的 records
215
+ */
216
+ refreshAllHolderFormRecords(params?: Pick<IRefreshAllFormRecordsParams, 'customer_id' | 'useCache' | 'recordsUrl' | 'num' | 'skip'>): Promise<import("../../modules/Holder").HolderFormMap>;
217
+ /**
218
+ * 添加表单记录
219
+ */
220
+ appendFormRecord(params: IAppendFormRecordParams): import("../../modules/Holder").IFormRecord;
202
221
  checkOpenDataAvailability(): Promise<OpenDataAvailabilityResult>;
203
222
  setOtherParams(params: Record<string, any>, { cover }?: {
204
223
  cover?: boolean;