@@ -25,6 +25,7 @@ import {
2525 NATIVE_AI_CREDITS_STANDARD_INCLUDED_CREDITS_POLICY ,
2626 NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ,
2727 TRANSITION_PERIOD_INCLUDED_CREDITS_POLICY ,
28+ type IncludedCreditsPolicy ,
2829} from './includedCreditsPolicy'
2930import { CostCenterAggregator } from './aggregators/costCenterAggregator'
3031import { OrganizationAggregator } from './aggregators/organizationAggregator'
@@ -177,6 +178,23 @@ describe('AIC included credit tiering and pool sizing', () => {
177178 expect ( TRANSITION_PERIOD_INCLUDED_CREDITS_POLICY . organizationPlans . enterprise . monthlyIncludedCredits ) . toBe (
178179 ENTERPRISE_MONTHLY_AIC_INCLUDED_CREDITS ,
179180 )
181+ expect ( TRANSITION_PERIOD_INCLUDED_CREDITS_POLICY . individualPlans [ 'pro-student' ] ?. identity ) . toEqual ( {
182+ tier : 'pro-student' ,
183+ quotaUnit : 'pru' ,
184+ monthlyQuota : PRO_MONTHLY_QUOTA ,
185+ } )
186+ expect ( TRANSITION_PERIOD_INCLUDED_CREDITS_POLICY . individualPlans [ 'pro-student' ] ?. monthlyIncludedCredits ) . toBe (
187+ PRO_MONTHLY_AIC_INCLUDED_CREDITS ,
188+ )
189+ expect ( TRANSITION_PERIOD_INCLUDED_CREDITS_POLICY . individualPlans [ 'pro-plus' ] ?. identity ) . toEqual ( {
190+ tier : 'pro-plus' ,
191+ quotaUnit : 'pru' ,
192+ monthlyQuota : PRO_PLUS_MONTHLY_QUOTA ,
193+ } )
194+ expect ( TRANSITION_PERIOD_INCLUDED_CREDITS_POLICY . individualPlans [ 'pro-plus' ] ?. monthlyIncludedCredits ) . toBe (
195+ PRO_PLUS_MONTHLY_AIC_INCLUDED_CREDITS ,
196+ )
197+ expect ( 'max' in TRANSITION_PERIOD_INCLUDED_CREDITS_POLICY . individualPlans ) . toBe ( false )
180198 } )
181199
182200 it ( 'keeps native AI Credits policies available without changing default transition-period tiering' , ( ) => {
@@ -222,6 +240,72 @@ describe('AIC included credit tiering and pool sizing', () => {
222240 )
223241 } )
224242
243+ it ( 'classifies post-preview individual quota identities by individual scope' , ( ) => {
244+ expect ( getIndividualPlanTier ( 1500 , 'individual' , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe (
245+ 'pro-student' ,
246+ )
247+ expect ( getIndividualPlanTier ( 7000 , 'individual' , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe (
248+ 'pro-plus' ,
249+ )
250+ expect ( getIndividualPlanTier ( 20000 , 'individual' , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe (
251+ 'max' ,
252+ )
253+ expect ( getPlanLabel ( 1500 , 'individual' , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe (
254+ 'Copilot Pro' ,
255+ )
256+ expect ( getPlanLabel ( 7000 , 'individual' , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe (
257+ 'Copilot Pro+' ,
258+ )
259+ expect ( getPlanLabel ( 20000 , 'individual' , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe (
260+ 'Copilot Max' ,
261+ )
262+ expect ( getIndividualMonthlyAicIncludedCredits (
263+ 1500 ,
264+ 'individual' ,
265+ NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ,
266+ ) ) . toBe ( 1500 )
267+ expect ( getIndividualMonthlyAicIncludedCredits (
268+ 7000 ,
269+ 'individual' ,
270+ NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ,
271+ ) ) . toBe ( 7000 )
272+ expect ( getIndividualMonthlyAicIncludedCredits (
273+ 20000 ,
274+ 'individual' ,
275+ NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ,
276+ ) ) . toBe ( 20000 )
277+ expect ( getIndividualPlanTier ( 20000 , 'individual' , NATIVE_AI_CREDITS_STANDARD_INCLUDED_CREDITS_POLICY ) ) . toBe (
278+ 'max' ,
279+ )
280+ expect ( getIndividualMonthlyAicIncludedCredits (
281+ 20000 ,
282+ 'individual' ,
283+ NATIVE_AI_CREDITS_STANDARD_INCLUDED_CREDITS_POLICY ,
284+ ) ) . toBe ( 20000 )
285+ } )
286+
287+ it ( 'does not apply post-preview individual quota identities to transition-period reports' , ( ) => {
288+ expect ( getIndividualPlanTier ( 7000 ) ) . toBeNull ( )
289+ expect ( getIndividualPlanTier ( 3900 ) ) . toBeNull ( )
290+ expect ( getIndividualPlanTier ( 20000 ) ) . toBeNull ( )
291+ expect ( getPlanLabel ( 7000 , 'individual' ) ) . toBe ( 'Unknown (7,000 PRUs/month)' )
292+ } )
293+
294+ it ( 'keeps native 3900 scope-aware as organization Enterprise instead of individual Pro+' , ( ) => {
295+ expect ( getIndividualPlanTier ( 3900 , 'individual' , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe (
296+ null ,
297+ )
298+ expect ( getAicIncludedCreditTier ( 3900 , 'organization' , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe (
299+ 'enterprise' ,
300+ )
301+ expect ( getPlanLabel ( 3900 , 'individual' , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe (
302+ 'Unknown (3,900 AI Credits/month)' ,
303+ )
304+ expect ( getPlanLabel ( 3900 , 'organization' , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe (
305+ 'Copilot Enterprise' ,
306+ )
307+ } )
308+
225309 it ( 'classifies 300 as Pro/Student for an individual report' , ( ) => {
226310 expect ( getIndividualPlanTier ( PRO_MONTHLY_QUOTA ) ) . toBe ( 'pro-student' )
227311 } )
@@ -267,11 +351,22 @@ describe('AIC included credit tiering and pool sizing', () => {
267351 expect ( getPlanLabel ( 0 ) ) . toBe ( 'Unknown' )
268352 } )
269353
354+ it ( 'formats unknown native individual quotas as AI Credits per month' , ( ) => {
355+ expect ( getPlanLabel ( 1234 , 'individual' , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe (
356+ 'Unknown (1,234 AI Credits/month)' ,
357+ )
358+ expect ( getPlanLabel ( 1234 , 'individual' , NATIVE_AI_CREDITS_STANDARD_INCLUDED_CREDITS_POLICY ) ) . toBe (
359+ 'Unknown (1,234 AI Credits/month)' ,
360+ )
361+ } )
362+
270363 it ( 'selects the maximum known monthly quota while ignoring unknown quota values' , ( ) => {
271364 expect ( selectKnownMonthlyQuota ( 0 , UNKNOWN_HIGH_MONTHLY_QUOTA ) ) . toBe ( 0 )
272365 expect ( selectKnownMonthlyQuota ( BUSINESS_MONTHLY_QUOTA , UNKNOWN_HIGH_MONTHLY_QUOTA ) ) . toBe ( BUSINESS_MONTHLY_QUOTA )
273366 expect ( selectKnownMonthlyQuota ( UNKNOWN_HIGH_MONTHLY_QUOTA , ENTERPRISE_MONTHLY_QUOTA ) ) . toBe ( ENTERPRISE_MONTHLY_QUOTA )
274367 expect ( selectKnownMonthlyQuota ( BUSINESS_MONTHLY_QUOTA , ENTERPRISE_MONTHLY_QUOTA ) ) . toBe ( ENTERPRISE_MONTHLY_QUOTA )
368+ expect ( selectKnownMonthlyQuota ( 0 , 10000 ) ) . toBe ( 0 )
369+ expect ( selectKnownMonthlyQuota ( 0 , 20000 , NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ) ) . toBe ( 20000 )
275370 } )
276371
277372 it ( 'does not create an organization pool for a single-user Pro/Student report' , async ( ) => {
@@ -464,6 +559,21 @@ describe('AIC included credit tiering and pool sizing', () => {
464559 } )
465560 } )
466561
562+ it ( 'summarizes a native summer single-user report as an individual plan' , ( ) => {
563+ const summary = calculateLicenseSummary (
564+ [ { totalMonthlyQuota : 7000 } ] ,
565+ NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY ,
566+ )
567+
568+ expect ( summary ) . toEqual ( {
569+ rows : [
570+ { label : 'Copilot Pro+' , users : 1 , includedAic : 7000 } ,
571+ ] ,
572+ totalUsers : 1 ,
573+ totalIncludedAic : 7000 ,
574+ } )
575+ } )
576+
467577 it ( 'summarizes a single-user report with organization metadata as a business plan' , ( ) => {
468578 const summary = calculateLicenseSummary ( [
469579 { totalMonthlyQuota : 300 , organizations : [ 'example-org' ] , costCenters : [ 'Cost Center A' ] } ,
@@ -607,6 +717,47 @@ describe('AIC included credit tiering and pool sizing', () => {
607717 totalIncludedAic : 10000 ,
608718 } )
609719 } )
720+
721+ it ( 'uses native summer individual plans end-to-end for pipeline allocation and license summaries' , async ( ) => {
722+ const file = createNativeCsv ( [
723+ [ '2026-08-01' , 'mona' , 'copilot' , 'copilot_ai_credit' , 'GPT-5' , '21000' , 'ai-credits' , '0.01' , '210.00' , '0' , '210.00' , '20000' , '' , '' , '21000' , '210.00' ] ,
724+ ] )
725+ const capturedRecords = new CaptureAggregator ( )
726+ let users ! : UserUsageAggregator
727+ let resolvedPolicy ! : IncludedCreditsPolicy
728+
729+ await runPipeline ( file , ( reportMetadata , includedCreditsPolicy ) => {
730+ resolvedPolicy = includedCreditsPolicy
731+ users = new UserUsageAggregator ( reportMetadata , includedCreditsPolicy )
732+ return [ capturedRecords , users ]
733+ } )
734+
735+ expect ( resolvedPolicy ) . toBe ( NATIVE_AI_CREDITS_SUMMER_PROMO_INCLUDED_CREDITS_POLICY )
736+ expect ( capturedRecords . result ( ) ) . toEqual ( [
737+ expect . objectContaining ( {
738+ total_monthly_quota : 20000 ,
739+ aic_net_amount : 10 ,
740+ } ) ,
741+ ] )
742+ expect ( users . result ( ) . users ) . toEqual ( [
743+ expect . objectContaining ( {
744+ username : 'mona' ,
745+ totalMonthlyQuota : 20000 ,
746+ totals : expect . objectContaining ( {
747+ aicQuantity : 21000 ,
748+ aicGrossAmount : 210 ,
749+ aicNetAmount : 10 ,
750+ } ) ,
751+ } ) ,
752+ ] )
753+ expect ( calculateLicenseSummary ( users . result ( ) . users , resolvedPolicy ) ) . toEqual ( {
754+ rows : [
755+ { label : 'Copilot Max' , users : 1 , includedAic : 20000 } ,
756+ ] ,
757+ totalUsers : 1 ,
758+ totalIncludedAic : 20000 ,
759+ } )
760+ } )
610761} )
611762
612763describe ( 'pooled AIC allocation and derived AIC discounts' , ( ) => {
0 commit comments