(params: {
organizationId: string
userId: string
logger: Logger
})
| 118 | * This consolidates logic from backend/src/api/usage.ts and web/src/app/api/orgs/[orgId]/usage/route.ts |
| 119 | */ |
| 120 | export async function getOrganizationUsageData(params: { |
| 121 | organizationId: string |
| 122 | userId: string |
| 123 | logger: Logger |
| 124 | }): Promise<OrganizationUsageData> { |
| 125 | const { organizationId, userId, logger } = params |
| 126 | |
| 127 | try { |
| 128 | // Check if user is a member of this organization |
| 129 | const membership = await db |
| 130 | .select({ role: schema.orgMember.role }) |
| 131 | .from(schema.orgMember) |
| 132 | .where( |
| 133 | and( |
| 134 | eq(schema.orgMember.org_id, organizationId), |
| 135 | eq(schema.orgMember.user_id, userId), |
| 136 | ), |
| 137 | ) |
| 138 | .limit(1) |
| 139 | |
| 140 | if (membership.length === 0) { |
| 141 | throw new Error('User is not a member of this organization') |
| 142 | } |
| 143 | |
| 144 | // Sync organization billing cycle with Stripe and get current cycle start |
| 145 | const startOfCurrentCycle = await syncOrganizationBillingCycle(params) |
| 146 | |
| 147 | // Get the organization to fetch the current period end date |
| 148 | const organization = await db.query.org.findFirst({ |
| 149 | where: eq(schema.org.id, organizationId), |
| 150 | columns: { |
| 151 | current_period_start: true, |
| 152 | current_period_end: true, |
| 153 | }, |
| 154 | }) |
| 155 | |
| 156 | // Use the synced dates or fallback to reasonable defaults |
| 157 | const cycleStartDate = |
| 158 | organization?.current_period_start || startOfCurrentCycle |
| 159 | const cycleEndDate = |
| 160 | organization?.current_period_end || |
| 161 | new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) // 30 days from now |
| 162 | |
| 163 | let currentBalance = 0 |
| 164 | let usageThisCycle = 0 |
| 165 | |
| 166 | try { |
| 167 | const now = new Date() |
| 168 | const { balance, usageThisCycle: usage } = |
| 169 | await calculateOrganizationUsageAndBalance({ |
| 170 | ...params, |
| 171 | quotaResetDate: startOfCurrentCycle, |
| 172 | now, |
| 173 | }) |
| 174 | currentBalance = balance.netBalance |
| 175 | usageThisCycle = usage |
| 176 | } catch (error) { |
| 177 | // If no credits exist yet, that's fine |
no test coverage detected