fix(meet-kevin): API smoke-test bugs from Task 17 QA

Three issues caught during end-to-end manual QA against docker-compose:

1. SAEnum field columns serialized to Python enum NAMES ('DISCOVERED')
   but the DB enum had VALUES ('discovered'). Added `values_callable`
   to all 5 SAEnum() declarations in shared/models/meet_kevin.py so they
   emit values, matching the migration's enum literals.

2. /dashboard's "last 7 days" / "last 14 days" filters used
   `func.cast("7 days", type_=None)` which produced NullType DDL.
   Replaced with `text("now() - interval '7 days'")`.

3. /dashboard's outlook trend query repeated `func.date_trunc("day", col)`
   in SELECT, GROUP BY and ORDER BY — Postgres treats each as a separate
   parameterized expression. Hoisted into a single `day_trunc` variable
   so all three clauses reference the same SQL fragment.

All 11 /api/meet-kevin/* endpoints now return valid JSON against a
docker-compose Postgres seeded with one analyzed video + NVDA mention.
This commit is contained in:
Viktor Barzin 2026-05-21 20:15:08 +00:00
parent 01856bab9f
commit 7b81980c66
2 changed files with 14 additions and 14 deletions

View file

@ -612,14 +612,15 @@ async def get_dashboard(
}
# Top conviction last 7 days
seven_days_ago = func.now() - func.cast("7 days", type_=None)
from sqlalchemy import text
seven_days_ago = text("now() - interval '7 days'")
top_conviction_result = await session.execute(
select(
KevinStockMention.symbol,
func.max(KevinStockMention.conviction).label("max_conviction"),
func.count().label("mention_count"),
)
.where(KevinStockMention.created_at >= func.now() - func.cast("7 days", type_=None))
.where(KevinStockMention.created_at >= text("now() - interval '7 days'"))
.group_by(KevinStockMention.symbol)
.order_by(desc(func.max(KevinStockMention.conviction)))
.limit(10)
@ -634,18 +635,17 @@ async def get_dashboard(
]
# 14-day outlook trend: date × direction → count
# Use a single trunc expression so SELECT/GROUP BY/ORDER BY reference the same SQL fragment
day_trunc = func.date_trunc("day", KevinAnalysis.created_at)
outlook_result = await session.execute(
select(
func.date_trunc("day", KevinAnalysis.created_at).label("day"),
day_trunc.label("day"),
KevinAnalysis.market_outlook_direction,
func.count().label("count"),
)
.where(KevinAnalysis.created_at >= func.now() - func.cast("14 days", type_=None))
.group_by(
func.date_trunc("day", KevinAnalysis.created_at),
KevinAnalysis.market_outlook_direction,
)
.order_by(func.date_trunc("day", KevinAnalysis.created_at))
.where(KevinAnalysis.created_at >= text("now() - interval '14 days'"))
.group_by(day_trunc, KevinAnalysis.market_outlook_direction)
.order_by(day_trunc)
)
outlook_trend = [
{