77 lines
2.1 KiB
TypeScript
77 lines
2.1 KiB
TypeScript
import { Decimal } from "decimal.js";
|
|
|
|
import type { Price } from "../../models/productModels/priceModels/priceModels";
|
|
import {
|
|
compareBillingIntervals,
|
|
getLargestInterval,
|
|
intervalsSame,
|
|
} from "../intervalUtils/priceIntervalUtils";
|
|
import { nullish } from "../utils";
|
|
import { isFreeProduct } from "./classifyProduct/classifyProductUtils";
|
|
import { isConsumablePrice } from "./priceUtils/classifyPriceUtils";
|
|
|
|
export const isProductUpgrade = ({
|
|
prices1,
|
|
prices2,
|
|
usageAlwaysUpgrade = true,
|
|
}: {
|
|
prices1: Price[];
|
|
prices2: Price[];
|
|
usageAlwaysUpgrade?: boolean;
|
|
}) => {
|
|
const prod1IsFree = isFreeProduct({ prices: prices1 });
|
|
const prod2IsFree = isFreeProduct({ prices: prices2 });
|
|
|
|
// 1. If one product is free and the other is not, then free -> paid is an upgrade
|
|
if (prod1IsFree && prod2IsFree) return true;
|
|
if (prod1IsFree && !prod2IsFree) return true;
|
|
if (!prod1IsFree && prod2IsFree) return false;
|
|
|
|
if (
|
|
prices1.every(isConsumablePrice) &&
|
|
prices2.every(isConsumablePrice) &&
|
|
usageAlwaysUpgrade
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
const billingInterval1 = getLargestInterval({ prices: prices1 }); // pro quarter
|
|
const billingInterval2 = getLargestInterval({ prices: prices2 }); // premium
|
|
|
|
// Billing is nullish if there's a free product. Should not happen!
|
|
if (nullish(billingInterval1) || nullish(billingInterval2)) return false;
|
|
|
|
// 2. Get total price for each product
|
|
const getTotalPrice = (prices: Price[]) => {
|
|
let totalPrice = new Decimal(0);
|
|
for (const price of prices) {
|
|
if ("usage_tiers" in price.config) {
|
|
const tiers = price.config.usage_tiers;
|
|
if (nullish(tiers) || tiers.length === 0) continue;
|
|
totalPrice = totalPrice.plus(tiers[0].amount);
|
|
} else {
|
|
totalPrice = totalPrice.plus(price.config.amount);
|
|
}
|
|
}
|
|
return totalPrice.toNumber();
|
|
};
|
|
|
|
// 3. Compare prices
|
|
|
|
if (
|
|
intervalsSame({
|
|
intervalA: billingInterval1,
|
|
intervalB: billingInterval2,
|
|
})
|
|
) {
|
|
return getTotalPrice(prices1) <= getTotalPrice(prices2);
|
|
} else {
|
|
return (
|
|
compareBillingIntervals({
|
|
configA: billingInterval1,
|
|
configB: billingInterval2,
|
|
}) > 0
|
|
);
|
|
}
|
|
};
|