'use client'; import { useQueryClient } from '@tanstack/react-query'; import Link from 'next/link'; import { Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { format } from 'date-fns'; import { useSearchParams } from 'next/navigation'; import { Area, AreaChart, Bar, BarChart, CartesianGrid, Line, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; import { AlertTriangle, ChartNoAxesCombined, ChevronDown, Download, GitCompareArrows, RefreshCcw, Search } from 'lucide-react'; import { AppShell } from '@/components/shell/app-shell'; import { MetricCard } from '@/components/dashboard/metric-card'; import { FinancialControlBar, type FinancialControlAction, type FinancialControlSection } from '@/components/financials/control-bar'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Panel } from '@/components/ui/panel'; import { useAuthGuard } from '@/hooks/use-auth-guard'; import { useLinkPrefetch } from '@/hooks/use-link-prefetch'; import { queueFilingSync } from '@/lib/api'; import { formatCurrencyByScale, formatPercent, type NumberScaleUnit } from '@/lib/format'; import { queryKeys } from '@/lib/query/keys'; import { companyFinancialStatementsQueryOptions } from '@/lib/query/options'; import type { CompanyFinancialStatementsResponse, DimensionBreakdownRow, FinancialHistoryWindow, FinancialStatementSurfaceKind, FinancialStatementKind, StandardizedStatementRow, TaxonomyStatementRow } from '@/lib/types'; type LoadOptions = { cursor?: string | null; append?: boolean; }; type OverviewPoint = { periodId: string; filingDate: string; periodEnd: string | null; label: string; revenue: number | null; netIncome: number | null; totalAssets: number | null; cash: number | null; debt: number | null; }; type DisplayRow = TaxonomyStatementRow | StandardizedStatementRow; const FINANCIAL_VALUE_SCALE_OPTIONS: Array<{ value: NumberScaleUnit; label: string }> = [ { value: 'thousands', label: 'Thousands (K)' }, { value: 'millions', label: 'Millions (M)' }, { value: 'billions', label: 'Billions (B)' } ]; const STATEMENT_OPTIONS: Array<{ value: FinancialStatementKind; label: string }> = [ { value: 'income', label: 'Income' }, { value: 'balance', label: 'Balance Sheet' }, { value: 'cash_flow', label: 'Cash Flow' }, { value: 'equity', label: 'Equity' }, { value: 'comprehensive_income', label: 'Comprehensive Income' } ]; const WINDOW_OPTIONS: Array<{ value: FinancialHistoryWindow; label: string }> = [ { value: '10y', label: '10 Years' }, { value: 'all', label: 'Full Available' } ]; const SURFACE_OPTIONS: Array<{ value: FinancialStatementSurfaceKind; label: string }> = [ { value: 'standardized', label: 'Standardized' }, { value: 'faithful', label: 'Filing-faithful' } ]; const CHART_MUTED = '#b4ced9'; const CHART_GRID = 'rgba(126, 217, 255, 0.24)'; const CHART_TOOLTIP_BG = 'rgba(6, 17, 24, 0.95)'; const CHART_TOOLTIP_BORDER = 'rgba(123, 255, 217, 0.45)'; function formatLongDate(value: string) { const parsed = new Date(value); if (Number.isNaN(parsed.getTime())) { return 'Unknown'; } return format(parsed, 'MMM dd, yyyy'); } function formatShortDate(value: string) { const parsed = new Date(value); if (Number.isNaN(parsed.getTime())) { return 'Unknown'; } return format(parsed, 'MMM yyyy'); } function asDisplayCurrency(value: number | null, scale: NumberScaleUnit) { return value === null ? 'n/a' : formatCurrencyByScale(value, scale); } function asAxisCurrencyTick(value: number, scale: NumberScaleUnit) { return formatCurrencyByScale(value, scale, { maximumFractionDigits: 1 }); } function asTooltipCurrency(value: unknown, scale: NumberScaleUnit) { const numeric = Number(value); if (!Number.isFinite(numeric)) { return 'n/a'; } return formatCurrencyByScale(numeric, scale); } function ratioPercent(numerator: number | null, denominator: number | null) { if (numerator === null || denominator === null || denominator === 0) { return null; } return (numerator / denominator) * 100; } function rowValue(row: { values: Record }, periodId: string) { return periodId in row.values ? row.values[periodId] : null; } function isFaithfulRow(row: DisplayRow): row is TaxonomyStatementRow { return 'localName' in row; } function isStandardizedRow(row: DisplayRow): row is StandardizedStatementRow { return 'sourceRowKeys' in row; } function mergeSurfaceRows; hasDimensions: boolean }>( rows: T[], mergeRow: (existing: T, row: T) => void ) { const rowMap = new Map(); for (const row of rows) { const existing = rowMap.get(row.key); if (!existing) { rowMap.set(row.key, structuredClone(row)); continue; } mergeRow(existing, row); } return [...rowMap.values()]; } function mergeFinancialPages( base: CompanyFinancialStatementsResponse | null, next: CompanyFinancialStatementsResponse ) { if (!base) { return next; } const periods = [...base.periods, ...next.periods] .filter((period, index, list) => list.findIndex((item) => item.id === period.id) === index) .sort((a, b) => Date.parse(a.filingDate) - Date.parse(b.filingDate)); const faithfulRows = mergeSurfaceRows( [...base.surfaces.faithful.rows, ...next.surfaces.faithful.rows], (existing, row) => { existing.hasDimensions = existing.hasDimensions || row.hasDimensions; existing.order = Math.min(existing.order, row.order); existing.depth = Math.min(existing.depth, row.depth); if (!existing.parentKey && row.parentKey) { existing.parentKey = row.parentKey; } for (const [periodId, value] of Object.entries(row.values)) { if (!(periodId in existing.values)) { existing.values[periodId] = value; } } for (const [periodId, unit] of Object.entries(row.units)) { if (!(periodId in existing.units)) { existing.units[periodId] = unit; } } for (const factId of row.sourceFactIds) { if (!existing.sourceFactIds.includes(factId)) { existing.sourceFactIds.push(factId); } } } ).sort((left, right) => { if (left.order !== right.order) { return left.order - right.order; } return left.label.localeCompare(right.label); }); const standardizedRows = mergeSurfaceRows( [...base.surfaces.standardized.rows, ...next.surfaces.standardized.rows], (existing, row) => { existing.hasDimensions = existing.hasDimensions || row.hasDimensions; existing.order = Math.min(existing.order, row.order); for (const [periodId, value] of Object.entries(row.values)) { if (!(periodId in existing.values)) { existing.values[periodId] = value; } } for (const [periodId, sourceRowKey] of Object.entries(row.resolvedSourceRowKeys)) { if (!(periodId in existing.resolvedSourceRowKeys)) { existing.resolvedSourceRowKeys[periodId] = sourceRowKey; } } for (const concept of row.sourceConcepts) { if (!existing.sourceConcepts.includes(concept)) { existing.sourceConcepts.push(concept); } } for (const rowKey of row.sourceRowKeys) { if (!existing.sourceRowKeys.includes(rowKey)) { existing.sourceRowKeys.push(rowKey); } } for (const factId of row.sourceFactIds) { if (!existing.sourceFactIds.includes(factId)) { existing.sourceFactIds.push(factId); } } } ).sort((left, right) => { if (left.order !== right.order) { return left.order - right.order; } return left.label.localeCompare(right.label); }); const dimensionBreakdown = (() => { if (!base.dimensionBreakdown && !next.dimensionBreakdown) { return null; } const map = new Map(); for (const source of [base.dimensionBreakdown, next.dimensionBreakdown]) { if (!source) { continue; } for (const [key, rows] of Object.entries(source)) { const existing = map.get(key); if (existing) { existing.push(...rows); } else { map.set(key, [...rows]); } } } return Object.fromEntries(map.entries()); })(); return { ...next, periods, surfaces: { faithful: { kind: 'faithful' as const, rows: faithfulRows }, standardized: { kind: 'standardized' as const, rows: standardizedRows } }, nextCursor: next.nextCursor, coverage: { ...next.coverage, filings: periods.length, rows: faithfulRows.length }, dataSourceStatus: { ...next.dataSourceStatus, queuedSync: base.dataSourceStatus.queuedSync || next.dataSourceStatus.queuedSync }, dimensionBreakdown }; } function findFaithfulRowByLocalNames(rows: TaxonomyStatementRow[], localNames: string[]) { const normalizedNames = localNames.map((name) => name.toLowerCase()); const exact = rows.find((row) => normalizedNames.includes(row.localName.toLowerCase())); if (exact) { return exact; } return rows.find((row) => { const haystack = `${row.key} ${row.label} ${row.localName} ${row.qname}`.toLowerCase(); return normalizedNames.some((name) => haystack.includes(name)); }) ?? null; } function findStandardizedRow(rows: StandardizedStatementRow[], key: string) { return rows.find((row) => row.key === key) ?? null; } function buildOverviewSeries( incomeData: CompanyFinancialStatementsResponse | null, balanceData: CompanyFinancialStatementsResponse | null ): OverviewPoint[] { const periodMap = new Map(); for (const source of [incomeData, balanceData]) { for (const period of source?.periods ?? []) { periodMap.set(period.id, { filingDate: period.filingDate, periodEnd: period.periodEnd }); } } const periods = [...periodMap.entries()] .map(([periodId, data]) => ({ periodId, filingDate: data.filingDate, periodEnd: data.periodEnd })) .sort((a, b) => Date.parse(a.periodEnd ?? a.filingDate) - Date.parse(b.periodEnd ?? b.filingDate)); const incomeStandardized = incomeData?.surfaces.standardized.rows ?? []; const balanceStandardized = balanceData?.surfaces.standardized.rows ?? []; const incomeFaithful = incomeData?.surfaces.faithful.rows ?? []; const balanceFaithful = balanceData?.surfaces.faithful.rows ?? []; const revenueRow = findStandardizedRow(incomeStandardized, 'revenue') ?? findFaithfulRowByLocalNames(incomeFaithful, ['RevenueFromContractWithCustomerExcludingAssessedTax', 'Revenues', 'SalesRevenueNet', 'Revenue']); const netIncomeRow = findStandardizedRow(incomeStandardized, 'net-income') ?? findFaithfulRowByLocalNames(incomeFaithful, ['NetIncomeLoss', 'ProfitLoss']); const assetsRow = findStandardizedRow(balanceStandardized, 'total-assets') ?? findFaithfulRowByLocalNames(balanceFaithful, ['Assets']); const cashRow = findStandardizedRow(balanceStandardized, 'cash-and-equivalents') ?? findFaithfulRowByLocalNames(balanceFaithful, ['CashAndCashEquivalentsAtCarryingValue', 'CashAndShortTermInvestments', 'Cash']); const debtRow = findStandardizedRow(balanceStandardized, 'total-debt') ?? findFaithfulRowByLocalNames(balanceFaithful, ['LongTermDebt', 'Debt', 'LongTermDebtNoncurrent']); return periods.map((period) => ({ periodId: period.periodId, filingDate: period.filingDate, periodEnd: period.periodEnd, label: formatShortDate(period.periodEnd ?? period.filingDate), revenue: revenueRow ? rowValue(revenueRow, period.periodId) : null, netIncome: netIncomeRow ? rowValue(netIncomeRow, period.periodId) : null, totalAssets: assetsRow ? rowValue(assetsRow, period.periodId) : null, cash: cashRow ? rowValue(cashRow, period.periodId) : null, debt: debtRow ? rowValue(debtRow, period.periodId) : null })); } function groupDimensionRows( rows: DimensionBreakdownRow[], surface: FinancialStatementSurfaceKind ) { if (surface === 'faithful') { return rows; } return [...rows].sort((left, right) => { if (left.periodId !== right.periodId) { return left.periodId.localeCompare(right.periodId); } return `${left.sourceLabel ?? ''}${left.concept ?? ''}`.localeCompare(`${right.sourceLabel ?? ''}${right.concept ?? ''}`); }); } function ChartFrame({ children }: { children: React.ReactNode }) { const containerRef = useRef(null); const [ready, setReady] = useState(false); useEffect(() => { const element = containerRef.current; if (!element) { return; } const observer = new ResizeObserver((entries) => { const next = entries[0]; if (!next) { return; } const { width, height } = next.contentRect; setReady(width > 0 && height > 0); }); observer.observe(element); return () => observer.disconnect(); }, []); return (
{ready ? children : null}
); } export default function FinancialsPage() { return ( Loading financial terminal...}> ); } function FinancialsPageContent() { const { isPending, isAuthenticated } = useAuthGuard(); const searchParams = useSearchParams(); const queryClient = useQueryClient(); const { prefetchResearchTicker } = useLinkPrefetch(); const [tickerInput, setTickerInput] = useState('MSFT'); const [ticker, setTicker] = useState('MSFT'); const [statement, setStatement] = useState('income'); const [window, setWindow] = useState('10y'); const [surface, setSurface] = useState('standardized'); const [valueScale, setValueScale] = useState('millions'); const [financials, setFinancials] = useState(null); const [overviewIncome, setOverviewIncome] = useState(null); const [overviewBalance, setOverviewBalance] = useState(null); const [selectedRowKey, setSelectedRowKey] = useState(null); const [dimensionsEnabled, setDimensionsEnabled] = useState(false); const [loading, setLoading] = useState(true); const [loadingMore, setLoadingMore] = useState(false); const [syncingFinancials, setSyncingFinancials] = useState(false); const [error, setError] = useState(null); useEffect(() => { const fromQuery = searchParams.get('ticker'); if (!fromQuery) { return; } const normalized = fromQuery.trim().toUpperCase(); if (!normalized) { return; } setTickerInput(normalized); setTicker(normalized); }, [searchParams]); const loadOverview = useCallback(async (symbol: string, selectedWindow: FinancialHistoryWindow) => { const [incomeResponse, balanceResponse] = await Promise.all([ queryClient.ensureQueryData(companyFinancialStatementsQueryOptions({ ticker: symbol, statement: 'income', window: selectedWindow, includeDimensions: false, includeFacts: false, limit: selectedWindow === 'all' ? 120 : 80 })), queryClient.ensureQueryData(companyFinancialStatementsQueryOptions({ ticker: symbol, statement: 'balance', window: selectedWindow, includeDimensions: false, includeFacts: false, limit: selectedWindow === 'all' ? 120 : 80 })) ]); setOverviewIncome(incomeResponse.financials); setOverviewBalance(balanceResponse.financials); }, [queryClient]); const loadFinancials = useCallback(async (symbol: string, options?: LoadOptions) => { const normalizedTicker = symbol.trim().toUpperCase(); const nextCursor = options?.cursor ?? null; const includeDimensions = dimensionsEnabled || selectedRowKey !== null; if (!options?.append) { setLoading(true); } else { setLoadingMore(true); } setError(null); try { const response = await queryClient.ensureQueryData(companyFinancialStatementsQueryOptions({ ticker: normalizedTicker, statement, window, includeDimensions, includeFacts: false, cursor: nextCursor, limit: window === 'all' ? 60 : 80 })); setFinancials((current) => { if (options?.append) { return mergeFinancialPages(current, response.financials); } return response.financials; }); await loadOverview(normalizedTicker, window); } catch (err) { setError(err instanceof Error ? err.message : 'Unable to load financial history'); if (!options?.append) { setFinancials(null); } } finally { setLoading(false); setLoadingMore(false); } }, [ dimensionsEnabled, loadOverview, queryClient, selectedRowKey, statement, window ]); const syncFinancials = useCallback(async () => { const targetTicker = (financials?.company.ticker ?? ticker).trim().toUpperCase(); if (!targetTicker) { return; } setSyncingFinancials(true); setError(null); try { await queueFilingSync({ ticker: targetTicker, limit: 20 }); void queryClient.invalidateQueries({ queryKey: queryKeys.recentTasks(20) }); void queryClient.invalidateQueries({ queryKey: ['filings'] }); void queryClient.invalidateQueries({ queryKey: ['financials-v3'] }); await loadFinancials(targetTicker); } catch (err) { setError(err instanceof Error ? err.message : `Failed to queue financial sync for ${targetTicker}`); } finally { setSyncingFinancials(false); } }, [financials?.company.ticker, loadFinancials, queryClient, ticker]); useEffect(() => { if (!isPending && isAuthenticated) { void loadFinancials(ticker); } }, [isPending, isAuthenticated, loadFinancials, ticker]); const periods = useMemo(() => { return [...(financials?.periods ?? [])] .sort((a, b) => Date.parse(a.filingDate) - Date.parse(b.filingDate)); }, [financials?.periods]); const faithfulRows = useMemo(() => financials?.surfaces.faithful.rows ?? [], [financials?.surfaces.faithful.rows]); const standardizedRows = useMemo(() => financials?.surfaces.standardized.rows ?? [], [financials?.surfaces.standardized.rows]); const statementRows = useMemo(() => { return surface === 'standardized' ? standardizedRows : faithfulRows; }, [faithfulRows, standardizedRows, surface]); const overviewSeries = useMemo(() => { return buildOverviewSeries(overviewIncome, overviewBalance); }, [overviewIncome, overviewBalance]); const latestOverview = overviewSeries[overviewSeries.length - 1] ?? null; const latestTaxonomyMetrics = financials?.metrics.taxonomy ?? overviewIncome?.metrics.taxonomy ?? overviewBalance?.metrics.taxonomy ?? null; const latestStandardizedIncome = overviewIncome?.surfaces.standardized.rows ?? []; const latestStandardizedBalance = overviewBalance?.surfaces.standardized.rows ?? []; const latestRevenue = latestOverview?.revenue ?? findStandardizedRow(latestStandardizedIncome, 'revenue')?.values[periods[periods.length - 1]?.id ?? ''] ?? latestTaxonomyMetrics?.revenue ?? null; const latestNetIncome = latestOverview?.netIncome ?? findStandardizedRow(latestStandardizedIncome, 'net-income')?.values[periods[periods.length - 1]?.id ?? ''] ?? latestTaxonomyMetrics?.netIncome ?? null; const latestTotalAssets = latestOverview?.totalAssets ?? findStandardizedRow(latestStandardizedBalance, 'total-assets')?.values[periods[periods.length - 1]?.id ?? ''] ?? latestTaxonomyMetrics?.totalAssets ?? null; const latestCash = latestOverview?.cash ?? findStandardizedRow(latestStandardizedBalance, 'cash-and-equivalents')?.values[periods[periods.length - 1]?.id ?? ''] ?? latestTaxonomyMetrics?.cash ?? null; const latestDebt = latestOverview?.debt ?? findStandardizedRow(latestStandardizedBalance, 'total-debt')?.values[periods[periods.length - 1]?.id ?? ''] ?? latestTaxonomyMetrics?.debt ?? null; const latestReferenceDate = latestOverview?.filingDate ?? periods[periods.length - 1]?.filingDate ?? null; const selectedRow = useMemo(() => { if (!selectedRowKey) { return null; } return statementRows.find((row) => row.key === selectedRowKey) ?? null; }, [selectedRowKey, statementRows]); const dimensionRows = useMemo(() => { if (!selectedRow || !financials?.dimensionBreakdown) { return []; } const direct = financials.dimensionBreakdown[selectedRow.key] ?? []; return groupDimensionRows(direct, surface); }, [financials?.dimensionBreakdown, selectedRow, surface]); const selectedScaleLabel = useMemo(() => { return FINANCIAL_VALUE_SCALE_OPTIONS.find((option) => option.value === valueScale)?.label ?? 'Millions (M)'; }, [valueScale]); const controlSections = useMemo(() => [ { id: 'statement', label: 'Statement', value: statement, options: STATEMENT_OPTIONS, onChange: (nextValue) => { setStatement(nextValue as FinancialStatementKind); setSelectedRowKey(null); } }, { id: 'history', label: 'Window', value: window, options: WINDOW_OPTIONS, onChange: (nextValue) => { setWindow(nextValue as FinancialHistoryWindow); setSelectedRowKey(null); } }, { id: 'scale', label: 'Scale', value: valueScale, options: FINANCIAL_VALUE_SCALE_OPTIONS, onChange: (nextValue) => setValueScale(nextValue as NumberScaleUnit) } ], [statement, valueScale, window]); const controlActions = useMemo(() => { const actions: FinancialControlAction[] = []; if (window === '10y') { actions.push({ id: 'load-full-history', label: 'Load Full History', variant: 'secondary', onClick: () => { setWindow('all'); setSelectedRowKey(null); } }); } if (window === 'all' && financials?.nextCursor) { actions.push({ id: 'load-older-periods', label: loadingMore ? 'Loading Older...' : 'Load Older Periods', variant: 'secondary', disabled: loadingMore, onClick: () => { if (!financials.nextCursor) { return; } void loadFinancials(ticker, { cursor: financials.nextCursor, append: true }); } }); } return actions; }, [financials?.nextCursor, loadFinancials, loadingMore, ticker, window]); if (isPending || !isAuthenticated) { return
Loading financial terminal...
; } return ( )} >
{ event.preventDefault(); const normalized = tickerInput.trim().toUpperCase(); if (!normalized) { return; } setTicker(normalized); }} > setTickerInput(event.target.value.toUpperCase())} placeholder="Ticker (AAPL)" className="max-w-xs" /> {financials ? ( prefetchResearchTicker(financials.company.ticker)} onFocus={() => prefetchResearchTicker(financials.company.ticker)} className="text-sm text-[color:var(--accent)] hover:text-[color:var(--accent-strong)]" > Open analysis ) : null}
{error ? (

{error}

) : null}
= 0} />
{SURFACE_OPTIONS.map((option) => ( ))}
{loading ? (

Loading overview chart...

) : overviewSeries.length === 0 ? (

No income history available yet.

) : ( asAxisCurrencyTick(value, valueScale)} /> asTooltipCurrency(value, valueScale)} contentStyle={{ backgroundColor: CHART_TOOLTIP_BG, border: `1px solid ${CHART_TOOLTIP_BORDER}`, borderRadius: '0.75rem' }} /> )}
{loading ? (

Loading balance chart...

) : overviewSeries.length === 0 ? (

No balance history available yet.

) : ( asAxisCurrencyTick(value, valueScale)} /> asTooltipCurrency(value, valueScale)} contentStyle={{ backgroundColor: CHART_TOOLTIP_BG, border: `1px solid ${CHART_TOOLTIP_BORDER}`, borderRadius: '0.75rem' }} /> )}
{loading ? (

Loading statement matrix...

) : periods.length === 0 || statementRows.length === 0 ? (

No statement rows available for the selected filters yet.

) : (
{periods.map((period) => ( ))} {statementRows.map((row) => ( { setSelectedRowKey(row.key); if (row.hasDimensions && !dimensionsEnabled) { setDimensionsEnabled(true); } }} > {periods.map((period) => ( ))} ))}
Metric
{formatLongDate(period.filingDate)} {period.filingType} ยท {period.periodLabel}
{row.label} {isFaithfulRow(row) && row.isExtension ? ( Ext ) : null} {row.hasDimensions ? : null}
{isStandardizedRow(row) ? (
Mapped from {row.sourceConcepts.length} concept{row.sourceConcepts.length === 1 ? '' : 's'}
{row.sourceConcepts.map((concept) => ( {concept} ))}
) : null}
{asDisplayCurrency(rowValue(row, period.id), valueScale)}
)}
{!selectedRow ? (

Select a statement row to inspect dimensional facts.

) : !selectedRow.hasDimensions ? (

No dimensional data is available for {selectedRow.label}.

) : !dimensionsEnabled ? (

Enable dimensions by selecting the row again.

) : dimensionRows.length === 0 ? (

Dimensions are still loading or unavailable for this row.

) : (
{surface === 'standardized' ? : null} {dimensionRows.map((row, index) => { const period = periods.find((item) => item.id === row.periodId); return ( {surface === 'standardized' ? : null} ); })}
PeriodSourceAxis Member Value
{period ? formatLongDate(period.filingDate) : row.periodId}{row.sourceLabel ?? row.concept ?? 'Unknown source'}{row.axis} {row.member} {asDisplayCurrency(row.value, valueScale)}
)}
{financials ? (
Overall status: {financials.metrics.validation?.status ?? 'not_run'}
{(financials.metrics.validation?.checks.length ?? 0) === 0 ? (

No validation checks available yet.

) : (
{financials.metrics.validation?.checks.map((check) => ( ))}
Metric Taxonomy LLM (PDF) Status Pages
{check.metricKey} {asDisplayCurrency(check.taxonomyValue, valueScale)} {asDisplayCurrency(check.llmValue, valueScale)} {check.status} {check.evidencePages.join(', ') || 'n/a'}
)}
) : null} {financials ? (

Hydrated

{financials.dataSourceStatus.hydratedFilings}

Partial

{financials.dataSourceStatus.partialFilings}

Failed

{financials.dataSourceStatus.failedFilings}

Pending

{financials.dataSourceStatus.pendingFilings}

Background Sync

{financials.dataSourceStatus.queuedSync ? 'Queued' : 'Idle'}

) : null}
Financial Statements V3: faithful filing reconstruction + standardized taxonomy comparison
); }