fix: blank company charts + competitor GUIDs instead of tickers
Trend charts blank: - trend_windows uses upsert (1 row per ticker/window), so charts had at most 1 data point. Added trend_history table (migration 024) that appends every snapshot. New /api/trends/history endpoint serves the time series. Frontend now uses useTrendHistory for charts and useTrends for the latest summary card. Competitor GUIDs: - list_competitors query returned raw company_b_id UUIDs without joining companies table. Added LEFT JOIN with CASE to resolve the other company's ticker and legal_name. Updated Pydantic model to include enriched fields. Frontend fallback changed from truncated UUID to ticker/legal_name/Unknown.
This commit is contained in:
@@ -415,6 +415,56 @@ async def list_trends(
|
||||
return results
|
||||
|
||||
|
||||
@app.get("/api/trends/history")
|
||||
async def list_trend_history(
|
||||
ticker: Optional[str] = None,
|
||||
window: Optional[str] = None,
|
||||
limit: int = Query(default=200, le=1000),
|
||||
):
|
||||
"""Return historical trend snapshots for charting.
|
||||
|
||||
Unlike /api/trends which returns the latest snapshot per entity/window,
|
||||
this endpoint returns the time series from the trend_history table.
|
||||
"""
|
||||
conditions: list[str] = []
|
||||
params: list[Any] = []
|
||||
idx = 1
|
||||
|
||||
if ticker:
|
||||
conditions.append(f"entity_id = ${idx}")
|
||||
params.append(ticker.upper())
|
||||
idx += 1
|
||||
if window:
|
||||
conditions.append(f"\"window\" = ${idx}")
|
||||
params.append(window)
|
||||
idx += 1
|
||||
|
||||
where = ("WHERE " + " AND ".join(conditions)) if conditions else ""
|
||||
|
||||
try:
|
||||
rows = await pool.fetch(
|
||||
f"""SELECT id, entity_type, entity_id, "window", trend_direction,
|
||||
trend_strength, confidence, contradiction_score,
|
||||
dominant_catalysts, material_risks, generated_at
|
||||
FROM trend_history
|
||||
{where}
|
||||
ORDER BY generated_at ASC
|
||||
LIMIT ${idx}""",
|
||||
*params, limit,
|
||||
)
|
||||
except Exception:
|
||||
# Table may not exist yet (pre-migration 024)
|
||||
return []
|
||||
|
||||
results = []
|
||||
for r in rows:
|
||||
d = _row_to_dict(r)
|
||||
d["dominant_catalysts"] = _parse_jsonb(d.get("dominant_catalysts"))
|
||||
d["material_risks"] = _parse_jsonb(d.get("material_risks"))
|
||||
results.append(d)
|
||||
return results
|
||||
|
||||
|
||||
@app.get("/api/trends/{trend_id}")
|
||||
async def get_trend(trend_id: str):
|
||||
"""Get a single trend summary by ID."""
|
||||
|
||||
Reference in New Issue
Block a user