Skip to content

Commit ab3247a

Browse files
asizikovCopilot
andcommitted
fix: address PR review feedback
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7e372f0 commit ab3247a

5 files changed

Lines changed: 32 additions & 32 deletions

File tree

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Sample reports are available in the `examples/` directory. Older examples withou
6464

6565
## CSV Report Format
6666

67-
The application expects CSV files with the following primary columns:
67+
The application expects CSV files with the following required columns:
6868

6969
- `date` - ISO date (YYYY-MM-DD)
7070
- `username` - GitHub username
@@ -81,6 +81,9 @@ The application expects CSV files with the following primary columns:
8181
- `total_monthly_quota` - Monthly quota amount
8282
- `organization` - Organization slug
8383
- `cost_center_name` - Optional cost center identifier
84+
85+
Newer exports may also include these AI Credit columns:
86+
8487
- `aic_quantity` - AI Credits for the same usage row
8588
- `aic_gross_amount` - AI Credit gross cost for the same usage row
8689

docs/report-format.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Source examples: files in `examples/`. Some existing sample exports still use the older token-oriented schema.
44

5-
## Primary columns used by the app
5+
## Required columns used by the app
66

77
| Column | Type | Description |
88
| --- | --- | --- |
@@ -21,12 +21,11 @@ Source examples: files in `examples/`. Some existing sample exports still use th
2121
| `total_monthly_quota` | number | Monthly quota for the user or plan applicable to the row. |
2222
| `organization` | string | Organization slug associated with the usage. |
2323
| `cost_center_name` | string | Optional cost center or tagging field. |
24-
| `aic_quantity` | number | Same usage converted to AI Credits. |
25-
26-
## Additional columns
24+
## Optional AI Credit columns
2725

2826
| Column | Status | Notes |
2927
| --- | --- | --- |
28+
| `aic_quantity` | Present in newer previews | Same usage converted to AI Credits. |
3029
| `aic_gross_amount` | Present in newer previews | Used for AI Credit gross cost when present. |
3130
| `total_input_tokens` | Legacy / optional | Older token-oriented export field; ignored by the app. |
3231
| `total_output_tokens` | Legacy / optional | Older token-oriented export field; ignored by the app. |

src/App.tsx

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { ProductUsageAggregator, type ProductUsageResult } from './pipeline/aggr
1818
import { CostCenterAggregator, type CostCenterResult } from './pipeline/aggregators/costCenterAggregator'
1919
import { OrganizationAggregator, type OrganizationResult } from './pipeline/aggregators/organizationAggregator'
2020
import { UserUsageAggregator, type UserUsageResult } from './pipeline/aggregators/userUsageAggregator'
21+
import { getMonthlyAicEntitlements } from './pipeline/aicEntitlements'
2122
import { runPipeline } from './pipeline/runPipeline'
2223
import { fillDataForRange } from './utils/fillDataForRange'
2324
import { formatAic, formatUsd } from './utils/format'
@@ -37,19 +38,6 @@ function createEmptyDailyUsage(date: string): DailyUsageData {
3738
}
3839
}
3940

40-
// Current pooled AI Credits estimate based on Copilot plan assumptions in the billing export:
41-
// quota >= 300 => 3,000 included credits, quota >= 1,000 => 7,000 included credits.
42-
const INCLUDED_AIC_BY_MONTHLY_QUOTA = [
43-
{ minimumQuota: 1000, includedCredits: 7000 },
44-
{ minimumQuota: 300, includedCredits: 3000 },
45-
] as const
46-
47-
function getIncludedAicCredits(totalMonthlyQuota: number): number {
48-
return INCLUDED_AIC_BY_MONTHLY_QUOTA.find((plan) => totalMonthlyQuota >= plan.minimumQuota)?.includedCredits ?? 0
49-
}
50-
51-
52-
5341
function App() {
5442
const [status, setStatus] = useState<Status>('idle')
5543
const [quickStats, setQuickStats] = useState<QuickStatsResult | null>(null)
@@ -200,7 +188,7 @@ function App() {
200188
{ requests: 0, aicQuantity: 0, grossAmount: 0, aicGrossAmount: 0, aicNetAmount: 0, discountAmount: 0, netAmount: 0 },
201189
)
202190

203-
const pooledAicCredits = (userUsage?.users ?? []).reduce((sum, user) => sum + getIncludedAicCredits(user.totalMonthlyQuota), 0)
191+
const pooledAicCredits = (userUsage?.users ?? []).reduce((sum, user) => sum + getMonthlyAicEntitlements(user.totalMonthlyQuota), 0)
204192

205193
const aicDiscountRate =
206194
overviewTotals.aicQuantity > 0

src/pipeline/aicEntitlements.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,24 @@ import {
77
} from './parser'
88
import { streamLines } from './streamer'
99

10-
const BUSINESS_MONTHLY_QUOTA = 300
11-
const ENTERPRISE_MONTHLY_QUOTA = 1000
10+
export const BUSINESS_MONTHLY_QUOTA = 300
11+
export const ENTERPRISE_MONTHLY_QUOTA = 1000
1212

13-
const BUSINESS_MONTHLY_AIC_ENTITLEMENTS = 3000
14-
const ENTERPRISE_MONTHLY_AIC_ENTITLEMENTS = 7000
13+
export const BUSINESS_MONTHLY_AIC_ENTITLEMENTS = 3000
14+
export const ENTERPRISE_MONTHLY_AIC_ENTITLEMENTS = 7000
15+
16+
export type AicEntitlementTier = 'business' | 'enterprise' | null
17+
18+
export function getAicEntitlementTier(totalMonthlyQuota: number): AicEntitlementTier {
19+
if (totalMonthlyQuota >= ENTERPRISE_MONTHLY_QUOTA) return 'enterprise'
20+
if (totalMonthlyQuota >= BUSINESS_MONTHLY_QUOTA) return 'business'
21+
return null
22+
}
1523

1624
export function getMonthlyAicEntitlements(totalMonthlyQuota: number): number {
17-
if (totalMonthlyQuota === ENTERPRISE_MONTHLY_QUOTA) return ENTERPRISE_MONTHLY_AIC_ENTITLEMENTS
18-
if (totalMonthlyQuota === BUSINESS_MONTHLY_QUOTA) return BUSINESS_MONTHLY_AIC_ENTITLEMENTS
25+
const tier = getAicEntitlementTier(totalMonthlyQuota)
26+
if (tier === 'enterprise') return ENTERPRISE_MONTHLY_AIC_ENTITLEMENTS
27+
if (tier === 'business') return BUSINESS_MONTHLY_AIC_ENTITLEMENTS
1928
return 0
2029
}
2130

@@ -60,14 +69,14 @@ export class PooledAicEntitlementAllocator {
6069
return record
6170
}
6271

63-
const coveredQuantity = Math.min(aicQuantity, this.remainingEntitlements)
64-
this.remainingEntitlements = Math.max(this.remainingEntitlements - coveredQuantity, 0)
65-
6672
if (aicGrossAmount <= 0) {
6773
record.aic_net_amount = aicGrossAmount
6874
return record
6975
}
7076

77+
const coveredQuantity = Math.min(aicQuantity, this.remainingEntitlements)
78+
this.remainingEntitlements = Math.max(this.remainingEntitlements - coveredQuantity, 0)
79+
7180
const uncoveredRatio = Math.max(aicQuantity - coveredQuantity, 0) / aicQuantity
7281
record.aic_net_amount = aicGrossAmount * uncoveredRatio
7382
return record
@@ -76,4 +85,4 @@ export class PooledAicEntitlementAllocator {
7685
remaining(): number {
7786
return this.remainingEntitlements
7887
}
79-
}
88+
}

src/views/UsersView.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useMemo, useState } from 'react'
22
import type { ChangeEvent } from 'react'
33
import type { UserUsage } from '../pipeline/aggregators/userUsageAggregator'
4-
import { getMonthlyAicEntitlements } from '../pipeline/aicEntitlements'
4+
import { getAicEntitlementTier, getMonthlyAicEntitlements } from '../pipeline/aicEntitlements'
55
import { formatAic } from '../utils/format'
66
import { Trie } from '../utils/trie'
77

@@ -28,14 +28,15 @@ export function UsersView({ users, onSelectUser }: UsersViewProps) {
2828
]
2929

3030
users.forEach((user) => {
31+
const tier = getAicEntitlementTier(user.totalMonthlyQuota)
3132
const includedAic = getMonthlyAicEntitlements(user.totalMonthlyQuota)
3233

33-
if (includedAic === 3000) {
34+
if (tier === 'business') {
3435
summary[0].users += 1
3536
summary[0].includedAic += includedAic
3637
}
3738

38-
if (includedAic === 7000) {
39+
if (tier === 'enterprise') {
3940
summary[1].users += 1
4041
summary[1].includedAic += includedAic
4142
}

0 commit comments

Comments
 (0)