from __future__ import annotations from datetime import datetime, timezone from sqlalchemy import delete, select from sqlalchemy.ext.asyncio import AsyncSession from app.db.models import SurgeryFinalResult, SurgeryResultDetailRow from app.domain.consumption import SurgeryConsumptionStored class SurgeryResultRepository: """持久化 / 读取手术结束后的最终结果(仅客户端返回结构)。""" async def save_final_result( self, session: AsyncSession, *, surgery_id: str, details: list[SurgeryConsumptionStored], completed_at: datetime | None = None, ) -> None: when = completed_at or datetime.now(timezone.utc) await session.execute( delete(SurgeryResultDetailRow).where( SurgeryResultDetailRow.surgery_id == surgery_id ) ) await session.execute( delete(SurgeryFinalResult).where(SurgeryFinalResult.surgery_id == surgery_id) ) row = SurgeryFinalResult(surgery_id=surgery_id, completed_at=when) session.add(row) for d in details: session.add( SurgeryResultDetailRow( surgery_id=surgery_id, item_id=d.item_id, item_name=d.item_name, quantity=d.qty, doctor_id=d.doctor_id, recorded_at=d.timestamp, source=d.source, ) ) await session.flush() async def load_final_details( self, session: AsyncSession, surgery_id: str ) -> list[SurgeryConsumptionStored] | None: """返回领域对象列表(含 source);HTTP 层的转换由 pipeline 负责。""" res = await session.execute( select(SurgeryFinalResult).where(SurgeryFinalResult.surgery_id == surgery_id) ) meta = res.scalar_one_or_none() if meta is None: return None q = await session.execute( select(SurgeryResultDetailRow) .where(SurgeryResultDetailRow.surgery_id == surgery_id) .order_by(SurgeryResultDetailRow.id) ) rows = q.scalars().all() out: list[SurgeryConsumptionStored] = [] for r in rows: pend: str | None = None iid = r.item_id if iid.startswith("pending:"): pend = iid.removeprefix("pending:") out.append( SurgeryConsumptionStored( item_id=r.item_id, item_name=r.item_name, qty=r.quantity, doctor_id=r.doctor_id, timestamp=r.recorded_at, source=r.source, pending_confirmation_id=pend, ) ) return out