(params: {
plan: string | null
seats: number | null
periodStart: Date | null
periodEnd: Date | null
organizationId: string
pooledCurrentPeriodCost: number
departedMemberUsage: number
memberIds: string[]
})
| 170 | * callers route through this to keep the overage math in one place. |
| 171 | */ |
| 172 | export async function computeOrgOverageAmount(params: { |
| 173 | plan: string | null |
| 174 | seats: number | null |
| 175 | periodStart: Date | null |
| 176 | periodEnd: Date | null |
| 177 | organizationId: string |
| 178 | pooledCurrentPeriodCost: number |
| 179 | departedMemberUsage: number |
| 180 | memberIds: string[] |
| 181 | }): Promise<{ |
| 182 | effectiveUsage: number |
| 183 | baseSubscriptionAmount: number |
| 184 | dailyRefreshDeduction: number |
| 185 | totalOverage: number |
| 186 | }> { |
| 187 | const totalUsage = params.pooledCurrentPeriodCost + params.departedMemberUsage |
| 188 | |
| 189 | let dailyRefreshDeduction = 0 |
| 190 | const planDollars = getPlanTierDollars(params.plan) |
| 191 | if (planDollars > 0 && params.periodStart && params.memberIds.length > 0) { |
| 192 | const userBounds = await getOrgMemberRefreshBounds(params.organizationId, params.periodStart) |
| 193 | dailyRefreshDeduction = await computeDailyRefreshConsumed({ |
| 194 | userIds: params.memberIds, |
| 195 | periodStart: params.periodStart, |
| 196 | periodEnd: params.periodEnd ?? null, |
| 197 | planDollars, |
| 198 | seats: params.seats || 1, |
| 199 | userBounds: Object.keys(userBounds).length > 0 ? userBounds : undefined, |
| 200 | billingEntity: { type: 'organization', id: params.organizationId }, |
| 201 | }) |
| 202 | } |
| 203 | |
| 204 | const effectiveUsage = Math.max(0, totalUsage - dailyRefreshDeduction) |
| 205 | const { basePrice } = getPlanPricing(params.plan ?? '') |
| 206 | const baseSubscriptionAmount = (params.seats || 1) * basePrice |
| 207 | const totalOverage = Math.max(0, effectiveUsage - baseSubscriptionAmount) |
| 208 | |
| 209 | return { effectiveUsage, baseSubscriptionAmount, dailyRefreshDeduction, totalOverage } |
| 210 | } |
| 211 | |
| 212 | /** |
| 213 | * Calculate overage amount for a subscription |
no test coverage detected