@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.
- package/dist/effects/index.d.ts +2 -2
- package/dist/model/strategy/adapter/dataVariant/type.d.ts +3 -3
- package/dist/model/strategy/adapter/itemRule/type.d.ts +6 -6
- package/dist/model/strategy/adapter/promotion/index.d.ts +4 -0
- package/dist/model/strategy/adapter/promotion/type.d.ts +5 -5
- package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
- package/dist/model/strategy/adapter/walletPass/evaluator.js +4 -2
- package/dist/model/strategy/type.d.ts +1 -1
- package/dist/modules/BookingContext/types.d.ts +4 -4
- package/dist/modules/BookingContext/utils/resourceErrors.d.ts +1 -1
- package/dist/modules/Customer/types.d.ts +1 -1
- package/dist/modules/Discount/availability.d.ts +7 -0
- package/dist/modules/Discount/availability.js +52 -0
- package/dist/modules/Discount/entitlementPass.d.ts +34 -0
- package/dist/modules/Discount/entitlementPass.js +147 -0
- package/dist/modules/Discount/entitlementState.d.ts +8 -0
- package/dist/modules/Discount/entitlementState.js +205 -0
- package/dist/modules/Discount/index.d.ts +5 -2
- package/dist/modules/Discount/index.js +124 -25
- package/dist/modules/Discount/types.d.ts +29 -6
- package/dist/modules/Holder/types.d.ts +1 -1
- package/dist/modules/OpenData/types.d.ts +1 -1
- package/dist/modules/Order/types.d.ts +5 -5
- package/dist/modules/Order/utils/bundleDiscountHydration.d.ts +1 -1
- package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +1 -1
- package/dist/modules/Order/utils.d.ts +1 -1
- package/dist/modules/Payment/types.d.ts +7 -7
- package/dist/modules/Product/index.d.ts +1 -1
- package/dist/modules/ResourcePlanner/types.d.ts +4 -4
- package/dist/modules/Rules/entitlementLines.d.ts +8 -0
- package/dist/modules/Rules/entitlementLines.js +159 -0
- package/dist/modules/Rules/index.d.ts +13 -3
- package/dist/modules/Rules/index.js +617 -342
- package/dist/modules/Rules/types.d.ts +4 -4
- package/dist/modules/ScanOrderLogger/types.d.ts +2 -2
- package/dist/modules/Schedule/getDateIsInSchedule.d.ts +1 -1
- package/dist/modules/Schedule/type.d.ts +7 -7
- package/dist/modules/Schedule/types.d.ts +9 -9
- package/dist/plugins/app.d.ts +1 -1
- package/dist/plugins/request.d.ts +2 -2
- package/dist/plugins/window.d.ts +2 -2
- package/dist/server/modules/floor-plan/types.d.ts +1 -1
- package/dist/server/modules/menu/types.d.ts +1 -1
- package/dist/server/modules/order/types.d.ts +16 -16
- package/dist/server/modules/products/types.d.ts +1 -1
- package/dist/server/modules/resource/types.d.ts +1 -1
- package/dist/server/modules/schedule/utils.d.ts +1 -1
- package/dist/server/types.d.ts +4 -4
- package/dist/server/utils/small-ticket.d.ts +1 -1
- package/dist/solution/BaseSales/index.d.ts +1 -1
- package/dist/solution/BaseSales/types.d.ts +7 -7
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -1
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingByStep/utils/resources.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +13 -1
- package/dist/solution/BookingTicket/types.d.ts +3 -3
- package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +1 -1
- package/dist/solution/BookingTicket/utils/bookingStatus.d.ts +1 -1
- package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +1 -1
- package/dist/solution/Sales/types.d.ts +4 -4
- package/dist/solution/ScanOrder/types.d.ts +5 -5
- package/dist/solution/ShopDiscount/index.d.ts +3 -0
- package/dist/solution/ShopDiscount/index.js +161 -78
- package/dist/solution/ShopDiscount/types.d.ts +1 -1
- package/dist/solution/ShopDiscount/utils.d.ts +3 -2
- package/dist/solution/ShopDiscount/utils.js +40 -1
- package/dist/solution/UnifiedBookingSales/types.d.ts +1 -1
- package/dist/solution/VenueBooking/types.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/task.d.ts +2 -2
- package/dist/utils/watch.d.ts +2 -2
- package/lib/effects/index.d.ts +2 -2
- package/lib/model/strategy/adapter/dataVariant/type.d.ts +3 -3
- package/lib/model/strategy/adapter/itemRule/type.d.ts +6 -6
- package/lib/model/strategy/adapter/promotion/index.d.ts +4 -0
- package/lib/model/strategy/adapter/promotion/type.d.ts +5 -5
- package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
- package/lib/model/strategy/adapter/walletPass/evaluator.js +2 -0
- package/lib/model/strategy/type.d.ts +1 -1
- package/lib/modules/BookingContext/types.d.ts +4 -4
- package/lib/modules/BookingContext/utils/resourceErrors.d.ts +1 -1
- package/lib/modules/Customer/types.d.ts +1 -1
- package/lib/modules/Discount/availability.d.ts +7 -0
- package/lib/modules/Discount/availability.js +46 -0
- package/lib/modules/Discount/entitlementPass.d.ts +34 -0
- package/lib/modules/Discount/entitlementPass.js +141 -0
- package/lib/modules/Discount/entitlementState.d.ts +8 -0
- package/lib/modules/Discount/entitlementState.js +150 -0
- package/lib/modules/Discount/index.d.ts +5 -2
- package/lib/modules/Discount/index.js +59 -14
- package/lib/modules/Discount/types.d.ts +29 -6
- package/lib/modules/Holder/types.d.ts +1 -1
- package/lib/modules/OpenData/types.d.ts +1 -1
- package/lib/modules/Order/types.d.ts +5 -5
- package/lib/modules/Order/utils/bundleDiscountHydration.d.ts +1 -1
- package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +1 -1
- package/lib/modules/Order/utils.d.ts +1 -1
- package/lib/modules/Payment/types.d.ts +7 -7
- package/lib/modules/Product/index.d.ts +1 -1
- package/lib/modules/ResourcePlanner/types.d.ts +4 -4
- package/lib/modules/Rules/entitlementLines.d.ts +8 -0
- package/lib/modules/Rules/entitlementLines.js +128 -0
- package/lib/modules/Rules/index.d.ts +13 -3
- package/lib/modules/Rules/index.js +284 -61
- package/lib/modules/Rules/types.d.ts +4 -4
- package/lib/modules/ScanOrderLogger/types.d.ts +2 -2
- package/lib/modules/Schedule/getDateIsInSchedule.d.ts +1 -1
- package/lib/modules/Schedule/type.d.ts +7 -7
- package/lib/modules/Schedule/types.d.ts +9 -9
- package/lib/plugins/app.d.ts +1 -1
- package/lib/plugins/request.d.ts +2 -2
- package/lib/plugins/window.d.ts +2 -2
- package/lib/server/modules/floor-plan/types.d.ts +1 -1
- package/lib/server/modules/menu/types.d.ts +1 -1
- package/lib/server/modules/order/types.d.ts +16 -16
- package/lib/server/modules/products/types.d.ts +1 -1
- package/lib/server/modules/resource/types.d.ts +1 -1
- package/lib/server/modules/schedule/utils.d.ts +1 -1
- package/lib/server/types.d.ts +4 -4
- package/lib/server/utils/small-ticket.d.ts +1 -1
- package/lib/solution/BaseSales/index.d.ts +1 -1
- package/lib/solution/BaseSales/types.d.ts +7 -7
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -1
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingByStep/utils/resources.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +13 -1
- package/lib/solution/BookingTicket/types.d.ts +3 -3
- package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +1 -1
- package/lib/solution/BookingTicket/utils/bookingStatus.d.ts +1 -1
- package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +1 -1
- package/lib/solution/Sales/types.d.ts +4 -4
- package/lib/solution/ScanOrder/types.d.ts +5 -5
- package/lib/solution/ShopDiscount/index.d.ts +3 -0
- package/lib/solution/ShopDiscount/index.js +55 -18
- package/lib/solution/ShopDiscount/types.d.ts +1 -1
- package/lib/solution/ShopDiscount/utils.d.ts +3 -2
- package/lib/solution/ShopDiscount/utils.js +39 -3
- package/lib/solution/UnifiedBookingSales/types.d.ts +1 -1
- package/lib/solution/VenueBooking/types.d.ts +1 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/utils/task.d.ts +2 -2
- package/lib/utils/watch.d.ts +2 -2
- package/package.json +19 -18
package/dist/effects/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
type EffectCallback = (payload: any) => void | Promise<void | {
|
|
2
2
|
status: boolean;
|
|
3
3
|
message?: string;
|
|
4
4
|
}>;
|
|
5
|
-
|
|
5
|
+
type UnsubscribeFunction = () => void;
|
|
6
6
|
declare class EffectsManager {
|
|
7
7
|
private listeners;
|
|
8
8
|
on(event: string, callback: EffectCallback): UnsubscribeFunction;
|
|
@@ -8,7 +8,7 @@ import type { ScheduleItem } from '../../../../modules/Schedule/types';
|
|
|
8
8
|
export declare const DATA_VARIANT_ACTION_TYPES: {
|
|
9
9
|
readonly APPLY: "DATA_VARIANT_APPLY";
|
|
10
10
|
};
|
|
11
|
-
export
|
|
11
|
+
export type DataVariantActionType = (typeof DATA_VARIANT_ACTION_TYPES)[keyof typeof DATA_VARIANT_ACTION_TYPES];
|
|
12
12
|
/**
|
|
13
13
|
* Data Variant 规则元数据。
|
|
14
14
|
*
|
|
@@ -116,7 +116,7 @@ export interface EffectiveRuleInfo {
|
|
|
116
116
|
productRules: ConditionRule[];
|
|
117
117
|
globalResult: EvaluationResult;
|
|
118
118
|
}
|
|
119
|
-
export
|
|
119
|
+
export type GlobalEffectiveRuleMap = Map<string, EffectiveRuleInfo>;
|
|
120
120
|
/**
|
|
121
121
|
* 单条商品命中的变体覆盖信息。
|
|
122
122
|
*/
|
|
@@ -145,4 +145,4 @@ export interface ResolvedDataVariantResult {
|
|
|
145
145
|
scheduleTimePoints: string[];
|
|
146
146
|
rawResults: EvaluationResult[];
|
|
147
147
|
}
|
|
148
|
-
export
|
|
148
|
+
export type ConditionScope = 'global' | 'product';
|
|
@@ -5,7 +5,7 @@ export declare const ITEM_RULE_ACTION_TYPES: {
|
|
|
5
5
|
/** 预填购物车 */
|
|
6
6
|
readonly PREFILL_CART: "PREFILL_CART";
|
|
7
7
|
};
|
|
8
|
-
export
|
|
8
|
+
export type ItemRuleActionType = (typeof ITEM_RULE_ACTION_TYPES)[keyof typeof ITEM_RULE_ACTION_TYPES];
|
|
9
9
|
export declare const ITEM_RULE_TEMPLATES: {
|
|
10
10
|
/** 空白规则 */
|
|
11
11
|
readonly BLANK: "blank";
|
|
@@ -16,15 +16,15 @@ export declare const ITEM_RULE_TEMPLATES: {
|
|
|
16
16
|
/** 必选商品 */
|
|
17
17
|
readonly MUST_INCLUDE: "must_include";
|
|
18
18
|
};
|
|
19
|
-
export
|
|
19
|
+
export type ItemRuleTemplate = (typeof ITEM_RULE_TEMPLATES)[keyof typeof ITEM_RULE_TEMPLATES];
|
|
20
20
|
/** 数量比较类型 */
|
|
21
|
-
export
|
|
21
|
+
export type QuantityComparison = 'minimum' | 'maximum' | 'exact' | 'must_include';
|
|
22
22
|
/** 数量来源 */
|
|
23
|
-
export
|
|
23
|
+
export type QuantitySource = 'total_pax' | 'adult_pax' | 'fixed';
|
|
24
24
|
/** 目标类型(当前仅支持按商品) */
|
|
25
|
-
export
|
|
25
|
+
export type TargetType = 'product';
|
|
26
26
|
/** 作用范围 */
|
|
27
|
-
export
|
|
27
|
+
export type RuleScope = 'each_submission' | 'first_submission_only' | 'subsequent_only' | 'cumulative';
|
|
28
28
|
/**
|
|
29
29
|
* 单条数量规则
|
|
30
30
|
*
|
|
@@ -17,7 +17,7 @@ export declare const PROMOTION_ACTION_TYPES: {
|
|
|
17
17
|
/** 固定减价 */
|
|
18
18
|
readonly DEDUCT_AMOUNT: "DEDUCT_AMOUNT";
|
|
19
19
|
};
|
|
20
|
-
export
|
|
20
|
+
export type PromotionActionType = (typeof PROMOTION_ACTION_TYPES)[keyof typeof PROMOTION_ACTION_TYPES];
|
|
21
21
|
/**
|
|
22
22
|
* X件Y元 - Action Value
|
|
23
23
|
*
|
|
@@ -54,7 +54,7 @@ export interface BuyXGetYFreeValue {
|
|
|
54
54
|
/**
|
|
55
55
|
* 赠品选择模式
|
|
56
56
|
*/
|
|
57
|
-
export
|
|
57
|
+
export type GiftSelectionMode = 'user_select' | 'auto' | 'cheapest';
|
|
58
58
|
/**
|
|
59
59
|
* 买X送Y - Action Config
|
|
60
60
|
*/
|
|
@@ -105,7 +105,7 @@ export interface BuyXGetYFreeAction extends Omit<ActionEffect, 'type' | 'value'
|
|
|
105
105
|
/**
|
|
106
106
|
* 促销活动 Action 联合类型
|
|
107
107
|
*/
|
|
108
|
-
export
|
|
108
|
+
export type PromotionAction = XItemsForYPriceAction | BuyXGetYFreeAction;
|
|
109
109
|
/**
|
|
110
110
|
* 促销相关运算符
|
|
111
111
|
*/
|
|
@@ -135,7 +135,7 @@ export interface PromotionBusinessData {
|
|
|
135
135
|
/** 自定义属性 */
|
|
136
136
|
custom?: Record<string, any>;
|
|
137
137
|
}
|
|
138
|
-
|
|
138
|
+
type ProductBundleItem = {
|
|
139
139
|
/** 主商品ID */
|
|
140
140
|
product_id: number;
|
|
141
141
|
/** 变体ID(0 表示无变体) */
|
|
@@ -195,7 +195,7 @@ export interface PromotionTransformResult {
|
|
|
195
195
|
/**
|
|
196
196
|
* Action 详情联合类型
|
|
197
197
|
*/
|
|
198
|
-
export
|
|
198
|
+
export type PromotionActionDetail = XItemsForYPriceActionDetail | BuyXGetYFreeActionDetail;
|
|
199
199
|
/**
|
|
200
200
|
* X件Y元 Action 详情
|
|
201
201
|
*/
|
|
@@ -28,6 +28,8 @@ export declare class WalletPassEvaluator {
|
|
|
28
28
|
/** 检查代金券/折扣卡是否可用 并返回config */
|
|
29
29
|
checkVoucherAvailability(input: EvaluatorInput): {
|
|
30
30
|
isAvailable: boolean;
|
|
31
|
+
reason: string | undefined;
|
|
32
|
+
reasonCode: string | undefined;
|
|
31
33
|
config: {
|
|
32
34
|
[x: string]: any;
|
|
33
35
|
};
|
|
@@ -283,7 +283,7 @@ export var WalletPassEvaluator = /*#__PURE__*/function () {
|
|
|
283
283
|
}, {
|
|
284
284
|
key: "checkVoucherAvailability",
|
|
285
285
|
value: function checkVoucherAvailability(input) {
|
|
286
|
-
var _results$, _results$2;
|
|
286
|
+
var _results$, _results$2, _results$3, _results$4;
|
|
287
287
|
var orderTotalAmount = input.orderTotalAmount,
|
|
288
288
|
products = input.products,
|
|
289
289
|
vouchers = input.vouchers;
|
|
@@ -291,7 +291,9 @@ export var WalletPassEvaluator = /*#__PURE__*/function () {
|
|
|
291
291
|
var isAvailable = ((_results$ = results[0]) === null || _results$ === void 0 ? void 0 : _results$.isApplicable) || false;
|
|
292
292
|
return {
|
|
293
293
|
isAvailable: isAvailable,
|
|
294
|
-
|
|
294
|
+
reason: (_results$2 = results[0]) === null || _results$2 === void 0 ? void 0 : _results$2.reason,
|
|
295
|
+
reasonCode: (_results$3 = results[0]) === null || _results$3 === void 0 ? void 0 : _results$3.reasonCode,
|
|
296
|
+
config: _objectSpread({}, (_results$4 = results[0]) === null || _results$4 === void 0 || (_results$4 = _results$4.strategyResult) === null || _results$4 === void 0 || (_results$4 = _results$4.config) === null || _results$4 === void 0 || (_results$4 = _results$4.metadata) === null || _results$4 === void 0 ? void 0 : _results$4.custom)
|
|
295
297
|
};
|
|
296
298
|
}
|
|
297
299
|
|
|
@@ -242,4 +242,4 @@ export interface EngineOptions {
|
|
|
242
242
|
/**
|
|
243
243
|
* 运算符处理器
|
|
244
244
|
*/
|
|
245
|
-
export
|
|
245
|
+
export type OperatorHandler = (fieldValue: any, compareValue: any, rule: ConditionRule) => boolean;
|
|
@@ -39,17 +39,17 @@ export interface InitBookingContextParams {
|
|
|
39
39
|
* 资源全集 map:key 为资源 id(数字),value 为资源原始对象,含 times / event_list 等运行态。
|
|
40
40
|
* 这里只声明 Record 形态;具体字段保留 `any`,与 ticketBooking 现网传入的数据形状兼容。
|
|
41
41
|
*/
|
|
42
|
-
export
|
|
43
|
-
export
|
|
42
|
+
export type BookingContextResource = Record<string, any>;
|
|
43
|
+
export type BookingContextResourceMap = Record<string, BookingContextResource>;
|
|
44
44
|
/**
|
|
45
45
|
* 形参 booking_config(结构来自 `/core/board/management/config` 接口)。
|
|
46
46
|
* OS 不强制 schema,保留 `Record<string, any>` 兼容现网;常用路径文档化在 SDK docs。
|
|
47
47
|
*/
|
|
48
|
-
export
|
|
48
|
+
export type BookingContextConfig = Record<string, any>;
|
|
49
49
|
/**
|
|
50
50
|
* 日期入参:接受 dayjs 实例、ISO 字符串、Date 实例;内部统一 normalize 为 ISO 字符串保存。
|
|
51
51
|
*/
|
|
52
|
-
export
|
|
52
|
+
export type BookingContextDateInput = string | Date | {
|
|
53
53
|
format?: (fmt?: string) => string;
|
|
54
54
|
} | null | undefined;
|
|
55
55
|
/**
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* OS 这边不耦合 i18n 文案,UI 拿到 reason + params 后自行渲染(参考 docs/SDK 中给出的 i18n key 对照表)。
|
|
11
11
|
*/
|
|
12
|
-
export
|
|
12
|
+
export type ResourceUnavailableReason = 'no_product' | 'time_out_of_range' | 'count_out_of_range' | 'resource_unbound';
|
|
13
13
|
export interface ResourceError {
|
|
14
14
|
reason: ResourceUnavailableReason;
|
|
15
15
|
params: {
|
|
@@ -33,7 +33,7 @@ export interface ShopCustomer extends ICustomer {
|
|
|
33
33
|
* walletDetails.wallet: 用户所有wallet
|
|
34
34
|
* latestWalletDetail.wallet: 用户最新wallet
|
|
35
35
|
*/
|
|
36
|
-
|
|
36
|
+
type CustomerWith = 'formRecord' | 'walletDetails.wallet' | 'latestWalletDetail.wallet';
|
|
37
37
|
/**
|
|
38
38
|
* 获取客户列表参数
|
|
39
39
|
*/
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Discount, DiscountFilterRejectKey } from './types';
|
|
2
|
+
/** 周期限制只影响当前使用;total_credits 才代表整张卡的次数耗尽。 */
|
|
3
|
+
export declare function getDiscountUsageLimitFailKey(discount: Discount): DiscountFilterRejectKey | null;
|
|
4
|
+
export declare function hasAvailableDiscountBalance(discount: Discount): boolean;
|
|
5
|
+
/** 按卡本身当前生命周期判断;预约时间或一次日程不匹配不代表已失效。 */
|
|
6
|
+
export declare function getDiscountLifecycleReason(discount: Discount): 'disabled' | 'exhausted' | 'expired' | 'not_shared_at_store' | undefined;
|
|
7
|
+
export declare function getDiscountUsageBlockReason(discount: Discount): string | undefined;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
2
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
4
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
5
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
|
+
import dayjs from 'dayjs';
|
|
8
|
+
import Decimal from 'decimal.js';
|
|
9
|
+
import { hasAvailableEntitlementUses, isEntitlementPass } from "./entitlementPass";
|
|
10
|
+
|
|
11
|
+
/** 周期限制只影响当前使用;total_credits 才代表整张卡的次数耗尽。 */
|
|
12
|
+
export function getDiscountUsageLimitFailKey(discount) {
|
|
13
|
+
var _discount$extension_d, _limits$find;
|
|
14
|
+
var value = (_discount$extension_d = discount.extension_data) === null || _discount$extension_d === void 0 || (_discount$extension_d = _discount$extension_d.find(function (field) {
|
|
15
|
+
return field.field_key === 'usage_credits';
|
|
16
|
+
})) === null || _discount$extension_d === void 0 ? void 0 : _discount$extension_d.value;
|
|
17
|
+
if (!value) return null;
|
|
18
|
+
var limits = [['total_credits', discount.total_order_behavior_count], ['per_user_limit', discount.customer_order_behavior_count], ['max_per_day', discount.today_order_behavior_count], ['max_per_week', discount.week_order_behavior_count], ['max_per_month', discount.month_order_behavior_count]];
|
|
19
|
+
return ((_limits$find = limits.find(function (_ref) {
|
|
20
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
21
|
+
key = _ref2[0],
|
|
22
|
+
count = _ref2[1];
|
|
23
|
+
return Number(value[key]) > 0 && Number(count || 0) >= Number(value[key]);
|
|
24
|
+
})) === null || _limits$find === void 0 ? void 0 : _limits$find[0]) || null;
|
|
25
|
+
}
|
|
26
|
+
export function hasAvailableDiscountBalance(discount) {
|
|
27
|
+
if (isEntitlementPass(discount)) return hasAvailableEntitlementUses(discount);
|
|
28
|
+
return new Decimal(discount.par_value || 0).minus(discount.used_par_value || 0).greaterThan(0);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** 按卡本身当前生命周期判断;预约时间或一次日程不匹配不代表已失效。 */
|
|
32
|
+
export function getDiscountLifecycleReason(discount) {
|
|
33
|
+
var _discount$franchisee_, _discount$metadata;
|
|
34
|
+
if (discount.is_franchisor_pass === 1 && ((_discount$franchisee_ = discount.franchisee_wallet_pass) === null || _discount$franchisee_ === void 0 ? void 0 : _discount$franchisee_.use) !== 'enabled') {
|
|
35
|
+
return 'not_shared_at_store';
|
|
36
|
+
}
|
|
37
|
+
if (discount.limit_status && discount.limit_status !== 'enable') {
|
|
38
|
+
return 'disabled';
|
|
39
|
+
}
|
|
40
|
+
if ((isEntitlementPass(discount) || discount.par_value != null) && !hasAvailableDiscountBalance(discount) || getDiscountUsageLimitFailKey(discount) === 'total_credits') {
|
|
41
|
+
return 'exhausted';
|
|
42
|
+
}
|
|
43
|
+
// 自定义日程沿用快照语义,不使用遗留固定有效期字段推断过期。
|
|
44
|
+
if (((_discount$metadata = discount.metadata) === null || _discount$metadata === void 0 ? void 0 : _discount$metadata.validity_type) !== 'custom_schedule_validity' && discount.expire_time) {
|
|
45
|
+
var expiry = dayjs(discount.expire_time);
|
|
46
|
+
if (expiry.isValid() && !dayjs().isBefore(expiry)) return 'expired';
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
export function getDiscountUsageBlockReason(discount) {
|
|
51
|
+
return getDiscountLifecycleReason(discount) || getDiscountUsageLimitFailKey(discount) || (discount.unified_available_status != null && String(discount.unified_available_status) !== '' && Number(discount.unified_available_status) === 0 ? 'server_unavailable' : undefined);
|
|
52
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const ENTITLEMENT_PASS_TYPE = "entitlement_pass";
|
|
2
|
+
export declare const GOOD_PASS_TYPE = "good_pass";
|
|
3
|
+
type DiscountLike = {
|
|
4
|
+
id?: number | string | null;
|
|
5
|
+
tag?: unknown;
|
|
6
|
+
type?: unknown;
|
|
7
|
+
discount?: object | null;
|
|
8
|
+
metadata?: object | null;
|
|
9
|
+
extension_data?: unknown;
|
|
10
|
+
balance?: unknown;
|
|
11
|
+
expire_time?: unknown;
|
|
12
|
+
};
|
|
13
|
+
export type EntitlementQuota = {
|
|
14
|
+
type: 'limited';
|
|
15
|
+
value: number;
|
|
16
|
+
balance: number;
|
|
17
|
+
} | {
|
|
18
|
+
type: 'unlimited';
|
|
19
|
+
value: null;
|
|
20
|
+
balance: null;
|
|
21
|
+
};
|
|
22
|
+
export declare function isEntitlementPass(discount: DiscountLike | null | undefined): boolean;
|
|
23
|
+
export declare function isFullCoveragePass(discount: DiscountLike | null | undefined): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the authoritative total-use contract for an Entitlement Pass.
|
|
26
|
+
* Invalid or missing configuration fails closed. Legacy mode/total_uses fields
|
|
27
|
+
* are intentionally unsupported.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveEntitlementQuota(discount: DiscountLike | null | undefined): EntitlementQuota | null;
|
|
30
|
+
export declare function getRemainingEntitlementUses(discount: DiscountLike | null | undefined, usedCount: number, requestedCount: number): number;
|
|
31
|
+
export declare function hasAvailableEntitlementUses(discount: DiscountLike | null | undefined): boolean;
|
|
32
|
+
/** Sort Entitlement Passes by expiry, finite balance, then card instance id. */
|
|
33
|
+
export declare function compareEntitlementPassPriority(left: DiscountLike, right: DiscountLike): number;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
2
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
4
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
5
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
8
|
+
import dayjs from 'dayjs';
|
|
9
|
+
export var ENTITLEMENT_PASS_TYPE = 'entitlement_pass';
|
|
10
|
+
export var GOOD_PASS_TYPE = 'good_pass';
|
|
11
|
+
function getDiscountType(discount) {
|
|
12
|
+
var nestedDiscount = discount === null || discount === void 0 ? void 0 : discount.discount;
|
|
13
|
+
return String((discount === null || discount === void 0 ? void 0 : discount.tag) || (discount === null || discount === void 0 ? void 0 : discount.type) || (nestedDiscount === null || nestedDiscount === void 0 ? void 0 : nestedDiscount.tag) || (nestedDiscount === null || nestedDiscount === void 0 ? void 0 : nestedDiscount.type) || '');
|
|
14
|
+
}
|
|
15
|
+
export function isEntitlementPass(discount) {
|
|
16
|
+
return getDiscountType(discount) === ENTITLEMENT_PASS_TYPE;
|
|
17
|
+
}
|
|
18
|
+
export function isFullCoveragePass(discount) {
|
|
19
|
+
var type = getDiscountType(discount);
|
|
20
|
+
return type === GOOD_PASS_TYPE || type === ENTITLEMENT_PASS_TYPE;
|
|
21
|
+
}
|
|
22
|
+
function resolveIncludedUses(discount) {
|
|
23
|
+
var _discount$extension_d;
|
|
24
|
+
var metadata = discount.metadata;
|
|
25
|
+
var hasMetadataIncludedUses = !!metadata && _typeof(metadata) === 'object' && Object.prototype.hasOwnProperty.call(metadata, 'included_uses');
|
|
26
|
+
var rawValue = hasMetadataIncludedUses ? metadata === null || metadata === void 0 ? void 0 : metadata.included_uses : Array.isArray(discount.extension_data) ? (_discount$extension_d = discount.extension_data.find(function (item) {
|
|
27
|
+
return (item === null || item === void 0 ? void 0 : item.field_key) === 'included_uses';
|
|
28
|
+
})) === null || _discount$extension_d === void 0 ? void 0 : _discount$extension_d.value : undefined;
|
|
29
|
+
if (!rawValue || _typeof(rawValue) !== 'object' || Array.isArray(rawValue)) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
var includedUses = rawValue;
|
|
33
|
+
if (includedUses.type === 'unlimited' && includedUses.value === null) {
|
|
34
|
+
return {
|
|
35
|
+
type: 'unlimited',
|
|
36
|
+
value: null
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (includedUses.type === 'limited' && typeof includedUses.value === 'number' && Number.isInteger(includedUses.value) && includedUses.value >= 1 && includedUses.value <= 9999) {
|
|
40
|
+
return {
|
|
41
|
+
type: 'limited',
|
|
42
|
+
value: includedUses.value
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
function resolveNonNegativeInteger(value) {
|
|
48
|
+
if (typeof value !== 'number' && typeof value !== 'string' || typeof value === 'string' && value.trim() === '') {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
var normalizedValue = Number(value);
|
|
52
|
+
if (!Number.isInteger(normalizedValue) || normalizedValue < 0) return null;
|
|
53
|
+
return normalizedValue;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Resolve the authoritative total-use contract for an Entitlement Pass.
|
|
58
|
+
* Invalid or missing configuration fails closed. Legacy mode/total_uses fields
|
|
59
|
+
* are intentionally unsupported.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveEntitlementQuota(discount) {
|
|
62
|
+
if (!isEntitlementPass(discount)) return null;
|
|
63
|
+
var includedUses = resolveIncludedUses(discount);
|
|
64
|
+
if (!includedUses) return null;
|
|
65
|
+
if (includedUses.type === 'unlimited') {
|
|
66
|
+
return {
|
|
67
|
+
type: 'unlimited',
|
|
68
|
+
value: null,
|
|
69
|
+
balance: null
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
var balance = resolveNonNegativeInteger(discount === null || discount === void 0 ? void 0 : discount.balance);
|
|
73
|
+
if (balance === null) return null;
|
|
74
|
+
return {
|
|
75
|
+
type: 'limited',
|
|
76
|
+
value: includedUses.value,
|
|
77
|
+
balance: balance
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export function getRemainingEntitlementUses(discount, usedCount, requestedCount) {
|
|
81
|
+
var quota = resolveEntitlementQuota(discount);
|
|
82
|
+
var normalizedRequestedCount = Math.max(Math.floor(Number(requestedCount) || 0), 0);
|
|
83
|
+
if (!quota || normalizedRequestedCount <= 0) return 0;
|
|
84
|
+
if (quota.type === 'unlimited') return normalizedRequestedCount;
|
|
85
|
+
var normalizedUsedCount = Math.max(Math.floor(Number(usedCount) || 0), 0);
|
|
86
|
+
return Math.min(Math.max(quota.balance - normalizedUsedCount, 0), normalizedRequestedCount);
|
|
87
|
+
}
|
|
88
|
+
export function hasAvailableEntitlementUses(discount) {
|
|
89
|
+
var quota = resolveEntitlementQuota(discount);
|
|
90
|
+
return !!quota && (quota.type === 'unlimited' || quota.balance > 0);
|
|
91
|
+
}
|
|
92
|
+
function resolveExpireTimestamp(value) {
|
|
93
|
+
if (typeof value !== 'string' || !value.trim()) return Number.POSITIVE_INFINITY;
|
|
94
|
+
var normalizedValue = value.trim();
|
|
95
|
+
var calendarParts = normalizedValue.match(/^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2}))?)?/);
|
|
96
|
+
if (calendarParts) {
|
|
97
|
+
var _calendarParts = _slicedToArray(calendarParts, 7),
|
|
98
|
+
year = _calendarParts[1],
|
|
99
|
+
month = _calendarParts[2],
|
|
100
|
+
day = _calendarParts[3],
|
|
101
|
+
_calendarParts$ = _calendarParts[4],
|
|
102
|
+
hour = _calendarParts$ === void 0 ? '0' : _calendarParts$,
|
|
103
|
+
_calendarParts$2 = _calendarParts[5],
|
|
104
|
+
minute = _calendarParts$2 === void 0 ? '0' : _calendarParts$2,
|
|
105
|
+
_calendarParts$3 = _calendarParts[6],
|
|
106
|
+
second = _calendarParts$3 === void 0 ? '0' : _calendarParts$3;
|
|
107
|
+
var yearNumber = Number(year);
|
|
108
|
+
var monthNumber = Number(month);
|
|
109
|
+
var dayNumber = Number(day);
|
|
110
|
+
var hourNumber = Number(hour);
|
|
111
|
+
var minuteNumber = Number(minute);
|
|
112
|
+
var secondNumber = Number(second);
|
|
113
|
+
var daysInMonth = new Date(Date.UTC(yearNumber, monthNumber, 0)).getUTCDate();
|
|
114
|
+
if (yearNumber <= 0 || monthNumber < 1 || monthNumber > 12 || dayNumber < 1 || dayNumber > daysInMonth || hourNumber < 0 || hourNumber > 23 || minuteNumber < 0 || minuteNumber > 59 || secondNumber < 0 || secondNumber > 59) {
|
|
115
|
+
return Number.POSITIVE_INFINITY;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
var date = dayjs(normalizedValue);
|
|
119
|
+
return date.isValid() ? date.valueOf() : Number.POSITIVE_INFINITY;
|
|
120
|
+
}
|
|
121
|
+
function compareIds(left, right) {
|
|
122
|
+
var leftNumber = Number(left);
|
|
123
|
+
var rightNumber = Number(right);
|
|
124
|
+
if (Number.isFinite(leftNumber) && Number.isFinite(rightNumber)) {
|
|
125
|
+
return leftNumber - rightNumber;
|
|
126
|
+
}
|
|
127
|
+
return String(left !== null && left !== void 0 ? left : '').localeCompare(String(right !== null && right !== void 0 ? right : ''), undefined, {
|
|
128
|
+
numeric: true
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Sort Entitlement Passes by expiry, finite balance, then card instance id. */
|
|
133
|
+
export function compareEntitlementPassPriority(left, right) {
|
|
134
|
+
var expireDifference = resolveExpireTimestamp(left.expire_time) - resolveExpireTimestamp(right.expire_time);
|
|
135
|
+
if (!Number.isNaN(expireDifference) && expireDifference !== 0) {
|
|
136
|
+
return expireDifference;
|
|
137
|
+
}
|
|
138
|
+
var leftQuota = resolveEntitlementQuota(left);
|
|
139
|
+
var rightQuota = resolveEntitlementQuota(right);
|
|
140
|
+
var leftBalance = (leftQuota === null || leftQuota === void 0 ? void 0 : leftQuota.type) === 'limited' ? leftQuota.balance : Number.POSITIVE_INFINITY;
|
|
141
|
+
var rightBalance = (rightQuota === null || rightQuota === void 0 ? void 0 : rightQuota.type) === 'limited' ? rightQuota.balance : Number.POSITIVE_INFINITY;
|
|
142
|
+
var balanceDifference = leftBalance - rightBalance;
|
|
143
|
+
if (!Number.isNaN(balanceDifference) && balanceDifference !== 0) {
|
|
144
|
+
return balanceDifference;
|
|
145
|
+
}
|
|
146
|
+
return compareIds(left.id, right.id);
|
|
147
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Discount } from './types';
|
|
2
|
+
export declare function hasEntitlementDiscount(product: any): boolean;
|
|
3
|
+
export declare function isPersistedEntitlementLine(product: any, mappedProduct?: any): boolean;
|
|
4
|
+
/** Refresh authoritative balances while retaining the user's scan/selection state. */
|
|
5
|
+
export declare function mergeEntitlementDiscountLists(current: Discount[], incoming: Discount[], observed?: Discount[]): Discount[];
|
|
6
|
+
export declare function retainScannedEntitlements(current: Discount[], scanned: Discount[]): Discount[];
|
|
7
|
+
/** Historical uses are display records; backend balance already excludes them. */
|
|
8
|
+
export declare function withCommittedEntitlementDetails(discounts: Discount[], products: any[], getProduct: (item: any) => any): Discount[];
|