Implement fiscal-style research MVP flows
Some checks failed
PR Checks / typecheck-and-build (push) Has been cancelled
Some checks failed
PR Checks / typecheck-and-build (push) Has been cancelled
This commit is contained in:
@@ -27,6 +27,9 @@ type TaxonomyAssetType =
|
||||
|
||||
type TaxonomyParseStatus = 'ready' | 'partial' | 'failed';
|
||||
type TaxonomyMetricValidationStatus = 'not_run' | 'matched' | 'mismatch' | 'error';
|
||||
type CoverageStatus = 'backlog' | 'active' | 'watch' | 'archive';
|
||||
type CoveragePriority = 'low' | 'medium' | 'high';
|
||||
type ResearchJournalEntryType = 'note' | 'filing_note' | 'status_change';
|
||||
|
||||
type FilingAnalysis = {
|
||||
provider?: string;
|
||||
@@ -269,16 +272,22 @@ export const watchlistItem = sqliteTable('watchlist_item', {
|
||||
sector: text('sector'),
|
||||
category: text('category'),
|
||||
tags: text('tags', { mode: 'json' }).$type<string[]>(),
|
||||
created_at: text('created_at').notNull()
|
||||
status: text('status').$type<CoverageStatus>().notNull().default('backlog'),
|
||||
priority: text('priority').$type<CoveragePriority>().notNull().default('medium'),
|
||||
created_at: text('created_at').notNull(),
|
||||
updated_at: text('updated_at').notNull(),
|
||||
last_reviewed_at: text('last_reviewed_at')
|
||||
}, (table) => ({
|
||||
watchlistUserTickerUnique: uniqueIndex('watchlist_user_ticker_uidx').on(table.user_id, table.ticker),
|
||||
watchlistUserCreatedIndex: index('watchlist_user_created_idx').on(table.user_id, table.created_at)
|
||||
watchlistUserCreatedIndex: index('watchlist_user_created_idx').on(table.user_id, table.created_at),
|
||||
watchlistUserUpdatedIndex: index('watchlist_user_updated_idx').on(table.user_id, table.updated_at)
|
||||
}));
|
||||
|
||||
export const holding = sqliteTable('holding', {
|
||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
||||
user_id: text('user_id').notNull().references(() => user.id, { onDelete: 'cascade' }),
|
||||
ticker: text('ticker').notNull(),
|
||||
company_name: text('company_name'),
|
||||
shares: numeric('shares').notNull(),
|
||||
avg_cost: numeric('avg_cost').notNull(),
|
||||
current_price: numeric('current_price'),
|
||||
@@ -520,6 +529,22 @@ export const portfolioInsight = sqliteTable('portfolio_insight', {
|
||||
insightUserCreatedIndex: index('insight_user_created_idx').on(table.user_id, table.created_at)
|
||||
}));
|
||||
|
||||
export const researchJournalEntry = sqliteTable('research_journal_entry', {
|
||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
||||
user_id: text('user_id').notNull().references(() => user.id, { onDelete: 'cascade' }),
|
||||
ticker: text('ticker').notNull(),
|
||||
accession_number: text('accession_number'),
|
||||
entry_type: text('entry_type').$type<ResearchJournalEntryType>().notNull(),
|
||||
title: text('title'),
|
||||
body_markdown: text('body_markdown').notNull(),
|
||||
metadata: text('metadata', { mode: 'json' }).$type<Record<string, unknown> | null>(),
|
||||
created_at: text('created_at').notNull(),
|
||||
updated_at: text('updated_at').notNull()
|
||||
}, (table) => ({
|
||||
researchJournalTickerIndex: index('research_journal_ticker_idx').on(table.user_id, table.ticker, table.created_at),
|
||||
researchJournalAccessionIndex: index('research_journal_accession_idx').on(table.user_id, table.accession_number)
|
||||
}));
|
||||
|
||||
export const authSchema = {
|
||||
user,
|
||||
session,
|
||||
@@ -543,7 +568,8 @@ export const appSchema = {
|
||||
filingLink,
|
||||
taskRun,
|
||||
taskStageEvent,
|
||||
portfolioInsight
|
||||
portfolioInsight,
|
||||
researchJournalEntry
|
||||
};
|
||||
|
||||
export const schema = {
|
||||
|
||||
Reference in New Issue
Block a user