Files
video-gen/video-gen-api/app/services/llm_billing/query_service.py
T
2026-08-11 09:24:18 +08:00

55 lines
2.0 KiB
Python

from __future__ import annotations
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.llm_billing.call_attempt import LlmCallAttempt
from app.models.llm_billing.execution import LlmBillingExecution
async def list_executions_with_calls(
db: AsyncSession,
*,
page: int = 1,
page_size: int = 20,
scene_code: str | None = None,
status: str | None = None,
user_id: str | None = None,
) -> tuple[list[dict], int]:
filters = []
if scene_code:
filters.append(LlmBillingExecution.scene_code == scene_code)
if status:
filters.append(LlmBillingExecution.status == status)
if user_id:
filters.append(LlmBillingExecution.user_id == user_id)
total_result = await db.execute(select(func.count(LlmBillingExecution.id)).where(*filters))
total = int(total_result.scalar_one() or 0)
result = await db.execute(
select(LlmBillingExecution)
.where(*filters)
.order_by(LlmBillingExecution.created_at.desc(), LlmBillingExecution.id.desc())
.offset((page - 1) * page_size)
.limit(page_size)
)
executions = list(result.scalars().all())
ids = [item.id for item in executions]
calls_by_execution: dict[str, list[LlmCallAttempt]] = {item_id: [] for item_id in ids}
if ids:
call_result = await db.execute(
select(LlmCallAttempt)
.where(LlmCallAttempt.billing_execution_id.in_(ids))
.order_by(LlmCallAttempt.billing_execution_id, LlmCallAttempt.call_sequence)
)
for call in call_result.scalars().all():
calls_by_execution.setdefault(call.billing_execution_id, []).append(call)
items = []
for execution in executions:
data = {
column.name: getattr(execution, column.name)
for column in LlmBillingExecution.__table__.columns
}
data["calls"] = calls_by_execution.get(execution.id, [])
items.append(data)
return items, total