@pisell/pisellos 0.10.8 → 0.10.9
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/core/index.js +0 -1
- package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
- package/dist/model/strategy/adapter/dataVariant/evaluator.js +287 -101
- package/dist/model/strategy/adapter/dataVariant/type.d.ts +25 -0
- package/dist/model/strategy/adapter/promotion/index.js +0 -9
- package/dist/model/strategy/adapter/walletPass/evaluator.js +0 -2
- package/dist/model/strategy/adapter/walletPass/type.d.ts +5 -0
- package/dist/model/strategy/adapter/walletPass/utils.js +57 -26
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +7 -3
- package/dist/modules/BookingContext/utils/productExtend.js +5 -9
- package/dist/modules/BookingContext/utils/timeSlices.js +24 -3
- package/dist/modules/Customer/index.d.ts +4 -0
- package/dist/modules/Customer/index.js +91 -59
- package/dist/modules/Customer/types.d.ts +2 -0
- package/dist/modules/Discount/index.d.ts +2 -0
- package/dist/modules/Discount/index.js +38 -5
- package/dist/modules/Discount/types.d.ts +11 -0
- package/dist/modules/Order/index.d.ts +20 -1
- package/dist/modules/Order/index.js +976 -730
- package/dist/modules/Order/types.d.ts +6 -1
- package/dist/modules/Order/utils/virtualSettlement.d.ts +56 -0
- package/dist/modules/Order/utils/virtualSettlement.js +271 -0
- package/dist/modules/Order/utils.js +89 -48
- package/dist/modules/Payment/types.d.ts +2 -0
- package/dist/modules/Payment/utils.js +4 -1
- package/dist/modules/Payment/walletpass.d.ts +11 -0
- package/dist/modules/Payment/walletpass.js +235 -60
- package/dist/modules/Product/types.d.ts +23 -0
- package/dist/modules/ProductList/index.d.ts +15 -2
- package/dist/modules/ProductList/index.js +92 -13
- package/dist/modules/SalesSummary/index.d.ts +1 -0
- package/dist/modules/SalesSummary/index.js +4 -3
- package/dist/modules/SalesSummary/types.d.ts +1 -0
- package/dist/modules/SalesSummary/utils.d.ts +1 -0
- package/dist/modules/SalesSummary/utils.js +21 -1
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.js +90 -58
- package/dist/server/modules/order/index.d.ts +1 -0
- package/dist/server/modules/order/index.js +252 -94
- package/dist/server/utils/small-ticket.js +2 -1
- package/dist/solution/BaseSales/index.d.ts +26 -2
- package/dist/solution/BaseSales/index.js +1310 -931
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +78 -12
- package/dist/solution/BookingByStep/index.d.ts +3 -3
- package/dist/solution/BookingTicket/index.d.ts +5 -1
- package/dist/solution/BookingTicket/index.js +221 -159
- package/dist/solution/BookingTicket/utils/addProductDecision.js +2 -1
- package/dist/solution/ScanOrder/index.js +25 -64
- package/lib/core/index.js +0 -1
- package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +170 -7
- package/lib/model/strategy/adapter/dataVariant/type.d.ts +25 -0
- package/lib/model/strategy/adapter/walletPass/evaluator.js +0 -2
- package/lib/model/strategy/adapter/walletPass/type.d.ts +5 -0
- package/lib/model/strategy/adapter/walletPass/utils.js +62 -11
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +3 -0
- package/lib/modules/BookingContext/utils/productExtend.js +4 -3
- package/lib/modules/BookingContext/utils/timeSlices.js +18 -3
- package/lib/modules/Customer/index.d.ts +4 -0
- package/lib/modules/Customer/index.js +11 -0
- package/lib/modules/Customer/types.d.ts +2 -0
- package/lib/modules/Discount/index.d.ts +2 -0
- package/lib/modules/Discount/index.js +37 -3
- package/lib/modules/Discount/types.d.ts +11 -0
- package/lib/modules/Order/index.d.ts +20 -1
- package/lib/modules/Order/index.js +393 -128
- package/lib/modules/Order/types.d.ts +6 -1
- package/lib/modules/Order/utils/virtualSettlement.d.ts +56 -0
- package/lib/modules/Order/utils/virtualSettlement.js +300 -0
- package/lib/modules/Order/utils.js +65 -21
- package/lib/modules/Payment/types.d.ts +2 -0
- package/lib/modules/Payment/utils.js +5 -1
- package/lib/modules/Payment/walletpass.d.ts +11 -0
- package/lib/modules/Payment/walletpass.js +198 -17
- package/lib/modules/Product/types.d.ts +23 -0
- package/lib/modules/ProductList/index.d.ts +15 -2
- package/lib/modules/ProductList/index.js +85 -3
- package/lib/modules/SalesSummary/index.d.ts +1 -0
- package/lib/modules/SalesSummary/index.js +10 -2
- package/lib/modules/SalesSummary/types.d.ts +1 -0
- package/lib/modules/SalesSummary/utils.d.ts +1 -0
- package/lib/modules/SalesSummary/utils.js +25 -1
- package/lib/server/index.d.ts +9 -0
- package/lib/server/index.js +54 -14
- package/lib/server/modules/order/index.d.ts +1 -0
- package/lib/server/modules/order/index.js +66 -2
- package/lib/server/utils/small-ticket.js +1 -1
- package/lib/solution/BaseSales/index.d.ts +26 -2
- package/lib/solution/BaseSales/index.js +261 -23
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +61 -11
- package/lib/solution/BookingByStep/index.d.ts +3 -3
- package/lib/solution/BookingTicket/index.d.ts +5 -1
- package/lib/solution/BookingTicket/index.js +30 -2
- package/lib/solution/BookingTicket/utils/addProductDecision.js +2 -1
- package/lib/solution/ScanOrder/index.js +17 -54
- package/package.json +1 -1
|
@@ -318,7 +318,7 @@ export function transformDetailToProductAndBooking(cacheItem, ctx) {
|
|
|
318
318
|
* 把 cacheItem._extend.other 中的字段 + 顶层运行态拼成 `BaseProductDetailPayload`。
|
|
319
319
|
*/
|
|
320
320
|
function buildBasePayloadFromCacheItem(cacheItem, ctx) {
|
|
321
|
-
var _cacheItem$_extend, _cacheItem$_extend$qu, _cacheItem$_extend2, _cacheItem$product_id, _cacheItem$id, _ref5, _other$product_varian, _extend$skuValue, _extend$_skuValue, _extend$price, _extend$price2;
|
|
321
|
+
var _cacheItem$_extend, _cacheItem$_extend$qu, _cacheItem$_extend2, _cacheItem$product_id, _cacheItem$id, _ref5, _other$product_varian, _extend$skuValue, _extend$_skuValue, _extend$price, _extend$price2, _cacheItem$metadata$s, _cacheItem$metadata, _extend$metadata;
|
|
322
322
|
var other = (cacheItem === null || cacheItem === void 0 || (_cacheItem$_extend = cacheItem._extend) === null || _cacheItem$_extend === void 0 ? void 0 : _cacheItem$_extend.other) || {};
|
|
323
323
|
var quantity = (ctx === null || ctx === void 0 ? void 0 : ctx.quantity) != null && ctx.quantity > 0 ? ctx.quantity : (_cacheItem$_extend$qu = cacheItem === null || cacheItem === void 0 || (_cacheItem$_extend2 = cacheItem._extend) === null || _cacheItem$_extend2 === void 0 ? void 0 : _cacheItem$_extend2.quantity) !== null && _cacheItem$_extend$qu !== void 0 ? _cacheItem$_extend$qu : 1;
|
|
324
324
|
var resolvedPid = (_cacheItem$product_id = cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.product_id) !== null && _cacheItem$product_id !== void 0 ? _cacheItem$product_id : cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.id;
|
|
@@ -347,6 +347,7 @@ function buildBasePayloadFromCacheItem(cacheItem, ctx) {
|
|
|
347
347
|
bundle_edit: extend === null || extend === void 0 ? void 0 : extend.bundle_edit,
|
|
348
348
|
discount_reason: extend === null || extend === void 0 ? void 0 : extend.discount_reason,
|
|
349
349
|
discount_list: cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.discount_list,
|
|
350
|
+
selected_settlement_snapshot: (_cacheItem$metadata$s = cacheItem === null || cacheItem === void 0 || (_cacheItem$metadata = cacheItem.metadata) === null || _cacheItem$metadata === void 0 ? void 0 : _cacheItem$metadata.selected_settlement_snapshot) !== null && _cacheItem$metadata$s !== void 0 ? _cacheItem$metadata$s : extend === null || extend === void 0 || (_extend$metadata = extend.metadata) === null || _extend$metadata === void 0 ? void 0 : _extend$metadata.selected_settlement_snapshot,
|
|
350
351
|
_extend: extend
|
|
351
352
|
};
|
|
352
353
|
}
|
|
@@ -2757,10 +2757,6 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseSalesImpl) {
|
|
|
2757
2757
|
ruleProductsForResource,
|
|
2758
2758
|
occupancyMinutes,
|
|
2759
2759
|
paxBounds,
|
|
2760
|
-
error,
|
|
2761
|
-
_occupancyMinutes,
|
|
2762
|
-
_paxBounds,
|
|
2763
|
-
_error,
|
|
2764
2760
|
occupyDetails,
|
|
2765
2761
|
occupyDetail,
|
|
2766
2762
|
resourceSelectType,
|
|
@@ -2903,59 +2899,24 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseSalesImpl) {
|
|
|
2903
2899
|
});
|
|
2904
2900
|
case 46:
|
|
2905
2901
|
loaded = _context37.sent;
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
if ((paxBounds === null || paxBounds === void 0 ? void 0 : paxBounds.max) !== undefined) pendingRequestPaxMax = paxBounds.max;
|
|
2919
|
-
}
|
|
2920
|
-
} else {
|
|
2921
|
-
this.enabledReservationRuleProducts = [];
|
|
2922
|
-
error = loaded instanceof Error ? loaded : new Error('预约规则商品列表接口返回异常');
|
|
2923
|
-
this.logMethodError('loadReservationRuleProducts', error, {
|
|
2924
|
-
resourceId: normalizedResourceId,
|
|
2925
|
-
reservationLinkIds: reservationLinkIds,
|
|
2926
|
-
scheduleDate: scheduleDate,
|
|
2927
|
-
scheduleDatetime: scheduleDatetime,
|
|
2928
|
-
cacheId: this.cacheId
|
|
2929
|
-
});
|
|
2930
|
-
if (Array.isArray(loaded)) {
|
|
2931
|
-
this.enabledReservationRuleProducts = loaded;
|
|
2932
|
-
_occupancyMinutes = pickFirstDurationMinutesFromProducts(loaded);
|
|
2933
|
-
if (_occupancyMinutes !== undefined) {
|
|
2934
|
-
tempOrder.metadata.table_occupancy_duration = _occupancyMinutes;
|
|
2935
|
-
}
|
|
2936
|
-
if (hasCustomCapacityProduct(loaded)) {
|
|
2937
|
-
pendingRequestEntryPax = 1;
|
|
2938
|
-
_paxBounds = pickFirstCustomCapacityPaxBounds(loaded);
|
|
2939
|
-
if ((_paxBounds === null || _paxBounds === void 0 ? void 0 : _paxBounds.min) !== undefined) pendingRequestPaxMin = _paxBounds.min;
|
|
2940
|
-
if ((_paxBounds === null || _paxBounds === void 0 ? void 0 : _paxBounds.max) !== undefined) pendingRequestPaxMax = _paxBounds.max;
|
|
2941
|
-
}
|
|
2942
|
-
} else {
|
|
2943
|
-
this.enabledReservationRuleProducts = [];
|
|
2944
|
-
_error = loaded instanceof Error ? loaded : new Error('预约规则商品列表接口返回异常');
|
|
2945
|
-
this.logMethodError('loadReservationRuleProducts', _error, {
|
|
2946
|
-
resourceId: resourceId,
|
|
2947
|
-
reservationLinkIds: reservationLinkIds,
|
|
2948
|
-
scheduleDate: scheduleDate,
|
|
2949
|
-
scheduleDatetime: scheduleDatetime,
|
|
2950
|
-
cacheId: this.cacheId
|
|
2951
|
-
});
|
|
2952
|
-
}
|
|
2902
|
+
matchedRuleProduct = findReservationRuleProductByResourceId(loaded, normalizedResourceId);
|
|
2903
|
+
ruleProductsForResource = matchedRuleProduct ? [matchedRuleProduct] : [];
|
|
2904
|
+
this.enabledReservationRuleProducts = ruleProductsForResource;
|
|
2905
|
+
occupancyMinutes = pickFirstDurationMinutesFromProducts(ruleProductsForResource);
|
|
2906
|
+
if (occupancyMinutes !== undefined) {
|
|
2907
|
+
tempOrder.metadata.table_occupancy_duration = occupancyMinutes;
|
|
2908
|
+
}
|
|
2909
|
+
if (hasCustomCapacityProduct(ruleProductsForResource)) {
|
|
2910
|
+
pendingRequestEntryPax = 1;
|
|
2911
|
+
paxBounds = pickFirstCustomCapacityPaxBounds(ruleProductsForResource);
|
|
2912
|
+
if ((paxBounds === null || paxBounds === void 0 ? void 0 : paxBounds.min) !== undefined) pendingRequestPaxMin = paxBounds.min;
|
|
2913
|
+
if ((paxBounds === null || paxBounds === void 0 ? void 0 : paxBounds.max) !== undefined) pendingRequestPaxMax = paxBounds.max;
|
|
2953
2914
|
}
|
|
2954
2915
|
|
|
2955
2916
|
// Step2: 请求新的资源占用详情接口。occupy_details 第一维是资源,不是订单。
|
|
2956
|
-
_context37.next =
|
|
2917
|
+
_context37.next = 55;
|
|
2957
2918
|
return this.fetchResourceOccupyDetailsByResourceId(normalizedResourceId);
|
|
2958
|
-
case
|
|
2919
|
+
case 55:
|
|
2959
2920
|
occupyDetails = _context37.sent;
|
|
2960
2921
|
occupyDetail = (_occupyDetails$ = occupyDetails[0]) !== null && _occupyDetails$ !== void 0 ? _occupyDetails$ : null; // Step3: 结合预约规则商品的 product_resource.resources 与占用接口返回的 form_id,
|
|
2961
2922
|
// 计算当前桌台的 resourceSelectType(single/multiple/capacity)
|
|
@@ -2963,7 +2924,7 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseSalesImpl) {
|
|
|
2963
2924
|
allowAddItems = toBoolean(dineInConfig === null || dineInConfig === void 0 ? void 0 : dineInConfig['sale.allow_add_items']);
|
|
2964
2925
|
additionalOrderResult = this.resolveAdditionalOrderFromOccupyDetail(occupyDetail, resourceSelectType, allowAddItems);
|
|
2965
2926
|
if (!(additionalOrderResult.reason === 'multiple_orders')) {
|
|
2966
|
-
_context37.next =
|
|
2927
|
+
_context37.next = 66;
|
|
2967
2928
|
break;
|
|
2968
2929
|
}
|
|
2969
2930
|
multipleOrdersState = _objectSpread(_objectSpread({}, this.normalizeResourceState(occupyDetail, resourceSelectType, hasOrderId)), {}, {
|
|
@@ -2984,7 +2945,7 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseSalesImpl) {
|
|
|
2984
2945
|
resourceSelectType: resourceSelectType
|
|
2985
2946
|
});
|
|
2986
2947
|
return _context37.abrupt("return", _availabilityInfo);
|
|
2987
|
-
case
|
|
2948
|
+
case 66:
|
|
2988
2949
|
// Step4: 用 occupyDetail + resourceSelectType 规整为 resourceState
|
|
2989
2950
|
resourceState = this.normalizeResourceState(occupyDetail, resourceSelectType, hasOrderId);
|
|
2990
2951
|
additionalOrderId = additionalOrderResult.order_id;
|
|
@@ -3030,12 +2991,12 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseSalesImpl) {
|
|
|
3030
2991
|
|
|
3031
2992
|
// 空闲状态下自动准备本地临时订单,供后续“购物车式”商品操作使用
|
|
3032
2993
|
if (!(availabilityInfo.mode === 'idle')) {
|
|
3033
|
-
_context37.next =
|
|
2994
|
+
_context37.next = 78;
|
|
3034
2995
|
break;
|
|
3035
2996
|
}
|
|
3036
|
-
_context37.next =
|
|
2997
|
+
_context37.next = 78;
|
|
3037
2998
|
return this.addNewOrder();
|
|
3038
|
-
case
|
|
2999
|
+
case 78:
|
|
3039
3000
|
isAdditionalOrderMode = availabilityInfo.mode === 'additional_order' || availabilityInfo.mode === 'additional_order_with_code'; // 如果是加单模式,tempOrder 里需要记录目标订单 id,提交的时候走加单接口
|
|
3040
3001
|
if (isAdditionalOrderMode) {
|
|
3041
3002
|
tempOrder.order_id = additionalOrderId;
|
|
@@ -3051,13 +3012,13 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseSalesImpl) {
|
|
|
3051
3012
|
} : {}));
|
|
3052
3013
|
return acc;
|
|
3053
3014
|
}, []) : []; // pax 由 setEntryPaxNumber 负责写入 itemRuleRuntimeConfig.pax
|
|
3054
|
-
_context37.next =
|
|
3015
|
+
_context37.next = 84;
|
|
3055
3016
|
return this.setItemRuleRuntimeConfig({
|
|
3056
3017
|
serviceType: (_this$otherParams18 = this.otherParams) === null || _this$otherParams18 === void 0 ? void 0 : _this$otherParams18.businessCode,
|
|
3057
3018
|
submissionIndex: isAdditionalOrderMode ? 1 : 0,
|
|
3058
3019
|
historicalItems: historicalItems
|
|
3059
3020
|
});
|
|
3060
|
-
case
|
|
3021
|
+
case 84:
|
|
3061
3022
|
// operating_hours 超出营业时段 + closed_behavior=show_menu_disabled:
|
|
3062
3023
|
// 允许浏览商品但 UI 层需拦截“下一步”,这里覆盖最终 mode 并回传错误提示
|
|
3063
3024
|
if (outsideOperatingHours && closedBehaviorValue === 'show_menu_disabled') {
|
|
@@ -3079,18 +3040,18 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseSalesImpl) {
|
|
|
3079
3040
|
isFull: resourceState.isFull
|
|
3080
3041
|
});
|
|
3081
3042
|
return _context37.abrupt("return", availabilityInfo);
|
|
3082
|
-
case
|
|
3083
|
-
_context37.prev =
|
|
3043
|
+
case 89:
|
|
3044
|
+
_context37.prev = 89;
|
|
3084
3045
|
_context37.t0 = _context37["catch"](3);
|
|
3085
3046
|
this.logMethodError('checkResourceAvailable', _context37.t0.message, {
|
|
3086
3047
|
resourceId: normalizedResourceId
|
|
3087
3048
|
});
|
|
3088
3049
|
throw _context37.t0;
|
|
3089
|
-
case
|
|
3050
|
+
case 93:
|
|
3090
3051
|
case "end":
|
|
3091
3052
|
return _context37.stop();
|
|
3092
3053
|
}
|
|
3093
|
-
}, _callee37, this, [[3,
|
|
3054
|
+
}, _callee37, this, [[3, 89]]);
|
|
3094
3055
|
}));
|
|
3095
3056
|
function checkResourceAvailable(_x20) {
|
|
3096
3057
|
return _checkResourceAvailable.apply(this, arguments);
|
package/lib/core/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import type { ConditionScope, DataVariantBusinessData, DataVariantMenu, DataVari
|
|
|
3
3
|
/**
|
|
4
4
|
* Data Variant 评估器。
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* OS Server 商品路由开启时由 ProductsModule 调用;路由关闭时由 ProductList 在远端响应后调用。
|
|
7
7
|
*/
|
|
8
8
|
export declare class DataVariantEvaluator {
|
|
9
9
|
private adapter;
|
|
@@ -17,7 +17,7 @@ export declare class DataVariantEvaluator {
|
|
|
17
17
|
/**
|
|
18
18
|
* 批量解析商品 Data Variant。
|
|
19
19
|
*
|
|
20
|
-
*
|
|
20
|
+
* 优先使用商品 metadata.data_variant_ids;缺少权威命中结果时才执行本地策略判断。
|
|
21
21
|
*/
|
|
22
22
|
resolveProducts(businessData: DataVariantBusinessData): ResolvedDataVariantResult;
|
|
23
23
|
/**
|
|
@@ -34,8 +34,24 @@ export declare class DataVariantEvaluator {
|
|
|
34
34
|
* 这里不依赖餐牌,只读取策略配置和调用方传入的 scheduleList。
|
|
35
35
|
*/
|
|
36
36
|
buildScheduleTimePoints(strategyConfigs: StrategyConfig<DataVariantRuleMetadata>[], scheduleList: NonNullable<DataVariantBusinessData['scheduleList']>): string[];
|
|
37
|
+
/**
|
|
38
|
+
* 判断商品(含套餐子商品)是否仍需要本地执行策略条件。
|
|
39
|
+
* metadata.data_variant_ids 只要是数组,即使为空,也表示接口已经给出权威命中结果。
|
|
40
|
+
*/
|
|
41
|
+
private requiresLocalStrategyEvaluation;
|
|
42
|
+
/**
|
|
43
|
+
* 将接口返回的高 -> 低优先级 Variant ID 转成数值优先级。
|
|
44
|
+
* 返回 null 表示接口没有提供该字段;空 Map 表示已计算但没有任何命中。
|
|
45
|
+
*/
|
|
46
|
+
private getAuthoritativeVariantPriorities;
|
|
47
|
+
private normalizeDataVariantId;
|
|
37
48
|
private buildGlobalEffectiveRuleMap;
|
|
38
49
|
private resolveProduct;
|
|
50
|
+
/**
|
|
51
|
+
* 多货币 Data Variant 只生成候选列表,不参与商品字段覆盖。
|
|
52
|
+
* rule_id=0 是无条件默认价;同币种命中的条件价优先于默认价。
|
|
53
|
+
*/
|
|
54
|
+
private resolveSettlementOptions;
|
|
39
55
|
/**
|
|
40
56
|
* 解析套餐子商品上的 Data Variant 覆盖。
|
|
41
57
|
*
|
|
@@ -43,7 +43,7 @@ var DataVariantEvaluator = class {
|
|
|
43
43
|
/**
|
|
44
44
|
* 批量解析商品 Data Variant。
|
|
45
45
|
*
|
|
46
|
-
*
|
|
46
|
+
* 优先使用商品 metadata.data_variant_ids;缺少权威命中结果时才执行本地策略判断。
|
|
47
47
|
*/
|
|
48
48
|
resolveProducts(businessData) {
|
|
49
49
|
const strategyConfigs = businessData.strategyConfigs ? this.normalizeStrategyConfigs(businessData.strategyConfigs) : this.strategyConfigs;
|
|
@@ -52,11 +52,17 @@ var DataVariantEvaluator = class {
|
|
|
52
52
|
strategyConfigs,
|
|
53
53
|
businessData.scheduleList || []
|
|
54
54
|
);
|
|
55
|
-
const
|
|
55
|
+
const shouldEvaluateStrategies = businessData.products.some(
|
|
56
|
+
(product) => this.requiresLocalStrategyEvaluation(product)
|
|
57
|
+
);
|
|
58
|
+
const { globalEffectiveRuleMap, rawResults } = shouldEvaluateStrategies ? this.buildGlobalEffectiveRuleMap(
|
|
56
59
|
strategyConfigs,
|
|
57
60
|
businessData,
|
|
58
61
|
menuScopeMap
|
|
59
|
-
)
|
|
62
|
+
) : {
|
|
63
|
+
globalEffectiveRuleMap: /* @__PURE__ */ new Map(),
|
|
64
|
+
rawResults: []
|
|
65
|
+
};
|
|
60
66
|
const products = businessData.products.map((product) => {
|
|
61
67
|
const resolvedProduct = this.resolveProduct(
|
|
62
68
|
product,
|
|
@@ -154,6 +160,56 @@ var DataVariantEvaluator = class {
|
|
|
154
160
|
);
|
|
155
161
|
return this.extractTimePointsFromSchedules(matchedSchedules);
|
|
156
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* 判断商品(含套餐子商品)是否仍需要本地执行策略条件。
|
|
165
|
+
* metadata.data_variant_ids 只要是数组,即使为空,也表示接口已经给出权威命中结果。
|
|
166
|
+
*/
|
|
167
|
+
requiresLocalStrategyEvaluation(product) {
|
|
168
|
+
const dataVariants = this.getProductDataVariants(product);
|
|
169
|
+
const hasConditionalVariant = dataVariants.some(
|
|
170
|
+
(variant) => Number(variant.data_variant_rule_id) !== 0
|
|
171
|
+
);
|
|
172
|
+
if (hasConditionalVariant && this.getAuthoritativeVariantPriorities(product) === null) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
const bundleGroups = Array.isArray(product.bundle_group) ? product.bundle_group : [];
|
|
176
|
+
return bundleGroups.some((group) => {
|
|
177
|
+
const bundleItems = Array.isArray(group == null ? void 0 : group.bundle_item) ? group.bundle_item : [];
|
|
178
|
+
return bundleItems.some(
|
|
179
|
+
(item) => this.requiresLocalStrategyEvaluation(
|
|
180
|
+
this.toBundleItemDataVariantProduct(item)
|
|
181
|
+
)
|
|
182
|
+
);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* 将接口返回的高 -> 低优先级 Variant ID 转成数值优先级。
|
|
187
|
+
* 返回 null 表示接口没有提供该字段;空 Map 表示已计算但没有任何命中。
|
|
188
|
+
*/
|
|
189
|
+
getAuthoritativeVariantPriorities(product) {
|
|
190
|
+
var _a;
|
|
191
|
+
const rawIds = (_a = product == null ? void 0 : product.metadata) == null ? void 0 : _a.data_variant_ids;
|
|
192
|
+
if (!Array.isArray(rawIds))
|
|
193
|
+
return null;
|
|
194
|
+
const orderedIds = [];
|
|
195
|
+
const seen = /* @__PURE__ */ new Set();
|
|
196
|
+
for (const rawId of rawIds) {
|
|
197
|
+
const id = this.normalizeDataVariantId(rawId);
|
|
198
|
+
if (id === null || seen.has(id))
|
|
199
|
+
continue;
|
|
200
|
+
seen.add(id);
|
|
201
|
+
orderedIds.push(id);
|
|
202
|
+
}
|
|
203
|
+
return new Map(
|
|
204
|
+
orderedIds.map((id, index) => [id, orderedIds.length - index])
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
normalizeDataVariantId(value) {
|
|
208
|
+
if (value === void 0 || value === null)
|
|
209
|
+
return null;
|
|
210
|
+
const normalized = String(value).trim();
|
|
211
|
+
return normalized || null;
|
|
212
|
+
}
|
|
157
213
|
buildGlobalEffectiveRuleMap(strategyConfigs, businessData, menuScopeMap) {
|
|
158
214
|
const globalEffectiveRuleMap = /* @__PURE__ */ new Map();
|
|
159
215
|
const rawResults = [];
|
|
@@ -182,7 +238,26 @@ var DataVariantEvaluator = class {
|
|
|
182
238
|
if (!dataVariants.length)
|
|
183
239
|
return product;
|
|
184
240
|
const matchedVariants = [];
|
|
241
|
+
const authoritativeVariantPriorities = this.getAuthoritativeVariantPriorities(product);
|
|
242
|
+
const settlementVariants = dataVariants.filter(
|
|
243
|
+
(variant) => variant.business_type === "multi_currency_settlement" && variant.status === "enable"
|
|
244
|
+
);
|
|
185
245
|
for (const variant of dataVariants) {
|
|
246
|
+
if (variant.business_type === "multi_currency_settlement")
|
|
247
|
+
continue;
|
|
248
|
+
if (authoritativeVariantPriorities !== null) {
|
|
249
|
+
const variantId = this.normalizeDataVariantId(variant.id);
|
|
250
|
+
const priority = variantId === null ? void 0 : authoritativeVariantPriorities.get(variantId);
|
|
251
|
+
if (priority === void 0)
|
|
252
|
+
continue;
|
|
253
|
+
matchedVariants.push({
|
|
254
|
+
ruleId: String(variant.data_variant_rule_id),
|
|
255
|
+
priority,
|
|
256
|
+
data: variant.data || {},
|
|
257
|
+
variant
|
|
258
|
+
});
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
186
261
|
const rule = globalEffectiveRuleMap.get(
|
|
187
262
|
String(variant.data_variant_rule_id)
|
|
188
263
|
);
|
|
@@ -198,9 +273,91 @@ var DataVariantEvaluator = class {
|
|
|
198
273
|
variant
|
|
199
274
|
});
|
|
200
275
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
276
|
+
const resolvedProduct = matchedVariants.length ? this.mergeMatchedVariants(product, matchedVariants) : product;
|
|
277
|
+
const availableSettlementOptions = this.resolveSettlementOptions(
|
|
278
|
+
settlementVariants,
|
|
279
|
+
product,
|
|
280
|
+
businessData,
|
|
281
|
+
globalEffectiveRuleMap,
|
|
282
|
+
menuScopeMap,
|
|
283
|
+
authoritativeVariantPriorities
|
|
284
|
+
);
|
|
285
|
+
if (!settlementVariants.length)
|
|
286
|
+
return resolvedProduct;
|
|
287
|
+
return {
|
|
288
|
+
...resolvedProduct,
|
|
289
|
+
available_settlement_options: availableSettlementOptions
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* 多货币 Data Variant 只生成候选列表,不参与商品字段覆盖。
|
|
294
|
+
* rule_id=0 是无条件默认价;同币种命中的条件价优先于默认价。
|
|
295
|
+
*/
|
|
296
|
+
resolveSettlementOptions(variants, product, businessData, globalEffectiveRuleMap, menuScopeMap, authoritativeVariantPriorities) {
|
|
297
|
+
if (!variants.length)
|
|
298
|
+
return [];
|
|
299
|
+
const candidates = variants.flatMap((variant) => {
|
|
300
|
+
var _a, _b;
|
|
301
|
+
const settlement = (_a = variant.data) == null ? void 0 : _a.multi_currency_settlement;
|
|
302
|
+
if (!settlement || typeof settlement !== "object")
|
|
303
|
+
return [];
|
|
304
|
+
const ruleId = String(variant.data_variant_rule_id);
|
|
305
|
+
const isDefault = Number(variant.data_variant_rule_id) === 0;
|
|
306
|
+
const rule = isDefault ? void 0 : globalEffectiveRuleMap.get(ruleId);
|
|
307
|
+
const variantId = this.normalizeDataVariantId(variant.id);
|
|
308
|
+
const authoritativePriority = variantId === null ? void 0 : authoritativeVariantPriorities == null ? void 0 : authoritativeVariantPriorities.get(variantId);
|
|
309
|
+
let available;
|
|
310
|
+
let priority;
|
|
311
|
+
if (isDefault) {
|
|
312
|
+
available = true;
|
|
313
|
+
priority = Number.NEGATIVE_INFINITY;
|
|
314
|
+
} else if (authoritativeVariantPriorities !== null) {
|
|
315
|
+
available = authoritativePriority !== void 0;
|
|
316
|
+
priority = authoritativePriority ?? (rule == null ? void 0 : rule.priority) ?? Number.NEGATIVE_INFINITY;
|
|
317
|
+
} else {
|
|
318
|
+
available = Boolean(
|
|
319
|
+
rule && this.evaluateProductRules(
|
|
320
|
+
rule,
|
|
321
|
+
product,
|
|
322
|
+
businessData,
|
|
323
|
+
menuScopeMap
|
|
324
|
+
)
|
|
325
|
+
);
|
|
326
|
+
priority = (rule == null ? void 0 : rule.priority) ?? Number.NEGATIVE_INFINITY;
|
|
327
|
+
}
|
|
328
|
+
const settlementType = String(settlement.settlement_type || "");
|
|
329
|
+
const currencyProductId = this.toNumber(settlement.currency_product_id);
|
|
330
|
+
const settlementKey = settlementType === "virtual_currency" ? `virtual_currency:${currencyProductId || ""}` : settlementType || `variant:${variant.id ?? ruleId}`;
|
|
331
|
+
return [{
|
|
332
|
+
key: settlementKey,
|
|
333
|
+
priority,
|
|
334
|
+
isDefault,
|
|
335
|
+
option: {
|
|
336
|
+
...settlement,
|
|
337
|
+
settlement_type: settlementType,
|
|
338
|
+
...currencyProductId ? { currency_product_id: currencyProductId } : {},
|
|
339
|
+
price: String(((_b = variant.data) == null ? void 0 : _b.price) ?? "0"),
|
|
340
|
+
data_variant_id: variant.id,
|
|
341
|
+
data_variant_rule_id: variant.data_variant_rule_id,
|
|
342
|
+
available,
|
|
343
|
+
disabled_reason: available ? "" : String(
|
|
344
|
+
settlement.disabled_reason || "Not available for this purchase."
|
|
345
|
+
)
|
|
346
|
+
}
|
|
347
|
+
}];
|
|
348
|
+
});
|
|
349
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
350
|
+
for (const candidate of candidates) {
|
|
351
|
+
const group = grouped.get(candidate.key) || [];
|
|
352
|
+
group.push(candidate);
|
|
353
|
+
grouped.set(candidate.key, group);
|
|
354
|
+
}
|
|
355
|
+
return Array.from(grouped.values()).map((group) => {
|
|
356
|
+
const matchedConditional = group.filter((candidate) => !candidate.isDefault && candidate.option.available).sort((a, b) => b.priority - a.priority)[0];
|
|
357
|
+
const defaultCandidate = group.find((candidate) => candidate.isDefault);
|
|
358
|
+
const unavailableCandidate = [...group].filter((candidate) => !candidate.option.available).sort((a, b) => b.priority - a.priority)[0];
|
|
359
|
+
return (matchedConditional || defaultCandidate || unavailableCandidate).option;
|
|
360
|
+
});
|
|
204
361
|
}
|
|
205
362
|
/**
|
|
206
363
|
* 解析套餐子商品上的 Data Variant 覆盖。
|
|
@@ -262,7 +419,8 @@ var DataVariantEvaluator = class {
|
|
|
262
419
|
product_variant_id: variantId,
|
|
263
420
|
variant_id: variantId,
|
|
264
421
|
collection: item.collection,
|
|
265
|
-
data_variants: item.data_variants
|
|
422
|
+
data_variants: item.data_variants,
|
|
423
|
+
metadata: item.metadata
|
|
266
424
|
};
|
|
267
425
|
}
|
|
268
426
|
/**
|
|
@@ -501,6 +659,11 @@ var DataVariantEvaluator = class {
|
|
|
501
659
|
}
|
|
502
660
|
result._dataVariant = {
|
|
503
661
|
appliedRuleIds,
|
|
662
|
+
appliedVariantIds: Array.from(
|
|
663
|
+
new Set(
|
|
664
|
+
[...sortedVariants].reverse().map((matched) => this.normalizeDataVariantId(matched.variant.id)).filter((id) => id !== null)
|
|
665
|
+
)
|
|
666
|
+
),
|
|
504
667
|
appliedFields: Array.from(appliedFields),
|
|
505
668
|
original
|
|
506
669
|
};
|
|
@@ -35,6 +35,10 @@ export interface DataVariantItem {
|
|
|
35
35
|
module_data_id?: number;
|
|
36
36
|
/** 关联策略模型 metadata.id / data_variant_rule.id */
|
|
37
37
|
data_variant_rule_id: number | string;
|
|
38
|
+
/** 业务类型;多货币结算候选不会走普通字段覆盖 */
|
|
39
|
+
business_type?: 'multi_currency_settlement' | string;
|
|
40
|
+
/** 数据状态;多货币结算仅处理 enable 记录 */
|
|
41
|
+
status?: 'enable' | 'disable' | string;
|
|
38
42
|
/** 命中策略后需要覆盖到商品上的字段 */
|
|
39
43
|
data: Record<string, any>;
|
|
40
44
|
created_at?: string | null;
|
|
@@ -53,11 +57,30 @@ export interface DataVariantProduct {
|
|
|
53
57
|
id?: number | string;
|
|
54
58
|
[key: string]: any;
|
|
55
59
|
}>;
|
|
60
|
+
/**
|
|
61
|
+
* 商品接口已经完成规则计算时返回的命中结果。
|
|
62
|
+
* 数组按 Data Variant 优先级从高到低排列;空数组表示已计算但无命中。
|
|
63
|
+
*/
|
|
64
|
+
metadata?: {
|
|
65
|
+
data_variant_ids?: Array<number | string>;
|
|
66
|
+
[key: string]: any;
|
|
67
|
+
};
|
|
56
68
|
/** 后端 /product/query with dataVariants 返回的智能定价变体列表 */
|
|
57
69
|
data_variants?: DataVariantItem[];
|
|
70
|
+
/** 当前上下文解析后的可选结算货币,不覆盖商品原始多货币配置 */
|
|
71
|
+
available_settlement_options?: AvailableSettlementOption[];
|
|
58
72
|
_dataVariant?: DataVariantAppliedInfo;
|
|
59
73
|
[key: string]: any;
|
|
60
74
|
}
|
|
75
|
+
export interface AvailableSettlementOption extends Record<string, any> {
|
|
76
|
+
settlement_type: 'legal_currency' | 'virtual_currency' | string;
|
|
77
|
+
currency_product_id?: number;
|
|
78
|
+
price: string;
|
|
79
|
+
data_variant_id?: number;
|
|
80
|
+
data_variant_rule_id: number | string;
|
|
81
|
+
available: boolean;
|
|
82
|
+
disabled_reason?: string;
|
|
83
|
+
}
|
|
61
84
|
/**
|
|
62
85
|
* 餐牌商品配置项。
|
|
63
86
|
*/
|
|
@@ -131,6 +154,8 @@ export interface MatchedDataVariant {
|
|
|
131
154
|
*/
|
|
132
155
|
export interface DataVariantAppliedInfo {
|
|
133
156
|
appliedRuleIds: string[];
|
|
157
|
+
/** 本地策略实际应用的 Data Variant ID,按优先级从高到低排列。 */
|
|
158
|
+
appliedVariantIds?: Array<number | string>;
|
|
134
159
|
appliedFields: string[];
|
|
135
160
|
original: DataVariantProduct;
|
|
136
161
|
}
|
|
@@ -214,7 +214,6 @@ var WalletPassEvaluator = class {
|
|
|
214
214
|
}
|
|
215
215
|
const rawText = this.getText(reasonCode);
|
|
216
216
|
const currency = failedField && AMOUNT_FIELDS.has(failedField) ? ((_g = (_f = this.otherParams) == null ? void 0 : _f.getData) == null ? void 0 : _g.call(_f, "shop_symbol")) || "" : "";
|
|
217
|
-
console.log(currency, "currency12345");
|
|
218
217
|
const reason = thresholdValue !== void 0 ? formatReason(rawText, thresholdValue, currency) : rawText;
|
|
219
218
|
results.push({
|
|
220
219
|
voucher,
|
|
@@ -416,7 +415,6 @@ var WalletPassEvaluator = class {
|
|
|
416
415
|
* 计算适用商品的总金额和数量
|
|
417
416
|
*/
|
|
418
417
|
calculateApplicableProducts(products, applicableProductIds, deductTaxAndFee) {
|
|
419
|
-
console.log(products, "products1234");
|
|
420
418
|
let total = 0;
|
|
421
419
|
let count = 0;
|
|
422
420
|
if (applicableProductIds !== null && applicableProductIds.length === 0) {
|
|
@@ -26,6 +26,11 @@ export interface Voucher {
|
|
|
26
26
|
recommended_usage_amount: number;
|
|
27
27
|
/** 后端计算推荐使用金额(仅商品) 不包含税费附加费 */
|
|
28
28
|
recommended_pure_product_usage_amount: number;
|
|
29
|
+
/**
|
|
30
|
+
* 扫码资产自身可供前端重新计算的金额基准。
|
|
31
|
+
* 后端 recommended_usage_amount 会包含当前已选券上下文,取消勾选后不能继续把它当作资产永久上限。
|
|
32
|
+
*/
|
|
33
|
+
_wallet_asset_recalculation_base_amount?: number;
|
|
29
34
|
/** 实际抵扣金额 */
|
|
30
35
|
actualDeduction: number;
|
|
31
36
|
/** 抵扣详情 */
|