"""rp_report / rp_input 的数据访问。**只有本模块可以触这两张表**(rp_share 归后续任务)。""" from __future__ import annotations from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from packages.shared.models import RpInput, RpReport STATUS_SUCCEEDED = "succeeded" TIER_BASIC = "basic" async def get_report(session: AsyncSession, report_id: int) -> RpReport | None: return await session.get(RpReport, report_id) async def find_succeeded_basic(session: AsyncSession, *, user_id: int) -> int | None: """首次终身资格:该用户是否已有 succeeded 的 basic 报告(需求 §2.1)。 只取 report_id 不取整行——资格判定不需要报告内容。 """ result = await session.execute( select(RpReport.report_id) .where( RpReport.user_id == user_id, RpReport.tier == TIER_BASIC, RpReport.status == STATUS_SUCCEEDED, ) .limit(1) ) return result.scalar_one_or_none() async def list_reports(session: AsyncSession, *, user_id: int, limit: int = 20) -> list[RpReport]: result = await session.execute( select(RpReport) .where(RpReport.user_id == user_id) .order_by(RpReport.created_at.desc(), RpReport.report_id.desc()) .limit(limit) ) return list(result.scalars().all()) async def get_input(session: AsyncSession, report_id: int) -> RpInput | None: result = await session.execute(select(RpInput).where(RpInput.report_id == report_id)) return result.scalar_one_or_none()