@pisell/pisellos 0.0.571 → 0.0.572

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 (143) hide show
  1. package/dist/effects/index.d.ts +2 -2
  2. package/dist/model/strategy/adapter/dataVariant/type.d.ts +3 -3
  3. package/dist/model/strategy/adapter/itemRule/type.d.ts +6 -6
  4. package/dist/model/strategy/adapter/promotion/index.d.ts +4 -0
  5. package/dist/model/strategy/adapter/promotion/type.d.ts +5 -5
  6. package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  7. package/dist/model/strategy/adapter/walletPass/evaluator.js +4 -2
  8. package/dist/model/strategy/type.d.ts +1 -1
  9. package/dist/modules/BookingContext/types.d.ts +4 -4
  10. package/dist/modules/BookingContext/utils/resourceErrors.d.ts +1 -1
  11. package/dist/modules/Customer/types.d.ts +1 -1
  12. package/dist/modules/Discount/availability.d.ts +7 -0
  13. package/dist/modules/Discount/availability.js +52 -0
  14. package/dist/modules/Discount/entitlementPass.d.ts +34 -0
  15. package/dist/modules/Discount/entitlementPass.js +147 -0
  16. package/dist/modules/Discount/entitlementState.d.ts +8 -0
  17. package/dist/modules/Discount/entitlementState.js +205 -0
  18. package/dist/modules/Discount/index.d.ts +5 -2
  19. package/dist/modules/Discount/index.js +124 -25
  20. package/dist/modules/Discount/types.d.ts +29 -6
  21. package/dist/modules/Holder/types.d.ts +1 -1
  22. package/dist/modules/OpenData/types.d.ts +1 -1
  23. package/dist/modules/Order/types.d.ts +5 -5
  24. package/dist/modules/Order/utils/bundleDiscountHydration.d.ts +1 -1
  25. package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +1 -1
  26. package/dist/modules/Order/utils.d.ts +1 -1
  27. package/dist/modules/Payment/types.d.ts +7 -7
  28. package/dist/modules/Product/index.d.ts +1 -1
  29. package/dist/modules/ResourcePlanner/types.d.ts +4 -4
  30. package/dist/modules/Rules/entitlementLines.d.ts +8 -0
  31. package/dist/modules/Rules/entitlementLines.js +159 -0
  32. package/dist/modules/Rules/index.d.ts +13 -3
  33. package/dist/modules/Rules/index.js +617 -342
  34. package/dist/modules/Rules/types.d.ts +4 -4
  35. package/dist/modules/ScanOrderLogger/types.d.ts +2 -2
  36. package/dist/modules/Schedule/getDateIsInSchedule.d.ts +1 -1
  37. package/dist/modules/Schedule/type.d.ts +7 -7
  38. package/dist/modules/Schedule/types.d.ts +9 -9
  39. package/dist/plugins/app.d.ts +1 -1
  40. package/dist/plugins/request.d.ts +2 -2
  41. package/dist/plugins/window.d.ts +2 -2
  42. package/dist/server/modules/floor-plan/types.d.ts +1 -1
  43. package/dist/server/modules/menu/types.d.ts +1 -1
  44. package/dist/server/modules/order/types.d.ts +16 -16
  45. package/dist/server/modules/products/types.d.ts +1 -1
  46. package/dist/server/modules/resource/types.d.ts +1 -1
  47. package/dist/server/modules/schedule/utils.d.ts +1 -1
  48. package/dist/server/types.d.ts +4 -4
  49. package/dist/server/utils/small-ticket.d.ts +1 -1
  50. package/dist/solution/BaseSales/index.d.ts +1 -1
  51. package/dist/solution/BaseSales/types.d.ts +7 -7
  52. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -1
  53. package/dist/solution/BookingByStep/index.d.ts +1 -1
  54. package/dist/solution/BookingByStep/utils/resources.d.ts +1 -1
  55. package/dist/solution/BookingTicket/index.d.ts +13 -1
  56. package/dist/solution/BookingTicket/types.d.ts +3 -3
  57. package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +1 -1
  58. package/dist/solution/BookingTicket/utils/bookingStatus.d.ts +1 -1
  59. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +1 -1
  60. package/dist/solution/Sales/types.d.ts +4 -4
  61. package/dist/solution/ScanOrder/types.d.ts +5 -5
  62. package/dist/solution/ShopDiscount/index.d.ts +3 -0
  63. package/dist/solution/ShopDiscount/index.js +161 -78
  64. package/dist/solution/ShopDiscount/types.d.ts +1 -1
  65. package/dist/solution/ShopDiscount/utils.d.ts +3 -2
  66. package/dist/solution/ShopDiscount/utils.js +40 -1
  67. package/dist/solution/UnifiedBookingSales/types.d.ts +1 -1
  68. package/dist/solution/VenueBooking/types.d.ts +1 -1
  69. package/dist/types/index.d.ts +1 -1
  70. package/dist/utils/task.d.ts +2 -2
  71. package/dist/utils/watch.d.ts +2 -2
  72. package/lib/effects/index.d.ts +2 -2
  73. package/lib/model/strategy/adapter/dataVariant/type.d.ts +3 -3
  74. package/lib/model/strategy/adapter/itemRule/type.d.ts +6 -6
  75. package/lib/model/strategy/adapter/promotion/index.d.ts +4 -0
  76. package/lib/model/strategy/adapter/promotion/type.d.ts +5 -5
  77. package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  78. package/lib/model/strategy/adapter/walletPass/evaluator.js +2 -0
  79. package/lib/model/strategy/type.d.ts +1 -1
  80. package/lib/modules/BookingContext/types.d.ts +4 -4
  81. package/lib/modules/BookingContext/utils/resourceErrors.d.ts +1 -1
  82. package/lib/modules/Customer/types.d.ts +1 -1
  83. package/lib/modules/Discount/availability.d.ts +7 -0
  84. package/lib/modules/Discount/availability.js +46 -0
  85. package/lib/modules/Discount/entitlementPass.d.ts +34 -0
  86. package/lib/modules/Discount/entitlementPass.js +141 -0
  87. package/lib/modules/Discount/entitlementState.d.ts +8 -0
  88. package/lib/modules/Discount/entitlementState.js +150 -0
  89. package/lib/modules/Discount/index.d.ts +5 -2
  90. package/lib/modules/Discount/index.js +59 -14
  91. package/lib/modules/Discount/types.d.ts +29 -6
  92. package/lib/modules/Holder/types.d.ts +1 -1
  93. package/lib/modules/OpenData/types.d.ts +1 -1
  94. package/lib/modules/Order/types.d.ts +5 -5
  95. package/lib/modules/Order/utils/bundleDiscountHydration.d.ts +1 -1
  96. package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +1 -1
  97. package/lib/modules/Order/utils.d.ts +1 -1
  98. package/lib/modules/Payment/types.d.ts +7 -7
  99. package/lib/modules/Product/index.d.ts +1 -1
  100. package/lib/modules/ResourcePlanner/types.d.ts +4 -4
  101. package/lib/modules/Rules/entitlementLines.d.ts +8 -0
  102. package/lib/modules/Rules/entitlementLines.js +128 -0
  103. package/lib/modules/Rules/index.d.ts +13 -3
  104. package/lib/modules/Rules/index.js +284 -61
  105. package/lib/modules/Rules/types.d.ts +4 -4
  106. package/lib/modules/ScanOrderLogger/types.d.ts +2 -2
  107. package/lib/modules/Schedule/getDateIsInSchedule.d.ts +1 -1
  108. package/lib/modules/Schedule/type.d.ts +7 -7
  109. package/lib/modules/Schedule/types.d.ts +9 -9
  110. package/lib/plugins/app.d.ts +1 -1
  111. package/lib/plugins/request.d.ts +2 -2
  112. package/lib/plugins/window.d.ts +2 -2
  113. package/lib/server/modules/floor-plan/types.d.ts +1 -1
  114. package/lib/server/modules/menu/types.d.ts +1 -1
  115. package/lib/server/modules/order/types.d.ts +16 -16
  116. package/lib/server/modules/products/types.d.ts +1 -1
  117. package/lib/server/modules/resource/types.d.ts +1 -1
  118. package/lib/server/modules/schedule/utils.d.ts +1 -1
  119. package/lib/server/types.d.ts +4 -4
  120. package/lib/server/utils/small-ticket.d.ts +1 -1
  121. package/lib/solution/BaseSales/index.d.ts +1 -1
  122. package/lib/solution/BaseSales/types.d.ts +7 -7
  123. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -1
  124. package/lib/solution/BookingByStep/index.d.ts +1 -1
  125. package/lib/solution/BookingByStep/utils/resources.d.ts +1 -1
  126. package/lib/solution/BookingTicket/index.d.ts +13 -1
  127. package/lib/solution/BookingTicket/types.d.ts +3 -3
  128. package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +1 -1
  129. package/lib/solution/BookingTicket/utils/bookingStatus.d.ts +1 -1
  130. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +1 -1
  131. package/lib/solution/Sales/types.d.ts +4 -4
  132. package/lib/solution/ScanOrder/types.d.ts +5 -5
  133. package/lib/solution/ShopDiscount/index.d.ts +3 -0
  134. package/lib/solution/ShopDiscount/index.js +55 -18
  135. package/lib/solution/ShopDiscount/types.d.ts +1 -1
  136. package/lib/solution/ShopDiscount/utils.d.ts +3 -2
  137. package/lib/solution/ShopDiscount/utils.js +39 -3
  138. package/lib/solution/UnifiedBookingSales/types.d.ts +1 -1
  139. package/lib/solution/VenueBooking/types.d.ts +1 -1
  140. package/lib/types/index.d.ts +1 -1
  141. package/lib/utils/task.d.ts +2 -2
  142. package/lib/utils/watch.d.ts +2 -2
  143. package/package.json +19 -18
@@ -8,6 +8,8 @@ var _utils = require("../../solution/ShopDiscount/utils");
8
8
  var _BaseModule = require("../BaseModule");
9
9
  var _types = require("./types");
10
10
  var _decimal = _interopRequireDefault(require("decimal.js"));
11
+ var _entitlementPass = require("./entitlementPass");
12
+ var _availability = require("./availability");
11
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
14
  class DiscountModule extends _BaseModule.BaseModule {
13
15
  defaultName = 'discount';
@@ -82,10 +84,13 @@ class DiscountModule extends _BaseModule.BaseModule {
82
84
  with_available_wallet_flag: params.with_available_wallet_flag ?? 1,
83
85
  with_available_wallet_pass_flag: params.with_available_wallet_pass_flag ?? 1
84
86
  });
85
- const rawDiscountList = [...(prepareConfig?.data?.good_pass_list || []), ...(prepareConfig?.data?.discount_card_list || [])];
87
+ const entitlementPassList = params.with_entitlement_pass ? prepareConfig?.data?.entitlement_pass_list || [] : [];
88
+ const ids = new Set(entitlementPassList.map(item => String(item.id)));
89
+ const rawDiscountList = [...entitlementPassList, ...(prepareConfig?.data?.good_pass_list || []).filter(item => !ids.has(String(item.id))), ...(prepareConfig?.data?.discount_card_list || []).filter(item => !ids.has(String(item.id)))].filter(item => params.with_entitlement_pass || !(0, _entitlementPass.isEntitlementPass)(item));
86
90
  const availableWalletList = [...(prepareConfig?.data?.avaiable_wallet_list || []), ...(prepareConfig?.data?.available_wallet_list || [])];
87
91
  const availableWalletPassList = prepareConfig?.data?.available_wallet_pass_list || [];
88
92
  const availableWalletIds = this.normalizePositiveNumberIds([...availableWalletList.map(item => item?.wallet_id), ...availableWalletPassList.map(item => item?.product_id)]);
93
+ if (params.with_entitlement_pass) await this.setOriginalDiscountList(rawDiscountList);
89
94
  const goodPassList = this.filterEnabledDiscountList(rawDiscountList) || [];
90
95
 
91
96
  // this.setDiscountList(goodPassList);
@@ -102,16 +107,19 @@ class DiscountModule extends _BaseModule.BaseModule {
102
107
  const walletPassProductIds = availableWalletPassList.map(item => Number(item?.product_id)).filter(id => Number.isFinite(id) && id > 0);
103
108
  return Array.from(new Set([...walletIds, ...walletPassProductIds]));
104
109
  }
105
- async batchSearch(code, options) {
110
+ async batchSearch(code, customerIdOrOptions) {
106
111
  const {
107
112
  customerId,
108
- orderId
109
- } = options || {};
110
- const result = await this.request.get(`/machinecode/batch-search`, {
113
+ orderId,
114
+ withEntitlementPass
115
+ } = typeof customerIdOrOptions === 'number' ? {
116
+ customerId: customerIdOrOptions,
117
+ orderId: undefined,
118
+ withEntitlementPass: false
119
+ } : customerIdOrOptions || {};
120
+ const params = {
111
121
  code,
112
122
  translate_flag: 1,
113
- tags: ['good_pass', 'product_discount_card'],
114
- // available: 1,
115
123
  relation_product: 1,
116
124
  with: ['extensionData', 'customScheduleSnapshot', 'holder.detail'],
117
125
  order_behavior_count: 1,
@@ -121,9 +129,42 @@ class DiscountModule extends _BaseModule.BaseModule {
121
129
  order_behavior_count_order_id: orderId
122
130
  } : {}),
123
131
  request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
124
- });
125
- const resultDiscountWithReason = this.filterEnabledDiscountListWithReason(result?.data || []) || [];
126
- return resultDiscountWithReason;
132
+ };
133
+ if (!withEntitlementPass) {
134
+ const result = await this.request.get(`/machinecode/batch-search`, {
135
+ ...params,
136
+ tags: ['good_pass', 'product_discount_card']
137
+ });
138
+ return this.filterEnabledDiscountListWithReason((result?.data || []).filter(item => !(0, _entitlementPass.isEntitlementPass)(item)));
139
+ }
140
+ // 保留 develop 的旧券查询参数,多次卡单独查询并携带跨店状态。
141
+ const search = query => this.request.get(`/machinecode/batch-search`, query).then(value => ({
142
+ status: 'fulfilled',
143
+ value
144
+ }), reason => ({
145
+ status: 'rejected',
146
+ reason
147
+ }));
148
+ const [legacy, entitlement] = await Promise.all([search({
149
+ ...params,
150
+ tags: ['good_pass', 'product_discount_card']
151
+ }), search({
152
+ ...params,
153
+ tags: ['entitlement_pass'],
154
+ with_franchisor_data: 1,
155
+ unified_status_info_flag: 1,
156
+ with: [...params.with, 'franchiseeWalletPass:shop_id,source_shop_id,product_id,use']
157
+ })]);
158
+ const entitlementList = (entitlement.status === 'fulfilled' ? entitlement.value?.data || [] : []).filter(_entitlementPass.isEntitlementPass);
159
+ const legacyList = legacy.status === 'fulfilled' ? legacy.value?.data || [] : [];
160
+ const ids = new Set(entitlementList.map(item => String(item.id)));
161
+ const result = this.filterEnabledDiscountListWithReason([...entitlementList, ...legacyList.filter(item => !(0, _entitlementPass.isEntitlementPass)(item) && !ids.has(String(item.id)))]);
162
+ // 任一类型查到可用卡即可继续,另一类型的查询失败不阻断该卡。
163
+ if (!result.discountList.length) {
164
+ if (legacy.status === 'rejected') throw legacy.reason;
165
+ if (entitlement.status === 'rejected') throw entitlement.reason;
166
+ }
167
+ return result;
127
168
  }
128
169
  async batchSearchByProductIds(productIds) {
129
170
  const result = await this.request.get(`/machinecode/batch-search`, {
@@ -135,7 +176,7 @@ class DiscountModule extends _BaseModule.BaseModule {
135
176
  return result?.data || [];
136
177
  }
137
178
  filterEnabledDiscountList(discountList) {
138
- return discountList.filter(discount => discount.limit_status === 'enable' && new _decimal.default(discount?.par_value || 0).minus(new _decimal.default(discount?.used_par_value || 0)).greaterThan(0) && this.checkUsageCreditsLimit(discount));
179
+ return discountList.filter(discount => (0, _entitlementPass.isEntitlementPass)(discount) ? !(0, _availability.getDiscountLifecycleReason)(discount) : discount.limit_status === 'enable' && new _decimal.default(discount?.par_value || 0).minus(new _decimal.default(discount?.used_par_value || 0)).greaterThan(0) && this.checkUsageCreditsLimit(discount));
139
180
  }
140
181
 
141
182
  // 检查使用次数限制
@@ -195,7 +236,8 @@ class DiscountModule extends _BaseModule.BaseModule {
195
236
 
196
237
  // 过滤启用且可用的优惠券,并返回校验失败原因
197
238
  filterEnabledDiscountListWithReason(discountList) {
198
- let lists = discountList.filter(discount => discount.limit_status === 'enable').filter(discount => {
239
+ const entitlementPasses = discountList.filter(item => (0, _entitlementPass.isEntitlementPass)(item) && !(0, _availability.getDiscountLifecycleReason)(item));
240
+ let lists = discountList.filter(item => !(0, _entitlementPass.isEntitlementPass)(item)).filter(discount => discount.limit_status === 'enable').filter(discount => {
199
241
  const remaining = new _decimal.default(discount?.par_value || 0).minus(new _decimal.default(discount?.used_par_value || 0)).greaterThan(0);
200
242
  return remaining;
201
243
  }).map(discount => {
@@ -211,8 +253,11 @@ class DiscountModule extends _BaseModule.BaseModule {
211
253
  // 不可用数据
212
254
  const currentFailDiscount = lists.find(item => item.usageLimitFailKey);
213
255
  return {
214
- discountList: availableLists,
215
- unavailableReasonKey: currentFailDiscount?.usageLimitFailKey
256
+ discountList: [...entitlementPasses.map(item => ({
257
+ ...item,
258
+ usageLimitFailKey: (0, _availability.getDiscountUsageLimitFailKey)(item)
259
+ })), ...availableLists],
260
+ unavailableReasonKey: currentFailDiscount?.usageLimitFailKey || discountList.filter(_entitlementPass.isEntitlementPass).map(_availability.getDiscountLifecycleReason).find(Boolean) || null
216
261
  };
217
262
  }
218
263
 
@@ -45,6 +45,8 @@ interface ApplicableProductDetails {
45
45
  num: number;
46
46
  metadata?: {
47
47
  product_discount_difference?: number;
48
+ num?: number;
49
+ custom_product_bundle_map_id?: string;
48
50
  };
49
51
  discount?: {
50
52
  fixed_amount?: number;
@@ -63,10 +65,17 @@ interface UsageCreditsValue {
63
65
  max_per_week: number;
64
66
  max_per_month: number;
65
67
  }
66
- export declare type DiscountFilterRejectKey = 'total_credits' | 'per_user_limit' | 'max_per_day' | 'max_per_week' | 'max_per_month';
68
+ export type IncludedUses = {
69
+ type: 'limited';
70
+ value: number;
71
+ } | {
72
+ type: 'unlimited';
73
+ value: null;
74
+ };
75
+ export type DiscountFilterRejectKey = 'total_credits' | 'per_user_limit' | 'max_per_day' | 'max_per_week' | 'max_per_month';
67
76
  export interface DiscountWithReason {
68
77
  discountList: Discount[];
69
- unavailableReasonKey: DiscountFilterRejectKey | null;
78
+ unavailableReasonKey: DiscountFilterRejectKey | string | null;
70
79
  }
71
80
  export interface DiscountPrepareConfigResult {
72
81
  discountList: Discount[];
@@ -97,20 +106,34 @@ export interface Discount {
97
106
  used_par_value: string;
98
107
  limit_status: string;
99
108
  limited_relation_product_data: Limitedrelationproductdata;
100
- balance: string;
109
+ balance?: string | number | null;
101
110
  format_title: Formattitle;
102
111
  metadata?: {
103
112
  num?: number;
104
113
  discount_card_type?: 'fixed_amount' | 'percent';
105
114
  custom_product_bundle_map_id?: string;
106
115
  validity_type?: "custom_schedule_validity" | "fixed_validity";
107
- discount_calculation_mode: 'item_level' | 'order_level';
108
- holder: {
116
+ included_uses?: IncludedUses;
117
+ discount_calculation_mode?: 'item_level' | 'order_level';
118
+ holder?: {
109
119
  type: "customer" | "custom";
110
120
  };
111
121
  };
112
122
  product: Product;
113
- type: "product" | 'good_pass';
123
+ type: 'product' | 'good_pass' | 'entitlement_pass' | 'discount_card' | 'product_discount_card';
124
+ shop_id?: number;
125
+ holder?: {
126
+ holder_type?: string;
127
+ holder_id?: number | string | Array<number | string>;
128
+ [key: string]: any;
129
+ };
130
+ reason?: string;
131
+ reasonCode?: string;
132
+ is_franchisor_pass?: number;
133
+ franchisee_wallet_pass?: {
134
+ use?: string;
135
+ };
136
+ committedAppliedProductDetails?: ApplicableProductDetails[];
114
137
  resource_id?: number;
115
138
  savedAmount?: number;
116
139
  isEditMode?: boolean;
@@ -39,7 +39,7 @@ export interface IFormItemData {
39
39
  /**
40
40
  * form_id 为 key 的 map 结构,如 948: { records: [], form: {} }
41
41
  */
42
- export declare type HolderFormMap = Record<string, IFormItemData>;
42
+ export type HolderFormMap = Record<string, IFormItemData>;
43
43
  /**
44
44
  * Holder 模块 reactive store,仅 holderMap 会触发 changed 事件
45
45
  */
@@ -61,7 +61,7 @@ export interface OpenDataApiResponse {
61
61
  message: string;
62
62
  data: OpenDataConfig;
63
63
  }
64
- export declare type OpenDataUnavailableReason = 'shop_disabled' | 'paused' | 'closed' | 'reservation_disabled';
64
+ export type OpenDataUnavailableReason = 'shop_disabled' | 'paused' | 'closed' | 'reservation_disabled';
65
65
  export interface OpenDataAvailabilityResult {
66
66
  available: boolean;
67
67
  reason: OpenDataUnavailableReason | null;
@@ -69,7 +69,7 @@ export interface OrderGiftSelectResult {
69
69
  *
70
70
  * 返回数组时沿用旧协议,只写 tempOrder.products;返回对象时可同时写入预约 bookings。
71
71
  */
72
- export declare type OrderGiftSelectResolver = (ctx: OrderGiftSelectContext) => Promise<Partial<OrderProduct>[] | OrderGiftSelectResult | null>;
72
+ export type OrderGiftSelectResolver = (ctx: OrderGiftSelectContext) => Promise<Partial<OrderProduct>[] | OrderGiftSelectResult | null>;
73
73
  /** 未满足的促销策略(购物车底部 alert 渲染源) */
74
74
  export interface OrderUnfulfilledPromotion {
75
75
  strategyId: string;
@@ -318,7 +318,7 @@ export interface ReplaceTempOrderOptions {
318
318
  persist?: boolean;
319
319
  saveDraft?: boolean;
320
320
  }
321
- export declare type AddProductBookingInput = Record<string, any>;
321
+ export type AddProductBookingInput = Record<string, any>;
322
322
  /** 更新购物车行:仅传 SKU 时命中同 SKU 第一行;多行同 SKU 须传 unique_identification_number / 选项指纹等 */
323
323
  export interface UpdateOrderProductParams {
324
324
  product_id: number | null;
@@ -376,7 +376,7 @@ export interface OrderProductMergeDecisionContext {
376
376
  booking?: AddProductBookingInput;
377
377
  defaultShouldMerge: boolean;
378
378
  }
379
- export declare type OrderProductMergeDecisionResult = boolean | {
379
+ export type OrderProductMergeDecisionResult = boolean | {
380
380
  shouldMerge: boolean;
381
381
  reason?: string;
382
382
  [key: string]: any;
@@ -524,11 +524,11 @@ export interface OrderPaymentData {
524
524
  created_at?: string;
525
525
  updated_at?: string;
526
526
  }
527
- export declare type OrderPaymentSource = PaymentItem | OrderPaymentData | Record<string, any>;
527
+ export type OrderPaymentSource = PaymentItem | OrderPaymentData | Record<string, any>;
528
528
  export interface MapOrderPaymentsOptions {
529
529
  includeVoided?: boolean;
530
530
  }
531
- export declare type OrderSyncState = 'local' | 'submitting' | 'submitted' | 'failed' | 'remoteLoaded';
531
+ export type OrderSyncState = 'local' | 'submitting' | 'submitted' | 'failed' | 'remoteLoaded';
532
532
  export interface LoadSalesDetailParams {
533
533
  orderId?: number | string;
534
534
  orderNumber?: string;
@@ -1,5 +1,5 @@
1
1
  import type { OrderProductDiscountItem } from '../types';
2
- declare type NormalizeDiscountList = (discountList?: unknown[] | null) => OrderProductDiscountItem[];
2
+ type NormalizeDiscountList = (discountList?: unknown[] | null) => OrderProductDiscountItem[];
3
3
  export declare function restoreHydratedBundleDiscounts<T extends Record<string, any>>(product: T, normalizeDiscountList: NormalizeDiscountList): T;
4
4
  export declare function expandHydratedProductsForDiscountCollection(products: any[] | undefined | null): any[];
5
5
  export {};
@@ -1,4 +1,4 @@
1
- export declare type OrderCollectionKind = 'product' | 'booking' | 'payment';
1
+ export type OrderCollectionKind = 'product' | 'booking' | 'payment';
2
2
  export interface OrderCollectionIdentityStats {
3
3
  backfilledUidCount: number;
4
4
  collapsedDuplicateCount: number;
@@ -209,7 +209,7 @@ export interface SubmitPayloadEnhancerContext {
209
209
  bookingUuid: string;
210
210
  now: Date;
211
211
  }
212
- export declare type SubmitPayloadEnhancer = (payload: OrderSubmitPayload, ctx: SubmitPayloadEnhancerContext) => OrderSubmitPayload;
212
+ export type SubmitPayloadEnhancer = (payload: OrderSubmitPayload, ctx: SubmitPayloadEnhancerContext) => OrderSubmitPayload;
213
213
  export declare function buildSubmitPayload(params: {
214
214
  tempOrder: OrderTempOrder;
215
215
  cacheId?: string;
@@ -629,12 +629,12 @@ export declare enum PaymentHooks {
629
629
  OnOrderAmountChanged = "payment:onOrderAmountChanged",
630
630
  OnPaymentSyncError = "payment:onPaymentSyncError",
631
631
  OnPaymentSyncSuccess = "payment:onPaymentSyncSuccess",
632
- OnWalletRecommendListUpdated = 0,
633
- OnWalletRecommendListCleared = 0,
634
- OnUserIdentificationCodesUpdated = 0,
635
- OnUserIdentificationCodesCleared = 0,
636
- OnWalletCacheCleared = 0,
637
- OnSearchIdentificationCodeCompleted = 0
632
+ OnWalletRecommendListUpdated = "wallet:onWalletRecommendListUpdated",
633
+ OnWalletRecommendListCleared = "wallet:onWalletRecommendListCleared",
634
+ OnUserIdentificationCodesUpdated = "wallet:onUserIdentificationCodesUpdated",
635
+ OnUserIdentificationCodesCleared = "wallet:onUserIdentificationCodesCleared",
636
+ OnWalletCacheCleared = "wallet:onWalletCacheCleared",
637
+ OnSearchIdentificationCodeCompleted = "wallet:onSearchIdentificationCodeCompleted"
638
638
  }
639
639
  /**
640
640
  * 钱包推荐扣款请求参数
@@ -797,7 +797,7 @@ export interface SearchIdentificationCodeResponse {
797
797
  /**
798
798
  * 搜索识别码结果类型
799
799
  */
800
- export declare type SearchIdentificationCodeResult = {
800
+ export type SearchIdentificationCodeResult = {
801
801
  type: 'walletCode';
802
802
  data: SearchIdentificationCodeItem[];
803
803
  } | {
@@ -49,5 +49,5 @@ export declare class Product extends BaseModule implements Module {
49
49
  getCategories(): ProductCategory[];
50
50
  setOtherParams(key: string, value: any): void;
51
51
  getOtherParams(): any;
52
- getProductType(): "duration" | "session" | "normal";
52
+ getProductType(): "normal" | "duration" | "session";
53
53
  }
@@ -1,7 +1,7 @@
1
- export declare type ResourcePlannerMode = 'appointment' | 'scan_order' | 'venue_grid';
2
- export declare type ResourcePlannerProductKind = 'normal' | 'duration' | 'session' | 'venue_slot';
3
- export declare type ResourcePlannerResourceType = 'single' | 'multiple' | 'capacity';
4
- export declare type ResourcePlannerStatus = 'available' | 'limited' | 'full' | 'conflict' | 'unavailable' | 'past';
1
+ export type ResourcePlannerMode = 'appointment' | 'scan_order' | 'venue_grid';
2
+ export type ResourcePlannerProductKind = 'normal' | 'duration' | 'session' | 'venue_slot';
3
+ export type ResourcePlannerResourceType = 'single' | 'multiple' | 'capacity';
4
+ export type ResourcePlannerStatus = 'available' | 'limited' | 'full' | 'conflict' | 'unavailable' | 'past';
5
5
  export interface ResourcePlannerTimeRange {
6
6
  start_at: string;
7
7
  end_at: string;
@@ -0,0 +1,8 @@
1
+ import type { RulesParamsHooks } from './types';
2
+ export declare function isEntitlementRuntimeLine(product: any, mappedProduct?: any): boolean;
3
+ /** 仅同步本次多次卡行的数量与价格,沿用 Rules 的主商品、套餐计算结果。 */
4
+ export declare function rebuildEntitlementLine(origin: any, bundle: any[], hooks: RulesParamsHooks, count?: number): any;
5
+ /** 重算只还原本次多次卡;套餐和多 Holder 按父商品份数计算,不再合并商品行。 */
6
+ export declare function prepareEntitlementLines(products: any[], hooks: RulesParamsHooks, canUseEntitlement: (product: any) => boolean): any[];
7
+ /** 客户端钩子可能保留原 _id,只给新增的重复行补标识,保留拆分结果。 */
8
+ export declare function finalizeEntitlementLines(products: any[], hooks: RulesParamsHooks): any[];
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.finalizeEntitlementLines = finalizeEntitlementLines;
7
+ exports.isEntitlementRuntimeLine = isEntitlementRuntimeLine;
8
+ exports.prepareEntitlementLines = prepareEntitlementLines;
9
+ exports.rebuildEntitlementLine = rebuildEntitlementLine;
10
+ var _lodashEs = require("lodash-es");
11
+ var _decimal = _interopRequireDefault(require("decimal.js"));
12
+ var _entitlementPass = require("../Discount/entitlementPass");
13
+ var _entitlementState = require("../Discount/entitlementState");
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+ const SOURCE = 'entitlement_source_identity';
16
+ function isManualDiscount(data) {
17
+ return data.isManualDiscount ?? (data.total != data.origin_total && (data.bundle || []).every(item => !item.discount_list?.length) && (!data.discount_list?.length || data.discount_list.every(item => item.type === 'product')));
18
+ }
19
+ function isEntitlementRuntimeLine(product, mappedProduct) {
20
+ return product.metadata?.[SOURCE] != null && !(0, _entitlementState.isPersistedEntitlementLine)(product, mappedProduct) && !isManualDiscount(mappedProduct ?? product);
21
+ }
22
+
23
+ /** 仅同步本次多次卡行的数量与价格,沿用 Rules 的主商品、套餐计算结果。 */
24
+ function rebuildEntitlementLine(origin, bundle, hooks, count) {
25
+ const data = hooks.getProduct(origin);
26
+ const quantity = count ?? data.quantity ?? data.num ?? 1;
27
+ const discounts = (data.discount_list || []).map(item => (0, _entitlementPass.isEntitlementPass)(item) && !item.metadata?.custom_product_bundle_map_id ? {
28
+ ...item,
29
+ _num: quantity,
30
+ metadata: {
31
+ ...item.metadata,
32
+ num: quantity
33
+ }
34
+ } : item);
35
+ const mainDiscount = discounts.filter(item => !item.metadata?.custom_product_bundle_map_id).reduce((sum, item) => sum.plus(item.metadata?.mainProductDiscountAmount ?? item.amount ?? 0), new _decimal.default(0));
36
+ const originalPrice = new _decimal.default(data.original_price ?? data.price ?? 0);
37
+ const sourceSellingPrice = originalPrice.minus(mainDiscount).toNumber();
38
+ const optionPrice = (data.options || []).reduce((sum, item) => sum.plus(new _decimal.default(item.price ?? item.add_price ?? 0).times(item.num ?? item.quantity ?? 1)), new _decimal.default(0));
39
+ const bundleTotal = bundle.reduce((sum, item) => sum.plus(new _decimal.default(item.price || 0).times(item.num || 1)), new _decimal.default(0));
40
+ const bundleOriginalTotal = bundle.reduce((sum, item) => sum.plus(new _decimal.default(item.original_price ?? item.price ?? 0).times(item.num || 1)), new _decimal.default(0));
41
+ return hooks.setProduct(origin, {
42
+ quantity,
43
+ discount_list: discounts,
44
+ bundle,
45
+ price: sourceSellingPrice,
46
+ main_product_selling_price: sourceSellingPrice,
47
+ total: new _decimal.default(sourceSellingPrice).plus(optionPrice).plus(bundleTotal).toNumber(),
48
+ origin_total: originalPrice.plus(optionPrice).plus(bundleOriginalTotal).toNumber()
49
+ });
50
+ }
51
+ function setLineIdentity(row, id) {
52
+ row._id = id;
53
+ row.metadata = {
54
+ ...row.metadata,
55
+ unique_identification_number: id
56
+ };
57
+ if (row._extend) row._extend.unique_identification_number = id;
58
+ return row;
59
+ }
60
+
61
+ /** 重算只还原本次多次卡;套餐和多 Holder 按父商品份数计算,不再合并商品行。 */
62
+ function prepareEntitlementLines(products, hooks, canUseEntitlement) {
63
+ return products.flatMap(original => {
64
+ const data = hooks.getProduct(original);
65
+ if ((0, _entitlementState.isPersistedEntitlementLine)(original, data) || isManualDiscount(data)) return [original];
66
+ const applicable = canUseEntitlement(original);
67
+ if (!original.metadata?.[SOURCE] && !(0, _entitlementState.hasEntitlementDiscount)(data) && !applicable) return [original];
68
+ const origin = (0, _lodashEs.cloneDeep)(original);
69
+ origin.metadata = {
70
+ ...origin.metadata,
71
+ [SOURCE]: origin.metadata?.[SOURCE] ?? data._id
72
+ };
73
+ const bundle = (data.bundle || []).map(item => {
74
+ const entitlement = (item.discount_list || []).find(_entitlementPass.isEntitlementPass);
75
+ if (!entitlement) return item;
76
+ const discounts = (item.discount_list || []).filter(discount => !(0, _entitlementPass.isEntitlementPass)(discount));
77
+ const originalPrice = item.original_price ?? entitlement.discount?.original_amount ?? item.product_price ?? item.price ?? 0;
78
+ const amount = discounts.reduce((sum, discount) => sum.plus(discount.amount || 0), new _decimal.default(0));
79
+ const price = new _decimal.default(originalPrice).minus(amount.div(item.num || 1)).toNumber();
80
+ return {
81
+ ...item,
82
+ original_price: originalPrice,
83
+ price,
84
+ bundle_selling_price: price,
85
+ discount_list: discounts
86
+ };
87
+ });
88
+ const mainEntitlement = data.discount_list?.find(_entitlementPass.isEntitlementPass);
89
+ const restored = hooks.setProduct(origin, {
90
+ original_price: data.original_price ?? mainEntitlement?.discount?.original_amount ?? data.price,
91
+ discount_list: (data.discount_list || []).filter(item => !(0, _entitlementPass.isEntitlementPass)(item)),
92
+ bundle
93
+ });
94
+ const row = rebuildEntitlementLine(restored, bundle, hooks);
95
+ const count = Math.max(1, Math.floor(Number(data.quantity || data.num || 1)));
96
+ if (!applicable || count <= 1 || !bundle.length && !Array.isArray(data.holder_id)) return [row];
97
+ return Array.from({
98
+ length: count
99
+ }, (_, index) => {
100
+ const unit = (0, _lodashEs.cloneDeep)(row);
101
+ // booking 使用 _extend.holder_id,appointmentBooking 使用购物车 Holder。
102
+ for (const source of [unit, unit._extend]) {
103
+ if (Array.isArray(source?.holder_id)) source.holder_id = source.holder_id.slice(index, index + 1);
104
+ }
105
+ if (Array.isArray(unit._origin?.holder?.form_record)) {
106
+ const records = unit._origin.holder.form_record;
107
+ // 单 Holder 的多份商品仍归属同一人;多个 Holder 才按份对应。
108
+ if (records.length > 1) unit._origin.holder.form_record = records.slice(index, index + 1);
109
+ }
110
+ return setLineIdentity(rebuildEntitlementLine(unit, hooks.getProduct(unit).bundle || [], hooks, 1), `${data._id}:entitlement-unit:${index}`);
111
+ });
112
+ });
113
+ }
114
+
115
+ /** 客户端钩子可能保留原 _id,只给新增的重复行补标识,保留拆分结果。 */
116
+ function finalizeEntitlementLines(products, hooks) {
117
+ const runtime = item => isEntitlementRuntimeLine(item, hooks.getProduct(item));
118
+ const seen = new Set(products.filter(item => !runtime(item)).map(item => String(item._id)));
119
+ return products.map((origin, index) => {
120
+ if (!runtime(origin)) return origin;
121
+ const base = String(origin._id ?? hooks.getProduct(origin)._id);
122
+ let id = base;
123
+ let ordinal = index;
124
+ while (seen.has(id)) id = `${base}:entitlement-split:${ordinal++}`;
125
+ seen.add(id);
126
+ return id === String(origin._id) ? origin : setLineIdentity((0, _lodashEs.cloneDeep)(origin), id);
127
+ });
128
+ }
@@ -2,6 +2,7 @@ import { Module, PisellCore, ModuleOptions } from '../../types';
2
2
  import { BaseModule } from '../BaseModule';
3
3
  import { Rules, RulesModuleAPI, DiscountResult, RulesFormSubject, RulesCalcDiscountOptions, UnavailableReason } from './types';
4
4
  import { Discount } from '../Discount/types';
5
+ import { WalletPassEvaluator } from '../../model/strategy/adapter/walletPass/evaluator';
5
6
  import { WindowPlugin } from '../../plugins';
6
7
  export declare class RulesModule extends BaseModule implements Module, RulesModuleAPI {
7
8
  protected defaultName: string;
@@ -9,11 +10,19 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
9
10
  private store;
10
11
  window: WindowPlugin;
11
12
  private hooks;
13
+ private entitlementPassEnabled;
14
+ private defaultWalletPassEvaluator?;
15
+ setEntitlementPassEnabled(enabled: boolean): void;
12
16
  constructor(name?: string, version?: string);
13
17
  initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
14
18
  setRulesList(rulesList: Rules[]): Promise<void>;
15
19
  getRulesList(): Rules[];
16
- getWalletPassEvaluator(): import("../..").WalletPassEvaluator | undefined;
20
+ getWalletPassEvaluator(): WalletPassEvaluator | undefined;
21
+ private normalizeHolderRecordIds;
22
+ /**
23
+ * 商品未开启 Holder 选择时跳过匹配;已开启时,特定 form Holder 卡
24
+ * 只适用于同一 Holder Record,是否必填不影响匹配规则。
25
+ */
17
26
  private checkHolderMatch;
18
27
  isDiscountListAvailable({ oldDiscountList, newDiscountList, productList, orderTotalAmount, holders, isFormSubject, }: {
19
28
  oldDiscountList: Discount[];
@@ -21,7 +30,7 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
21
30
  productList: any[];
22
31
  orderTotalAmount: number;
23
32
  holders: {
24
- form_record_id: number;
33
+ form_record_id: number | string;
25
34
  }[];
26
35
  isFormSubject: RulesFormSubject;
27
36
  }): {
@@ -29,6 +38,7 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
29
38
  discountList: Discount[];
30
39
  productList: any[];
31
40
  unavailableReason?: UnavailableReason;
41
+ evaluatedDiscountList?: Discount[];
32
42
  };
33
43
  filterDiscountListByType(discountList: Discount[], type: string): Discount[];
34
44
  /** 剔除指定 type/tag 的折扣项,保留手动改价(type=product) / 券等 */
@@ -40,7 +50,7 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
40
50
  discountList: Discount[];
41
51
  productList: any[];
42
52
  holders: {
43
- form_record_id: number;
53
+ form_record_id: number | string;
44
54
  }[];
45
55
  isFormSubject: RulesFormSubject;
46
56
  orderTotalAmount: number;