@pisell/pisellos 2.1.119 → 2.1.121
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/apis/picoding.d.ts +0 -0
- package/dist/apis/picoding.js +1 -0
- package/dist/model/index.d.ts +1 -0
- package/dist/model/index.js +1 -0
- package/dist/model/strategy/adapter/index.d.ts +7 -0
- package/dist/model/strategy/adapter/index.js +7 -0
- package/dist/model/strategy/adapter/itemRule/adapter.d.ts +59 -0
- package/dist/model/strategy/adapter/itemRule/adapter.js +439 -0
- package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +43 -0
- package/dist/model/strategy/adapter/itemRule/evaluator.js +169 -0
- package/dist/model/strategy/adapter/itemRule/examples.d.ts +64 -0
- package/dist/model/strategy/adapter/itemRule/examples.js +315 -0
- package/dist/model/strategy/adapter/itemRule/index.d.ts +5 -0
- package/dist/model/strategy/adapter/itemRule/index.js +5 -0
- package/dist/model/strategy/adapter/itemRule/type.d.ts +206 -0
- package/dist/model/strategy/adapter/itemRule/type.js +101 -0
- package/dist/model/strategy/adapter/promotion/adapter.d.ts +66 -0
- package/dist/model/strategy/adapter/promotion/adapter.js +271 -0
- package/dist/model/strategy/adapter/promotion/evaluator.d.ts +213 -0
- package/dist/model/strategy/adapter/promotion/evaluator.js +1206 -0
- package/dist/model/strategy/adapter/promotion/examples.d.ts +138 -0
- package/dist/model/strategy/adapter/promotion/examples.js +166 -0
- package/dist/model/strategy/adapter/promotion/index.d.ts +4 -0
- package/dist/model/strategy/adapter/promotion/index.js +0 -0
- package/dist/model/strategy/adapter/promotion/type.d.ts +447 -0
- package/dist/model/strategy/adapter/promotion/type.js +209 -0
- package/dist/model/strategy/adapter/type.d.ts +28 -0
- package/dist/model/strategy/adapter/type.js +1 -0
- package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +84 -0
- package/dist/model/strategy/adapter/walletPass/evaluator.js +502 -0
- package/dist/model/strategy/adapter/walletPass/example.d.ts +4 -0
- package/dist/model/strategy/adapter/walletPass/example.js +258 -0
- package/dist/model/strategy/adapter/walletPass/index.d.ts +32 -0
- package/dist/model/strategy/adapter/walletPass/index.js +182 -0
- package/dist/model/strategy/adapter/walletPass/locales.d.ts +1 -0
- package/dist/model/strategy/adapter/walletPass/locales.js +26 -0
- package/dist/model/strategy/adapter/walletPass/type.d.ts +187 -0
- package/dist/model/strategy/adapter/walletPass/type.js +1 -0
- package/dist/model/strategy/adapter/walletPass/utils.d.ts +50 -0
- package/dist/model/strategy/adapter/walletPass/utils.js +1104 -0
- package/dist/model/strategy/engine.d.ts +106 -0
- package/dist/model/strategy/engine.js +611 -0
- package/dist/model/strategy/index.d.ts +3 -0
- package/dist/model/strategy/index.js +8 -0
- package/dist/model/strategy/strategy-example.d.ts +5 -0
- package/dist/model/strategy/strategy-example.js +331 -0
- package/dist/model/strategy/type.d.ts +228 -0
- package/dist/model/strategy/type.js +94 -0
- package/dist/modules/Cart/utils/cartProduct.js +1 -0
- package/dist/modules/OpenData/index.d.ts +24 -0
- package/dist/modules/OpenData/index.js +173 -0
- package/dist/modules/OpenData/types.d.ts +73 -0
- package/dist/modules/OpenData/types.js +1 -0
- package/dist/modules/OpenData/utils.d.ts +2 -0
- package/dist/modules/OpenData/utils.js +75 -0
- package/dist/modules/Order/index.d.ts +58 -1
- package/dist/modules/Order/index.js +796 -29
- package/dist/modules/Order/types.d.ts +144 -12
- package/dist/modules/Order/utils.d.ts +28 -0
- package/dist/modules/Order/utils.js +250 -1
- package/dist/modules/Product/index.d.ts +1 -1
- package/dist/modules/Product/utils.js +2 -2
- package/dist/modules/ProductList/index.d.ts +1 -1
- package/dist/modules/ProductList/index.js +2 -1
- package/dist/modules/Quotation/index.d.ts +48 -0
- package/dist/modules/Quotation/index.js +245 -0
- package/dist/modules/Quotation/types.d.ts +42 -0
- package/dist/modules/Quotation/types.js +1 -0
- package/dist/modules/Rules/index.js +4 -1
- package/dist/modules/SalesSummary/index.d.ts +63 -0
- package/dist/modules/SalesSummary/index.js +174 -0
- package/dist/modules/SalesSummary/types.d.ts +59 -0
- package/dist/modules/SalesSummary/types.js +1 -0
- package/dist/modules/SalesSummary/utils.d.ts +30 -0
- package/dist/modules/SalesSummary/utils.js +513 -0
- package/dist/modules/ScanOrderLogger/index.d.ts +21 -0
- package/dist/modules/ScanOrderLogger/index.js +161 -0
- package/dist/modules/ScanOrderLogger/providers/feishu.d.ts +2 -0
- package/dist/modules/ScanOrderLogger/providers/feishu.js +95 -0
- package/dist/modules/ScanOrderLogger/providers/grafana.d.ts +2 -0
- package/dist/modules/ScanOrderLogger/providers/grafana.js +50 -0
- package/dist/modules/ScanOrderLogger/types.d.ts +46 -0
- package/dist/modules/ScanOrderLogger/types.js +1 -0
- package/dist/modules/Schedule/getDateIsInSchedule.js +11 -18
- package/dist/modules/Summary/utils.d.ts +3 -3
- package/dist/modules/Summary/utils.js +4 -4
- package/dist/modules/index.d.ts +4 -0
- package/dist/modules/index.js +5 -1
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingByStep/types.d.ts +3 -1
- package/dist/solution/BookingByStep/types.js +5 -1
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/ScanOrder/index.d.ts +90 -0
- package/dist/solution/ScanOrder/index.js +1853 -0
- package/dist/solution/ScanOrder/types.d.ts +210 -0
- package/dist/solution/ScanOrder/types.js +16 -0
- package/dist/solution/ScanOrder/utils.d.ts +93 -0
- package/dist/solution/ScanOrder/utils.js +397 -0
- package/dist/solution/VenueBooking/index.d.ts +163 -0
- package/dist/solution/VenueBooking/index.js +2931 -0
- package/dist/solution/VenueBooking/sales-section-4-annotated.json +343 -0
- package/dist/solution/VenueBooking/types.d.ts +130 -0
- package/dist/solution/VenueBooking/types.js +21 -0
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +10 -0
- package/dist/solution/VenueBooking/utils/dateSummary.js +102 -0
- package/dist/solution/VenueBooking/utils/resource.d.ts +4 -0
- package/dist/solution/VenueBooking/utils/resource.js +94 -0
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +29 -0
- package/dist/solution/VenueBooking/utils/slotMerge.js +203 -0
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +32 -0
- package/dist/solution/VenueBooking/utils/timeSlot.js +256 -0
- package/dist/solution/VenueBooking/utils.d.ts +1 -0
- package/dist/solution/VenueBooking/utils.js +1 -0
- package/dist/solution/index.d.ts +2 -0
- package/dist/solution/index.js +3 -1
- package/lib/apis/picoding.d.ts +0 -0
- package/lib/apis/picoding.js +0 -0
- package/lib/model/index.d.ts +1 -0
- package/lib/model/index.js +23 -0
- package/lib/model/strategy/adapter/index.d.ts +7 -0
- package/lib/model/strategy/adapter/index.js +57 -0
- package/lib/model/strategy/adapter/itemRule/adapter.d.ts +59 -0
- package/lib/model/strategy/adapter/itemRule/adapter.js +338 -0
- package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +43 -0
- package/lib/model/strategy/adapter/itemRule/evaluator.js +124 -0
- package/lib/model/strategy/adapter/itemRule/examples.d.ts +64 -0
- package/lib/model/strategy/adapter/itemRule/examples.js +269 -0
- package/lib/model/strategy/adapter/itemRule/index.d.ts +5 -0
- package/lib/model/strategy/adapter/itemRule/index.js +58 -0
- package/lib/model/strategy/adapter/itemRule/type.d.ts +206 -0
- package/lib/model/strategy/adapter/itemRule/type.js +46 -0
- package/lib/model/strategy/adapter/promotion/adapter.d.ts +66 -0
- package/lib/model/strategy/adapter/promotion/adapter.js +217 -0
- package/lib/model/strategy/adapter/promotion/evaluator.d.ts +213 -0
- package/lib/model/strategy/adapter/promotion/evaluator.js +844 -0
- package/lib/model/strategy/adapter/promotion/examples.d.ts +138 -0
- package/lib/model/strategy/adapter/promotion/examples.js +192 -0
- package/lib/model/strategy/adapter/promotion/index.d.ts +4 -0
- package/lib/model/strategy/adapter/promotion/index.js +49 -0
- package/lib/model/strategy/adapter/promotion/type.d.ts +447 -0
- package/lib/model/strategy/adapter/promotion/type.js +51 -0
- package/lib/model/strategy/adapter/type.d.ts +28 -0
- package/lib/model/strategy/adapter/type.js +17 -0
- package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +84 -0
- package/lib/model/strategy/adapter/walletPass/evaluator.js +424 -0
- package/lib/model/strategy/adapter/walletPass/example.d.ts +4 -0
- package/lib/model/strategy/adapter/walletPass/example.js +207 -0
- package/lib/model/strategy/adapter/walletPass/index.d.ts +32 -0
- package/lib/model/strategy/adapter/walletPass/index.js +142 -0
- package/lib/model/strategy/adapter/walletPass/locales.d.ts +1 -0
- package/lib/model/strategy/adapter/walletPass/locales.js +54 -0
- package/lib/model/strategy/adapter/walletPass/type.d.ts +187 -0
- package/lib/model/strategy/adapter/walletPass/type.js +17 -0
- package/lib/model/strategy/adapter/walletPass/utils.d.ts +50 -0
- package/lib/model/strategy/adapter/walletPass/utils.js +791 -0
- package/lib/model/strategy/engine.d.ts +106 -0
- package/lib/model/strategy/engine.js +450 -0
- package/lib/model/strategy/index.d.ts +3 -0
- package/lib/model/strategy/index.js +38 -0
- package/lib/model/strategy/strategy-example.d.ts +5 -0
- package/lib/model/strategy/strategy-example.js +318 -0
- package/lib/model/strategy/type.d.ts +228 -0
- package/lib/model/strategy/type.js +44 -0
- package/lib/modules/Cart/utils/cartProduct.js +1 -0
- package/lib/modules/OpenData/index.d.ts +24 -0
- package/lib/modules/OpenData/index.js +119 -0
- package/lib/modules/OpenData/types.d.ts +73 -0
- package/lib/modules/OpenData/types.js +17 -0
- package/lib/modules/OpenData/utils.d.ts +2 -0
- package/lib/modules/OpenData/utils.js +111 -0
- package/lib/modules/Order/index.d.ts +58 -1
- package/lib/modules/Order/index.js +437 -1
- package/lib/modules/Order/types.d.ts +144 -12
- package/lib/modules/Order/utils.d.ts +28 -0
- package/lib/modules/Order/utils.js +250 -2
- package/lib/modules/Product/index.d.ts +1 -1
- package/lib/modules/Product/utils.js +2 -2
- package/lib/modules/ProductList/index.d.ts +1 -1
- package/lib/modules/ProductList/index.js +2 -1
- package/lib/modules/Quotation/index.d.ts +48 -0
- package/lib/modules/Quotation/index.js +149 -0
- package/lib/modules/Quotation/types.d.ts +42 -0
- package/lib/modules/Quotation/types.js +17 -0
- package/lib/modules/Rules/index.js +4 -1
- package/lib/modules/SalesSummary/index.d.ts +63 -0
- package/lib/modules/SalesSummary/index.js +105 -0
- package/lib/modules/SalesSummary/types.d.ts +59 -0
- package/lib/modules/SalesSummary/types.js +17 -0
- package/lib/modules/SalesSummary/utils.d.ts +30 -0
- package/lib/modules/SalesSummary/utils.js +452 -0
- package/lib/modules/ScanOrderLogger/index.d.ts +21 -0
- package/lib/modules/ScanOrderLogger/index.js +135 -0
- package/lib/modules/ScanOrderLogger/providers/feishu.d.ts +2 -0
- package/lib/modules/ScanOrderLogger/providers/feishu.js +82 -0
- package/lib/modules/ScanOrderLogger/providers/grafana.d.ts +2 -0
- package/lib/modules/ScanOrderLogger/providers/grafana.js +52 -0
- package/lib/modules/ScanOrderLogger/types.d.ts +46 -0
- package/lib/modules/ScanOrderLogger/types.js +17 -0
- package/lib/modules/Schedule/getDateIsInSchedule.js +9 -11
- package/lib/modules/Summary/utils.d.ts +3 -3
- package/lib/modules/Summary/utils.js +4 -4
- package/lib/modules/index.d.ts +4 -0
- package/lib/modules/index.js +9 -1
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingByStep/types.d.ts +3 -1
- package/lib/solution/BookingByStep/types.js +10 -0
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/ScanOrder/index.d.ts +90 -0
- package/lib/solution/ScanOrder/index.js +1071 -0
- package/lib/solution/ScanOrder/types.d.ts +210 -0
- package/lib/solution/ScanOrder/types.js +36 -0
- package/lib/solution/ScanOrder/utils.d.ts +93 -0
- package/lib/solution/ScanOrder/utils.js +359 -0
- package/lib/solution/VenueBooking/index.d.ts +163 -0
- package/lib/solution/VenueBooking/index.js +1578 -0
- package/lib/solution/VenueBooking/sales-section-4-annotated.json +343 -0
- package/lib/solution/VenueBooking/types.d.ts +130 -0
- package/lib/solution/VenueBooking/types.js +44 -0
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +10 -0
- package/lib/solution/VenueBooking/utils/dateSummary.js +101 -0
- package/lib/solution/VenueBooking/utils/resource.d.ts +4 -0
- package/lib/solution/VenueBooking/utils/resource.js +80 -0
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +29 -0
- package/lib/solution/VenueBooking/utils/slotMerge.js +208 -0
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +32 -0
- package/lib/solution/VenueBooking/utils/timeSlot.js +200 -0
- package/lib/solution/VenueBooking/utils.d.ts +1 -0
- package/lib/solution/VenueBooking/utils.js +69 -0
- package/lib/solution/index.d.ts +2 -0
- package/lib/solution/index.js +5 -1
- package/package.json +1 -1
|
@@ -0,0 +1,791 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/model/strategy/adapter/walletPass/utils.ts
|
|
30
|
+
var utils_exports = {};
|
|
31
|
+
__export(utils_exports, {
|
|
32
|
+
getApplicableProductIds: () => getApplicableProductIds,
|
|
33
|
+
getBundleItemIsDiscountPrice: () => getBundleItemIsDiscountPrice,
|
|
34
|
+
getBundleItemIsMarkupOrDiscountPrice: () => getBundleItemIsMarkupOrDiscountPrice,
|
|
35
|
+
getBundleItemIsMarkupPrice: () => getBundleItemIsMarkupPrice,
|
|
36
|
+
getBundleItemIsOriginalPrice: () => getBundleItemIsOriginalPrice,
|
|
37
|
+
getBundleItemPrice: () => getBundleItemPrice,
|
|
38
|
+
getMainProductPrice: () => getMainProductPrice,
|
|
39
|
+
getProductQuantity: () => getProductQuantity,
|
|
40
|
+
processVouchers: () => processVouchers,
|
|
41
|
+
recalculateVouchers: () => recalculateVouchers,
|
|
42
|
+
resolveWalletPassLineKey: () => resolveWalletPassLineKey
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(utils_exports);
|
|
45
|
+
var import_decimal = __toESM(require("decimal.js"));
|
|
46
|
+
var getProductQuantity = (product) => {
|
|
47
|
+
return product.quantity || product.product_quantity || 1;
|
|
48
|
+
};
|
|
49
|
+
function resolveWalletPassLineKey(product, indexInOrder) {
|
|
50
|
+
const m = (product == null ? void 0 : product.metadata) || {};
|
|
51
|
+
const u1 = m.product_unique;
|
|
52
|
+
if (u1 != null && String(u1).length > 0)
|
|
53
|
+
return String(u1);
|
|
54
|
+
const u2 = m.unique_identification_number;
|
|
55
|
+
if (u2 != null && String(u2).length > 0)
|
|
56
|
+
return String(u2);
|
|
57
|
+
if ((product == null ? void 0 : product.id) != null && String(product.id).length > 0)
|
|
58
|
+
return `order_item:${product.id}`;
|
|
59
|
+
if ((product == null ? void 0 : product.product_unique_string) != null && String(product.product_unique_string).length > 0) {
|
|
60
|
+
return String(product.product_unique_string);
|
|
61
|
+
}
|
|
62
|
+
return `order_line_${indexInOrder}`;
|
|
63
|
+
}
|
|
64
|
+
function getExpandedOrderLineQuantity(p) {
|
|
65
|
+
if ((p == null ? void 0 : p._orderLineQuantity) != null && p._orderLineQuantity > 0)
|
|
66
|
+
return p._orderLineQuantity;
|
|
67
|
+
return getProductQuantity(p);
|
|
68
|
+
}
|
|
69
|
+
function getMaxPassSlotsForExpandedLine(maxPassesPerItem, p) {
|
|
70
|
+
if (maxPassesPerItem <= 0)
|
|
71
|
+
return Infinity;
|
|
72
|
+
return maxPassesPerItem * getExpandedOrderLineQuantity(p);
|
|
73
|
+
}
|
|
74
|
+
function computePassSlotsIncrement(deductAmount, deductQty, maxPassesPerItem, orderLineQuantity, currentUsage) {
|
|
75
|
+
if (maxPassesPerItem <= 0 || !deductAmount.greaterThan(0))
|
|
76
|
+
return 0;
|
|
77
|
+
const cap = maxPassesPerItem * orderLineQuantity;
|
|
78
|
+
const room = Math.max(0, cap - currentUsage);
|
|
79
|
+
if (room <= 0)
|
|
80
|
+
return 0;
|
|
81
|
+
const raw = Math.max(1, Math.ceil(Number(deductQty)) || 1);
|
|
82
|
+
return Math.min(raw, room);
|
|
83
|
+
}
|
|
84
|
+
function applyMaxPassUsageIncrements(usageMap, walletPassProductId, maxPassesPerItem, deductionDetails) {
|
|
85
|
+
deductionDetails.forEach((detail) => {
|
|
86
|
+
var _a;
|
|
87
|
+
const lineKey = detail.lineKey;
|
|
88
|
+
if (!lineKey || maxPassesPerItem <= 0)
|
|
89
|
+
return;
|
|
90
|
+
const orderLineQty = detail.orderLineQuantity != null && detail.orderLineQuantity > 0 ? detail.orderLineQuantity : 1;
|
|
91
|
+
const cur = ((_a = usageMap.get(walletPassProductId)) == null ? void 0 : _a.get(lineKey)) || 0;
|
|
92
|
+
const inc = computePassSlotsIncrement(
|
|
93
|
+
new import_decimal.default(detail.deductAmount),
|
|
94
|
+
detail.deductQuantity,
|
|
95
|
+
maxPassesPerItem,
|
|
96
|
+
orderLineQty,
|
|
97
|
+
cur
|
|
98
|
+
);
|
|
99
|
+
if (inc <= 0)
|
|
100
|
+
return;
|
|
101
|
+
if (!usageMap.has(walletPassProductId))
|
|
102
|
+
usageMap.set(walletPassProductId, /* @__PURE__ */ new Map());
|
|
103
|
+
const inner = usageMap.get(walletPassProductId);
|
|
104
|
+
inner.set(lineKey, cur + inc);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
var getRecommendedAmount = (voucher) => {
|
|
108
|
+
console.log("voucher312", voucher);
|
|
109
|
+
const { config, recommended_usage_amount, recommended_pure_product_usage_amount } = voucher;
|
|
110
|
+
const deductTaxAndFee = (config == null ? void 0 : config.deductTaxAndFee) ?? true;
|
|
111
|
+
return deductTaxAndFee ? recommended_usage_amount : recommended_pure_product_usage_amount ?? recommended_usage_amount;
|
|
112
|
+
};
|
|
113
|
+
var getApplicableProductIds = (voucher) => {
|
|
114
|
+
const { available_product_type, available_product_ids } = voucher;
|
|
115
|
+
const productType = available_product_type || "product_all";
|
|
116
|
+
if (productType === "product_all") {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
if (productType === "product_collection" || productType === "products") {
|
|
120
|
+
return available_product_ids || [];
|
|
121
|
+
}
|
|
122
|
+
return [];
|
|
123
|
+
};
|
|
124
|
+
var getApplicableProductsAmount = (voucher, productsData) => {
|
|
125
|
+
const applicableProductIds = getApplicableProductIds(voucher);
|
|
126
|
+
const { config } = voucher;
|
|
127
|
+
const deductTaxAndFee = (config == null ? void 0 : config.deductTaxAndFee) ?? true;
|
|
128
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
129
|
+
if (applicableProductIds === null) {
|
|
130
|
+
return productsData.filter((p) => p[amountField].greaterThan(0)).reduce((sum, p) => sum.plus(p[amountField]), new import_decimal.default(0));
|
|
131
|
+
}
|
|
132
|
+
if (applicableProductIds.length === 0) {
|
|
133
|
+
return new import_decimal.default(0);
|
|
134
|
+
}
|
|
135
|
+
return productsData.filter((p) => applicableProductIds.includes(p.product_id) && p[amountField].greaterThan(0)).reduce((sum, p) => sum.plus(p[amountField]), new import_decimal.default(0));
|
|
136
|
+
};
|
|
137
|
+
var getApplicableProducts = (voucher, productsData) => {
|
|
138
|
+
const applicableProductIds = getApplicableProductIds(voucher);
|
|
139
|
+
if (applicableProductIds === null) {
|
|
140
|
+
return productsData;
|
|
141
|
+
}
|
|
142
|
+
if (applicableProductIds.length === 0) {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
return productsData.filter((p) => applicableProductIds.includes(p.product_id));
|
|
146
|
+
};
|
|
147
|
+
function processVouchers(applicableVouchers, orderTotalAmount, products) {
|
|
148
|
+
console.log(products, "products123");
|
|
149
|
+
const productsCopy = expandProductsWithBundleItems(products, true);
|
|
150
|
+
let remainingOrderAmount = new import_decimal.default(orderTotalAmount);
|
|
151
|
+
const getItemPassUsage = (usageMap, walletPassProductId, lineKey) => {
|
|
152
|
+
var _a;
|
|
153
|
+
return ((_a = usageMap.get(walletPassProductId)) == null ? void 0 : _a.get(lineKey)) || 0;
|
|
154
|
+
};
|
|
155
|
+
const filterByMaxPassesPerItem = (products2, usageMap, walletPassProductId, maxPassesPerItem) => {
|
|
156
|
+
if (maxPassesPerItem <= 0)
|
|
157
|
+
return products2;
|
|
158
|
+
return products2.filter((p) => {
|
|
159
|
+
const lineKey = p._walletPassLineKey;
|
|
160
|
+
if (!lineKey)
|
|
161
|
+
return true;
|
|
162
|
+
return getItemPassUsage(usageMap, walletPassProductId, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p);
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
const calculateAvailableMaxAmount = (voucher, productsData, itemPassUsage) => {
|
|
166
|
+
const { config } = voucher;
|
|
167
|
+
const { maxDeductionAmount = 0, allowCrossProduct = true, applicableProductLimit = 0, deductTaxAndFee = true, maxPassesPerItem = 0 } = config ?? {};
|
|
168
|
+
const recommendedAmount = getRecommendedAmount(voucher);
|
|
169
|
+
const baseAmount = import_decimal.default.min(
|
|
170
|
+
new import_decimal.default(recommendedAmount),
|
|
171
|
+
new import_decimal.default(maxDeductionAmount)
|
|
172
|
+
);
|
|
173
|
+
const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
|
|
174
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
175
|
+
let applicableProducts = getApplicableProducts(voucher, productsData).filter((p) => p[amountField].greaterThan(0));
|
|
176
|
+
if (itemPassUsage) {
|
|
177
|
+
applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsage, voucher.product_id, maxPassesPerItem);
|
|
178
|
+
}
|
|
179
|
+
if (applicableProducts.length === 0) {
|
|
180
|
+
return new import_decimal.default(0);
|
|
181
|
+
}
|
|
182
|
+
let finalApplicableAmount = new import_decimal.default(0);
|
|
183
|
+
if (allowCrossProduct) {
|
|
184
|
+
if (applicableProductLimit > 0) {
|
|
185
|
+
const sortedProducts = [...applicableProducts].sort((a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1);
|
|
186
|
+
let remainingLimit = applicableProductLimit;
|
|
187
|
+
for (const product of sortedProducts) {
|
|
188
|
+
if (remainingLimit <= 0)
|
|
189
|
+
break;
|
|
190
|
+
const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
191
|
+
const deductQty = Math.min(currentAvailableQty, remainingLimit);
|
|
192
|
+
const deductAmount = import_decimal.default.min(
|
|
193
|
+
product[unitPriceField].times(deductQty),
|
|
194
|
+
product[amountField]
|
|
195
|
+
);
|
|
196
|
+
finalApplicableAmount = finalApplicableAmount.plus(deductAmount);
|
|
197
|
+
remainingLimit -= deductQty;
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
finalApplicableAmount = applicableProducts.reduce(
|
|
201
|
+
(sum, p) => sum.plus(p[amountField]),
|
|
202
|
+
new import_decimal.default(0)
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
const maxProduct = applicableProducts.reduce(
|
|
207
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
208
|
+
);
|
|
209
|
+
if (maxPassesPerItem > 0) {
|
|
210
|
+
finalApplicableAmount = import_decimal.default.min(
|
|
211
|
+
maxProduct[unitPriceField].times(maxPassesPerItem),
|
|
212
|
+
maxProduct[amountField]
|
|
213
|
+
);
|
|
214
|
+
} else {
|
|
215
|
+
finalApplicableAmount = maxProduct[amountField];
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return import_decimal.default.min(baseAmount, finalApplicableAmount, remainingOrderAmount);
|
|
219
|
+
};
|
|
220
|
+
const isVoucherAvailable = (voucher, productsData, usedVoucherCounts2, itemPassUsage) => {
|
|
221
|
+
const { config, id, product_id } = voucher;
|
|
222
|
+
const recommendedAmount = getRecommendedAmount(voucher);
|
|
223
|
+
if (recommendedAmount <= 0) {
|
|
224
|
+
return { isAvailable: false, reasonCode: "not_meet_the_required_conditions" };
|
|
225
|
+
}
|
|
226
|
+
if (remainingOrderAmount.lessThanOrEqualTo(0)) {
|
|
227
|
+
return { isAvailable: false, reasonCode: "exceeds_the_maximum_deduction_limit" };
|
|
228
|
+
}
|
|
229
|
+
const applicableAmount = getApplicableProductsAmount(voucher, productsData);
|
|
230
|
+
if (applicableAmount.lessThanOrEqualTo(0)) {
|
|
231
|
+
return { isAvailable: false, reasonCode: "not_meet_the_required_conditions" };
|
|
232
|
+
}
|
|
233
|
+
if (((config == null ? void 0 : config.maxUsagePerOrder) || 0) > 0) {
|
|
234
|
+
const usedCount = usedVoucherCounts2.get(product_id) || 0;
|
|
235
|
+
if (usedCount >= ((config == null ? void 0 : config.maxUsagePerOrder) || 0)) {
|
|
236
|
+
return { isAvailable: false, reasonCode: "usage_limit_reached" };
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const maxPassesPerItem = (config == null ? void 0 : config.maxPassesPerItem) || 0;
|
|
240
|
+
if (maxPassesPerItem > 0 && itemPassUsage) {
|
|
241
|
+
const deductTaxAndFee = (config == null ? void 0 : config.deductTaxAndFee) ?? true;
|
|
242
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
243
|
+
const availableAfterPassLimit = getApplicableProducts(voucher, productsData).filter((p) => p[amountField].greaterThan(0)).filter((p) => {
|
|
244
|
+
const lineKey = p._walletPassLineKey;
|
|
245
|
+
if (!lineKey)
|
|
246
|
+
return true;
|
|
247
|
+
return getItemPassUsage(itemPassUsage, product_id, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p);
|
|
248
|
+
});
|
|
249
|
+
if (availableAfterPassLimit.length === 0) {
|
|
250
|
+
return { isAvailable: false, reasonCode: "max_passes_per_item_reached" };
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return { isAvailable: true };
|
|
254
|
+
};
|
|
255
|
+
const usedVoucherCountsForAll = /* @__PURE__ */ new Map();
|
|
256
|
+
const allVouchersWithStatus = applicableVouchers.map((voucher) => {
|
|
257
|
+
const _available_max_amount = calculateAvailableMaxAmount(
|
|
258
|
+
voucher,
|
|
259
|
+
productsCopy
|
|
260
|
+
);
|
|
261
|
+
const availabilityResult = isVoucherAvailable(
|
|
262
|
+
voucher,
|
|
263
|
+
productsCopy,
|
|
264
|
+
usedVoucherCountsForAll
|
|
265
|
+
);
|
|
266
|
+
const _unified_available_status = availabilityResult.isAvailable ? 1 : 0;
|
|
267
|
+
return {
|
|
268
|
+
...voucher,
|
|
269
|
+
_available_max_amount: _available_max_amount.toNumber(),
|
|
270
|
+
// 转换为数字
|
|
271
|
+
_unified_available_status,
|
|
272
|
+
...availabilityResult.reasonCode && { reasonCode: availabilityResult.reasonCode }
|
|
273
|
+
};
|
|
274
|
+
});
|
|
275
|
+
const recommendedVouchers = [];
|
|
276
|
+
const usedVoucherCounts = /* @__PURE__ */ new Map();
|
|
277
|
+
const productsForRecommendation = expandProductsWithBundleItems(products, true);
|
|
278
|
+
remainingOrderAmount = new import_decimal.default(orderTotalAmount);
|
|
279
|
+
const itemPassUsageMap = /* @__PURE__ */ new Map();
|
|
280
|
+
const applyVoucher = (voucher) => {
|
|
281
|
+
const availabilityCheck = isVoucherAvailable(
|
|
282
|
+
voucher,
|
|
283
|
+
productsForRecommendation,
|
|
284
|
+
usedVoucherCounts,
|
|
285
|
+
itemPassUsageMap
|
|
286
|
+
);
|
|
287
|
+
if (!availabilityCheck.isAvailable) {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
const { config, id, product_id } = voucher;
|
|
291
|
+
const { maxDeductionAmount = 0, allowCrossProduct = true, applicableProductLimit = 0, deductTaxAndFee = true, maxPassesPerItem = 0 } = config ?? {};
|
|
292
|
+
const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
|
|
293
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
294
|
+
let applicableProducts = getApplicableProducts(
|
|
295
|
+
voucher,
|
|
296
|
+
productsForRecommendation
|
|
297
|
+
).filter((p) => p[amountField].greaterThan(0));
|
|
298
|
+
applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsageMap, product_id, maxPassesPerItem);
|
|
299
|
+
if (applicableProducts.length === 0)
|
|
300
|
+
return false;
|
|
301
|
+
const usageAmount = typeof voucher.edit_current_amount === "number" ? voucher.edit_current_amount : getRecommendedAmount(voucher);
|
|
302
|
+
const baseAmount = import_decimal.default.min(
|
|
303
|
+
new import_decimal.default(usageAmount),
|
|
304
|
+
new import_decimal.default(maxDeductionAmount)
|
|
305
|
+
);
|
|
306
|
+
let calculatedAvailableMaxAmount = new import_decimal.default(0);
|
|
307
|
+
if (allowCrossProduct) {
|
|
308
|
+
if (applicableProductLimit > 0) {
|
|
309
|
+
const sortedProducts = [...applicableProducts].sort((a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1);
|
|
310
|
+
let remainingLimit = applicableProductLimit;
|
|
311
|
+
for (const product of sortedProducts) {
|
|
312
|
+
if (remainingLimit <= 0)
|
|
313
|
+
break;
|
|
314
|
+
const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
315
|
+
const deductQty = Math.min(currentAvailableQty, remainingLimit);
|
|
316
|
+
const deductAmount = import_decimal.default.min(
|
|
317
|
+
product[unitPriceField].times(deductQty),
|
|
318
|
+
product[amountField]
|
|
319
|
+
);
|
|
320
|
+
calculatedAvailableMaxAmount = calculatedAvailableMaxAmount.plus(deductAmount);
|
|
321
|
+
remainingLimit -= deductQty;
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
calculatedAvailableMaxAmount = applicableProducts.reduce(
|
|
325
|
+
(sum, p) => sum.plus(p[amountField]),
|
|
326
|
+
new import_decimal.default(0)
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
const maxProduct = applicableProducts.reduce(
|
|
331
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
332
|
+
);
|
|
333
|
+
if (maxPassesPerItem > 0) {
|
|
334
|
+
calculatedAvailableMaxAmount = import_decimal.default.min(
|
|
335
|
+
maxProduct[unitPriceField].times(maxPassesPerItem),
|
|
336
|
+
maxProduct[amountField]
|
|
337
|
+
);
|
|
338
|
+
} else {
|
|
339
|
+
calculatedAvailableMaxAmount = maxProduct[amountField];
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
const availableMaxAmount = import_decimal.default.min(
|
|
343
|
+
baseAmount,
|
|
344
|
+
calculatedAvailableMaxAmount,
|
|
345
|
+
remainingOrderAmount
|
|
346
|
+
);
|
|
347
|
+
const maxDeduction = import_decimal.default.min(
|
|
348
|
+
new import_decimal.default(usageAmount),
|
|
349
|
+
new import_decimal.default(maxDeductionAmount)
|
|
350
|
+
);
|
|
351
|
+
let deductionLeft = maxDeduction;
|
|
352
|
+
const deductionDetails = [];
|
|
353
|
+
if (allowCrossProduct) {
|
|
354
|
+
const sortedProducts = [...applicableProducts].sort(
|
|
355
|
+
(a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1
|
|
356
|
+
);
|
|
357
|
+
let remainingLimit = applicableProductLimit > 0 ? applicableProductLimit : Infinity;
|
|
358
|
+
for (const product of sortedProducts) {
|
|
359
|
+
if (deductionLeft.lessThanOrEqualTo(0) || remainingLimit <= 0)
|
|
360
|
+
break;
|
|
361
|
+
const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
362
|
+
const availableQty = Math.min(currentAvailableQty, remainingLimit);
|
|
363
|
+
const maxDeductForProduct = import_decimal.default.min(
|
|
364
|
+
product[unitPriceField].times(availableQty),
|
|
365
|
+
product[amountField]
|
|
366
|
+
);
|
|
367
|
+
const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
|
|
368
|
+
const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(product[unitPriceField]).toNumber());
|
|
369
|
+
product[amountField] = product[amountField].minus(actualDeductAmount);
|
|
370
|
+
deductionLeft = deductionLeft.minus(actualDeductAmount);
|
|
371
|
+
remainingLimit -= actualDeductQty;
|
|
372
|
+
deductionDetails.push({
|
|
373
|
+
product_id: product.product_id,
|
|
374
|
+
parent_product_id: product.parent_product_id || null,
|
|
375
|
+
is_bundle_item: product.is_bundle_item || false,
|
|
376
|
+
lineKey: product._walletPassLineKey,
|
|
377
|
+
orderLineQuantity: getExpandedOrderLineQuantity(product),
|
|
378
|
+
deductAmount: actualDeductAmount.toNumber(),
|
|
379
|
+
// 转换为数字
|
|
380
|
+
deductQuantity: actualDeductQty
|
|
381
|
+
// 抵扣涉及的数量(用于记录)
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
} else {
|
|
385
|
+
const targetProduct = applicableProducts.reduce(
|
|
386
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
387
|
+
);
|
|
388
|
+
let maxDeductForProduct = targetProduct[amountField];
|
|
389
|
+
if (maxPassesPerItem > 0) {
|
|
390
|
+
maxDeductForProduct = import_decimal.default.min(
|
|
391
|
+
targetProduct[unitPriceField].times(maxPassesPerItem),
|
|
392
|
+
targetProduct[amountField]
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
|
|
396
|
+
const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(targetProduct[unitPriceField]).toNumber());
|
|
397
|
+
targetProduct[amountField] = targetProduct[amountField].minus(actualDeductAmount);
|
|
398
|
+
deductionLeft = deductionLeft.minus(actualDeductAmount);
|
|
399
|
+
deductionDetails.push({
|
|
400
|
+
product_id: targetProduct.product_id,
|
|
401
|
+
parent_product_id: targetProduct.parent_product_id || null,
|
|
402
|
+
is_bundle_item: targetProduct.is_bundle_item || false,
|
|
403
|
+
lineKey: targetProduct._walletPassLineKey,
|
|
404
|
+
orderLineQuantity: getExpandedOrderLineQuantity(targetProduct),
|
|
405
|
+
deductAmount: actualDeductAmount.toNumber(),
|
|
406
|
+
deductQuantity: actualDeductQty
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
const totalDeducted = maxDeduction.minus(deductionLeft);
|
|
410
|
+
if (totalDeducted.greaterThan(0)) {
|
|
411
|
+
remainingOrderAmount = remainingOrderAmount.minus(totalDeducted);
|
|
412
|
+
usedVoucherCounts.set(product_id, (usedVoucherCounts.get(product_id) || 0) + 1);
|
|
413
|
+
applyMaxPassUsageIncrements(itemPassUsageMap, product_id, maxPassesPerItem, deductionDetails);
|
|
414
|
+
recommendedVouchers.push({
|
|
415
|
+
...voucher,
|
|
416
|
+
actualDeduction: totalDeducted.toNumber(),
|
|
417
|
+
// 转换为数字
|
|
418
|
+
deductionDetails,
|
|
419
|
+
_available_max_amount: availableMaxAmount.toNumber(),
|
|
420
|
+
// 转换为数字
|
|
421
|
+
_unified_available_status: 1
|
|
422
|
+
});
|
|
423
|
+
return true;
|
|
424
|
+
}
|
|
425
|
+
return false;
|
|
426
|
+
};
|
|
427
|
+
applicableVouchers.forEach((voucher) => {
|
|
428
|
+
applyVoucher(voucher);
|
|
429
|
+
});
|
|
430
|
+
const recommendedMap = /* @__PURE__ */ new Map();
|
|
431
|
+
recommendedVouchers.forEach((v) => {
|
|
432
|
+
recommendedMap.set(v.id, v);
|
|
433
|
+
});
|
|
434
|
+
const allWithEnhancedData = allVouchersWithStatus.map((voucher) => {
|
|
435
|
+
if (recommendedMap.has(voucher.id)) {
|
|
436
|
+
return recommendedMap.get(voucher.id);
|
|
437
|
+
} else {
|
|
438
|
+
return {
|
|
439
|
+
...voucher,
|
|
440
|
+
actualDeduction: 0,
|
|
441
|
+
deductionDetails: []
|
|
442
|
+
// 保留 reasonCode(如果不可用的话)
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
return {
|
|
447
|
+
recommended: recommendedVouchers,
|
|
448
|
+
transformList: allWithEnhancedData
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, products) {
|
|
452
|
+
const productsForCalc = expandProductsWithBundleItems(products, true);
|
|
453
|
+
let remainingOrderAmount = new import_decimal.default(orderTotalAmount);
|
|
454
|
+
const selectedWithDetails = [];
|
|
455
|
+
const itemPassUsageMap = /* @__PURE__ */ new Map();
|
|
456
|
+
const getItemPassUsageRecalc = (walletPassProductId, lineKey) => {
|
|
457
|
+
var _a;
|
|
458
|
+
return ((_a = itemPassUsageMap.get(walletPassProductId)) == null ? void 0 : _a.get(lineKey)) || 0;
|
|
459
|
+
};
|
|
460
|
+
const filterByMaxPassesPerItemRecalc = (products2, walletPassProductId, maxPassesPerItem) => {
|
|
461
|
+
if (maxPassesPerItem <= 0)
|
|
462
|
+
return products2;
|
|
463
|
+
return products2.filter((p) => {
|
|
464
|
+
const lineKey = p._walletPassLineKey;
|
|
465
|
+
if (!lineKey)
|
|
466
|
+
return true;
|
|
467
|
+
return getItemPassUsageRecalc(walletPassProductId, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p);
|
|
468
|
+
});
|
|
469
|
+
};
|
|
470
|
+
selectedVouchers.forEach((selectedVoucher) => {
|
|
471
|
+
const { config, id } = selectedVoucher;
|
|
472
|
+
const { maxDeductionAmount, allowCrossProduct, applicableProductLimit, deductTaxAndFee = true, maxPassesPerItem = 0 } = config;
|
|
473
|
+
const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
|
|
474
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
475
|
+
let applicableProducts = getApplicableProducts(
|
|
476
|
+
selectedVoucher,
|
|
477
|
+
productsForCalc
|
|
478
|
+
).filter((p) => p[amountField].greaterThan(0));
|
|
479
|
+
applicableProducts = filterByMaxPassesPerItemRecalc(applicableProducts, selectedVoucher.product_id, maxPassesPerItem);
|
|
480
|
+
if (applicableProducts.length === 0) {
|
|
481
|
+
selectedWithDetails.push({
|
|
482
|
+
...selectedVoucher,
|
|
483
|
+
actualDeduction: 0,
|
|
484
|
+
deductionDetails: [],
|
|
485
|
+
_available_max_amount: 0,
|
|
486
|
+
_unified_available_status: 0,
|
|
487
|
+
reasonCode: "not_meet_the_required_conditions"
|
|
488
|
+
});
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
const usageAmount = typeof selectedVoucher.edit_current_amount === "number" ? selectedVoucher.edit_current_amount : getRecommendedAmount(selectedVoucher);
|
|
492
|
+
const maxDeduction = import_decimal.default.min(
|
|
493
|
+
new import_decimal.default(usageAmount),
|
|
494
|
+
new import_decimal.default(maxDeductionAmount),
|
|
495
|
+
remainingOrderAmount
|
|
496
|
+
);
|
|
497
|
+
let deductionLeft = maxDeduction;
|
|
498
|
+
const deductionDetails = [];
|
|
499
|
+
if (allowCrossProduct) {
|
|
500
|
+
const sortedProducts = [...applicableProducts].sort(
|
|
501
|
+
(a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1
|
|
502
|
+
);
|
|
503
|
+
let remainingLimit = applicableProductLimit > 0 ? applicableProductLimit : Infinity;
|
|
504
|
+
for (const product of sortedProducts) {
|
|
505
|
+
if (deductionLeft.lessThanOrEqualTo(0) || remainingLimit <= 0)
|
|
506
|
+
break;
|
|
507
|
+
const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
508
|
+
const availableQty = Math.min(currentAvailableQty, remainingLimit);
|
|
509
|
+
const maxDeductForProduct = import_decimal.default.min(
|
|
510
|
+
product[unitPriceField].times(availableQty),
|
|
511
|
+
product[amountField]
|
|
512
|
+
);
|
|
513
|
+
const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
|
|
514
|
+
const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(product[unitPriceField]).toNumber());
|
|
515
|
+
product[amountField] = product[amountField].minus(actualDeductAmount);
|
|
516
|
+
deductionLeft = deductionLeft.minus(actualDeductAmount);
|
|
517
|
+
remainingLimit -= actualDeductQty;
|
|
518
|
+
deductionDetails.push({
|
|
519
|
+
product_id: product.product_id,
|
|
520
|
+
parent_product_id: product.parent_product_id || null,
|
|
521
|
+
is_bundle_item: product.is_bundle_item || false,
|
|
522
|
+
lineKey: product._walletPassLineKey,
|
|
523
|
+
orderLineQuantity: getExpandedOrderLineQuantity(product),
|
|
524
|
+
deductAmount: actualDeductAmount.toNumber(),
|
|
525
|
+
// 转换为数字
|
|
526
|
+
deductQuantity: actualDeductQty
|
|
527
|
+
// 抵扣涉及的数量(用于记录)
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
} else {
|
|
531
|
+
const targetProduct = applicableProducts.reduce(
|
|
532
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
533
|
+
);
|
|
534
|
+
let maxDeductForProduct = targetProduct[amountField];
|
|
535
|
+
if (maxPassesPerItem > 0) {
|
|
536
|
+
maxDeductForProduct = import_decimal.default.min(
|
|
537
|
+
targetProduct[unitPriceField].times(maxPassesPerItem),
|
|
538
|
+
targetProduct[amountField]
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
|
|
542
|
+
const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(targetProduct[unitPriceField]).toNumber());
|
|
543
|
+
targetProduct[amountField] = targetProduct[amountField].minus(actualDeductAmount);
|
|
544
|
+
deductionLeft = deductionLeft.minus(actualDeductAmount);
|
|
545
|
+
deductionDetails.push({
|
|
546
|
+
product_id: targetProduct.product_id,
|
|
547
|
+
parent_product_id: targetProduct.parent_product_id || null,
|
|
548
|
+
is_bundle_item: targetProduct.is_bundle_item || false,
|
|
549
|
+
lineKey: targetProduct._walletPassLineKey,
|
|
550
|
+
orderLineQuantity: getExpandedOrderLineQuantity(targetProduct),
|
|
551
|
+
deductAmount: actualDeductAmount.toNumber(),
|
|
552
|
+
deductQuantity: actualDeductQty
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
const totalDeducted = maxDeduction.minus(deductionLeft);
|
|
556
|
+
remainingOrderAmount = remainingOrderAmount.minus(totalDeducted);
|
|
557
|
+
applyMaxPassUsageIncrements(itemPassUsageMap, selectedVoucher.product_id, maxPassesPerItem, deductionDetails);
|
|
558
|
+
selectedWithDetails.push({
|
|
559
|
+
...selectedVoucher,
|
|
560
|
+
actualDeduction: totalDeducted.toNumber(),
|
|
561
|
+
// 转换为数字
|
|
562
|
+
deductionDetails,
|
|
563
|
+
_available_max_amount: totalDeducted.toNumber(),
|
|
564
|
+
// 转换为数字
|
|
565
|
+
_unified_available_status: totalDeducted.greaterThan(0) ? 1 : 0
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
const selectedIds = new Set(selectedVouchers.map((v) => v.id));
|
|
569
|
+
const usedVoucherCounts = /* @__PURE__ */ new Map();
|
|
570
|
+
selectedVouchers.forEach((v) => {
|
|
571
|
+
usedVoucherCounts.set(v.product_id, (usedVoucherCounts.get(v.product_id) || 0) + 1);
|
|
572
|
+
});
|
|
573
|
+
const allWithUpdatedStatus = allVouchers.map((voucher) => {
|
|
574
|
+
if (selectedIds.has(voucher.id)) {
|
|
575
|
+
const selectedDetail = selectedWithDetails.find(
|
|
576
|
+
(v) => v.id === voucher.id
|
|
577
|
+
);
|
|
578
|
+
return selectedDetail || voucher;
|
|
579
|
+
}
|
|
580
|
+
const { config, id, product_id } = voucher;
|
|
581
|
+
const { maxDeductionAmount, allowCrossProduct, applicableProductLimit, deductTaxAndFee = true, maxPassesPerItem = 0 } = config;
|
|
582
|
+
const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
|
|
583
|
+
const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
|
|
584
|
+
const recommendedAmount = getRecommendedAmount(voucher);
|
|
585
|
+
let isAvailable = true;
|
|
586
|
+
let calculatedMaxAmount = new import_decimal.default(0);
|
|
587
|
+
let reasonCode;
|
|
588
|
+
if (recommendedAmount <= 0) {
|
|
589
|
+
isAvailable = false;
|
|
590
|
+
reasonCode = "not_meet_the_required_conditions";
|
|
591
|
+
} else if (remainingOrderAmount.lessThanOrEqualTo(0)) {
|
|
592
|
+
isAvailable = false;
|
|
593
|
+
reasonCode = "exceeds_the_maximum_deduction_limit";
|
|
594
|
+
} else {
|
|
595
|
+
if (config.maxUsagePerOrder > 0) {
|
|
596
|
+
const usedCount = usedVoucherCounts.get(product_id) || 0;
|
|
597
|
+
if (usedCount >= config.maxUsagePerOrder) {
|
|
598
|
+
isAvailable = false;
|
|
599
|
+
reasonCode = "usage_limit_reached";
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
if (isAvailable) {
|
|
603
|
+
let applicableProducts = getApplicableProducts(
|
|
604
|
+
voucher,
|
|
605
|
+
productsForCalc
|
|
606
|
+
).filter((p) => p[amountField].greaterThan(0));
|
|
607
|
+
applicableProducts = filterByMaxPassesPerItemRecalc(applicableProducts, product_id, maxPassesPerItem);
|
|
608
|
+
if (applicableProducts.length === 0) {
|
|
609
|
+
isAvailable = false;
|
|
610
|
+
reasonCode = "not_meet_the_required_conditions";
|
|
611
|
+
} else {
|
|
612
|
+
const baseAmount = import_decimal.default.min(
|
|
613
|
+
new import_decimal.default(recommendedAmount),
|
|
614
|
+
new import_decimal.default(maxDeductionAmount)
|
|
615
|
+
);
|
|
616
|
+
if (allowCrossProduct) {
|
|
617
|
+
if (applicableProductLimit > 0) {
|
|
618
|
+
const sortedProducts = [...applicableProducts].sort((a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1);
|
|
619
|
+
let remainingLimit = applicableProductLimit;
|
|
620
|
+
for (const product of sortedProducts) {
|
|
621
|
+
if (remainingLimit <= 0)
|
|
622
|
+
break;
|
|
623
|
+
const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
|
|
624
|
+
const deductQty = Math.min(currentAvailableQty, remainingLimit);
|
|
625
|
+
const deductAmount = import_decimal.default.min(
|
|
626
|
+
product[unitPriceField].times(deductQty),
|
|
627
|
+
product[amountField]
|
|
628
|
+
);
|
|
629
|
+
calculatedMaxAmount = calculatedMaxAmount.plus(deductAmount);
|
|
630
|
+
remainingLimit -= deductQty;
|
|
631
|
+
}
|
|
632
|
+
} else {
|
|
633
|
+
calculatedMaxAmount = applicableProducts.reduce(
|
|
634
|
+
(sum, p) => sum.plus(p[amountField]),
|
|
635
|
+
new import_decimal.default(0)
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
} else {
|
|
639
|
+
const maxProduct = applicableProducts.reduce(
|
|
640
|
+
(max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
|
|
641
|
+
);
|
|
642
|
+
if (maxPassesPerItem > 0) {
|
|
643
|
+
calculatedMaxAmount = import_decimal.default.min(
|
|
644
|
+
maxProduct[unitPriceField].times(maxPassesPerItem),
|
|
645
|
+
maxProduct[amountField]
|
|
646
|
+
);
|
|
647
|
+
} else {
|
|
648
|
+
calculatedMaxAmount = maxProduct[amountField];
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
calculatedMaxAmount = import_decimal.default.min(
|
|
652
|
+
baseAmount,
|
|
653
|
+
calculatedMaxAmount,
|
|
654
|
+
remainingOrderAmount
|
|
655
|
+
);
|
|
656
|
+
if (calculatedMaxAmount.lessThanOrEqualTo(0)) {
|
|
657
|
+
isAvailable = false;
|
|
658
|
+
reasonCode = "exceeds_the_maximum_deduction_limit";
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
return {
|
|
664
|
+
...voucher,
|
|
665
|
+
_available_max_amount: calculatedMaxAmount.toNumber(),
|
|
666
|
+
// 转换为数字
|
|
667
|
+
_unified_available_status: isAvailable ? 1 : 0,
|
|
668
|
+
...reasonCode && { reasonCode }
|
|
669
|
+
};
|
|
670
|
+
});
|
|
671
|
+
return {
|
|
672
|
+
allWithUpdatedStatus,
|
|
673
|
+
selectedWithDetails
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
var getMainProductPrice = (product, isDeductTaxAndFee) => {
|
|
677
|
+
var _a, _b, _c, _d, _e;
|
|
678
|
+
let mainProductPrice = new import_decimal.default((product == null ? void 0 : product.main_product_selling_price) || ((_a = product.metadata) == null ? void 0 : _a.main_product_selling_price) || 0);
|
|
679
|
+
for (let bundleItem of (product == null ? void 0 : product.product_bundle) || []) {
|
|
680
|
+
if (getBundleItemIsMarkupOrDiscountPrice(bundleItem)) {
|
|
681
|
+
const bundleItemPrice = new import_decimal.default(bundleItem.bundle_selling_price ?? 0);
|
|
682
|
+
mainProductPrice = mainProductPrice.add(bundleItemPrice.times(bundleItem.num));
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
let taxFee = new import_decimal.default((product == null ? void 0 : product.tax_fee) || ((_b = product == null ? void 0 : product.metadata) == null ? void 0 : _b.main_product_attached_bundle_tax_fee) || 0).add(((_c = product == null ? void 0 : product.metadata) == null ? void 0 : _c.tax_fee_rounding_remainder) || 0);
|
|
686
|
+
if (product.is_price_include_tax === 1) {
|
|
687
|
+
taxFee = new import_decimal.default(0);
|
|
688
|
+
}
|
|
689
|
+
const surchargeFee = new import_decimal.default(((_d = product == null ? void 0 : product.metadata) == null ? void 0 : _d.main_product_attached_bundle_surcharge_fee) || 0).add(((_e = product == null ? void 0 : product.metadata) == null ? void 0 : _e.surcharge_rounding_remainder) || 0);
|
|
690
|
+
const taxAndFeeTotal = taxFee.add(surchargeFee);
|
|
691
|
+
if (isDeductTaxAndFee) {
|
|
692
|
+
mainProductPrice = mainProductPrice.add(taxAndFeeTotal);
|
|
693
|
+
}
|
|
694
|
+
return mainProductPrice.toNumber();
|
|
695
|
+
};
|
|
696
|
+
var getBundleItemPrice = (bundleItem, parentQuantity, isDeductTaxAndFee) => {
|
|
697
|
+
var _a;
|
|
698
|
+
const totalQuantity = bundleItem.num * parentQuantity;
|
|
699
|
+
let bundleItemPrice = new import_decimal.default(bundleItem.bundle_selling_price ?? 0).times(totalQuantity);
|
|
700
|
+
if (isDeductTaxAndFee) {
|
|
701
|
+
let taxFee = new import_decimal.default(bundleItem.tax_fee ?? 0).times(totalQuantity);
|
|
702
|
+
if (bundleItem.is_price_include_tax === 1) {
|
|
703
|
+
taxFee = new import_decimal.default(0);
|
|
704
|
+
}
|
|
705
|
+
const surchargeFee = new import_decimal.default(((_a = bundleItem.metadata) == null ? void 0 : _a.surcharge_fee) ?? 0).times(totalQuantity);
|
|
706
|
+
bundleItemPrice = bundleItemPrice.add(taxFee).add(surchargeFee);
|
|
707
|
+
}
|
|
708
|
+
return bundleItemPrice.toNumber();
|
|
709
|
+
};
|
|
710
|
+
var expandProductsWithBundleItems = (products, deductTaxAndFee) => {
|
|
711
|
+
const expandedProducts = [];
|
|
712
|
+
products.forEach((product, indexInOrder) => {
|
|
713
|
+
const productQuantity = getProductQuantity(product);
|
|
714
|
+
const parentLineKey = resolveWalletPassLineKey(product, indexInOrder);
|
|
715
|
+
const unitPriceWithTax = getMainProductPrice(product, true);
|
|
716
|
+
const unitPricePure = getMainProductPrice(product, false);
|
|
717
|
+
expandedProducts.push({
|
|
718
|
+
...product,
|
|
719
|
+
is_bundle_item: false,
|
|
720
|
+
parent_product_id: null,
|
|
721
|
+
_walletPassLineKey: parentLineKey,
|
|
722
|
+
_orderLineQuantity: productQuantity,
|
|
723
|
+
// 单价(用于按 quantity 计算抵扣)
|
|
724
|
+
unitPriceWithTax: new import_decimal.default(unitPriceWithTax),
|
|
725
|
+
unitPricePure: new import_decimal.default(unitPricePure),
|
|
726
|
+
// 剩余可抵扣数量
|
|
727
|
+
remainingQuantity: productQuantity,
|
|
728
|
+
// 含税费的剩余金额
|
|
729
|
+
remainingAmountWithTax: new import_decimal.default(unitPriceWithTax).times(productQuantity),
|
|
730
|
+
// 纯商品金额(不含税费)
|
|
731
|
+
remainingAmountPure: new import_decimal.default(unitPricePure).times(productQuantity)
|
|
732
|
+
});
|
|
733
|
+
if (product.product_bundle && product.product_bundle.length > 0) {
|
|
734
|
+
product.product_bundle.forEach((bundleItem) => {
|
|
735
|
+
if (getBundleItemIsOriginalPrice(bundleItem)) {
|
|
736
|
+
const bundleQuantity = bundleItem.num * productQuantity;
|
|
737
|
+
const bundleLineKey = `${parentLineKey}#bundle:${bundleItem.bundle_id}:${bundleItem.bundle_product_id}`;
|
|
738
|
+
const bundleUnitPriceWithTax = new import_decimal.default(getBundleItemPrice(bundleItem, 1, true)).dividedBy(bundleItem.num);
|
|
739
|
+
const bundleUnitPricePure = new import_decimal.default(getBundleItemPrice(bundleItem, 1, false)).dividedBy(bundleItem.num);
|
|
740
|
+
expandedProducts.push({
|
|
741
|
+
...bundleItem,
|
|
742
|
+
product_id: bundleItem.bundle_product_id,
|
|
743
|
+
// 使用 bundle_product_id 作为 product_id
|
|
744
|
+
is_bundle_item: true,
|
|
745
|
+
parent_product_id: product.product_id,
|
|
746
|
+
quantity: bundleQuantity,
|
|
747
|
+
// 子商品数量 * 主商品数量
|
|
748
|
+
_walletPassLineKey: bundleLineKey,
|
|
749
|
+
_orderLineQuantity: bundleQuantity,
|
|
750
|
+
// 单价(用于按 quantity 计算抵扣)
|
|
751
|
+
unitPriceWithTax: bundleUnitPriceWithTax,
|
|
752
|
+
unitPricePure: bundleUnitPricePure,
|
|
753
|
+
// 剩余可抵扣数量
|
|
754
|
+
remainingQuantity: bundleQuantity,
|
|
755
|
+
// 含税费的剩余金额
|
|
756
|
+
remainingAmountWithTax: new import_decimal.default(getBundleItemPrice(bundleItem, productQuantity, true)),
|
|
757
|
+
// 纯商品金额(不含税费)
|
|
758
|
+
remainingAmountPure: new import_decimal.default(getBundleItemPrice(bundleItem, productQuantity, false))
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
return expandedProducts;
|
|
765
|
+
};
|
|
766
|
+
var getBundleItemIsOriginalPrice = (item) => {
|
|
767
|
+
return (item == null ? void 0 : item.price_type) === "markup" && (item == null ? void 0 : item.price_type_ext) === "product_price";
|
|
768
|
+
};
|
|
769
|
+
var getBundleItemIsMarkupPrice = (item) => {
|
|
770
|
+
return (item == null ? void 0 : item.price_type) === "markup" && ((item == null ? void 0 : item.price_type_ext) === "" || !(item == null ? void 0 : item.price_type_ext));
|
|
771
|
+
};
|
|
772
|
+
var getBundleItemIsDiscountPrice = (item) => {
|
|
773
|
+
return (item == null ? void 0 : item.price_type) === "markdown" && ((item == null ? void 0 : item.price_type_ext) === "" || !(item == null ? void 0 : item.price_type_ext));
|
|
774
|
+
};
|
|
775
|
+
var getBundleItemIsMarkupOrDiscountPrice = (item) => {
|
|
776
|
+
return getBundleItemIsMarkupPrice(item) || getBundleItemIsDiscountPrice(item);
|
|
777
|
+
};
|
|
778
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
779
|
+
0 && (module.exports = {
|
|
780
|
+
getApplicableProductIds,
|
|
781
|
+
getBundleItemIsDiscountPrice,
|
|
782
|
+
getBundleItemIsMarkupOrDiscountPrice,
|
|
783
|
+
getBundleItemIsMarkupPrice,
|
|
784
|
+
getBundleItemIsOriginalPrice,
|
|
785
|
+
getBundleItemPrice,
|
|
786
|
+
getMainProductPrice,
|
|
787
|
+
getProductQuantity,
|
|
788
|
+
processVouchers,
|
|
789
|
+
recalculateVouchers,
|
|
790
|
+
resolveWalletPassLineKey
|
|
791
|
+
});
|