feat(financials-v2): add statement snapshot schema and shared types

This commit is contained in:
2026-03-02 09:33:44 -05:00
parent f34c4bbcee
commit bcf4c69c92
4 changed files with 183 additions and 1 deletions

View File

@@ -40,6 +40,63 @@ type FilingAnalysis = {
};
};
type FinancialStatementKind = 'income' | 'balance' | 'cash_flow' | 'equity' | 'comprehensive_income';
type FilingStatementPeriod = {
id: string;
filingId: number;
accessionNumber: string;
filingDate: string;
periodEnd: string | null;
filingType: '10-K' | '10-Q';
periodLabel: string;
};
type StatementValuesByPeriod = Record<string, number | null>;
type FilingFaithfulStatementSnapshotRow = {
key: string;
label: string;
concept: string | null;
order: number;
depth: number;
isSubtotal: boolean;
values: StatementValuesByPeriod;
};
type StandardizedStatementSnapshotRow = {
key: string;
label: string;
concept: string;
category: string;
sourceConcepts: string[];
values: StatementValuesByPeriod;
};
type DimensionStatementSnapshotRow = {
rowKey: string;
concept: string | null;
periodId: string;
axis: string;
member: string;
value: number | null;
unit: string | null;
};
type FilingStatementBundle = {
periods: FilingStatementPeriod[];
statements: Record<FinancialStatementKind, FilingFaithfulStatementSnapshotRow[]>;
};
type StandardizedStatementBundle = {
periods: FilingStatementPeriod[];
statements: Record<FinancialStatementKind, StandardizedStatementSnapshotRow[]>;
};
type DimensionStatementBundle = {
statements: Record<FinancialStatementKind, DimensionStatementSnapshotRow[]>;
};
const authDateColumn = {
mode: 'timestamp_ms'
} as const;
@@ -192,6 +249,28 @@ export const filing = sqliteTable('filing', {
filingDateIndex: index('filing_date_idx').on(table.filing_date)
}));
export const filingStatementSnapshot = sqliteTable('filing_statement_snapshot', {
id: integer('id').primaryKey({ autoIncrement: true }),
filing_id: integer('filing_id').notNull().references(() => filing.id, { onDelete: 'cascade' }),
ticker: text('ticker').notNull(),
filing_date: text('filing_date').notNull(),
filing_type: text('filing_type').$type<'10-K' | '10-Q'>().notNull(),
period_end: text('period_end'),
statement_bundle: text('statement_bundle', { mode: 'json' }).$type<FilingStatementBundle | null>(),
standardized_bundle: text('standardized_bundle', { mode: 'json' }).$type<StandardizedStatementBundle | null>(),
dimension_bundle: text('dimension_bundle', { mode: 'json' }).$type<DimensionStatementBundle | null>(),
parse_status: text('parse_status').$type<'ready' | 'partial' | 'failed'>().notNull(),
parse_error: text('parse_error'),
source: text('source').$type<'sec_filing_summary' | 'xbrl_instance' | 'companyfacts_fallback'>().notNull(),
created_at: text('created_at').notNull(),
updated_at: text('updated_at').notNull()
}, (table) => ({
filingStatementFilingUnique: uniqueIndex('filing_stmt_filing_uidx').on(table.filing_id),
filingStatementTickerDateIndex: index('filing_stmt_ticker_date_idx').on(table.ticker, table.filing_date),
filingStatementDateIndex: index('filing_stmt_date_idx').on(table.filing_date),
filingStatementStatusIndex: index('filing_stmt_status_idx').on(table.parse_status)
}));
export const filingLink = sqliteTable('filing_link', {
id: integer('id').primaryKey({ autoIncrement: true }),
filing_id: integer('filing_id').notNull().references(() => filing.id, { onDelete: 'cascade' }),
@@ -250,6 +329,7 @@ export const appSchema = {
watchlistItem,
holding,
filing,
filingStatementSnapshot,
filingLink,
taskRun,
portfolioInsight