import { describe, expect, it } from 'bun:test'; import { __financialTaxonomyInternals } from './financial-taxonomy'; import type { FilingTaxonomySnapshotRecord } from './repos/filing-taxonomy'; import type { FinancialStatementKind, FinancialStatementPeriod, TaxonomyFactRow, TaxonomyStatementRow } from '@/lib/types'; function createRow(input: { key?: string; label?: string; conceptKey?: string; qname?: string; localName?: string; statement?: FinancialStatementKind; order?: number; depth?: number; hasDimensions?: boolean; values: Record; sourceFactIds?: number[]; }): 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.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, '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])) }); 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', 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 })), statement_rows: { 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: [] }, derived_metrics: null, validation_result: 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 }; } 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.selectPrimaryPeriods([snapshot], 'income'); 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.selectPrimaryPeriods([snapshot], 'balance'); 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 periods = __financialTaxonomyInternals.buildPeriods([annual, quarterly], 'income'); expect(periods.map((period) => period.id)).toEqual(['annual', 'quarter']); }); 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( faithfulRows, 'income', [period2024, period2025] ); 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 }, hasDimensions: true }), createRow({ localName: 'CostOfGoodsSold', label: 'Cost of Goods Sold', values: { '2025-q4': 48_000 }, hasDimensions: true }) ]; const standardizedRows = __financialTaxonomyInternals.buildStandardizedRows( faithfulRows, 'income', [period2024, period2025] ); 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' ]); }); });