@pisell/pisellos 0.10.46 → 0.10.48

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.
@@ -1 +1,46 @@
1
- "use strict";
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "BUY_X_GET_Y_FREE_STRATEGY", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _examples.BUY_X_GET_Y_FREE_STRATEGY;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "ITEM_REWARD_STRATEGY", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _examples.ITEM_REWARD_STRATEGY;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "PromotionAdapter", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _adapter.PromotionAdapter;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "PromotionEvaluator", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _evaluator.PromotionEvaluator;
28
+ }
29
+ });
30
+ Object.defineProperty(exports, "X_ITEMS_FOR_Y_PRICE_STRATEGY", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return _examples.X_ITEMS_FOR_Y_PRICE_STRATEGY;
34
+ }
35
+ });
36
+ Object.defineProperty(exports, "default", {
37
+ enumerable: true,
38
+ get: function () {
39
+ return _adapter.default;
40
+ }
41
+ });
42
+ var _evaluator = require("./evaluator");
43
+ var _adapter = _interopRequireWildcard(require("./adapter"));
44
+ var _examples = require("./examples");
45
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
46
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -45,6 +45,8 @@ interface ApplicableProductDetails {
45
45
  num: number;
46
46
  metadata?: {
47
47
  product_discount_difference?: number;
48
+ /** 月卡扣除本单新增使用后的剩余次数;不限次数时为 null。 */
49
+ balance?: number | null;
48
50
  };
49
51
  discount?: {
50
52
  fixed_amount?: number;
@@ -16,8 +16,8 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
16
16
  getWalletPassEvaluator(): import("../..").WalletPassEvaluator | undefined;
17
17
  private normalizeHolderRecordIds;
18
18
  /**
19
- * 特定 form Holder 卡只授权给绑定同一 Holder Record 的商品行。
20
- * required/isNeedHolder 仅控制是否强制选择 Holder,不参与优惠资格。
19
+ * 商品未开启 Holder 选择时跳过匹配;已开启时,特定 form Holder 卡
20
+ * 只适用于同一 Holder Record,是否必填不影响匹配规则。
21
21
  */
22
22
  private checkHolderMatch;
23
23
  isDiscountListAvailable({ oldDiscountList, newDiscountList, productList, orderTotalAmount, holders, isFormSubject, }: {
@@ -51,12 +51,20 @@ class RulesModule extends _BaseModule.BaseModule {
51
51
  }
52
52
 
53
53
  /**
54
- * 特定 form Holder 卡只授权给绑定同一 Holder Record 的商品行。
55
- * required/isNeedHolder 仅控制是否强制选择 Holder,不参与优惠资格。
54
+ * 商品未开启 Holder 选择时跳过匹配;已开启时,特定 form Holder 卡
55
+ * 只适用于同一 Holder Record,是否必填不影响匹配规则。
56
56
  */
57
- checkHolderMatch(discount, product, holders) {
57
+ checkHolderMatch(discount, product, holderSource, holders) {
58
58
  // 非表单类型 holder 视为匹配
59
59
  if (discount.holder?.holder_type !== 'form') return true;
60
+
61
+ // getProduct 会裁剪商品字段,从原始商品读取配置,套餐子项沿用父商品。
62
+ const holderConfig = holderSource?.holder_config ?? holderSource?.metadata?.holder_config ?? holderSource?.origin?.holder_config ?? holderSource?.metadata?.origin?.holder_config ?? holderSource?._origin?.holder_config ?? holderSource?._extend?.holder_config ?? holderSource?._extend?.product?.holder_config ?? holderSource?._extend?.product?.metadata?.holder_config;
63
+ const holderStatus = holderConfig?.status;
64
+ const holderEnabled = holderStatus === true || ['enable', '1'].includes(String(holderStatus).trim().toLowerCase());
65
+ if (!holderEnabled || holderConfig?.resource_id === undefined || holderConfig?.resource_id === null || holderConfig?.resource_id === '') {
66
+ return true;
67
+ }
60
68
  const discountHolderIds = this.normalizeHolderRecordIds(discount.holder.holder_id);
61
69
  if (!discountHolderIds.length) return false;
62
70
  const productHolderIds = this.normalizeHolderRecordIds(product.holder_id);
@@ -914,7 +922,7 @@ class RulesModule extends _BaseModule.BaseModule {
914
922
  const isHolderMatch = this.checkHolderMatch(discount, {
915
923
  isNeedHolder: resolveIsFormSubject(_tempVar) && !_tempVar?.isNormalProduct,
916
924
  holder_id: _tempVar?.holder_id || product.holder_id
917
- }, holders);
925
+ }, flatItem.originProduct, holders);
918
926
  const timeReason = (0, _utils.getDiscountTimeUnavailableReason)(discount, (product?.startDate || (0, _dayjs.default)()).format('YYYY-MM-DD HH:mm:ss'));
919
927
  const timeLimit = !timeReason;
920
928
  // 是符合折扣的商品
@@ -1127,7 +1135,7 @@ class RulesModule extends _BaseModule.BaseModule {
1127
1135
  const isHolderMatch = this.checkHolderMatch(discount, {
1128
1136
  isNeedHolder: resolveIsFormSubject(_tempVar) && !_tempVar?.isNormalProduct,
1129
1137
  holder_id: _tempVar?.holder_id || product.holder_id
1130
- }, holders);
1138
+ }, flatItem.originProduct, holders);
1131
1139
  // 如果 holder 不匹配,则不适用
1132
1140
  if (!isHolderMatch) return false;
1133
1141
  let timeLimit = true;
@@ -2118,9 +2126,65 @@ class RulesModule extends _BaseModule.BaseModule {
2118
2126
  appliedProductDetails: committedAppliedProductDetails
2119
2127
  };
2120
2128
  });
2129
+
2130
+ // 整单分配完成后统一记录卡余额;历史使用已包含在服务端余额中,只扣本次新增次数。
2131
+ const entitlementBalances = new Map();
2132
+ addModeDiscount.forEach(discount => {
2133
+ const quota = (0, _entitlementPass.resolveEntitlementQuota)(discount);
2134
+ if (!quota) return;
2135
+ entitlementBalances.set(String(discount.id), quota.type === 'unlimited' ? null : Math.max(quota.balance - (entitlementUsageCounts.get(discount.id) || 0), 0));
2136
+ });
2137
+ const getEntitlementBalance = detail => {
2138
+ if (!(0, _entitlementPass.isEntitlementPass)(detail)) return undefined;
2139
+ const resourceId = detail?.discount?.resource_id ?? detail?.resource_id;
2140
+ return entitlementBalances.get(String(resourceId));
2141
+ };
2142
+ const needsEntitlementBalance = detail => {
2143
+ const balance = getEntitlementBalance(detail);
2144
+ return balance !== undefined && detail?.metadata?.balance !== balance;
2145
+ };
2146
+ const withEntitlementBalance = detail => {
2147
+ if (!needsEntitlementBalance(detail)) return detail;
2148
+ return {
2149
+ ...detail,
2150
+ metadata: {
2151
+ ...(detail.metadata || {}),
2152
+ balance: getEntitlementBalance(detail)
2153
+ }
2154
+ };
2155
+ };
2156
+ const getProductDiscountDetails = originProduct => {
2157
+ const product = this.hooks.getProduct(originProduct);
2158
+ return [...(product.discount_list || []), ...(product.bundle || []).flatMap(bundle => bundle.discount_list || [])];
2159
+ };
2160
+ const productsWithEntitlementBalances = entitlementBalances.size ? processedProductList.map(product => {
2161
+ if (!getProductDiscountDetails(product).some(needsEntitlementBalance)) {
2162
+ return product;
2163
+ }
2164
+ // 历史商品及套餐可能仍引用输入快照;仅复制有变化的行,并直接更新 metadata。
2165
+ // 不再次调用价格换算钩子,避免只补余额时改变商品价格。
2166
+ const nextProduct = (0, _lodashEs.cloneDeep)(product);
2167
+ getProductDiscountDetails(nextProduct).forEach(detail => {
2168
+ if (!needsEntitlementBalance(detail)) return;
2169
+ detail.metadata = withEntitlementBalance(detail).metadata;
2170
+ });
2171
+ return nextProduct;
2172
+ }) : processedProductList;
2173
+ const discountsWithEntitlementBalances = [...editModeDiscount, ...updatedDiscountList].map(discount => {
2174
+ if (!(0, _entitlementPass.isEntitlementPass)(discount) || !entitlementBalances.has(String(discount.id))) {
2175
+ return discount;
2176
+ }
2177
+ return {
2178
+ ...discount,
2179
+ appliedProductDetails: (discount.appliedProductDetails || []).map(withEntitlementBalance),
2180
+ ...(discount.committedAppliedProductDetails ? {
2181
+ committedAppliedProductDetails: discount.committedAppliedProductDetails.map(withEntitlementBalance)
2182
+ } : {})
2183
+ };
2184
+ });
2121
2185
  return {
2122
- productList: processedProductList,
2123
- discountList: [...editModeDiscount, ...updatedDiscountList]
2186
+ productList: productsWithEntitlementBalances,
2187
+ discountList: discountsWithEntitlementBalances
2124
2188
  };
2125
2189
  }
2126
2190
 
@@ -36,6 +36,8 @@ export type OrderSurchargeType = string;
36
36
  export interface OrderProductDiscountMetadata {
37
37
  /** 设备端本地唯一标识,用于与服务端记录对齐 */
38
38
  unique_identification_number?: string;
39
+ /** 月卡扣除本单新增使用后的剩余次数;不限次数时为 null。 */
40
+ balance?: number | null;
39
41
  [key: string]: unknown;
40
42
  }
41
43
  /**