Rebuild company overview analysis page

This commit is contained in:
2026-03-12 20:39:30 -04:00
parent b9a1d8ba40
commit ba385586bc
29 changed files with 2040 additions and 888 deletions

View File

@@ -70,6 +70,10 @@ import {
upsertWatchlistItemRecord
} from '@/lib/server/repos/watchlist';
import { getPriceHistory, getQuote } from '@/lib/server/prices';
import { synthesizeCompanyOverview } from '@/lib/server/company-overview-synthesis';
import { getRecentDevelopments } from '@/lib/server/recent-developments';
import { deriveValuationSnapshot, getSecCompanyProfile, toCompanyProfile } from '@/lib/server/sec-company-profile';
import { getCompanyDescription } from '@/lib/server/sec-description';
import { answerSearchQuery, searchKnowledgeBase } from '@/lib/server/search';
import {
enqueueTask,
@@ -1362,13 +1366,15 @@ export const app = new Elysia({ prefix: '/api' })
return jsonError('ticker is required');
}
const [filings, holding, watchlistItem, liveQuote, priceHistory, journalPreview] = await Promise.all([
const [filings, holding, watchlistItem, liveQuote, priceHistory, journalPreview, memo, secProfile] = await Promise.all([
listFilingsRecords({ ticker, limit: 40 }),
getHoldingByTicker(session.user.id, ticker),
getWatchlistItemByTicker(session.user.id, ticker),
getQuote(ticker),
getPriceHistory(ticker),
listResearchJournalEntries(session.user.id, ticker, 6)
listResearchJournalEntries(session.user.id, ticker, 6),
getResearchMemoByTicker(session.user.id, ticker),
getSecCompanyProfile(ticker)
]);
const redactedFilings = filings
.map(redactInternalFilingAnalysisFields)
@@ -1376,6 +1382,7 @@ export const app = new Elysia({ prefix: '/api' })
const latestFiling = redactedFilings[0] ?? null;
const companyName = latestFiling?.company_name
?? secProfile?.companyName
?? holding?.company_name
?? watchlistItem?.company_name
?? ticker;
@@ -1416,6 +1423,11 @@ export const app = new Elysia({ prefix: '/api' })
? (referenceMetrics.netIncome / referenceMetrics.revenue) * 100
: null
};
const annualFiling = redactedFilings.find((entry) => entry.filing_type === '10-K') ?? null;
const [description, synthesizedDevelopments] = await Promise.all([
getCompanyDescription(annualFiling),
getRecentDevelopments(ticker, { filings: redactedFilings })
]);
const latestFilingSummary = latestFiling
? {
accessionNumber: latestFiling.accession_number,
@@ -1427,6 +1439,31 @@ export const app = new Elysia({ prefix: '/api' })
hasAnalysis: Boolean(latestFiling.analysis?.text || latestFiling.analysis?.legacyInsights)
}
: null;
const companyProfile = toCompanyProfile(secProfile, description);
const valuationSnapshot = deriveValuationSnapshot({
quote: liveQuote,
sharesOutstanding: secProfile?.sharesOutstanding ?? null,
revenue: keyMetrics.revenue,
cash: keyMetrics.cash,
debt: keyMetrics.debt,
netIncome: keyMetrics.netIncome
});
const synthesis = await synthesizeCompanyOverview({
ticker,
companyName,
description,
memo,
latestFilingSummary,
recentAiReports: aiReports.slice(0, 5),
recentDevelopments: synthesizedDevelopments.items
});
const recentDevelopments = {
...synthesizedDevelopments,
weeklySnapshot: synthesis.weeklySnapshot,
status: synthesizedDevelopments.items.length > 0
? synthesis.weeklySnapshot ? 'ready' : 'partial'
: synthesis.weeklySnapshot ? 'partial' : 'unavailable'
} as const;
return Response.json({
analysis: {
@@ -1453,7 +1490,11 @@ export const app = new Elysia({ prefix: '/api' })
journalPreview,
recentAiReports: aiReports.slice(0, 5),
latestFilingSummary,
keyMetrics
keyMetrics,
companyProfile,
valuationSnapshot,
bullBear: synthesis.bullBear,
recentDevelopments
}
});
}, {