window._ABConfig.getProductDiscountedPricing = ({ variantId, amount, quantity, sellingPlanId }) => {
console.log("Executed DiscountBundlesByBundleType");
if (!variantId) {
console.error('Please provide a current variant id');
return [];
}
//helper functions
const isDiscountUsageLimitExceed = (customerDiscountUsage, bundle) => {
if (customerDiscountUsage && customerDiscountUsage.length) {
const targetDiscountUsage = customerDiscountUsage.find(
(discountUsage) => discountUsage?.uniqueRef === bundle?.uniqueRef
);
return targetDiscountUsage && targetDiscountUsage?.usageCount >= bundle?.limitToUsePerCustomer;
}
return false;
};
const isBundleRestrictedCustomerByTagsByDiscount = (item, customerTags) => {
if (!item?.restrictTags) return false;
const restrictTags = item?.restrictTags?.split(',');
return customerTags && customerTags.length > 0 && customerTags.some((tag) => restrictTags?.includes(tag));
};
const isBundleAllowedByCustomersTagByDiscount = (item, customerTags) => {
if (!item?.allowedTags) return true;
const allowedCustomersOnly = item?.allowedTags?.split(',');
return (
customerTags &&
customerTags.length > 0 &&
customerTags.some((tag) => allowedCustomersOnly?.includes(tag))
);
};
const isBundleRestrictedByDiscount = (item, customerTags) => {
return isBundleRestrictedCustomerByTagsByDiscount(item, customerTags) || !isBundleAllowedByCustomersTagByDiscount(item, customerTags);
};
const processBundleRules = (bundles, type, fields) =>
bundles
.filter((bundle) => bundle?.bundleType === type)
.map((rule) => {
const parsedRule = { ...rule };
fields.forEach((field) => {
parsedRule[field] = JSON.parse(rule[field]);
});
return parsedRule;
});
const getBestDiscount = (applicableDiscounts, lineItem, discountKey = 'discount') => {
return applicableDiscounts.reduce((greater, current) => {
const greaterDiscount = greater?.[discountKey];
const currentDiscount = current?.[discountKey];
if ((greater?.discountType === "PERCENTAGE" && current?.discountType === "PERCENTAGE") ||
(greater?.discountType === "FIXED_AMOUNT" && current?.discountType === "FIXED_AMOUNT")) {
return currentDiscount > greaterDiscount ? current : greater;
} else if (current?.discountType === "FIXED_AMOUNT" && greater?.discountType === "PERCENTAGE") {
return currentDiscount > ((greaterDiscount / 100) * lineItem?.totalAmount) ? current : greater;
} else if (current?.discountType === "PERCENTAGE" && greater?.discountType === "FIXED_AMOUNT") {
return ((currentDiscount / 100) * lineItem?.totalAmount) > greaterDiscount ? current : greater;
}
return currentDiscount > greaterDiscount ? current : greater;
});
};
const getApplicableTieredDiscount = (volumeDiscountBundles, lineItem) => {
let applicableDiscount = null;
const updatedVolumeDiscountBundles = volumeDiscountBundles.map(bundle => {
const updatedTieredDiscount = bundle?.tieredDiscount.map(discount => {
return {
...discount,
appliesOn: bundle?.appliesOn
};
})
return {
...bundle,
tieredDiscount: updatedTieredDiscount
}
});
const volumeDiscountBundlesTieredDiscount = updatedVolumeDiscountBundles.reduce((acc, item) => {
return acc.concat(item?.tieredDiscount);
}, []);
let applicableQuantityBasedDiscount = volumeDiscountBundlesTieredDiscount
.filter(tieredDiscount => tieredDiscount?.discountBasedOn === "QUANTITY")
.filter(tieredDiscount => lineItem?.quantity >= tieredDiscount?.value);
applicableQuantityBasedDiscount = applicableQuantityBasedDiscount.length > 0 ? getBestDiscount(applicableQuantityBasedDiscount, lineItem) : null;
let applicableSpendAmountBasedDiscount = volumeDiscountBundlesTieredDiscount
.filter(tieredDiscount => tieredDiscount?.discountBasedOn === "AMOUNT")
.filter(tieredDiscount => lineItem?.totalAmount >= tieredDiscount?.value);
applicableSpendAmountBasedDiscount = applicableSpendAmountBasedDiscount.length > 0 ? getBestDiscount(applicableSpendAmountBasedDiscount, lineItem, ) : null;
if (applicableQuantityBasedDiscount && applicableSpendAmountBasedDiscount) {
if ((applicableQuantityBasedDiscount?.discountType === "PERCENTAGE" && applicableSpendAmountBasedDiscount?.discountType === "PERCENTAGE") || (applicableQuantityBasedDiscount?.discountType === "FIXED_AMOUNT" && applicableSpendAmountBasedDiscount?.discountType === "FIXED_AMOUNT")) {
if (applicableQuantityBasedDiscount?.discount > applicableSpendAmountBasedDiscount?.discount) {
applicableDiscount = applicableQuantityBasedDiscount;
} else {
applicableDiscount = applicableSpendAmountBasedDiscount;
}
}else if(applicableQuantityBasedDiscount?.discountType === "PERCENTAGE" && applicableSpendAmountBasedDiscount?.discountType === "FIXED_AMOUNT"){
if (((applicableQuantityBasedDiscount?.discount / 100) * lineItem?.totalAmount) > applicableSpendAmountBasedDiscount?.discount) {
applicableDiscount = applicableQuantityBasedDiscount;
} else {
applicableDiscount = applicableSpendAmountBasedDiscount;
}
}else if(applicableQuantityBasedDiscount?.discountType === "FIXED_AMOUNT" && applicableSpendAmountBasedDiscount?.discountType === "PERCENTAGE"){
if (applicableQuantityBasedDiscount?.discount > ((applicableSpendAmountBasedDiscount?.discount / 100) * lineItem?.totalAmount)) {
applicableDiscount = applicableQuantityBasedDiscount;
} else {
applicableDiscount = applicableSpendAmountBasedDiscount;
}
}
} else if (applicableQuantityBasedDiscount) {
applicableDiscount = applicableQuantityBasedDiscount;
} else if (applicableSpendAmountBasedDiscount) {
applicableDiscount = applicableSpendAmountBasedDiscount;
}
return applicableDiscount;
}
const getApplicablePercentOrFixedDiscount = (discountedPricingBundles, lineItem) => {
let applicableDiscount = null;
let applicableQuantityBasedDiscount = discountedPricingBundles
.map(bundle => {
return {
...bundle,
minProductCount: bundle?.minProductCount || 0,
maxProductCount: bundle?.maxProductCount || 0,
minOrderAmount: bundle?.minOrderAmount || 0
};
})
.filter(bundle => {
const minCount = bundle.minProductCount;
const maxCount = bundle.maxProductCount;
const minAmount = bundle.minOrderAmount;
if (minCount > 0 && lineItem.quantity < minCount) return false;
if (maxCount > 0 && lineItem.quantity > maxCount) return false;
if (minAmount > 0 && lineItem.amount < minAmount) return false;
return true;
});
applicableDiscount = applicableQuantityBasedDiscount.length > 0 ? getBestDiscount(applicableQuantityBasedDiscount, lineItem, 'discountValue') : null;
if(applicableDiscount){
applicableDiscount = {
discountBasedOn: applicableDiscount?.minOrderAmount > 0 && applicableDiscount?.minProductCount === 0 ? "AMOUNT" : "QUANTITY",
value: applicableDiscount?.minOrderAmount > 0 && applicableDiscount?.minProductCount === 0 ? lineItem?.totalAmount : lineItem?.quantity,
discount: applicableDiscount?.discountValue,
discountType: applicableDiscount?.discountType,
appliesOn: applicableDiscount?.appliesOn
}
}
return applicableDiscount;
}
const discountBundles = [];
const customerTags = null;
let customerDiscountUsage = [];
let isLoggedIn = false;
const filteredDiscountBundles = Array.isArray(discountBundles) && discountBundles.length > 0 && discountBundles?.filter((bundle) => {
if (bundle?.status !== 'ACTIVE') {
return false;
}
if ((bundle?.allowedTags || bundle?.restrictTags || bundle?.limitToUsePerCustomer > 0) && !isLoggedIn) {
return false;
}
if ((bundle?.allowedTags || bundle?.restrictTags) && isLoggedIn && isBundleRestrictedByDiscount(bundle, customerTags)) {
return false;
}
if (bundle?.limitToUsePerCustomer > 0 && isDiscountUsageLimitExceed(customerDiscountUsage, bundle)) {
return false;
}
if (bundle?.appliesOn === "ONE_TIME" && sellingPlanId != null) {
return false;
}
if (bundle?.appliesOn === "SUBSCRIPTION" && sellingPlanId === null) {
return false;
}
try {
const variants = JSON.parse(bundle?.variants || '[]');
return variants.some((variant) => parseInt(variant?.variantId) === parseInt(variantId));
} catch (e) {
console.error('Failed to parse JSON:', e);
return false;
}
}) || [];
const totalAmount = amount * quantity;
const lineItem = {variantId, quantity, amount, totalAmount };
const volumeDiscountBundles = processBundleRules(filteredDiscountBundles, 'VOLUME_DISCOUNT', ["variants", "tieredDiscount"]);
const discountedPricingBundles = processBundleRules(filteredDiscountBundles, 'DISCOUNTED_PRICING', ["variants"]);
let applicableDiscount = null;
const volumeDiscount = getApplicableTieredDiscount(volumeDiscountBundles, lineItem);
const pricingDiscount = getApplicablePercentOrFixedDiscount(discountedPricingBundles, lineItem);
if (volumeDiscount && pricingDiscount) {
applicableDiscount = getBestDiscount([volumeDiscount, pricingDiscount], lineItem);
} else {
applicableDiscount = volumeDiscount || pricingDiscount;
}
const discountAmount = applicableDiscount?.discountType === "PERCENTAGE" ? (totalAmount * applicableDiscount?.discount) / 100 : applicableDiscount?.discount;
const discountedPrice = applicableDiscount?.discountType === "PERCENTAGE" ? (totalAmount - discountAmount) : ( totalAmount - applicableDiscount?.discount);
return {
variantId,
quantity,
amount,
totalAmount,
discountType: applicableDiscount?.discountType,
discountValue: applicableDiscount?.discount,
discountAmount,
discountedPrice: !isNaN(discountedPrice) ? discountedPrice : undefined,
discountConfigure: applicableDiscount?.appliesOn
};
};