import {z} from 'zod' export type PricingCycleInterval = 'WEEKLY' | 'MONTHLY' | 'QUARTERLY' | 'HALF_YEARLY' | 'ANNUALLY'; export type PricingCycleConfig = {interval: PricingCycleInterval, startOffset?: {dayOffset: string, monthOffset: string} | undefined, gracePeriod: number, anniversaryCycle?: boolean | undefined}; export type PricingModel = 'TIERED' | 'VOLUME'; export type PriceType = 'FLAT' | 'PER_UNIT' | 'PACKAGE'; export type Slab = {order: number, startAfter: number, priceType: PriceType, slabConfig?: {[key: string]: string} | undefined}; export type RatePlan = {pricingModel: PricingModel, slabs: Array}; export type SlabRate = {order: number, rate: number, slabRateConfig?: {[key: string]: string} | undefined}; export type RateValue = {currency: string, slabRates: Array, rateConfig?: {[key: string]: string} | undefined}; export type UsageRateCard = {displayName?: string | undefined, tag?: string | undefined, usageMeterId: string, ratePlan: RatePlan, rateValues: Array}; export type InvoiceTiming = 'IN_ADVANCE' | 'IN_ARREARS' | 'PREPAID'; export type FixedFeeType = 'ONE_TIME' | 'RECURRING'; export type CurrencyRateValue = {currency: string, rate: number}; export type RecurrenceConfig = {interval?: number | undefined, offset?: number | undefined}; export type FixedFeeRateCard = {id: string, displayName?: string | undefined, tag?: string | undefined, invoiceTiming?: InvoiceTiming | undefined, type?: FixedFeeType | undefined, rateValues: Array, enableProration: boolean, recurrenceConfig?: RecurrenceConfig | undefined}; export type AddOnType = 'LICENSE' | 'FIXED_FEE' | 'CREDIT_GRANT' | 'NAMED_LICENSE'; export type UsageCycleInterval = 'WEEKLY' | 'MONTHLY' | 'QUARTERLY' | 'HALF_YEARLY' | 'ANNUALLY'; export type MaxQuantityBreachAction = 'DO_NOTHING'; export type LicenseRateCardConfig = {maxQuantity?: number | undefined, maxQuantityBreachAction?: MaxQuantityBreachAction | undefined}; export type ProratedRefundMode = 'NONE' | 'CREDITS' | 'PAYMENT' | 'WALLET'; export type LicenseRateCard = {id: string, type?: AddOnType | undefined, displayName?: string | undefined, tag?: string | undefined, invoiceTiming?: InvoiceTiming | undefined, usageCycle?: UsageCycleInterval | undefined, enableProration: boolean, config?: LicenseRateCardConfig | undefined, ratePlan: RatePlan, rateValues: Array, proratedRefundMode?: ProratedRefundMode | undefined}; export type FeatureConfig = {effectiveFrom?: unknown | undefined, effectiveUntil: unknown, featureCreditLimit: number}; export type BillingEntitlementRateCard = {featureId: string, featureConfigs: Array, tag?: string | undefined, invoiceTiming: InvoiceTiming, displayName?: string | undefined, ratePlan: RatePlan, rateValues: Array, recurrenceConfig?: RecurrenceConfig | undefined}; export type MinimumCommitment = {displayName: string, rateValues: Array}; export type ExpiryType = 'PRICING_CYCLE' | 'NO_EXPIRY' | 'CUSTOM'; export type GrantDetails = {priority: number, expiryType: ExpiryType, expiryDuration?: unknown | undefined, applicableEntityIds?: Array | undefined}; export type SlabDetail = {startAfter: number, priceType: PriceType, slabConfig?: {[key: string]: string} | undefined, rate: number, slabRateConfig?: {[key: string]: string} | undefined}; export type CurrencySlabRateDetail = {currency: string, creditAmount: number, slabDetails: Array, rateConfig?: {[key: string]: string} | undefined}; export type CreditRateDetails = {pricingModel: PricingModel, currencySlabRateDetails: Array}; export type CreditGrantType = 'ONE_TIME' | 'RECURRING'; export type CreditGrantRateCard = {id: string, displayName?: string | undefined, tag?: string | undefined, grantDetails: GrantDetails, rateDetails: CreditRateDetails, invoiceTiming?: InvoiceTiming | undefined, type?: CreditGrantType | undefined, recurrenceConfig?: RecurrenceConfig | undefined}; export type BillingConfig = {interval?: number | undefined, startOffset?: number | undefined}; export type EntitlementOverageRateCard = {featureId: string, displayName?: string | undefined, tag?: string | undefined, maxQuantity?: number | undefined, ratePlan: RatePlan, rateValues: Array, billingConfig?: BillingConfig | undefined}; export type CreatePricePlanDetails = {pricingCycleConfig?: PricingCycleConfig | undefined, supportedCurrencies: Array, usageRateCards?: Array | undefined, fixedFeeRateCards?: Array | undefined, licenseRateCards?: Array | undefined, billingEntitlementRateCards?: Array | undefined, minimumCommitment?: MinimumCommitment | undefined, creditGrantRateCards?: Array | undefined, entitlementOverageRateCards?: Array | undefined, deferredRevenue?: boolean | undefined}; export type CalculateRevenueRequest = {currencyConfig: {mode: 'CUSTOM' | 'ACCOUNT_INVOICE', currency?: string | undefined, accountId?: string | undefined}, pricePlanDetailsConfig: {mode: 'CUSTOM' | 'PRICE_PLAN' | 'ACCOUNT', pricePlanDetails?: CreatePricePlanDetails | undefined, pricePlanId?: string | undefined, accountId?: string | undefined, effectiveOn?: string | undefined, pricingCycleOrdinal?: number | undefined}, usageConfig: {mode: 'CUSTOM' | 'LOOKUP_RANGE' | 'LOOKUP_CYCLE', usageMap?: {[key: string]: number} | undefined, lookupRange?: {start: string, end: string, accountId: string} | undefined, lookupCycle?: ({cycleEffectiveOn?: string | undefined, accountId: string}) | undefined}, licenseEntriesConfig: {mode: 'CUSTOM' | 'LOOKUP_RANGE' | 'LOOKUP_CYCLE', custom?: Array<{licenseId: string, quantity: number, effectiveFrom: string}> | undefined, lookupRange?: {start: string, end: string, accountId: string} | undefined, lookupCycle?: ({cycleEffectiveOn?: string | undefined, accountId: string}) | undefined}, namedLicenseEntriesConfig?: ({mode: 'CUSTOM' | 'LOOKUP_RANGE' | 'LOOKUP_CYCLE', custom?: (Array<{licenseId: string, name: number, effectiveFrom: string, effectiveUntil?: string | undefined}>) | undefined, lookupRange?: {start: string, end: string, accountId: string} | undefined, lookupCycle?: ({cycleEffectiveOn?: string | undefined, accountId: string}) | undefined}) | undefined, prorationConfig?: ({mode: 'CUSTOM' | 'LOOKUP_CYCLE', customConfig?: {cycleStartDate: string, cycleEndDate: string, currentDate: string} | undefined, lookupCycleConfig?: ({currentDateTime?: string | undefined, cycleEffectiveOn?: string | undefined, accountId: string}) | undefined}) | undefined, entitlementOverageConfig?: ({mode: 'CUSTOM' | 'LOOKUP_CYCLE', custom?: Array<{featureId: string, quantity: number}> | undefined, lookupCycle?: {billingCycleEndDate: string, accountId: string} | undefined}) | undefined}; export type CreateApiRevenueCalculatorArgs = {body: CalculateRevenueRequest}; export type CreateApiRevenueCalculatorOptions = {baseUrl?: string | undefined, bearerAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const pricingCycleInterval = z.enum(["WEEKLY", "MONTHLY", "QUARTERLY", "HALF_YEARLY", "ANNUALLY"]); export const pricingCycleConfig = z.object({interval: pricingCycleInterval, startOffset: z.object({dayOffset: z.string(), monthOffset: z.string()}).optional(), gracePeriod: z.number().int(), anniversaryCycle: z.boolean().optional()}); export const pricingModel = z.enum(["TIERED", "VOLUME"]); export const priceType = z.enum(["FLAT", "PER_UNIT", "PACKAGE"]); export const slab = z.object({order: z.number().int().gte(1).lte(10), startAfter: z.number(), priceType: priceType, slabConfig: z.record(z.string(), z.string()).optional()}); export const ratePlan = z.object({pricingModel: pricingModel, slabs: z.array(slab)}); export const slabRate = z.object({order: z.number().int(), rate: z.number(), slabRateConfig: z.record(z.string(), z.string()).optional()}); export const rateValue = z.object({currency: z.string(), slabRates: z.array(slabRate), rateConfig: z.record(z.string(), z.string()).optional()}); export const usageRateCard = z.object({displayName: z.string().optional(), tag: z.string().optional(), usageMeterId: z.string(), ratePlan: ratePlan, rateValues: z.array(rateValue)}); export const invoiceTiming = z.enum(["IN_ADVANCE", "IN_ARREARS", "PREPAID"]); export const fixedFeeType = z.enum(["ONE_TIME", "RECURRING"]); export const currencyRateValue = z.object({currency: z.string(), rate: z.number()}); export const recurrenceConfig = z.object({interval: z.number().int().optional(), offset: z.number().int().optional()}); export const fixedFeeRateCard = z.object({id: z.string().max(50), displayName: z.string().optional(), tag: z.string().optional(), invoiceTiming: invoiceTiming.optional(), type: fixedFeeType.optional(), rateValues: z.array(currencyRateValue), enableProration: z.boolean(), recurrenceConfig: recurrenceConfig.optional()}); export const addOnType = z.enum(["LICENSE", "FIXED_FEE", "CREDIT_GRANT", "NAMED_LICENSE"]); export const usageCycleInterval = z.enum(["WEEKLY", "MONTHLY", "QUARTERLY", "HALF_YEARLY", "ANNUALLY"]); export const maxQuantityBreachAction = z.literal("DO_NOTHING"); export const licenseRateCardConfig = z.object({maxQuantity: z.number().int().optional(), maxQuantityBreachAction: maxQuantityBreachAction.optional()}); export const proratedRefundMode = z.enum(["NONE", "CREDITS", "PAYMENT", "WALLET"]); export const licenseRateCard = z.object({id: z.string().max(50), type: addOnType.optional(), displayName: z.string().optional(), tag: z.string().optional(), invoiceTiming: invoiceTiming.optional(), usageCycle: usageCycleInterval.optional(), enableProration: z.boolean(), config: licenseRateCardConfig.optional(), ratePlan: ratePlan, rateValues: z.array(rateValue), proratedRefundMode: proratedRefundMode.optional()}); export const featureConfig = z.object({effectiveFrom: z.string().optional(), effectiveUntil: z.string(), featureCreditLimit: z.number().gte(0)}); export const billingEntitlementRateCard = z.object({featureId: z.string(), featureConfigs: z.array(featureConfig), tag: z.string().optional(), invoiceTiming: invoiceTiming, displayName: z.string().optional(), ratePlan: ratePlan, rateValues: z.array(rateValue), recurrenceConfig: recurrenceConfig.optional()}); export const billingConfig = z.object({interval: z.number().int().optional(), startOffset: z.number().int().optional()}); export const entitlementOverageRateCard = z.object({featureId: z.string().max(50), displayName: z.string().optional(), tag: z.string().optional(), maxQuantity: z.number().optional(), ratePlan: ratePlan, rateValues: z.array(rateValue), billingConfig: billingConfig.optional()}); export const minimumCommitment = z.object({displayName: z.string(), rateValues: z.array(currencyRateValue)}); export const expiryType = z.enum(["PRICING_CYCLE", "NO_EXPIRY", "CUSTOM"]); export const grantDetails = z.object({priority: z.number().int().gte(0), expiryType: expiryType, expiryDuration: z.string().optional(), applicableEntityIds: z.array(z.string()).optional()}); export const slabDetail = z.object({startAfter: z.number(), priceType: priceType, slabConfig: z.record(z.string(), z.string()).optional(), rate: z.number(), slabRateConfig: z.record(z.string(), z.string()).optional()}); export const currencySlabRateDetail = z.object({currency: z.string(), creditAmount: z.number().gte(0), slabDetails: z.array(slabDetail), rateConfig: z.record(z.string(), z.string()).optional()}); export const creditRateDetails = z.object({pricingModel: pricingModel, currencySlabRateDetails: z.array(currencySlabRateDetail)}); export const creditGrantType = z.enum(["ONE_TIME", "RECURRING"]); export const creditGrantRateCard = z.object({id: z.string(), displayName: z.string().optional(), tag: z.string().optional(), grantDetails: grantDetails, rateDetails: creditRateDetails, invoiceTiming: invoiceTiming.optional(), type: creditGrantType.optional(), recurrenceConfig: recurrenceConfig.optional()}); export const pricePlanType = z.enum(["BILLING", "PURCHASE"]); export const pricePlanDetails = z.object({supportedCurrencies: z.array(z.string()), activeCurrencies: z.array(z.string()), pricingCycleConfig: pricingCycleConfig.optional(), usageRateCards: z.array(usageRateCard).optional(), fixedFeeRateCards: z.array(fixedFeeRateCard).optional(), licenseRateCards: z.array(licenseRateCard).optional(), billingEntitlementRateCards: z.array(billingEntitlementRateCard).optional(), entitlementOverageRateCards: z.array(entitlementOverageRateCard).optional(), minimumCommitment: minimumCommitment.optional(), creditGrantRateCards: z.array(creditGrantRateCard).optional(), type: pricePlanType.optional(), deferredRevenue: z.boolean().optional()}); export const slabRevenueSummary = z.object({order: z.number().int(), usage: z.number(), revenue: z.number(), metadata: z.object({minimumRateApplied: z.boolean().optional(), maximumRateApplied: z.boolean().optional(), packageQuantity: z.number().int().optional()}).optional()}); export const calculateRevenueResponse = z.object({currency: z.string(), usageLookupRange: z.object({start: z.string(), end: z.string()}).optional(), pricePlanDetails: pricePlanDetails, revenueInfo: z.array(z.object({usageRateCard: usageRateCard.optional(), fixedFeeRateCard: fixedFeeRateCard.optional(), licenseRateCard: licenseRateCard.optional(), billingEntitlementRateCard: billingEntitlementRateCard.optional(), creditGrantRateCard: creditGrantRateCard.optional(), entitlementOverageRateCard: entitlementOverageRateCard.optional(), usages: z.record(z.string(), z.number()), fixedFeeRevenueSummary: z.object({revenue: z.number()}).optional(), licenseRevenueSummary: z.array(slabRevenueSummary).optional(), billingEntitlementRevenueSummary: z.object({revenue: z.number()}).optional(), creditGrantRevenueSummary: z.object({revenue: z.number()}).optional(), entitlementOverageRevenueSummary: z.object({revenue: z.number()}).optional(), slabRevenueSummaries: z.array(slabRevenueSummary).optional()}))}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Calculate and return the revenue for a existing or new price plan * * POST /revenue_calculator */ export const createApiRevenueCalculator = async (args: CreateApiRevenueCalculatorArgs, options?: CreateApiRevenueCalculatorOptions) => { const {baseUrl = "https://api.togai.com", fetch: fetchFn = fetch, bearerAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (bearerAuth !== undefined) headers.set('authorization', `Bearer ${bearerAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/revenue_calculator${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(calculateRevenueResponse, await res.json()) };