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:
Celes Renata
2026-04-17 00:42:55 +00:00
parent f2d8744a4f
commit 7c589353f8
6 changed files with 169 additions and 16 deletions
+35 -2
View File
@@ -742,11 +742,23 @@ RETURNING id
"""
_INSERT_TREND_HISTORY = """
INSERT INTO trend_history (
entity_type, entity_id, "window", trend_direction,
trend_strength, confidence, contradiction_score,
dominant_catalysts, material_risks, generated_at
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9::jsonb, $10)
"""
async def persist_trend_summary(
pool: asyncpg.Pool,
summary: TrendSummary,
) -> str:
"""Insert a trend summary row and return its UUID."""
"""Insert a trend summary row and return its UUID.
Also appends a snapshot to trend_history for time-series charting.
"""
row = await pool.fetchrow(
_UPSERT_TREND,
summary.entity_type,
@@ -764,7 +776,28 @@ async def persist_trend_summary(
json.dumps(summary.market_context.model_dump() if summary.market_context else {}, default=str),
summary.generated_at,
)
return str(row["id"])
trend_id = str(row["id"])
# Append to trend_history for time-series charts
try:
await pool.execute(
_INSERT_TREND_HISTORY,
summary.entity_type,
summary.entity_id,
summary.window.value,
summary.trend_direction.value,
summary.trend_strength,
summary.confidence,
summary.contradiction_score,
json.dumps(summary.dominant_catalysts),
json.dumps(summary.material_risks),
summary.generated_at,
)
except Exception:
# Don't fail the main upsert if history insert fails (table may not exist yet)
logger.debug("Could not insert trend history for %s/%s", summary.entity_id, summary.window.value, exc_info=True)
return trend_id
# ---------------------------------------------------------------------------