diff --git a/packages/console/app/src/routes/workspace/[id]/graph-section.tsx b/packages/console/app/src/routes/workspace/[id]/graph-section.tsx index cbcd1a629..b13309d3d 100644 --- a/packages/console/app/src/routes/workspace/[id]/graph-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/graph-section.tsx @@ -1,4 +1,4 @@ -import { and, Database, eq, gte, inArray, isNull, lte, or, sql } from "@opencode-ai/console-core/drizzle/index.js" +import { and, Database, eq, gte, inArray, isNull, lte, or, sql, sum } from "@opencode-ai/console-core/drizzle/index.js" import { UsageTable } from "@opencode-ai/console-core/schema/billing.sql.js" import { KeyTable } from "@opencode-ai/console-core/schema/key.sql.js" import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js" @@ -35,7 +35,7 @@ async function getCosts(workspaceID: string, year: number, month: number) { .select({ date: sql`DATE(${UsageTable.timeCreated})`, model: UsageTable.model, - totalCost: sql`SUM(${UsageTable.cost})`, + totalCost: sum(UsageTable.cost), keyId: UsageTable.keyID, }) .from(UsageTable) @@ -46,7 +46,13 @@ async function getCosts(workspaceID: string, year: number, month: number) { lte(UsageTable.timeCreated, endDate), ), ) - .groupBy(sql`DATE(${UsageTable.timeCreated})`, UsageTable.model, UsageTable.keyID), + .groupBy(sql`DATE(${UsageTable.timeCreated})`, UsageTable.model, UsageTable.keyID) + .then((x) => + x.map((r) => ({ + ...r, + totalCost: r.totalCost ? parseInt(r.totalCost) : 0, + })), + ), ) // Get unique key IDs from usage @@ -204,18 +210,16 @@ export function GraphSection() { const dates = getDates() if (!data?.usage?.length) return null - const filteredUsageResults = store.key ? data.usage.filter((row) => row.keyId === store.key) : data.usage - const dailyData = new Map>() for (const dateKey of dates) dailyData.set(dateKey, new Map()) - for (const row of filteredUsageResults) { - const dayMap = dailyData.get(row.date) - if (dayMap) { - const existing = dayMap.get(row.model) || 0 - dayMap.set(row.model, existing + row.totalCost) - } - } + data.usage + .filter((row) => (store.key ? row.keyId === store.key : true)) + .forEach((row) => { + const dayMap = dailyData.get(row.date) + if (!dayMap) return + dayMap.set(row.model, (dayMap.get(row.model) ?? 0) + row.totalCost) + }) const filteredModels = store.model === null ? getModels() : [store.model] @@ -223,7 +227,7 @@ export function GraphSection() { const color = getModelColor(model) return { label: model, - data: dates.map((date) => (dailyData.get(date)?.get(model) || 0) / 100000000), + data: dates.map((date) => (dailyData.get(date)?.get(model) || 0) / 100_000_000), backgroundColor: color, hoverBackgroundColor: color, borderWidth: 0,