import { describe, expect, it } from 'bun:test'; import { __financialTaxonomyInternals, getCompanyFinancialTaxonomy } from './financial-taxonomy'; import type { FilingTaxonomySnapshotRecord } from './repos/filing-taxonomy'; import type { FinancialStatementKind, FinancialStatementPeriod, StructuredKpiRow, TaxonomyFactRow, TaxonomyStatementRow } from '@/lib/types'; function createRow(input: { key?: string; label?: string; conceptKey?: string; qname?: string; localName?: string; statement?: FinancialStatementKind; roleUri?: string | null; order?: number; depth?: number; hasDimensions?: boolean; values: Record; sourceFactIds?: number[]; unit?: string | null; }): TaxonomyStatementRow { const localName = input.localName ?? 'RevenueFromContractWithCustomerExcludingAssessedTax'; const conceptKey = input.conceptKey ?? `http://fasb.org/us-gaap/2024#${localName}`; const qname = input.qname ?? `us-gaap:${localName}`; return { key: input.key ?? conceptKey, label: input.label ?? localName, conceptKey, qname, namespaceUri: 'http://fasb.org/us-gaap/2024', localName, isExtension: false, statement: input.statement ?? 'income', roleUri: input.roleUri ?? input.statement ?? 'income', order: input.order ?? 1, depth: input.depth ?? 0, parentKey: null, values: input.values, units: Object.fromEntries(Object.keys(input.values).map((periodId) => [periodId, input.unit ?? 'iso4217:USD'])), hasDimensions: input.hasDimensions ?? false, sourceFactIds: input.sourceFactIds ?? [1] }; } function createSnapshot(input: { filingId: number; filingType: '10-K' | '10-Q'; filingDate: string; periods: Array<{ id: string; periodStart: string | null; periodEnd: string; periodLabel: string; }>; statement: FinancialStatementKind; rows?: TaxonomyStatementRow[]; }) { const defaultRow = createRow({ statement: input.statement, values: Object.fromEntries(input.periods.map((period, index) => [period.id, 100 + index])) }); const faithfulRows = { income: input.statement === 'income' ? (input.rows ?? [defaultRow]) : [], balance: input.statement === 'balance' ? (input.rows ?? [{ ...defaultRow, statement: 'balance' }]) : [], cash_flow: input.statement === 'cash_flow' ? (input.rows ?? [{ ...defaultRow, statement: 'cash_flow' }]) : [], equity: [], comprehensive_income: [] } satisfies FilingTaxonomySnapshotRecord['faithful_rows']; return { id: input.filingId, filing_id: input.filingId, ticker: 'MSFT', filing_date: input.filingDate, filing_type: input.filingType, parse_status: 'ready', parse_error: null, source: 'xbrl_instance', parser_engine: 'fiscal-xbrl', parser_version: '0.1.0', taxonomy_regime: 'us-gaap', fiscal_pack: 'core', periods: input.periods.map((period) => ({ id: period.id, filingId: input.filingId, accessionNumber: `0000-${input.filingId}`, filingDate: input.filingDate, periodStart: period.periodStart, periodEnd: period.periodEnd, filingType: input.filingType, periodLabel: period.periodLabel })), faithful_rows: faithfulRows, statement_rows: faithfulRows, surface_rows: { income: [], balance: [], cash_flow: [], equity: [], comprehensive_income: [] }, detail_rows: { income: {}, balance: {}, cash_flow: {}, equity: {}, comprehensive_income: {} }, kpi_rows: [], derived_metrics: null, validation_result: null, normalization_summary: null, facts_count: 0, concepts_count: 0, dimensions_count: 0, created_at: input.filingDate, updated_at: input.filingDate } satisfies FilingTaxonomySnapshotRecord; } function createPeriod(input: { id: string; filingId: number; filingDate: string; periodEnd: string; periodStart?: string | null; filingType?: '10-K' | '10-Q'; }): FinancialStatementPeriod { return { id: input.id, filingId: input.filingId, accessionNumber: `0000-${input.filingId}`, filingDate: input.filingDate, periodStart: input.periodStart ?? null, periodEnd: input.periodEnd, filingType: input.filingType ?? '10-Q', periodLabel: 'Test period' }; } function createDimensionFact(input: { filingId: number; filingDate: string; conceptKey: string; qname: string; localName: string; periodEnd: string; value: number; axis?: string; member?: string; }): TaxonomyFactRow { return { id: input.filingId, snapshotId: input.filingId, filingId: input.filingId, filingDate: input.filingDate, statement: 'income', roleUri: 'income', conceptKey: input.conceptKey, qname: input.qname, namespaceUri: 'http://fasb.org/us-gaap/2024', localName: input.localName, value: input.value, contextId: `ctx-${input.filingId}`, unit: 'iso4217:USD', decimals: null, periodStart: '2025-01-01', periodEnd: input.periodEnd, periodInstant: null, dimensions: [{ axis: input.axis ?? 'srt:ProductOrServiceAxis', member: input.member ?? 'msft:CloudMember' }], isDimensionless: false, sourceFile: null }; } function createFact(input: { id?: number; filingId: number; filingDate: string; statement?: FinancialStatementKind; conceptKey?: string; qname?: string; localName: string; periodEnd: string; periodStart?: string | null; periodInstant?: string | null; value: number; unit?: string | null; }): TaxonomyFactRow { const conceptKey = input.conceptKey ?? `http://fasb.org/us-gaap/2024#${input.localName}`; const qname = input.qname ?? `us-gaap:${input.localName}`; return { id: input.id ?? input.filingId, snapshotId: input.filingId, filingId: input.filingId, filingDate: input.filingDate, statement: input.statement ?? 'income', roleUri: input.statement ?? 'income', conceptKey, qname, namespaceUri: 'http://fasb.org/us-gaap/2024', localName: input.localName, value: input.value, contextId: `ctx-${input.filingId}-${input.localName}`, unit: input.unit ?? 'iso4217:USD', decimals: null, periodStart: input.periodStart ?? null, periodEnd: input.periodEnd, periodInstant: input.periodInstant ?? null, dimensions: [], isDimensionless: true, sourceFile: null }; } function createKpiRow(input: { key: string; values: Record; provenanceType?: StructuredKpiRow['provenanceType']; sourceConcepts?: string[]; sourceFactIds?: number[]; }): StructuredKpiRow { return { key: input.key, label: input.key, category: 'operating_kpi', unit: 'percent', order: 10, segment: null, axis: null, member: null, values: input.values, sourceConcepts: input.sourceConcepts ?? [], sourceFactIds: input.sourceFactIds ?? [], provenanceType: input.provenanceType ?? 'taxonomy', hasDimensions: false }; } function findRow(rows: ReturnType, key: string) { const row = rows.find((entry) => entry.key === key); expect(row).toBeDefined(); return row!; } function findPeriodId(periods: FinancialStatementPeriod[], periodEnd: string) { const period = periods.find((entry) => entry.periodEnd === periodEnd); expect(period).toBeDefined(); return period!.id; } function findStandardizedResponseRow( response: Awaited>, key: string ) { const row = response.statementRows?.standardized.find((entry) => entry.key === key); expect(row).toBeDefined(); return row!; } describe('financial taxonomy internals', () => { it('selects the primary quarter duration for 10-Q income statements', () => { const snapshot = createSnapshot({ filingId: 1, filingType: '10-Q', filingDate: '2026-01-28', statement: 'income', periods: [ { id: 'instant', periodStart: null, periodEnd: '2025-12-31', periodLabel: 'Instant' }, { id: 'quarter', periodStart: '2025-10-01', periodEnd: '2025-12-31', periodLabel: '2025-10-01 to 2025-12-31' }, { id: 'ytd', periodStart: '2025-07-01', periodEnd: '2025-12-31', periodLabel: '2025-07-01 to 2025-12-31' } ] }); const selection = __financialTaxonomyInternals.selectPrimaryPeriodsByCadence([snapshot], 'income', 'quarterly'); expect(selection.periods).toHaveLength(1); expect(selection.periods[0]?.id).toBe('quarter'); }); it('selects the latest instant for balance sheets', () => { const snapshot = createSnapshot({ filingId: 2, filingType: '10-K', filingDate: '2025-07-30', statement: 'balance', periods: [ { id: 'prior', periodStart: null, periodEnd: '2024-06-30', periodLabel: 'Instant' }, { id: 'current', periodStart: null, periodEnd: '2025-06-30', periodLabel: 'Instant' } ] }); const selection = __financialTaxonomyInternals.selectPrimaryPeriodsByCadence([snapshot], 'balance', 'annual'); expect(selection.periods).toHaveLength(1); expect(selection.periods[0]?.id).toBe('current'); }); it('builds one reporting period per filing for the selected statement', () => { const annual = createSnapshot({ filingId: 10, filingType: '10-K', filingDate: '2025-07-30', statement: 'income', periods: [ { id: 'annual', periodStart: '2024-07-01', periodEnd: '2025-06-30', periodLabel: '2024-07-01 to 2025-06-30' }, { id: 'quarter', periodStart: '2025-04-01', periodEnd: '2025-06-30', periodLabel: '2025-04-01 to 2025-06-30' } ] }); const quarterly = createSnapshot({ filingId: 11, filingType: '10-Q', filingDate: '2025-10-29', statement: 'income', periods: [ { id: 'instant', periodStart: null, periodEnd: '2025-09-30', periodLabel: 'Instant' }, { id: 'quarter', periodStart: '2025-07-01', periodEnd: '2025-09-30', periodLabel: '2025-07-01 to 2025-09-30' }, { id: 'ytd', periodStart: '2025-01-01', periodEnd: '2025-09-30', periodLabel: '2025-01-01 to 2025-09-30' } ] }); const annualPeriods = __financialTaxonomyInternals.selectPrimaryPeriodsByCadence([annual, quarterly], 'income', 'annual').periods; const quarterlyPeriods = __financialTaxonomyInternals.selectPrimaryPeriodsByCadence([annual, quarterly], 'income', 'quarterly').periods; expect(annualPeriods.map((period) => period.id)).toEqual(['annual']); expect(quarterlyPeriods.map((period) => period.id)).toEqual(['quarter']); }); it('ignores future-dated fallback note periods for annual income selection', () => { const snapshot = createSnapshot({ filingId: 12, filingType: '10-K', filingDate: '2025-11-05', statement: 'income', periods: [ { id: 'annual', periodStart: '2024-09-30', periodEnd: '2025-09-28', periodLabel: '2024-09-30 to 2025-09-28' }, { id: 'future-note', periodStart: '2026-09-28', periodEnd: '2027-09-26', periodLabel: '2026-09-28 to 2027-09-26' } ], rows: [ createRow({ localName: 'Revenues', label: 'Revenues', values: { annual: 44_284_000_000 } }), createRow({ localName: 'CostOfSales', label: 'Cost of Sales', values: { annual: 19_738_000_000 }, order: 2 }), createRow({ localName: 'EffectiveIncomeTaxRateContinuingOperations', label: 'Effective Income Tax Rate Continuing Operations', roleUri: null, order: Number.MAX_SAFE_INTEGER, values: { 'future-note': 0.16 }, unit: 'pure' }) ] }); const selection = __financialTaxonomyInternals.selectPrimaryPeriodsByCadence([snapshot], 'income', 'annual'); expect(selection.periods).toHaveLength(1); expect(selection.periods[0]?.id).toBe('annual'); }); it('prefers broader presented-row coverage over sparser later annual periods', () => { const snapshot = createSnapshot({ filingId: 13, filingType: '10-K', filingDate: '2025-07-30', statement: 'income', periods: [ { id: 'primary', periodStart: '2024-07-01', periodEnd: '2025-06-30', periodLabel: '2024-07-01 to 2025-06-30' }, { id: 'sparse-later', periodStart: '2024-07-16', periodEnd: '2025-07-15', periodLabel: '2024-07-16 to 2025-07-15' } ], rows: [ createRow({ localName: 'Revenues', label: 'Revenues', values: { primary: 245_122_000_000, 'sparse-later': 246_000_000_000 } }), createRow({ localName: 'OperatingIncomeLoss', label: 'Operating Income', values: { primary: 109_433_000_000 }, order: 2 }), createRow({ localName: 'NetIncomeLoss', label: 'Net Income', values: { primary: 88_136_000_000 }, order: 3 }) ] }); const selection = __financialTaxonomyInternals.selectPrimaryPeriodsByCadence([snapshot], 'income', 'annual'); expect(selection.periods).toHaveLength(1); expect(selection.periods[0]?.id).toBe('primary'); }); it('falls back to plausible non-presented periods when no presented rows exist', () => { const snapshot = createSnapshot({ filingId: 14, filingType: '10-K', filingDate: '2025-11-05', statement: 'income', periods: [ { id: 'annual', periodStart: '2024-09-30', periodEnd: '2025-09-28', periodLabel: '2024-09-30 to 2025-09-28' }, { id: 'future-note', periodStart: '2026-09-28', periodEnd: '2027-09-26', periodLabel: '2026-09-28 to 2027-09-26' } ], rows: [ createRow({ localName: 'Revenues', label: 'Revenues', roleUri: null, order: Number.MAX_SAFE_INTEGER, values: { annual: 44_284_000_000 } }), createRow({ localName: 'EffectiveIncomeTaxRateContinuingOperations', label: 'Effective Income Tax Rate Continuing Operations', roleUri: null, order: Number.MAX_SAFE_INTEGER, values: { 'future-note': 0.16 }, unit: 'pure' }) ] }); const selection = __financialTaxonomyInternals.selectPrimaryPeriodsByCadence([snapshot], 'income', 'annual'); expect(selection.periods).toHaveLength(1); expect(selection.periods[0]?.id).toBe('annual'); }); it('maps overlapping GAAP aliases into one standardized COGS row while preserving faithful rows', () => { const period2024 = createPeriod({ id: '2024-q4', filingId: 30, filingDate: '2025-01-29', periodEnd: '2024-12-31' }); const period2025 = createPeriod({ id: '2025-q4', filingId: 31, filingDate: '2026-01-28', periodEnd: '2025-12-31' }); const faithfulRows = __financialTaxonomyInternals.buildRows([ createSnapshot({ filingId: 30, filingType: '10-Q', filingDate: '2025-01-29', statement: 'income', periods: [{ id: '2024-q4', periodStart: '2024-10-01', periodEnd: '2024-12-31', periodLabel: '2024-10-01 to 2024-12-31' }], rows: [ createRow({ localName: 'CostOfRevenue', label: 'Cost of Revenue', values: { '2024-q4': 45_000 }, sourceFactIds: [101] }) ] }), createSnapshot({ filingId: 31, filingType: '10-Q', filingDate: '2026-01-28', statement: 'income', periods: [{ id: '2025-q4', periodStart: '2025-10-01', periodEnd: '2025-12-31', periodLabel: '2025-10-01 to 2025-12-31' }], rows: [ createRow({ localName: 'CostOfGoodsSold', label: 'Cost of Goods Sold', values: { '2025-q4': 48_000 }, sourceFactIds: [202] }) ] }) ], 'income', new Set(['2024-q4', '2025-q4'])); const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows( { rows: faithfulRows, statement: 'income', periods: [period2024, period2025], facts: [] } ); expect(faithfulRows).toHaveLength(2); const cogs = standardizedRows.find((row) => row.key === 'cost_of_revenue'); expect(cogs).toBeDefined(); expect(cogs?.values['2024-q4']).toBe(45_000); expect(cogs?.values['2025-q4']).toBe(48_000); expect(cogs?.sourceConcepts).toEqual([ 'us-gaap:CostOfGoodsSold', 'us-gaap:CostOfRevenue' ]); expect(cogs?.sourceRowKeys).toHaveLength(2); }); it('aggregates standardized dimension drill-down across mapped source concepts', () => { const period2024 = createPeriod({ id: '2024-q4', filingId: 40, filingDate: '2025-01-29', periodEnd: '2024-12-31' }); const period2025 = createPeriod({ id: '2025-q4', filingId: 41, filingDate: '2026-01-28', periodEnd: '2025-12-31' }); const faithfulRows = [ createRow({ localName: 'CostOfRevenue', label: 'Cost of Revenue', values: { '2024-q4': 45_000 } }), createRow({ localName: 'CostOfGoodsSold', label: 'Cost of Goods Sold', values: { '2025-q4': 48_000 } }) ]; const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows( { rows: faithfulRows, statement: 'income', periods: [period2024, period2025], facts: [] } ); const breakdown = __financialTaxonomyInternals.buildDimensionBreakdown([ createDimensionFact({ filingId: 40, filingDate: '2025-01-29', conceptKey: faithfulRows[0].key, qname: faithfulRows[0].qname, localName: faithfulRows[0].localName, periodEnd: '2024-12-31', value: 20_000, member: 'msft:ProductivityMember' }), createDimensionFact({ filingId: 41, filingDate: '2026-01-28', conceptKey: faithfulRows[1].key, qname: faithfulRows[1].qname, localName: faithfulRows[1].localName, periodEnd: '2025-12-31', value: 28_000, member: 'msft:IntelligentCloudMember' }) ], [period2024, period2025], faithfulRows, standardizedRows); const cogs = breakdown?.['cost_of_revenue'] ?? []; expect(cogs).toHaveLength(2); expect(cogs.map((row) => row.sourceLabel)).toEqual([ 'Cost of Revenue', 'Cost of Goods Sold' ]); }); it('prefers exact Microsoft income aliases over pro forma and reconciliation rows', () => { const period = createPeriod({ id: '2024-fy', filingId: 80, filingDate: '2024-07-30', periodStart: '2023-07-01', periodEnd: '2024-06-30', filingType: '10-K' }); const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'income', periods: [period], facts: [], rows: [ createRow({ localName: 'BusinessAcquisitionsProFormaRevenue', label: 'Business Acquisitions Pro Forma Revenue', values: { '2024-fy': 247_442_000_000 } }), createRow({ localName: 'RevenueFromContractWithCustomerExcludingAssessedTax', label: 'Revenue From Contract With Customer Excluding Assessed Tax', values: { '2024-fy': 245_122_000_000 } }), createRow({ localName: 'NonoperatingIncomeExpense', label: 'Nonoperating Income Expense', values: { '2024-fy': -1_646_000_000 } }), createRow({ localName: 'SellingAndMarketingExpense', label: 'Selling And Marketing Expense', values: { '2024-fy': 24_456_000_000 } }), createRow({ localName: 'GeneralAndAdministrativeExpense', label: 'General And Administrative Expense', values: { '2024-fy': 7_609_000_000 } }), createRow({ localName: 'OperatingIncomeLoss', label: 'Operating Income Loss', values: { '2024-fy': 109_433_000_000 } }), createRow({ localName: 'BusinessAcquisitionsProFormaNetIncomeLoss', label: 'Business Acquisitions Pro Forma Net Income Loss', values: { '2024-fy': 88_308_000_000 }, hasDimensions: true }), createRow({ localName: 'NetIncomeLoss', label: 'Net Income Loss', values: { '2024-fy': 88_136_000_000 } }), createRow({ localName: 'CurrentIncomeTaxExpenseBenefit', label: 'Current Income Tax Expense Benefit', values: { '2024-fy': 24_389_000_000 } }), createRow({ localName: 'IncomeTaxExpenseBenefit', label: 'Income Tax Expense Benefit', values: { '2024-fy': 19_651_000_000 } }), createRow({ localName: 'IncomeLossFromContinuingOperationsBeforeIncomeTaxesExtraordinaryItemsNoncontrollingInterest', label: 'Income Loss From Continuing Operations Before Income Taxes Extraordinary Items Noncontrolling Interest', values: { '2024-fy': 107_787_000_000 } }), createRow({ localName: 'EffectiveIncomeTaxRateReconciliationInterestIncomeExpense', label: 'Effective Income Tax Rate Reconciliation Interest Income Expense', values: { '2024-fy': 0.011 }, unit: 'pure' }), createRow({ localName: 'InvestmentIncomeNet', label: 'Investment Income Net', values: { '2024-fy': 3_157_000_000 } }), createRow({ localName: 'CostOfGoodsAndServicesSold', label: 'Cost Of Goods And Services Sold', values: { '2024-fy': 74_114_000_000 } }) ] }); const revenue = findRow(standardizedRows, 'revenue'); expect(revenue.values['2024-fy']).toBe(245_122_000_000); expect(revenue.resolvedSourceRowKeys['2024-fy']).toContain('RevenueFromContractWithCustomerExcludingAssessedTax'); const operatingIncome = findRow(standardizedRows, 'operating_income'); expect(operatingIncome.values['2024-fy']).toBe(109_433_000_000); expect(operatingIncome.resolvedSourceRowKeys['2024-fy']).toContain('OperatingIncomeLoss'); const sga = findRow(standardizedRows, 'selling_general_and_administrative'); expect(sga.values['2024-fy']).toBe(32_065_000_000); expect(sga.formulaKey).toBe('selling_general_and_administrative'); const netIncome = findRow(standardizedRows, 'net_income'); expect(netIncome.values['2024-fy']).toBe(88_136_000_000); expect(netIncome.resolvedSourceRowKeys['2024-fy']).toContain('NetIncomeLoss'); const taxExpense = findRow(standardizedRows, 'income_tax_expense'); expect(taxExpense.values['2024-fy']).toBe(19_651_000_000); expect(taxExpense.resolvedSourceRowKeys['2024-fy']).toContain('IncomeTaxExpenseBenefit'); const pretaxIncome = findRow(standardizedRows, 'pretax_income'); expect(pretaxIncome.values['2024-fy']).toBe(107_787_000_000); const interestIncome = findRow(standardizedRows, 'interest_income'); expect(interestIncome.values['2024-fy']).toBe(3_157_000_000); expect(interestIncome.resolvedSourceRowKeys['2024-fy']).toContain('InvestmentIncomeNet'); const cogs = findRow(standardizedRows, 'cost_of_revenue'); expect(cogs.label).toBe('Cost of Sales'); expect(cogs.values['2024-fy']).toBe(74_114_000_000); expect(standardizedRows.some((row) => row.key.includes('BusinessAcquisitionsProFormaRevenue'))).toBe(true); expect(standardizedRows.some((row) => row.key.includes('BusinessAcquisitionsProFormaNetIncomeLoss'))).toBe(true); }); it('merges detail rows across taxonomy-version concept drift for Microsoft residuals', () => { const aggregated = __financialTaxonomyInternals.aggregateDetailRows({ statement: 'income', selectedPeriodIds: new Set(['2024-fy', '2025-fy']), snapshots: [ { ...createSnapshot({ filingId: 90, filingType: '10-K', filingDate: '2024-07-30', statement: 'income', periods: [{ id: '2024-fy', periodStart: '2023-07-01', periodEnd: '2024-06-30', periodLabel: 'FY24' }] }), detail_rows: { income: { unmapped: [ { key: 'http://fasb.org/us-gaap/2024#AdvertisingExpense', parentSurfaceKey: 'unmapped', label: 'Advertising Expense', conceptKey: 'http://fasb.org/us-gaap/2024#AdvertisingExpense', qname: 'us-gaap:AdvertisingExpense', namespaceUri: 'http://fasb.org/us-gaap/2024', localName: 'AdvertisingExpense', unit: 'iso4217:USD', values: { '2024-fy': 1_500_000_000 }, sourceFactIds: [101], isExtension: false, dimensionsSummary: [], residualFlag: true }, { key: 'https://xbrl.microsoft.com/2024#BusinessAcquisitionsProFormaRevenue', parentSurfaceKey: 'unmapped', label: 'Business Acquisitions Pro Forma Revenue', conceptKey: 'https://xbrl.microsoft.com/2024#BusinessAcquisitionsProFormaRevenue', qname: 'msft:BusinessAcquisitionsProFormaRevenue', namespaceUri: 'https://xbrl.microsoft.com/2024', localName: 'BusinessAcquisitionsProFormaRevenue', unit: 'iso4217:USD', values: { '2024-fy': 247_442_000_000 }, sourceFactIds: [102], isExtension: true, dimensionsSummary: [], residualFlag: true } ] }, balance: {}, cash_flow: {}, equity: {}, comprehensive_income: {} } } satisfies FilingTaxonomySnapshotRecord, { ...createSnapshot({ filingId: 91, filingType: '10-K', filingDate: '2025-07-30', statement: 'income', periods: [{ id: '2025-fy', periodStart: '2024-07-01', periodEnd: '2025-06-30', periodLabel: 'FY25' }] }), detail_rows: { income: { unmapped: [ { key: 'http://fasb.org/us-gaap/2025#AdvertisingExpense', parentSurfaceKey: 'unmapped', label: 'Advertising Expense', conceptKey: 'http://fasb.org/us-gaap/2025#AdvertisingExpense', qname: 'us-gaap:AdvertisingExpense', namespaceUri: 'http://fasb.org/us-gaap/2025', localName: 'AdvertisingExpense', unit: 'iso4217:USD', values: { '2025-fy': 1_700_000_000 }, sourceFactIds: [201], isExtension: false, dimensionsSummary: [], residualFlag: true }, { key: 'https://xbrl.microsoft.com/2025#BusinessAcquisitionsProFormaRevenue', parentSurfaceKey: 'unmapped', label: 'Business Acquisitions Pro Forma Revenue', conceptKey: 'https://xbrl.microsoft.com/2025#BusinessAcquisitionsProFormaRevenue', qname: 'msft:BusinessAcquisitionsProFormaRevenue', namespaceUri: 'https://xbrl.microsoft.com/2025', localName: 'BusinessAcquisitionsProFormaRevenue', unit: 'iso4217:USD', values: { '2025-fy': 219_790_000_000 }, sourceFactIds: [202], isExtension: true, dimensionsSummary: [], residualFlag: true } ] }, balance: {}, cash_flow: {}, equity: {}, comprehensive_income: {} } } satisfies FilingTaxonomySnapshotRecord ] }); const unmapped = aggregated.unmapped ?? []; expect(unmapped).toHaveLength(2); const advertising = unmapped.find((row) => row.label === 'Advertising Expense'); expect(advertising?.values).toEqual({ '2024-fy': 1_500_000_000, '2025-fy': 1_700_000_000 }); const proFormaRevenue = unmapped.find((row) => row.label === 'Business Acquisitions Pro Forma Revenue'); expect(proFormaRevenue?.values).toEqual({ '2024-fy': 247_442_000_000, '2025-fy': 219_790_000_000 }); }); it('resolves CASY-style income gaps with ordered fallbacks and tighter interest income exclusions', () => { const period = createPeriod({ id: '2025-fy', filingId: 81, filingDate: '2025-06-23', periodStart: '2024-05-01', periodEnd: '2025-04-30', filingType: '10-K' }); const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'income', periods: [period], facts: [], rows: [ createRow({ localName: 'Revenues', label: 'Revenues', values: { '2025-fy': 15_940_899_000 } }), createRow({ localName: 'CostOfGoodsAndServiceExcludingDepreciationDepletionAndAmortization', label: 'Cost Of Goods And Service Excluding Depreciation Depletion And Amortization', values: { '2025-fy': 12_188_496_000 } }), createRow({ localName: 'OperatingExpenses', label: 'Operating Expenses', values: { '2025-fy': 2_552_356_000 } }), createRow({ localName: 'CostOfGoodsAndServicesSoldDepreciationAndAmortization', label: 'Cost Of Goods And Services Sold Depreciation And Amortization', values: { '2025-fy': 403_647_000 } }), createRow({ localName: 'NetIncomeLoss', label: 'Net Income Loss', values: { '2025-fy': 546_520_000 } }), createRow({ localName: 'IncomeTaxExpenseBenefit', label: 'Income Tax Expense Benefit', values: { '2025-fy': 165_929_000 } }), createRow({ localName: 'InterestExpense', label: 'Interest Expense', values: { '2025-fy': 83_951_000 } }), createRow({ localName: 'InterestIncomeExpenseNet', label: 'Interest Income Expense Net', values: { '2025-fy': 13_102_000 } }), createRow({ localName: 'EffectiveIncomeTaxRateContinuingOperations', label: 'Effective Income Tax Rate Continuing Operations', values: { '2025-fy': 0.233 }, unit: 'pure' }) ] }); expect(findRow(standardizedRows, 'cost_of_revenue').values['2025-fy']).toBe(12_188_496_000); expect(findRow(standardizedRows, 'gross_profit').values['2025-fy']).toBe(3_752_403_000); expect(findRow(standardizedRows, 'selling_general_and_administrative').values['2025-fy']).toBe(2_552_356_000); expect(findRow(standardizedRows, 'pretax_income').values['2025-fy']).toBe(712_449_000); expect(findRow(standardizedRows, 'operating_income').values['2025-fy']).toBe(796_400_000); expect(findRow(standardizedRows, 'depreciation_and_amortization').values['2025-fy']).toBe(403_647_000); expect(findRow(standardizedRows, 'depreciation_and_amortization_expenses').values['2025-fy']).toBe(403_647_000); expect(findRow(standardizedRows, 'ebitda').values['2025-fy']).toBe(1_200_047_000); expect(findRow(standardizedRows, 'effective_tax_rate').values['2025-fy']).toBe(0.233); expect(standardizedRows.some((row) => row.key === 'interest_income')).toBe(false); }); it('keeps EBITDA formula-only instead of mapping it directly from operating income', () => { const period = createPeriod({ id: '2024-fy', filingId: 90, filingDate: '2024-07-30', periodStart: '2023-07-01', periodEnd: '2024-06-30', filingType: '10-K' }); const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'income', periods: [period], facts: [], rows: [ createRow({ localName: 'OperatingIncomeLoss', label: 'Operating Income Loss', values: { '2024-fy': 109_433_000_000 } }), createRow({ localName: 'DepreciationDepletionAndAmortization', label: 'Depreciation Depletion And Amortization', values: { '2024-fy': 22_287_000_000 } }) ] }); const ebitda = findRow(standardizedRows, 'ebitda'); expect(ebitda.values['2024-fy']).toBe(131_720_000_000); expect(ebitda.formulaKey).toBe('ebitda'); expect(ebitda.resolvedSourceRowKeys['2024-fy']).toBeNull(); expect(ebitda.sourceRowKeys).toHaveLength(0); }); it('uses balance template ordering and sections, with equity falling back to assets minus liabilities', () => { const period = createPeriod({ id: '2025-balance', filingId: 95, filingDate: '2025-07-30', periodEnd: '2025-06-30', filingType: '10-K' }); const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'balance', periods: [period], facts: [], rows: [ createRow({ statement: 'balance', localName: 'Assets', label: 'Assets', values: { '2025-balance': 619_003_000_000 } }), createRow({ statement: 'balance', localName: 'Liabilities', label: 'Liabilities', values: { '2025-balance': 275_524_000_000 } }), createRow({ statement: 'balance', localName: 'AssetsCurrent', label: 'Assets Current', values: { '2025-balance': 191_131_000_000 } }) ] }); const currentAssets = findRow(standardizedRows, 'current_assets'); const totalAssets = findRow(standardizedRows, 'total_assets'); const totalLiabilities = findRow(standardizedRows, 'total_liabilities'); const totalEquity = findRow(standardizedRows, 'total_equity'); expect(currentAssets.category).toBe('assets'); expect(totalLiabilities.category).toBe('liabilities'); expect(totalEquity.category).toBe('equity'); expect(totalEquity.values['2025-balance']).toBe(343_479_000_000); expect(totalEquity.formulaKey).toBe('total_equity'); expect(currentAssets.order).toBeLessThan(totalAssets.order); expect(totalAssets.order).toBeLessThan(totalLiabilities.order); expect(totalLiabilities.order).toBeLessThan(totalEquity.order); }); it('maps cash flow capex and computes free cash flow from the template formula', () => { const period = createPeriod({ id: '2024-cf', filingId: 100, filingDate: '2024-07-30', periodStart: '2023-07-01', periodEnd: '2024-06-30', filingType: '10-K' }); const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'cash_flow', periods: [period], facts: [], rows: [ createRow({ statement: 'cash_flow', localName: 'NetCashProvidedByUsedInOperatingActivities', label: 'Net Cash Provided By Used In Operating Activities', values: { '2024-cf': 118_548_000_000 } }), createRow({ statement: 'cash_flow', localName: 'PaymentsToAcquirePropertyPlantAndEquipment', label: 'Payments To Acquire Property Plant And Equipment', values: { '2024-cf': 46_937_000_000 } }) ] }); const capex = findRow(standardizedRows, 'capital_expenditures'); expect(capex.values['2024-cf']).toBe(-46_937_000_000); const freeCashFlow = findRow(standardizedRows, 'free_cash_flow'); expect(freeCashFlow.values['2024-cf']).toBe(71_611_000_000); expect(freeCashFlow.formulaKey).toBe('free_cash_flow'); }); it('prefers dimensionless facts over dimensioned or label-only rows for canonical balance rows', () => { const period = createPeriod({ id: '2025-balance', filingId: 110, filingDate: '2025-02-05', periodEnd: '2024-12-31', filingType: '10-K' }); const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'balance', periods: [period], rows: [ createRow({ statement: 'balance', localName: 'Assets', label: 'Assets', values: { '2025-balance': 8_700_000_000 }, hasDimensions: true }), createRow({ statement: 'balance', localName: 'IntangibleAssetsGrossExcludingGoodwill', label: 'Intangible Assets Gross Excluding Goodwill', values: { '2025-balance': 2_793_000_000 } }) ], facts: [ createFact({ filingId: 110, filingDate: '2025-02-05', statement: 'balance', localName: 'Assets', periodEnd: '2024-12-31', periodInstant: '2024-12-31', value: 450_256_000_000 }), createFact({ id: 111, filingId: 110, filingDate: '2025-02-05', statement: 'balance', localName: 'Goodwill', periodEnd: '2024-12-31', periodInstant: '2024-12-31', value: 31_885_000_000 }) ] }); const totalAssets = findRow(standardizedRows, 'total_assets'); expect(totalAssets.values['2025-balance']).toBe(450_256_000_000); expect(totalAssets.resolvedSourceRowKeys['2025-balance']).toContain('Assets'); expect(standardizedRows.some((row) => row.key === 'other:http://fasb.org/us-gaap/2024#Assets')).toBe(false); const goodwill = findRow(standardizedRows, 'goodwill'); expect(goodwill.values['2025-balance']).toBe(31_885_000_000); expect(goodwill.resolvedSourceRowKeys['2025-balance']).toContain('Goodwill'); }); it('uses alias priority for Apple-style long-term investments and unearned revenue rows', () => { const period = createPeriod({ id: '2025-balance', filingId: 120, filingDate: '2025-10-31', periodEnd: '2025-09-27', filingType: '10-K' }); const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'balance', periods: [period], rows: [ createRow({ statement: 'balance', localName: 'AvailableForSaleSecuritiesDebtSecurities', label: 'Available For Sale Securities Debt Securities', values: { '2025-balance': 98_027_000_000 } }), createRow({ statement: 'balance', localName: 'AvailableForSaleSecuritiesDebtMaturitiesSingleMaturityDate', label: 'Available For Sale Securities Debt Maturities Single Maturity Date', values: { '2025-balance': 77_723_000_000 } }), createRow({ statement: 'balance', localName: 'ContractWithCustomerLiability', label: 'Contract With Customer Liability', values: { '2025-balance': 13_700_000_000 } }), createRow({ statement: 'balance', localName: 'ContractWithCustomerLiabilityCurrent', label: 'Contract With Customer Liability Current', values: { '2025-balance': 9_055_000_000 } }) ], facts: [] }); const longTermInvestments = findRow(standardizedRows, 'long_term_investments'); expect(longTermInvestments.values['2025-balance']).toBe(77_723_000_000); expect(longTermInvestments.resolvedSourceRowKeys['2025-balance']).toContain('AvailableForSaleSecuritiesDebtMaturitiesSingleMaturityDate'); const unearnedRevenue = findRow(standardizedRows, 'unearned_revenue'); expect(unearnedRevenue.values['2025-balance']).toBe(9_055_000_000); expect(unearnedRevenue.resolvedSourceRowKeys['2025-balance']).toContain('ContractWithCustomerLiabilityCurrent'); }); it('maps WMS extension aliases and direct effective tax rate values', () => { const period = createPeriod({ id: '2025-fy', filingId: 130, filingDate: '2025-05-15', periodStart: '2024-04-01', periodEnd: '2025-03-31', filingType: '10-K' }); const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'income', periods: [period], rows: [ createRow({ localName: 'CostOfGoodsAndServicesSold', label: 'Cost Of Goods And Services Sold', values: { '2025-fy': 340_800_000 } }), createRow({ localName: 'SellingGeneralAndAdministrativeExpenseEmployeeStockOptionPlanSpecialDividendCompensation', label: 'Selling General And Administrative Expense Employee Stock Option Plan Special Dividend Compensation', values: { '2025-fy': 0 } }) ], facts: [ createFact({ filingId: 130, filingDate: '2025-05-15', localName: 'CostOfGoodsSoldExcludingEmployeeStockOptionPlanSpecialDividendCompensation', periodStart: '2024-04-01', periodEnd: '2025-03-31', value: 1_810_004_000 }), createFact({ id: 131, filingId: 130, filingDate: '2025-05-15', localName: 'SellingGeneralAndAdministrativeExpenseExcludingEmployeeStockOptionPlanSpecialDividendCompensation', periodStart: '2024-04-01', periodEnd: '2025-03-31', value: 380_378_000 }), createFact({ id: 132, filingId: 130, filingDate: '2025-05-15', localName: 'EffectiveIncomeTaxRateContinuingOperations', periodStart: '2024-04-01', periodEnd: '2025-03-31', value: 0.239, unit: 'pure' }), createFact({ id: 133, filingId: 130, filingDate: '2025-05-15', localName: 'InterestIncomeExpenseNonoperatingNet', periodStart: '2024-04-01', periodEnd: '2025-03-31', value: -91_803_000 }) ] }); expect(findRow(standardizedRows, 'cost_of_revenue').values['2025-fy']).toBe(1_810_004_000); expect(findRow(standardizedRows, 'selling_general_and_administrative').values['2025-fy']).toBe(380_378_000); expect(findRow(standardizedRows, 'effective_tax_rate').values['2025-fy']).toBe(0.239); expect(findRow(standardizedRows, 'interest_expense').values['2025-fy']).toBe(91_803_000); }); it('inverts Fiscal.ai cash flow outflows and working-capital changes', () => { const period = createPeriod({ id: '2025-cf', filingId: 140, filingDate: '2025-05-15', periodStart: '2024-04-01', periodEnd: '2025-03-31', filingType: '10-K' }); const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'cash_flow', periods: [period], facts: [], rows: [ createRow({ statement: 'cash_flow', localName: 'NetCashProvidedByUsedInOperatingActivities', label: 'Net Cash Provided By Used In Operating Activities', values: { '2025-cf': 1_000_000_000 } }), createRow({ statement: 'cash_flow', localName: 'PaymentsToAcquirePropertyPlantAndEquipment', label: 'Payments To Acquire Property Plant And Equipment', values: { '2025-cf': 250_000_000 } }), createRow({ statement: 'cash_flow', localName: 'IncreaseDecreaseInReceivables', label: 'Increase Decrease In Receivables', values: { '2025-cf': -37_487_000 } }), createRow({ statement: 'cash_flow', localName: 'IncreaseDecreaseInInventories', label: 'Increase Decrease In Inventories', values: { '2025-cf': 15_749_000 } }), createRow({ statement: 'cash_flow', localName: 'PaymentsForRepurchaseOfCommonStock', label: 'Payments For Repurchase Of Common Stock', values: { '2025-cf': 100_000_000 } }), createRow({ statement: 'cash_flow', localName: 'PaymentsOfDividends', label: 'Payments Of Dividends', values: { '2025-cf': 40_000_000 } }), createRow({ statement: 'cash_flow', localName: 'OtherInvestingActivitiesNet', label: 'Other Investing Activities Net', values: { '2025-cf': 12_000_000 } }) ] }); expect(findRow(standardizedRows, 'changes_trade_receivables').values['2025-cf']).toBe(37_487_000); expect(findRow(standardizedRows, 'changes_inventories').values['2025-cf']).toBe(-15_749_000); expect(findRow(standardizedRows, 'capital_expenditures').values['2025-cf']).toBe(-250_000_000); expect(findRow(standardizedRows, 'share_repurchases').values['2025-cf']).toBe(-100_000_000); expect(findRow(standardizedRows, 'dividends_paid').values['2025-cf']).toBe(-40_000_000); expect(findRow(standardizedRows, 'other_investing_activities').values['2025-cf']).toBe(-12_000_000); expect(findRow(standardizedRows, 'free_cash_flow').values['2025-cf']).toBe(750_000_000); }); it('aggregates multiple matching component rows for template rows that require it', () => { const period = createPeriod({ id: '2025-cf', filingId: 150, filingDate: '2025-05-15', periodStart: '2024-04-01', periodEnd: '2025-03-31', filingType: '10-K' }); const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'cash_flow', periods: [period], facts: [], rows: [ createRow({ statement: 'cash_flow', localName: 'IncreaseDecreaseInOtherOperatingAssets', label: 'Increase Decrease In Other Operating Assets', values: { '2025-cf': 25_000_000 } }), createRow({ statement: 'cash_flow', localName: 'IncreaseDecreaseInOtherOperatingLiabilities', label: 'Increase Decrease In Other Operating Liabilities', values: { '2025-cf': -40_000_000 } }) ] }); const otherOperating = findRow(standardizedRows, 'changes_other_operating_activities'); expect(otherOperating.values['2025-cf']).toBe(15_000_000); expect(otherOperating.resolvedSourceRowKeys['2025-cf']).toBeNull(); expect(otherOperating.sourceRowKeys).toHaveLength(2); }); it('aggregates CASY balance and cash-flow component rows from dimensionless facts', () => { const balancePeriod = createPeriod({ id: '2025-balance', filingId: 151, filingDate: '2025-06-23', periodEnd: '2025-04-30', filingType: '10-K' }); const cashFlowPeriod = createPeriod({ id: '2025-cf', filingId: 152, filingDate: '2025-06-23', periodStart: '2024-05-01', periodEnd: '2025-04-30', filingType: '10-K' }); const balanceRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'balance', periods: [balancePeriod], facts: [], rows: [ createRow({ statement: 'balance', localName: 'PropertyPlantAndEquipmentAndFinanceLeaseRightOfUseAssetAfterAccumulatedDepreciationAndAmortization', label: 'Property Plant And Equipment And Finance Lease Right Of Use Asset After Accumulated Depreciation And Amortization', values: { '2025-balance': 5_413_244_000 } }), createRow({ statement: 'balance', localName: 'EmployeeRelatedLiabilitiesCurrent', label: 'Employee Related Liabilities Current', values: { '2025-balance': 80_633_000 } }), createRow({ statement: 'balance', localName: 'OtherLiabilitiesCurrent', label: 'Other Liabilities Current', values: { '2025-balance': 189_870_000 } }), createRow({ statement: 'balance', localName: 'AccruedPropertyTaxes', qname: 'caseys:AccruedPropertyTaxes', conceptKey: 'http://www.caseys.com/20250430#AccruedPropertyTaxes', label: 'Accrued Property Taxes', values: { '2025-balance': 59_843_000 } }), createRow({ statement: 'balance', localName: 'DeferredIncomeTaxLiabilitiesNet', label: 'Deferred Income Tax Liabilities Net', values: { '2025-balance': 646_905_000 } }), createRow({ statement: 'balance', localName: 'OtherLiabilitiesNoncurrent', label: 'Other Liabilities Noncurrent', values: { '2025-balance': 69_380_000 } }), createRow({ statement: 'balance', localName: 'LiabilitiesCurrent', label: 'Liabilities Current', values: { '2025-balance': 1_101_693_000 } }), createRow({ statement: 'balance', localName: 'OperatingLeaseLiability', label: 'Operating Lease Liability', values: { '2025-balance': 449_354_000 } }), createRow({ statement: 'balance', localName: 'FinanceLeaseLiability', label: 'Finance Lease Liability', values: { '2025-balance': 108_920_000 } }) ] }); expect(findRow(balanceRows, 'property_plant_equipment').values['2025-balance']).toBe(5_413_244_000); expect(findRow(balanceRows, 'accrued_liabilities').values['2025-balance']).toBe(330_346_000); expect(findRow(balanceRows, 'other_long_term_liabilities').values['2025-balance']).toBe(69_380_000); expect(findRow(balanceRows, 'total_current_liabilities').values['2025-balance']).toBe(1_101_693_000); expect(findRow(balanceRows, 'leases').values['2025-balance']).toBe(558_274_000); const cashFlowRows = __financialTaxonomyInternals.buildStandardizedRows({ statement: 'cash_flow', periods: [cashFlowPeriod], facts: [ createFact({ id: 2001, filingId: 152, filingDate: '2025-06-23', statement: 'income', localName: 'IncreaseDecreaseInDeferredIncomeTaxes', periodStart: '2024-05-01', periodEnd: '2025-04-30', value: -59_958_000 }), createFact({ id: 2002, filingId: 152, filingDate: '2025-06-23', statement: 'cash_flow', localName: 'OtherNoncashIncomeExpense', periodStart: '2024-05-01', periodEnd: '2025-04-30', value: 4_054_000 }), createFact({ id: 2003, filingId: 152, filingDate: '2025-06-23', statement: 'income', localName: 'IncreaseDecreaseInIncomeTaxes', periodStart: '2024-05-01', periodEnd: '2025-04-30', value: -84_000 }), createFact({ id: 2004, filingId: 152, filingDate: '2025-06-23', statement: 'income', localName: 'IncreaseDecreaseInIncomeTaxesReceivable', periodStart: '2024-05-01', periodEnd: '2025-04-30', value: -15_460_000 }), createFact({ id: 2005, filingId: 152, filingDate: '2025-06-23', statement: 'balance', localName: 'IncreaseDecreaseInAccruedLiabilities', periodStart: '2024-05-01', periodEnd: '2025-04-30', value: 21_525_000 }), createFact({ id: 2006, filingId: 152, filingDate: '2025-06-23', statement: 'income', localName: 'IncreaseDecreaseInPrepaidExpense', periodStart: '2024-05-01', periodEnd: '2025-04-30', value: -3_658_000 }), createFact({ id: 2007, filingId: 152, filingDate: '2025-06-23', statement: 'cash_flow', localName: 'ProceedsFromSaleOfPropertyPlantAndEquipment', periodStart: '2024-05-01', periodEnd: '2025-04-30', value: 18_805_000 }) ], rows: [] }); expect(findRow(cashFlowRows, 'changes_income_taxes_payable').values['2025-cf']).toBe(-84_000); expect(findRow(cashFlowRows, 'changes_accrued_expenses').values['2025-cf']).toBe(21_525_000); expect(findRow(cashFlowRows, 'other_adjustments').values['2025-cf']).toBe(55_904_000); expect(findRow(cashFlowRows, 'changes_other_operating_activities').values['2025-cf']).toBe(63_616_000); expect(findRow(cashFlowRows, 'proceeds_from_sale_of_property_plant_and_equipment').values['2025-cf']).toBe(18_805_000); }); it('matches local MSFT annual income regression on exact period-end dates', async () => { const response = await getCompanyFinancialTaxonomy({ ticker: 'MSFT', surfaceKind: 'income_statement', cadence: 'annual', includeDimensions: false, includeFacts: false, queuedSync: false, v3Enabled: true }); const period2024 = findPeriodId(response.periods, '2024-06-30'); expect(response.periods.map((period) => period.periodEnd)).toEqual([ '2022-06-30', '2023-06-30', '2024-06-30', '2025-06-30' ]); expect(findStandardizedResponseRow(response, 'revenue').values[period2024]).toBe(245_122_000_000); expect(findStandardizedResponseRow(response, 'operating_income').values[period2024]).toBe(109_433_000_000); expect(findStandardizedResponseRow(response, 'net_income').values[period2024]).toBe(88_136_000_000); expect(findStandardizedResponseRow(response, 'pretax_income').values[period2024]).toBe(107_787_000_000); expect(findStandardizedResponseRow(response, 'income_tax_expense').values[period2024]).toBe(19_651_000_000); expect(findStandardizedResponseRow(response, 'effective_tax_rate').values[period2024]).toBe(0.182); expect(findStandardizedResponseRow(response, 'revenue').templateSection).toBe('statement'); }); it('matches local QCOM annual income regression on exact period-end dates', async () => { const response = await getCompanyFinancialTaxonomy({ ticker: 'QCOM', surfaceKind: 'income_statement', cadence: 'annual', includeDimensions: false, includeFacts: false, queuedSync: false, v3Enabled: true }); const period2024 = findPeriodId(response.periods, '2024-09-29'); const period2025 = findPeriodId(response.periods, '2025-09-28'); expect(response.periods.map((period) => period.periodEnd)).toEqual([ '2022-09-25', '2023-09-24', '2024-09-29', '2025-09-28' ]); expect(response.periods.some((period) => period.periodEnd === '2026-09-28')).toBe(false); expect(response.periods.some((period) => period.periodEnd === '2027-09-26')).toBe(false); expect(findStandardizedResponseRow(response, 'revenue').values[period2024]).toBe(38_962_000_000); expect(findStandardizedResponseRow(response, 'cost_of_revenue').values[period2024]).toBe(17_060_000_000); expect(findStandardizedResponseRow(response, 'gross_profit').values[period2024]).toBe(21_902_000_000); expect(findStandardizedResponseRow(response, 'selling_general_and_administrative').values[period2024]).toBe(2_759_000_000); expect(findStandardizedResponseRow(response, 'research_and_development').values[period2024]).toBe(8_893_000_000); expect(findStandardizedResponseRow(response, 'pretax_income').values[period2024]).toBe(10_336_000_000); expect(findStandardizedResponseRow(response, 'ebitda').values[period2024]).toBe(11_777_000_000); expect(findStandardizedResponseRow(response, 'effective_tax_rate').values[period2024]).toBe(0.02); expect(findStandardizedResponseRow(response, 'revenue').values[period2025]).toBe(44_284_000_000); expect(findStandardizedResponseRow(response, 'income_tax_expense').values[period2025]).toBe(7_122_000_000); expect(findStandardizedResponseRow(response, 'net_income').values[period2025]).toBe(5_541_000_000); }); it('matches local MSFT annual balance regression on the June 30, 2025 balance sheet', async () => { const response = await getCompanyFinancialTaxonomy({ ticker: 'MSFT', surfaceKind: 'balance_sheet', cadence: 'annual', includeDimensions: false, includeFacts: false, queuedSync: false, v3Enabled: true }); const period2025 = findPeriodId(response.periods, '2025-06-30'); expect(findStandardizedResponseRow(response, 'total_assets').values[period2025]).toBe(619_003_000_000); expect(findStandardizedResponseRow(response, 'total_liabilities').values[period2025]).toBe(275_524_000_000); expect(findStandardizedResponseRow(response, 'total_equity').values[period2025]).toBe(343_479_000_000); expect(findStandardizedResponseRow(response, 'total_assets').templateSection).toBe('assets'); expect(findStandardizedResponseRow(response, 'total_liabilities').templateSection).toBe('liabilities'); expect(findStandardizedResponseRow(response, 'total_equity').templateSection).toBe('equity'); }); it('matches local MSFT annual cash flow regression on the June 30, 2025 filing period', async () => { const response = await getCompanyFinancialTaxonomy({ ticker: 'MSFT', surfaceKind: 'cash_flow_statement', cadence: 'annual', includeDimensions: false, includeFacts: false, queuedSync: false, v3Enabled: true }); const period2025 = findPeriodId(response.periods, '2025-06-30'); expect(findStandardizedResponseRow(response, 'depreciation_and_amortization').values[period2025]).toBe(34_153_000_000); expect(findStandardizedResponseRow(response, 'stock_based_compensation').values[period2025]).toBe(11_974_000_000); expect(findStandardizedResponseRow(response, 'free_cash_flow').values[period2025]).toBe(71_611_000_000); expect(findStandardizedResponseRow(response, 'operating_cash_flow').templateSection).toBe('operating'); expect(findStandardizedResponseRow(response, 'free_cash_flow').templateSection).toBe('free_cash_flow'); }); it('matches local CASY annual income regression on the April 30, 2025 period', async () => { const response = await getCompanyFinancialTaxonomy({ ticker: 'CASY', surfaceKind: 'income_statement', cadence: 'annual', includeDimensions: false, includeFacts: false, queuedSync: false, v3Enabled: true }); const period2025 = findPeriodId(response.periods, '2025-04-30'); expect(findStandardizedResponseRow(response, 'revenue').values[period2025]).toBe(15_940_899_000); expect(findStandardizedResponseRow(response, 'cost_of_revenue').values[period2025]).toBe(12_188_496_000); expect(findStandardizedResponseRow(response, 'gross_profit').values[period2025]).toBe(3_752_403_000); expect(findStandardizedResponseRow(response, 'selling_general_and_administrative').values[period2025]).toBe(2_552_356_000); expect(findStandardizedResponseRow(response, 'operating_income').values[period2025]).toBe(796_400_000); expect(findStandardizedResponseRow(response, 'pretax_income').values[period2025]).toBe(712_449_000); expect(findStandardizedResponseRow(response, 'income_tax_expense').values[period2025]).toBe(165_929_000); expect(findStandardizedResponseRow(response, 'net_income').values[period2025]).toBe(546_520_000); expect(findStandardizedResponseRow(response, 'ebitda').values[period2025]).toBe(1_200_047_000); expect(findStandardizedResponseRow(response, 'effective_tax_rate').values[period2025]).toBe(0.233); }); it('matches local CASY annual balance and cash-flow regression on the April 30, 2025 period', async () => { const balance = await getCompanyFinancialTaxonomy({ ticker: 'CASY', surfaceKind: 'balance_sheet', cadence: 'annual', includeDimensions: false, includeFacts: false, queuedSync: false, v3Enabled: true }); const cash = await getCompanyFinancialTaxonomy({ ticker: 'CASY', surfaceKind: 'cash_flow_statement', cadence: 'annual', includeDimensions: false, includeFacts: false, queuedSync: false, v3Enabled: true }); const balancePeriod2025 = findPeriodId(balance.periods, '2025-04-30'); const cashPeriod2025 = findPeriodId(cash.periods, '2025-04-30'); expect(findStandardizedResponseRow(balance, 'total_assets').values[balancePeriod2025]).toBe(8_208_118_000); expect(findStandardizedResponseRow(balance, 'total_liabilities').values[balancePeriod2025]).toBe(4_699_448_000); expect(findStandardizedResponseRow(balance, 'total_equity').values[balancePeriod2025]).toBe(3_508_670_000); expect(findStandardizedResponseRow(balance, 'cash_and_equivalents').values[balancePeriod2025]).toBe(326_662_000); expect(findStandardizedResponseRow(balance, 'accrued_liabilities').values[balancePeriod2025]).toBe(330_731_000); expect(findStandardizedResponseRow(balance, 'other_long_term_liabilities').values[balancePeriod2025]).toBe(121_485_000); expect(findStandardizedResponseRow(cash, 'operating_cash_flow').values[cashPeriod2025]).toBe(1_090_854_000); expect(findStandardizedResponseRow(cash, 'capital_expenditures').values[cashPeriod2025]).toBe(-506_224_000); expect(findStandardizedResponseRow(cash, 'free_cash_flow').values[cashPeriod2025]).toBe(584_630_000); expect(findStandardizedResponseRow(cash, 'acquisitions').values[cashPeriod2025]).toBe(-1_239_249_000); expect(findStandardizedResponseRow(cash, 'long_term_debt_issued').values[cashPeriod2025]).toBe(1_100_000_000); expect(findStandardizedResponseRow(cash, 'debt_repaid').values[cashPeriod2025]).toBe(-239_492_000); expect(findStandardizedResponseRow(cash, 'dividends_paid').values[cashPeriod2025]).toBe(-72_309_000); expect(findStandardizedResponseRow(cash, 'financing_cash_flow').values[cashPeriod2025]).toBe(755_994_000); expect(findStandardizedResponseRow(cash, 'changes_income_taxes_payable').values[cashPeriod2025]).toBe(-84_000); expect(findStandardizedResponseRow(cash, 'changes_accrued_expenses').values[cashPeriod2025]).toBe(21_525_000); expect(findStandardizedResponseRow(cash, 'other_adjustments').values[cashPeriod2025]).toBe(55_904_000); }); it('merges KPI rows by priority without overwriting higher-priority periods', () => { const merged = __financialTaxonomyInternals.mergeStructuredKpiRowsByPriority([ [ createKpiRow({ key: 'loan_growth', values: { p1: 0.12 }, sourceConcepts: ['us-gaap:LoansReceivableNetReportedAmount'], sourceFactIds: [1] }) ], [ createKpiRow({ key: 'loan_growth', values: { p1: 0.11, p2: 0.09 }, sourceConcepts: ['us-gaap:FinancingReceivableRecordedInvestment'], sourceFactIds: [2] }) ], [ createKpiRow({ key: 'loan_growth', values: { p2: 0.08, p3: 0.07 }, provenanceType: 'structured_note', sourceFactIds: [3] }) ] ]); expect(merged).toHaveLength(1); expect(merged[0]?.values).toEqual({ p1: 0.12, p2: 0.09, p3: 0.07 }); expect(merged[0]?.sourceConcepts).toEqual([ 'us-gaap:FinancingReceivableRecordedInvestment', 'us-gaap:LoansReceivableNetReportedAmount' ]); expect(merged[0]?.sourceFactIds).toEqual([1, 2, 3]); expect(merged[0]?.provenanceType).toBe('taxonomy'); }); it('builds faithful rows when persisted statement rows are missing sourceFactIds', () => { const malformedSnapshot = { ...createSnapshot({ filingId: 19, filingType: '10-K', filingDate: '2026-02-20', statement: 'income', periods: [ { id: '2025-fy', periodStart: '2025-01-01', periodEnd: '2025-12-31', periodLabel: '2025 FY' } ] }), statement_rows: { income: [{ ...createRow({ key: 'revenue', label: 'Revenue', statement: 'income', values: { '2025-fy': 123_000_000 } }), sourceFactIds: undefined } as unknown as TaxonomyStatementRow], balance: [], cash_flow: [], equity: [], comprehensive_income: [] } } satisfies FilingTaxonomySnapshotRecord; const rows = __financialTaxonomyInternals.buildRows( [malformedSnapshot], 'income', new Set(['2025-fy']) ); expect(rows).toHaveLength(1); expect(rows[0]?.key).toBe('revenue'); expect(rows[0]?.sourceFactIds).toEqual([]); }); it('aggregates persisted surface rows when legacy snapshots are missing source arrays', () => { const snapshot = { ...createSnapshot({ filingId: 20, filingType: '10-K', filingDate: '2026-02-21', statement: 'income', periods: [ { id: '2025-fy', periodStart: '2025-01-01', periodEnd: '2025-12-31', periodLabel: '2025 FY' } ] }), surface_rows: { income: [{ key: 'revenue', label: 'Revenue', category: 'revenue', templateSection: 'statement', order: 10, unit: 'currency', values: { '2025-fy': 123_000_000 }, sourceConcepts: undefined, sourceRowKeys: undefined, sourceFactIds: undefined, formulaKey: null, hasDimensions: false, resolvedSourceRowKeys: {}, statement: 'income', detailCount: 0, resolutionMethod: 'direct', confidence: 'high', warningCodes: [] } as unknown as FilingTaxonomySnapshotRecord['surface_rows']['income'][number]], balance: [], cash_flow: [], equity: [], comprehensive_income: [] } } satisfies FilingTaxonomySnapshotRecord; const rows = __financialTaxonomyInternals.aggregateSurfaceRows({ snapshots: [snapshot], statement: 'income', selectedPeriodIds: new Set(['2025-fy']) }); expect(rows).toHaveLength(1); expect(rows[0]).toMatchObject({ key: 'revenue', sourceConcepts: [], sourceRowKeys: [], sourceFactIds: [] }); }); it('aggregates persisted detail rows when legacy snapshots are missing dimension arrays', () => { const snapshot = { ...createSnapshot({ filingId: 21, filingType: '10-K', filingDate: '2026-02-22', statement: 'income', periods: [ { id: '2025-fy', periodStart: '2025-01-01', periodEnd: '2025-12-31', periodLabel: '2025 FY' } ] }), detail_rows: { income: { revenue: [{ key: 'revenue_detail', parentSurfaceKey: 'revenue', label: 'Revenue Detail', conceptKey: 'us-gaap:RevenueDetail', qname: 'us-gaap:RevenueDetail', namespaceUri: 'http://fasb.org/us-gaap/2024', localName: 'RevenueDetail', unit: 'iso4217:USD', values: { '2025-fy': 123_000_000 }, sourceFactIds: undefined, isExtension: false, dimensionsSummary: undefined, residualFlag: false } as unknown as FilingTaxonomySnapshotRecord['detail_rows']['income'][string][number]] }, balance: {}, cash_flow: {}, equity: {}, comprehensive_income: {} } } satisfies FilingTaxonomySnapshotRecord; const rows = __financialTaxonomyInternals.aggregateDetailRows({ snapshots: [snapshot], statement: 'income', selectedPeriodIds: new Set(['2025-fy']) }); expect(rows.revenue).toHaveLength(1); expect(rows.revenue?.[0]).toMatchObject({ key: 'revenue_detail', sourceFactIds: [], dimensionsSummary: [] }); }); it('builds normalization metadata from snapshot fiscal pack and counts', () => { const snapshot = { ...createSnapshot({ filingId: 15, filingType: '10-Q', filingDate: '2026-01-28', statement: 'income', periods: [ { id: 'quarter', periodStart: '2025-10-01', periodEnd: '2025-12-31', periodLabel: '2025-10-01 to 2025-12-31' } ] }), parser_version: '0.1.0', fiscal_pack: 'bank_lender', normalization_summary: { surfaceRowCount: 5, detailRowCount: 3, kpiRowCount: 2, unmappedRowCount: 4, materialUnmappedRowCount: 1, warnings: [] } } satisfies FilingTaxonomySnapshotRecord; expect(__financialTaxonomyInternals.buildNormalizationMetadata([snapshot])).toEqual({ parserEngine: 'fiscal-xbrl', regime: 'us-gaap', fiscalPack: 'bank_lender', parserVersion: '0.1.0', surfaceRowCount: 5, detailRowCount: 3, kpiRowCount: 2, unmappedRowCount: 4, materialUnmappedRowCount: 1, warnings: [] }); }); it('aggregates normalization counts and warning codes across snapshots while using the latest parser identity', () => { const olderSnapshot = { ...createSnapshot({ filingId: 17, filingType: '10-K', filingDate: '2025-02-13', statement: 'income', periods: [ { id: '2024-fy', periodStart: '2024-01-01', periodEnd: '2024-12-31', periodLabel: '2024 FY' } ] }), parser_engine: 'fiscal-xbrl', parser_version: '0.9.0', fiscal_pack: 'core', normalization_summary: { surfaceRowCount: 4, detailRowCount: 2, kpiRowCount: 1, unmappedRowCount: 3, materialUnmappedRowCount: 1, warnings: ['balance_residual_detected', 'income_sparse_mapping'] } } satisfies FilingTaxonomySnapshotRecord; const latestSnapshot = { ...createSnapshot({ filingId: 18, filingType: '10-Q', filingDate: '2026-02-13', statement: 'income', periods: [ { id: '2025-q4', periodStart: '2025-10-01', periodEnd: '2025-12-31', periodLabel: '2025 Q4' } ] }), parser_engine: 'fiscal-xbrl', parser_version: '1.1.0', fiscal_pack: 'bank_lender', normalization_summary: { surfaceRowCount: 6, detailRowCount: 5, kpiRowCount: 4, unmappedRowCount: 2, materialUnmappedRowCount: 0, warnings: ['income_sparse_mapping', 'unmapped_cash_flow_bridge'] } } satisfies FilingTaxonomySnapshotRecord; expect(__financialTaxonomyInternals.buildNormalizationMetadata([olderSnapshot, latestSnapshot])).toEqual({ parserEngine: 'fiscal-xbrl', regime: 'us-gaap', fiscalPack: 'bank_lender', parserVersion: '1.1.0', surfaceRowCount: 10, detailRowCount: 7, kpiRowCount: 5, unmappedRowCount: 5, materialUnmappedRowCount: 1, warnings: [ 'balance_residual_detected', 'income_sparse_mapping', 'unmapped_cash_flow_bridge' ] }); }); it('retains pinned income surface rows even when they are intentionally null', () => { const snapshot = { ...createSnapshot({ filingId: 16, filingType: '10-K', filingDate: '2026-02-13', statement: 'income', periods: [ { id: '2025-fy', periodStart: '2025-01-01', periodEnd: '2025-12-31', periodLabel: '2025 FY' } ] }), fiscal_pack: 'bank_lender', surface_rows: { income: [ { key: 'revenue', label: 'Revenue', category: 'surface', templateSection: 'surface', order: 10, unit: 'currency', values: { '2025-fy': 100_000_000 }, sourceConcepts: ['us-gaap:TotalNetRevenues'], sourceRowKeys: ['revenue'], sourceFactIds: [1], formulaKey: null, hasDimensions: false, resolvedSourceRowKeys: { '2025-fy': 'revenue' }, statement: 'income', detailCount: 0, resolutionMethod: 'direct', confidence: 'high', warningCodes: [] }, { key: 'gross_profit', label: 'Gross Profit', category: 'surface', templateSection: 'surface', order: 20, unit: 'currency', values: { '2025-fy': null }, sourceConcepts: [], sourceRowKeys: [], sourceFactIds: [], formulaKey: null, hasDimensions: false, resolvedSourceRowKeys: { '2025-fy': null }, statement: 'income', detailCount: 0, resolutionMethod: 'not_meaningful', confidence: 'low', warningCodes: ['gross_profit_not_meaningful_bank_pack'] }, { key: 'selling_general_and_administrative', label: 'SG&A', category: 'surface', templateSection: 'surface', order: 31, unit: 'currency', values: { '2025-fy': null }, sourceConcepts: [], sourceRowKeys: [], sourceFactIds: [], formulaKey: null, hasDimensions: false, resolvedSourceRowKeys: { '2025-fy': null }, statement: 'income', detailCount: 0, resolutionMethod: 'not_meaningful', confidence: 'low', warningCodes: ['selling_general_and_administrative_not_meaningful_bank_pack'] } ], balance: [], cash_flow: [], equity: [], comprehensive_income: [] } } satisfies FilingTaxonomySnapshotRecord; const rows = __financialTaxonomyInternals.aggregateSurfaceRows({ snapshots: [snapshot], statement: 'income', selectedPeriodIds: new Set(['2025-fy']) }); const grossProfit = rows.find((row) => row.key === 'gross_profit'); const sga = rows.find((row) => row.key === 'selling_general_and_administrative'); expect(grossProfit).toBeDefined(); expect(grossProfit?.values['2025-fy']).toBeNull(); expect(grossProfit?.resolutionMethod).toBe('not_meaningful'); expect(grossProfit?.warningCodes).toEqual(['gross_profit_not_meaningful_bank_pack']); expect(sga).toBeDefined(); expect(sga?.values['2025-fy']).toBeNull(); expect(sga?.resolutionMethod).toBe('not_meaningful'); expect(sga?.warningCodes).toEqual(['selling_general_and_administrative_not_meaningful_bank_pack']); }); });