Skip to content

Commit d637cba

Browse files
improvement(admin): remove included usage for enterprise provisioning (#5749)
1 parent 4c86757 commit d637cba

5 files changed

Lines changed: 15 additions & 15 deletions

File tree

apps/sim/app/api/v1/admin/dashboard/enterprise-provisioning/route.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,11 @@ export const POST = withRouteHandler(
3535
if (!parsed.success) return parsed.response
3636
try {
3737
const actor = await getAdminAuditActor(request)
38-
const { includedMonthlyDollars, usageLimitDollars, ...body } = parsed.data.body
38+
const { usageLimitDollars, ...body } = parsed.data.body
3939
return singleResponse(
4040
toDashboardProvisioning(
4141
await issueEnterpriseProvisioning({
4242
...body,
43-
includedMonthlyCredits: dollarsToCredits(includedMonthlyDollars),
4443
usageLimitCredits:
4544
usageLimitDollars === undefined ? undefined : dollarsToCredits(usageLimitDollars),
4645
requestedByEmail: actor.email ?? 'admin-api',

apps/sim/lib/api/contracts/v1/admin/dashboard.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ describe('admin dashboard credit grant contract', () => {
7474
adminDashboardIssueEnterpriseBodySchema.safeParse({
7575
ownerUserId: 'owner-1',
7676
monthlyInvoiceAmountUsd: 500,
77-
includedMonthlyDollars: 500,
7877
seats: 10,
7978
concurrencyLimit: 1250,
8079
pausePaymentCollection: true,
@@ -90,7 +89,6 @@ describe('admin dashboard credit grant contract', () => {
9089
adminDashboardIssueEnterpriseBodySchema.safeParse({
9190
ownerUserId: 'owner-1',
9291
monthlyInvoiceAmountUsd: 500,
93-
includedMonthlyDollars: 500,
9492
seats: 10,
9593
concurrencyLimit: null,
9694
}).success

apps/sim/lib/api/contracts/v1/admin/dashboard.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ export const adminDashboardIssueEnterpriseBodySchema = z.object({
112112
ownerUserId: z.string().min(1),
113113
organizationName: z.string().trim().min(1).max(120).optional(),
114114
monthlyInvoiceAmountUsd: z.number().min(0.01).max(10_000_000).multipleOf(0.01),
115-
includedMonthlyDollars: creditAlignedDollarAmountSchema,
116115
usageLimitDollars: creditAlignedDollarAmountSchema.optional(),
117116
seats: z.number().int().positive().max(100_000),
118117
concurrencyLimit: z.number().int().positive().max(MAX_BILLING_CONCURRENCY_LIMIT).optional(),

apps/sim/lib/billing/enterprise-provisioning.test.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,26 +160,28 @@ function context() {
160160
}
161161

162162
describe('Enterprise issuance serialization decisions', () => {
163-
it('preserves legacy request keys when no concurrency override is supplied', () => {
163+
it('derives included usage from invoice amount in the request key', () => {
164164
const input = {
165165
ownerUserId: 'owner-1',
166166
monthlyInvoiceAmountUsd: 125,
167-
includedMonthlyCredits: 20000,
168167
usageLimitCredits: 24000,
169168
seats: 12,
170169
requestedByEmail: 'admin@sim.ai',
171170
requestedByUserId: 'admin-1',
172171
}
173172

174173
expect(buildEnterpriseProvisioningRequestKey(input, 'org-1')).toBe(
175-
'enterprise-v2:owner-1:org-1:12500:20000:24000:12'
174+
'enterprise-v2:owner-1:org-1:12500:25000:24000:12'
176175
)
177176
expect(
178177
buildEnterpriseProvisioningRequestKey({ ...input, concurrencyLimit: 1250 }, 'org-1')
179-
).toBe('enterprise-v2:owner-1:org-1:12500:20000:24000:12:1250')
178+
).toBe('enterprise-v2:owner-1:org-1:12500:25000:24000:12:1250')
180179
expect(
181180
buildEnterpriseProvisioningRequestKey({ ...input, pausePaymentCollection: true }, 'org-1')
182-
).toBe('enterprise-v2:owner-1:org-1:12500:20000:24000:12:draft-collection')
181+
).toBe('enterprise-v2:owner-1:org-1:12500:25000:24000:12:draft-collection')
182+
expect(
183+
buildEnterpriseProvisioningRequestKey({ ...input, usageLimitCredits: undefined }, 'org-1')
184+
).toBe('enterprise-v2:owner-1:org-1:12500:25000:25000:12')
183185
})
184186

185187
it('deduplicates an identical unresolved request to the existing outbox operation', () => {

apps/sim/lib/billing/enterprise-provisioning.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { and, count, desc, eq, inArray, isNull, sql } from 'drizzle-orm'
66
import type Stripe from 'stripe'
77
import { parseBillingConcurrencyLimit } from '@/lib/billing/concurrency-defaults'
88
import { getBillingConcurrencyLimit } from '@/lib/billing/concurrency-limits'
9+
import { dollarsToCredits } from '@/lib/billing/credits/conversion'
910
import {
1011
deriveEnterpriseOperationStatus,
1112
ENTERPRISE_METADATA_SYNC_EVENT_TYPE,
@@ -234,7 +235,6 @@ export interface IssueEnterpriseProvisioningInput {
234235
ownerUserId: string
235236
organizationName?: string
236237
monthlyInvoiceAmountUsd: number
237-
includedMonthlyCredits: number
238238
usageLimitCredits?: number
239239
seats: number
240240
concurrencyLimit?: number
@@ -281,13 +281,14 @@ export function buildEnterpriseProvisioningRequestKey(
281281
input: IssueEnterpriseProvisioningInput,
282282
organizationId: string
283283
): string {
284+
const includedMonthlyCredits = dollarsToCredits(input.monthlyInvoiceAmountUsd)
284285
const requestTerms: Array<string | number> = [
285286
'enterprise-v2',
286287
input.ownerUserId,
287288
organizationId,
288289
Math.round(input.monthlyInvoiceAmountUsd * 100),
289-
input.includedMonthlyCredits,
290-
input.usageLimitCredits ?? input.includedMonthlyCredits,
290+
includedMonthlyCredits,
291+
input.usageLimitCredits ?? includedMonthlyCredits,
291292
input.seats,
292293
]
293294
if (input.concurrencyLimit !== undefined) requestTerms.push(input.concurrencyLimit)
@@ -422,6 +423,7 @@ export async function issueEnterpriseProvisioning(
422423
'Monthly invoice amount must be at least $0.01 and use whole cents'
423424
)
424425
}
426+
const includedMonthlyCredits = dollarsToCredits(input.monthlyInvoiceAmountUsd)
425427
if (
426428
input.concurrencyLimit !== undefined &&
427429
parseBillingConcurrencyLimit(input.concurrencyLimit) !== input.concurrencyLimit
@@ -548,8 +550,8 @@ export async function issueEnterpriseProvisioning(
548550
requestedByEmail: input.requestedByEmail,
549551
requestedByUserId: input.requestedByUserId,
550552
invoiceAmountCents,
551-
includedMonthlyCredits: input.includedMonthlyCredits,
552-
usageLimitCredits: input.usageLimitCredits ?? input.includedMonthlyCredits,
553+
includedMonthlyCredits,
554+
usageLimitCredits: input.usageLimitCredits ?? includedMonthlyCredits,
553555
seats: input.seats,
554556
...(input.concurrencyLimit !== undefined ? { concurrencyLimit: input.concurrencyLimit } : {}),
555557
pausePaymentCollection: input.pausePaymentCollection ?? false,

0 commit comments

Comments
 (0)