Expand financials surfaces with ratios, KPIs, and cadence support

- Add bundled financial modeling pipeline (ratios, KPI dimensions/notes, trend series, standardization)
- Introduce company financial bundles storage (Drizzle migration + repo wiring)
- Refactor financials page/API/query flow to use surfaceKind + cadence and new response shapes
This commit is contained in:
2026-03-07 15:16:35 -05:00
parent a42622ba6e
commit db01f207a5
33 changed files with 3589 additions and 1643 deletions

View File

@@ -30,6 +30,15 @@ type TaxonomyMetricValidationStatus = 'not_run' | 'matched' | 'mismatch' | 'erro
type CoverageStatus = 'backlog' | 'active' | 'watch' | 'archive';
type CoveragePriority = 'low' | 'medium' | 'high';
type ResearchJournalEntryType = 'note' | 'filing_note' | 'status_change';
type FinancialCadence = 'annual' | 'quarterly' | 'ltm';
type FinancialSurfaceKind =
| 'income_statement'
| 'balance_sheet'
| 'cash_flow_statement'
| 'ratios'
| 'segments_kpis'
| 'adjusted'
| 'custom_metrics';
type FilingAnalysis = {
provider?: string;
@@ -460,6 +469,22 @@ export const filingTaxonomyMetricValidation = sqliteTable('filing_taxonomy_metri
filingTaxonomyMetricValidationUnique: uniqueIndex('filing_taxonomy_metric_validation_uidx').on(table.snapshot_id, table.metric_key)
}));
export const companyFinancialBundle = sqliteTable('company_financial_bundle', {
id: integer('id').primaryKey({ autoIncrement: true }),
ticker: text('ticker').notNull(),
surface_kind: text('surface_kind').$type<FinancialSurfaceKind>().notNull(),
cadence: text('cadence').$type<FinancialCadence>().notNull(),
bundle_version: integer('bundle_version').notNull(),
source_snapshot_ids: text('source_snapshot_ids', { mode: 'json' }).$type<number[]>().notNull(),
source_signature: text('source_signature').notNull(),
payload: text('payload', { mode: 'json' }).$type<Record<string, unknown>>().notNull(),
created_at: text('created_at').notNull(),
updated_at: text('updated_at').notNull()
}, (table) => ({
companyFinancialBundleUnique: uniqueIndex('company_financial_bundle_uidx').on(table.ticker, table.surface_kind, table.cadence),
companyFinancialBundleTickerIndex: index('company_financial_bundle_ticker_idx').on(table.ticker, table.updated_at)
}));
export const filingLink = sqliteTable('filing_link', {
id: integer('id').primaryKey({ autoIncrement: true }),
filing_id: integer('filing_id').notNull().references(() => filing.id, { onDelete: 'cascade' }),
@@ -565,6 +590,7 @@ export const appSchema = {
filingTaxonomyConcept,
filingTaxonomyFact,
filingTaxonomyMetricValidation,
companyFinancialBundle,
filingLink,
taskRun,
taskStageEvent,