Merge branch 'dev' of https://github.com/useautumn/autumn into dev
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
import { InternalError } from "@api/errors/base/InternalError.js";
|
||||
import type { FullCusProduct } from "../../../models/cusProductModels/cusProductModels";
|
||||
import type { Feature } from "../../../models/featureModels/featureModels";
|
||||
import type { Price } from "../../../models/productModels/priceModels/priceModels";
|
||||
|
||||
import {
|
||||
isFixedPrice,
|
||||
isPrepaidPrice,
|
||||
priceOnFeature,
|
||||
} from "../../productUtils/priceUtils/classifyPriceUtils";
|
||||
import { cusProductToPrices } from "../convertCusProduct";
|
||||
|
||||
// Overload: errorOnNotFound = true → guaranteed Price
|
||||
export function customerProductToBasePrice(params: {
|
||||
customerProduct: FullCusProduct;
|
||||
errorOnNotFound: true;
|
||||
}): Price;
|
||||
|
||||
// Overload: errorOnNotFound = false/undefined → Price | undefined
|
||||
export function customerProductToBasePrice(params: {
|
||||
customerProduct: FullCusProduct;
|
||||
errorOnNotFound?: false;
|
||||
}): Price | undefined;
|
||||
|
||||
// Implementation
|
||||
export function customerProductToBasePrice({
|
||||
customerProduct,
|
||||
errorOnNotFound,
|
||||
}: {
|
||||
customerProduct: FullCusProduct;
|
||||
errorOnNotFound?: boolean;
|
||||
}): Price | undefined {
|
||||
const prices = cusProductToPrices({ cusProduct: customerProduct });
|
||||
const result = prices.find((p) => isFixedPrice(p));
|
||||
|
||||
if (errorOnNotFound && !result) {
|
||||
throw new InternalError({
|
||||
message: `Base price not found for customer product ${customerProduct.id}`,
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Overload: errorOnNotFound = true → guaranteed Price
|
||||
export function customerProductToPrepaidPrice(params: {
|
||||
customerProduct: FullCusProduct;
|
||||
feature?: Feature;
|
||||
errorOnNotFound: true;
|
||||
}): Price;
|
||||
|
||||
// Overload: errorOnNotFound = false/undefined → Price | undefined
|
||||
export function customerProductToPrepaidPrice(params: {
|
||||
customerProduct: FullCusProduct;
|
||||
feature?: Feature;
|
||||
errorOnNotFound?: false;
|
||||
}): Price | undefined;
|
||||
|
||||
// Implementation
|
||||
export function customerProductToPrepaidPrice({
|
||||
customerProduct,
|
||||
feature,
|
||||
errorOnNotFound,
|
||||
}: {
|
||||
customerProduct: FullCusProduct;
|
||||
feature?: Feature;
|
||||
errorOnNotFound?: boolean;
|
||||
}): Price | undefined {
|
||||
const prices = cusProductToPrices({ cusProduct: customerProduct });
|
||||
const result = prices.find((p) => {
|
||||
const featureMatch = feature
|
||||
? priceOnFeature({ price: p, feature })
|
||||
: true;
|
||||
return isPrepaidPrice(p) && featureMatch;
|
||||
});
|
||||
|
||||
if (errorOnNotFound && !result) {
|
||||
const featureMsg = feature ? ` for feature ${feature.id}` : "";
|
||||
throw new InternalError({
|
||||
message: `Prepaid price not found${featureMsg} for customer product ${customerProduct.id}`,
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -34,20 +34,22 @@ export const findMainActiveCustomerProductByGroup = ({
|
||||
};
|
||||
|
||||
export const findActiveCustomerProductById = ({
|
||||
fullCustomer,
|
||||
fullCus,
|
||||
productId,
|
||||
internalEntityId,
|
||||
}: {
|
||||
fullCustomer: FullCustomer;
|
||||
fullCus: FullCustomer;
|
||||
productId: string;
|
||||
internalEntityId?: string;
|
||||
}) => {
|
||||
const cusProducts = fullCustomer.customer_products;
|
||||
if (!internalEntityId) {
|
||||
internalEntityId = fullCus.entity?.internal_id;
|
||||
}
|
||||
|
||||
const cusProducts = fullCus.customer_products;
|
||||
|
||||
const activeMainCusProduct = cusProducts.find((customerProduct) => {
|
||||
const { valid } = cp(customerProduct)
|
||||
.activeRecurring()
|
||||
.main()
|
||||
.hasProductId({ productId })
|
||||
.onEntity({ internalEntityId });
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Feature } from "@models/featureModels/featureModels";
|
||||
import { Infinite } from "@models/productModels/productEnums";
|
||||
import { BillingInterval } from "../../../models/productModels/intervals/billingInterval";
|
||||
import type { FixedPriceConfig } from "../../../models/productModels/priceModels/priceConfig/fixedPriceConfig";
|
||||
@@ -89,3 +90,16 @@ export const isNotFinalTier = (
|
||||
): tier is UsageTier & { to: number } => {
|
||||
return tier.to !== -1 && tier.to !== Infinite;
|
||||
};
|
||||
|
||||
export const priceOnFeature = ({
|
||||
price,
|
||||
feature,
|
||||
}: {
|
||||
price: Price;
|
||||
feature: Feature;
|
||||
}) => {
|
||||
return (
|
||||
price.config.internal_feature_id === feature.internal_id ||
|
||||
price.config.feature_id === feature.id
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user