@pisell/pisellos 0.0.479 → 0.0.480
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.
|
@@ -101,6 +101,18 @@ var getApplicableProducts = function getApplicableProducts(voucher, productsData
|
|
|
101
101
|
});
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* 计算指定 product_id 在展开后的商品列表中的总 quantity
|
|
106
|
+
* 处理同一 product_id 可能分散在多条记录中的情况(如3个独立的 quantity=1 条目)
|
|
107
|
+
*/
|
|
108
|
+
var getTotalQuantityByProductId = function getTotalQuantityByProductId(allProducts, productId) {
|
|
109
|
+
return allProducts.filter(function (p) {
|
|
110
|
+
return p.product_id === productId;
|
|
111
|
+
}).reduce(function (sum, p) {
|
|
112
|
+
return sum + getProductQuantity(p);
|
|
113
|
+
}, 0);
|
|
114
|
+
};
|
|
115
|
+
|
|
104
116
|
/**
|
|
105
117
|
* 优惠券处理函数
|
|
106
118
|
* @param applicableVouchers 可用的券列表
|
|
@@ -136,11 +148,11 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
|
|
|
136
148
|
};
|
|
137
149
|
|
|
138
150
|
// 按 maxPassesPerItem 过滤商品:排除已达到单商品可用卡券上限的商品
|
|
139
|
-
// maxPassesPerItem 是 per-unit 的限制,总上限 = maxPassesPerItem × quantity
|
|
140
|
-
var filterByMaxPassesPerItem = function filterByMaxPassesPerItem(products, usageMap, walletPassProductId, maxPassesPerItem) {
|
|
151
|
+
// maxPassesPerItem 是 per-unit 的限制,总上限 = maxPassesPerItem × 该 product_id 的总 quantity
|
|
152
|
+
var filterByMaxPassesPerItem = function filterByMaxPassesPerItem(products, allProducts, usageMap, walletPassProductId, maxPassesPerItem) {
|
|
141
153
|
if (maxPassesPerItem <= 0) return products; // 0 = 不限制
|
|
142
154
|
return products.filter(function (p) {
|
|
143
|
-
return getItemPassUsage(usageMap, walletPassProductId, p.product_id) < maxPassesPerItem *
|
|
155
|
+
return getItemPassUsage(usageMap, walletPassProductId, p.product_id) < maxPassesPerItem * getTotalQuantityByProductId(allProducts, p.product_id);
|
|
144
156
|
});
|
|
145
157
|
};
|
|
146
158
|
// ================================================================
|
|
@@ -177,7 +189,7 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
|
|
|
177
189
|
|
|
178
190
|
// 按 maxPassesPerItem 过滤:排除已达到单商品可用卡券上限的商品
|
|
179
191
|
if (itemPassUsage) {
|
|
180
|
-
applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsage, voucher.product_id, maxPassesPerItem);
|
|
192
|
+
applicableProducts = filterByMaxPassesPerItem(applicableProducts, productsData, itemPassUsage, voucher.product_id, maxPassesPerItem);
|
|
181
193
|
}
|
|
182
194
|
if (applicableProducts.length === 0) {
|
|
183
195
|
return new Decimal(0);
|
|
@@ -219,9 +231,9 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
|
|
|
219
231
|
}, new Decimal(0));
|
|
220
232
|
}
|
|
221
233
|
} else {
|
|
222
|
-
//
|
|
234
|
+
// 非跨商品券:选择单价最高的商品(优先抵扣高价商品)
|
|
223
235
|
var maxProduct = applicableProducts.reduce(function (max, p) {
|
|
224
|
-
return p[
|
|
236
|
+
return p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max;
|
|
225
237
|
});
|
|
226
238
|
// maxPassesPerItem 限制每张券最多抵扣的单位数
|
|
227
239
|
if (maxPassesPerItem > 0) {
|
|
@@ -289,7 +301,7 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
|
|
|
289
301
|
var availableAfterPassLimit = getApplicableProducts(voucher, productsData).filter(function (p) {
|
|
290
302
|
return p[amountField].greaterThan(0);
|
|
291
303
|
}).filter(function (p) {
|
|
292
|
-
return getItemPassUsage(itemPassUsage, product_id, p.product_id) < maxPassesPerItem *
|
|
304
|
+
return getItemPassUsage(itemPassUsage, product_id, p.product_id) < maxPassesPerItem * getTotalQuantityByProductId(productsData, p.product_id);
|
|
293
305
|
});
|
|
294
306
|
if (availableAfterPassLimit.length === 0) {
|
|
295
307
|
return {
|
|
@@ -386,7 +398,7 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
|
|
|
386
398
|
});
|
|
387
399
|
|
|
388
400
|
// 按 maxPassesPerItem 过滤:排除已达到单商品可用卡券上限的商品
|
|
389
|
-
applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsageMap, product_id, maxPassesPerItem);
|
|
401
|
+
applicableProducts = filterByMaxPassesPerItem(applicableProducts, productsForRecommendation, itemPassUsageMap, product_id, maxPassesPerItem);
|
|
390
402
|
if (applicableProducts.length === 0) return false;
|
|
391
403
|
|
|
392
404
|
// ========== 关键修改:在应用券之前,基于当前剩余金额计算 _available_max_amount ==========
|
|
@@ -428,9 +440,9 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
|
|
|
428
440
|
}, new Decimal(0));
|
|
429
441
|
}
|
|
430
442
|
} else {
|
|
431
|
-
//
|
|
443
|
+
// 非跨商品券:选择单价最高的商品(优先抵扣高价商品)
|
|
432
444
|
var maxProduct = applicableProducts.reduce(function (max, p) {
|
|
433
|
-
return p[
|
|
445
|
+
return p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max;
|
|
434
446
|
});
|
|
435
447
|
// maxPassesPerItem 限制每张券最多抵扣的单位数
|
|
436
448
|
if (maxPassesPerItem > 0) {
|
|
@@ -491,9 +503,9 @@ export function processVouchers(applicableVouchers, orderTotalAmount, products)
|
|
|
491
503
|
_iterator3.f();
|
|
492
504
|
}
|
|
493
505
|
} else {
|
|
494
|
-
//
|
|
506
|
+
// 非跨商品券:选择单价最高的商品(优先抵扣高价商品)
|
|
495
507
|
var targetProduct = applicableProducts.reduce(function (max, p) {
|
|
496
|
-
return p[
|
|
508
|
+
return p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max;
|
|
497
509
|
});
|
|
498
510
|
|
|
499
511
|
// maxPassesPerItem 限制每张券最多抵扣的单位数
|
|
@@ -629,7 +641,7 @@ export function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmo
|
|
|
629
641
|
var filterByMaxPassesPerItem = function filterByMaxPassesPerItem(products, walletPassProductId, maxPassesPerItem) {
|
|
630
642
|
if (maxPassesPerItem <= 0) return products; // 0 = 不限制
|
|
631
643
|
return products.filter(function (p) {
|
|
632
|
-
return getItemPassUsage(walletPassProductId, p.product_id) < maxPassesPerItem *
|
|
644
|
+
return getItemPassUsage(walletPassProductId, p.product_id) < maxPassesPerItem * getTotalQuantityByProductId(productsForCalc, p.product_id);
|
|
633
645
|
});
|
|
634
646
|
};
|
|
635
647
|
|
|
@@ -717,9 +729,9 @@ export function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmo
|
|
|
717
729
|
_iterator4.f();
|
|
718
730
|
}
|
|
719
731
|
} else {
|
|
720
|
-
//
|
|
732
|
+
// 非跨商品券:选择单价最高的商品(优先抵扣高价商品)
|
|
721
733
|
var targetProduct = applicableProducts.reduce(function (max, p) {
|
|
722
|
-
return p[
|
|
734
|
+
return p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max;
|
|
723
735
|
});
|
|
724
736
|
|
|
725
737
|
// maxPassesPerItem 限制每张券最多抵扣的单位数
|
|
@@ -864,9 +876,9 @@ export function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmo
|
|
|
864
876
|
}, new Decimal(0));
|
|
865
877
|
}
|
|
866
878
|
} else {
|
|
867
|
-
//
|
|
879
|
+
// 非跨商品券:选择单价最高的商品(优先抵扣高价商品)
|
|
868
880
|
var maxProduct = applicableProducts.reduce(function (max, p) {
|
|
869
|
-
return p[
|
|
881
|
+
return p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max;
|
|
870
882
|
});
|
|
871
883
|
// maxPassesPerItem 限制每张券最多抵扣的单位数
|
|
872
884
|
if (maxPassesPerItem > 0) {
|
|
@@ -86,6 +86,9 @@ var getApplicableProducts = (voucher, productsData) => {
|
|
|
86
86
|
}
|
|
87
87
|
return productsData.filter((p) => applicableProductIds.includes(p.product_id));
|
|
88
88
|
};
|
|
89
|
+
var getTotalQuantityByProductId = (allProducts, productId) => {
|
|
90
|
+
return allProducts.filter((p) => p.product_id === productId).reduce((sum, p) => sum + getProductQuantity(p), 0);
|
|
91
|
+
};
|
|
89
92
|
function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
90
93
|
console.log(products, "products123");
|
|
91
94
|
const productsCopy = expandProductsWithBundleItems(products, true);
|
|
@@ -101,11 +104,11 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
|
101
104
|
const innerMap = usageMap.get(walletPassProductId);
|
|
102
105
|
innerMap.set(orderItemProductId, (innerMap.get(orderItemProductId) || 0) + count);
|
|
103
106
|
};
|
|
104
|
-
const filterByMaxPassesPerItem = (products2, usageMap, walletPassProductId, maxPassesPerItem) => {
|
|
107
|
+
const filterByMaxPassesPerItem = (products2, allProducts, usageMap, walletPassProductId, maxPassesPerItem) => {
|
|
105
108
|
if (maxPassesPerItem <= 0)
|
|
106
109
|
return products2;
|
|
107
110
|
return products2.filter(
|
|
108
|
-
(p) => getItemPassUsage(usageMap, walletPassProductId, p.product_id) < maxPassesPerItem *
|
|
111
|
+
(p) => getItemPassUsage(usageMap, walletPassProductId, p.product_id) < maxPassesPerItem * getTotalQuantityByProductId(allProducts, p.product_id)
|
|
109
112
|
);
|
|
110
113
|
};
|
|
111
114
|
const calculateAvailableMaxAmount = (voucher, productsData, itemPassUsage) => {
|
|
@@ -120,7 +123,7 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
|
120
123
|
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
121
124
|
let applicableProducts = getApplicableProducts(voucher, productsData).filter((p) => p[amountField].greaterThan(0));
|
|
122
125
|
if (itemPassUsage) {
|
|
123
|
-
applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsage, voucher.product_id, maxPassesPerItem);
|
|
126
|
+
applicableProducts = filterByMaxPassesPerItem(applicableProducts, productsData, itemPassUsage, voucher.product_id, maxPassesPerItem);
|
|
124
127
|
}
|
|
125
128
|
if (applicableProducts.length === 0) {
|
|
126
129
|
return new import_decimal.default(0);
|
|
@@ -150,7 +153,7 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
|
150
153
|
}
|
|
151
154
|
} else {
|
|
152
155
|
const maxProduct = applicableProducts.reduce(
|
|
153
|
-
(max, p) => p[
|
|
156
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
154
157
|
);
|
|
155
158
|
if (maxPassesPerItem > 0) {
|
|
156
159
|
finalApplicableAmount = import_decimal.default.min(
|
|
@@ -186,7 +189,7 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
|
186
189
|
if (maxPassesPerItem > 0 && itemPassUsage) {
|
|
187
190
|
const deductTaxAndFee = (config == null ? void 0 : config.deductTaxAndFee) ?? true;
|
|
188
191
|
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
189
|
-
const availableAfterPassLimit = getApplicableProducts(voucher, productsData).filter((p) => p[amountField].greaterThan(0)).filter((p) => getItemPassUsage(itemPassUsage, product_id, p.product_id) < maxPassesPerItem *
|
|
192
|
+
const availableAfterPassLimit = getApplicableProducts(voucher, productsData).filter((p) => p[amountField].greaterThan(0)).filter((p) => getItemPassUsage(itemPassUsage, product_id, p.product_id) < maxPassesPerItem * getTotalQuantityByProductId(productsData, p.product_id));
|
|
190
193
|
if (availableAfterPassLimit.length === 0) {
|
|
191
194
|
return { isAvailable: false, reasonCode: "max_passes_per_item_reached" };
|
|
192
195
|
}
|
|
@@ -236,7 +239,7 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
|
236
239
|
voucher,
|
|
237
240
|
productsForRecommendation
|
|
238
241
|
).filter((p) => p[amountField].greaterThan(0));
|
|
239
|
-
applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsageMap, product_id, maxPassesPerItem);
|
|
242
|
+
applicableProducts = filterByMaxPassesPerItem(applicableProducts, productsForRecommendation, itemPassUsageMap, product_id, maxPassesPerItem);
|
|
240
243
|
if (applicableProducts.length === 0)
|
|
241
244
|
return false;
|
|
242
245
|
const usageAmount = typeof voucher.edit_current_amount === "number" ? voucher.edit_current_amount : getRecommendedAmount(voucher);
|
|
@@ -269,7 +272,7 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
|
269
272
|
}
|
|
270
273
|
} else {
|
|
271
274
|
const maxProduct = applicableProducts.reduce(
|
|
272
|
-
(max, p) => p[
|
|
275
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
273
276
|
);
|
|
274
277
|
if (maxPassesPerItem > 0) {
|
|
275
278
|
calculatedAvailableMaxAmount = import_decimal.default.min(
|
|
@@ -322,7 +325,7 @@ function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
|
322
325
|
}
|
|
323
326
|
} else {
|
|
324
327
|
const targetProduct = applicableProducts.reduce(
|
|
325
|
-
(max, p) => p[
|
|
328
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
326
329
|
);
|
|
327
330
|
let maxDeductForProduct = targetProduct[amountField];
|
|
328
331
|
if (maxPassesPerItem > 0) {
|
|
@@ -407,7 +410,7 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
|
|
|
407
410
|
if (maxPassesPerItem <= 0)
|
|
408
411
|
return products2;
|
|
409
412
|
return products2.filter(
|
|
410
|
-
(p) => getItemPassUsage(walletPassProductId, p.product_id) < maxPassesPerItem *
|
|
413
|
+
(p) => getItemPassUsage(walletPassProductId, p.product_id) < maxPassesPerItem * getTotalQuantityByProductId(productsForCalc, p.product_id)
|
|
411
414
|
);
|
|
412
415
|
};
|
|
413
416
|
selectedVouchers.forEach((selectedVoucher) => {
|
|
@@ -470,7 +473,7 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
|
|
|
470
473
|
}
|
|
471
474
|
} else {
|
|
472
475
|
const targetProduct = applicableProducts.reduce(
|
|
473
|
-
(max, p) => p[
|
|
476
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
474
477
|
);
|
|
475
478
|
let maxDeductForProduct = targetProduct[amountField];
|
|
476
479
|
if (maxPassesPerItem > 0) {
|
|
@@ -578,7 +581,7 @@ function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, pr
|
|
|
578
581
|
}
|
|
579
582
|
} else {
|
|
580
583
|
const maxProduct = applicableProducts.reduce(
|
|
581
|
-
(max, p) => p[
|
|
584
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
582
585
|
);
|
|
583
586
|
if (maxPassesPerItem > 0) {
|
|
584
587
|
calculatedMaxAmount = import_decimal.default.min(
|