Add company analysis view with financials, price history, filings, and AI reports

This commit is contained in:
2026-02-27 09:57:44 -05:00
parent e7320f3bdb
commit 7c3836068f
9 changed files with 512 additions and 2 deletions

View File

@@ -17,6 +17,7 @@ import {
listWatchlistItems,
upsertWatchlistItemRecord
} from '@/lib/server/repos/watchlist';
import { getPriceHistory, getQuote } from '@/lib/server/prices';
import {
enqueueTask,
getTaskById,
@@ -313,6 +314,78 @@ export const app = new Elysia({ prefix: '/api' })
return Response.json({ insight });
})
.get('/analysis/company', async ({ query }) => {
const { session, response } = await requireAuthenticatedSession();
if (response) {
return response;
}
const ticker = typeof query.ticker === 'string' ? query.ticker.trim().toUpperCase() : '';
if (!ticker) {
return jsonError('ticker is required');
}
const [filings, holdings, watchlist, liveQuote, priceHistory] = await Promise.all([
listFilingsRecords({ ticker, limit: 40 }),
listUserHoldings(session.user.id),
listWatchlistItems(session.user.id),
getQuote(ticker),
getPriceHistory(ticker)
]);
const latestFiling = filings[0] ?? null;
const holding = holdings.find((entry) => entry.ticker === ticker) ?? null;
const watchlistItem = watchlist.find((entry) => entry.ticker === ticker) ?? null;
const companyName = latestFiling?.company_name
?? watchlistItem?.company_name
?? ticker;
const financials = filings
.filter((entry) => entry.metrics)
.map((entry) => ({
filingDate: entry.filing_date,
filingType: entry.filing_type,
revenue: entry.metrics?.revenue ?? null,
netIncome: entry.metrics?.netIncome ?? null,
totalAssets: entry.metrics?.totalAssets ?? null,
cash: entry.metrics?.cash ?? null,
debt: entry.metrics?.debt ?? null
}));
const aiReports = filings
.filter((entry) => entry.analysis?.text || entry.analysis?.legacyInsights)
.slice(0, 8)
.map((entry) => ({
accessionNumber: entry.accession_number,
filingDate: entry.filing_date,
filingType: entry.filing_type,
provider: entry.analysis?.provider ?? 'unknown',
model: entry.analysis?.model ?? 'unknown',
summary: entry.analysis?.text ?? entry.analysis?.legacyInsights ?? ''
}));
return Response.json({
analysis: {
company: {
ticker,
companyName,
sector: watchlistItem?.sector ?? null,
cik: latestFiling?.cik ?? null
},
quote: liveQuote,
position: holding,
priceHistory,
financials,
filings: filings.slice(0, 20),
aiReports
}
});
}, {
query: t.Object({
ticker: t.String({ minLength: 1 })
})
})
.get('/filings', async ({ query }) => {
const { response } = await requireAuthenticatedSession();
if (response) {