-
Notifications
You must be signed in to change notification settings - Fork 5
Enhance usage and spending tracking logic #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,9 +2,10 @@ import * as vscode from "vscode"; | |||||||||||
| import * as api from "./api"; | ||||||||||||
| import * as statusBar from "./statusBar"; | ||||||||||||
| import * as config from "./configuration"; | ||||||||||||
| import { TeamMemberSpend } from "./models"; | ||||||||||||
| import { SpendData, TeamMemberSpend } from "./models"; | ||||||||||||
|
|
||||||||||||
| let refreshTimer: NodeJS.Timeout | undefined; | ||||||||||||
| const CENTS_PER_DOLLAR = 100; | ||||||||||||
|
|
||||||||||||
| /** | ||||||||||||
| * Calculates the next reset date based on the start of month date. | ||||||||||||
|
|
@@ -33,6 +34,63 @@ function calculateResetInfo(startOfMonth: string): { | |||||||||||
| return { resetDate, daysRemaining, resetDateStr }; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| function resolveHardLimitDollars( | ||||||||||||
| spendData?: SpendData, | ||||||||||||
| memberSpend?: TeamMemberSpend | ||||||||||||
| ): number | undefined { | ||||||||||||
| const memberCandidates = [ | ||||||||||||
| memberSpend?.hardLimitOverrideDollars, | ||||||||||||
| memberSpend?.hardLimitDollars, | ||||||||||||
| ]; | ||||||||||||
|
|
||||||||||||
| for (const candidate of memberCandidates) { | ||||||||||||
| if (isValidNumber(candidate)) { | ||||||||||||
| return candidate; | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| if (!spendData) { | ||||||||||||
| return undefined; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| const teamDollarCandidates = [ | ||||||||||||
| spendData.teamHardLimitDollars, | ||||||||||||
| spendData.hardLimitDollars, | ||||||||||||
| spendData.defaultHardLimitDollars, | ||||||||||||
| ]; | ||||||||||||
|
|
||||||||||||
| for (const candidate of teamDollarCandidates) { | ||||||||||||
| if (isValidNumber(candidate)) { | ||||||||||||
| return candidate; | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| const teamCentCandidates = [ | ||||||||||||
| spendData.teamHardLimitCents, | ||||||||||||
| spendData.hardLimitCents, | ||||||||||||
| spendData.defaultHardLimitCents, | ||||||||||||
| ]; | ||||||||||||
|
|
||||||||||||
| for (const candidate of teamCentCandidates) { | ||||||||||||
| if (isValidNumber(candidate)) { | ||||||||||||
| return candidate / 100; | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| return undefined; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| function isValidNumber(value?: number | null): value is number { | ||||||||||||
| return typeof value === "number" && Number.isFinite(value); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| function dollarsToCents(amount?: number | null): number | undefined { | ||||||||||||
| if (!isValidNumber(amount)) { | ||||||||||||
| return undefined; | ||||||||||||
| } | ||||||||||||
| return Math.round(amount ); | ||||||||||||
|
||||||||||||
| return Math.round(amount ); | |
| return Math.round(amount * CENTS_PER_DOLLAR); |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent indentation: this line should be indented with 4 spaces to align with the surrounding code block, not 2 spaces.
| let teamSpendData: SpendData | undefined; | |
| let teamSpendData: SpendData | undefined; |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent indentation: this line should be indented with 6 spaces to align with the code inside the try block, not 4 spaces.
| teamSpendData = await api.fetchTeamSpend(teamId, cookie); | |
| teamSpendData = await api.fetchTeamSpend(teamId, cookie); |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent indentation: this line should be indented with 6 spaces to align with the code inside the try block, not 4 spaces.
| mySpend = teamSpendData.teamMemberSpend.find( | |
| mySpend = teamSpendData.teamMemberSpend.find( |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic is incorrect. dollarsToCents(onDemandUsage.limit) returns a value in cents, but then divides by 100 again on line 303. This results in hardLimitDollars being set to the wrong value (off by a factor of 100).
Since onDemandUsage.limit is already in dollars and we want hardLimitDollars in dollars, we should either:
- Use
hardLimitDollars = onDemandUsage.limitdirectly, or - Fix the
dollarsToCentsfunction to properly multiply by 100, then keep this division
The current code will set hardLimitDollars to 1/100th of the intended value.
| hardLimitDollars = dollarsToCents(onDemandUsage.limit); | |
| if (hardLimitDollars !== undefined) { | |
| hardLimitDollars = hardLimitDollars / 100; | |
| } | |
| hardLimitDollars = onDemandUsage.limit; |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -30,6 +30,7 @@ export interface TeamMemberSpend { | |||||||||||||
| userId?: number; | ||||||||||||||
| spendCents?: number; | ||||||||||||||
| hardLimitOverrideDollars?: number; | ||||||||||||||
| hardLimitDollars?: number; | ||||||||||||||
| name?: string; | ||||||||||||||
| role?: string; | ||||||||||||||
| } | ||||||||||||||
|
|
@@ -40,6 +41,43 @@ export interface TeamMemberSpend { | |||||||||||||
| */ | ||||||||||||||
| export interface SpendData { | ||||||||||||||
| teamMemberSpend: TeamMemberSpend[]; | ||||||||||||||
| hardLimitDollars?: number; | ||||||||||||||
| hardLimitCents?: number; | ||||||||||||||
| defaultHardLimitDollars?: number; | ||||||||||||||
| defaultHardLimitCents?: number; | ||||||||||||||
| teamHardLimitDollars?: number; | ||||||||||||||
| teamHardLimitCents?: number; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| interface UsageSummaryBreakdown { | ||||||||||||||
| included?: number; | ||||||||||||||
| bonus?: number; | ||||||||||||||
| total?: number; | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+52
to
+56
|
||||||||||||||
|
|
||||||||||||||
| export interface UsageSummaryMetric { | ||||||||||||||
| enabled: boolean; | ||||||||||||||
| used: number; | ||||||||||||||
| limit: number; | ||||||||||||||
| remaining: number; | ||||||||||||||
| breakdown?: UsageSummaryBreakdown; | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+58
to
+64
|
||||||||||||||
|
|
||||||||||||||
| export interface UsageSummaryResponse { | ||||||||||||||
| billingCycleStart: string; | ||||||||||||||
| billingCycleEnd: string; | ||||||||||||||
| membershipType?: string; | ||||||||||||||
| limitType?: string; | ||||||||||||||
| isUnlimited?: boolean; | ||||||||||||||
| individualUsage?: { | ||||||||||||||
| plan?: UsageSummaryMetric; | ||||||||||||||
| onDemand?: UsageSummaryMetric; | ||||||||||||||
| }; | ||||||||||||||
| teamUsage?: Record<string, unknown>; | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+66
to
+77
|
||||||||||||||
|
|
||||||||||||||
|
||||||||||||||
| /** | |
| * Represents the hard limit response for on-demand spending. | |
| * Returned by the /api/dashboard/get-hard-limit endpoint. | |
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
CENTS_PER_DOLLARconstant is defined but never used. It should be used in thedollarsToCentsfunction (line 91) for the conversion:return Math.round(amount * CENTS_PER_DOLLAR);and could also be used inresolveHardLimitDollars(line 76) for clarity:return candidate / CENTS_PER_DOLLAR;