|
1 | | -"""Billing routes: usage ledger summaries (tokens per user).""" |
| 1 | +"""Billing routes: usage ledger summaries (tokens per user). |
| 2 | +
|
| 3 | +HTTP wiring only; the aggregation lives in ``controllers.usage``. |
| 4 | +""" |
2 | 5 |
|
3 | 6 | from __future__ import annotations |
4 | 7 |
|
5 | 8 | from fastapi import APIRouter, Depends |
6 | | -from sqlalchemy import func, select |
7 | 9 | from sqlalchemy.orm import Session |
8 | 10 |
|
9 | | -from ..models import Conversation, Run, UsageEvent, User |
| 11 | +from ..controllers import usage |
| 12 | +from ..models import User |
10 | 13 | from ..models.db import get_db |
11 | 14 | from ..routes.auth import authenticate_user |
12 | 15 | from ..validation.schemas import UsageSummary |
|
18 | 21 | def usage_summary( |
19 | 22 | user: User = Depends(authenticate_user), db: Session = Depends(get_db) |
20 | 23 | ) -> UsageSummary: |
21 | | - rows = db.execute( |
22 | | - select( |
23 | | - UsageEvent.conversation_id, |
24 | | - func.sum(UsageEvent.input_tokens), |
25 | | - func.sum(UsageEvent.output_tokens), |
26 | | - func.sum(UsageEvent.rounds), |
27 | | - ) |
28 | | - .where(UsageEvent.user_id == user.id) |
29 | | - .group_by(UsageEvent.conversation_id) |
30 | | - ).all() |
31 | | - by_conversation: dict[str, int] = {} |
32 | | - input_total = output_total = rounds_total = 0 |
33 | | - for conversation_id, inp, out, rounds in rows: |
34 | | - inp_i, out_i, rounds_i = int(inp or 0), int(out or 0), int(rounds or 0) |
35 | | - input_total += inp_i |
36 | | - output_total += out_i |
37 | | - rounds_total += rounds_i |
38 | | - by_conversation[conversation_id] = inp_i + out_i |
39 | | - run_count = ( |
40 | | - db.query(func.count(Run.id)) |
41 | | - .join(Conversation, Run.conversation_id == Conversation.id) |
42 | | - .filter(Conversation.user_id == user.id) |
43 | | - .scalar() |
44 | | - or 0 |
45 | | - ) |
| 24 | + totals = usage.summary(db, user) |
46 | 25 | return UsageSummary( |
47 | | - input_tokens=input_total, |
48 | | - output_tokens=output_total, |
49 | | - rounds=rounds_total, |
50 | | - runs=int(run_count), |
51 | | - by_conversation=by_conversation, |
| 26 | + input_tokens=totals.input_tokens, |
| 27 | + output_tokens=totals.output_tokens, |
| 28 | + rounds=totals.rounds, |
| 29 | + runs=totals.runs, |
| 30 | + by_conversation=totals.by_conversation, |
52 | 31 | ) |
0 commit comments