from datetime import datetime from uuid import uuid4 from fastapi import HTTPException, status from sqlalchemy import asc, desc, func, select from app.db.session import AsyncSessionLocal from app.models.scheme import SchemeRecord from app.models.scheme_version import SchemeVersionRecord async def create_initial_scheme_version( *, scheme_id: str, normalized_storage_path: str, normalized_elements_count: int, normalized_seats_count: int, normalized_groups_count: int, normalized_sectors_count: int, display_svg_storage_path: str | None = None, display_svg_status: str = "pending", display_svg_generated_at: datetime | None = None, ) -> str: scheme_version_id = uuid4().hex async with AsyncSessionLocal() as session: row = SchemeVersionRecord( scheme_version_id=scheme_version_id, scheme_id=scheme_id, version_number=1, status="draft", normalized_storage_path=normalized_storage_path, normalized_elements_count=normalized_elements_count, normalized_seats_count=normalized_seats_count, normalized_groups_count=normalized_groups_count, normalized_sectors_count=normalized_sectors_count, display_svg_storage_path=display_svg_storage_path, display_svg_status=display_svg_status, display_svg_generated_at=display_svg_generated_at, ) session.add(row) await session.commit() return scheme_version_id async def list_scheme_versions(scheme_id: str, limit: int = 100, offset: int = 0) -> list[SchemeVersionRecord]: async with AsyncSessionLocal() as session: result = await session.execute( select(SchemeVersionRecord) .where(SchemeVersionRecord.scheme_id == scheme_id) .order_by(asc(SchemeVersionRecord.version_number), desc(SchemeVersionRecord.id)) .limit(limit) .offset(offset) ) return list(result.scalars().all()) async def count_scheme_versions(scheme_id: str) -> int: async with AsyncSessionLocal() as session: result = await session.execute( select(func.count()).select_from(SchemeVersionRecord).where(SchemeVersionRecord.scheme_id == scheme_id) ) return int(result.scalar_one()) async def get_current_scheme_version(scheme_id: str, current_version_number: int) -> SchemeVersionRecord: async with AsyncSessionLocal() as session: result = await session.execute( select(SchemeVersionRecord).where( SchemeVersionRecord.scheme_id == scheme_id, SchemeVersionRecord.version_number == current_version_number, ) ) row = result.scalar_one_or_none() if row is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Current scheme version not found", ) return row async def update_scheme_version_display_artifact( *, scheme_version_id: str, display_svg_storage_path: str, display_svg_status: str, display_svg_generated_at: datetime, ) -> None: async with AsyncSessionLocal() as session: result = await session.execute( select(SchemeVersionRecord).where( SchemeVersionRecord.scheme_version_id == scheme_version_id ) ) row = result.scalar_one_or_none() if row is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Scheme version not found", ) row.display_svg_storage_path = display_svg_storage_path row.display_svg_status = display_svg_status row.display_svg_generated_at = display_svg_generated_at await session.commit() async def create_next_scheme_version_from_current(scheme_id: str) -> SchemeVersionRecord: async with AsyncSessionLocal() as session: scheme_result = await session.execute( select(SchemeRecord).where(SchemeRecord.scheme_id == scheme_id) ) scheme = scheme_result.scalar_one_or_none() if scheme is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Scheme not found", ) current_result = await session.execute( select(SchemeVersionRecord).where( SchemeVersionRecord.scheme_id == scheme.scheme_id, SchemeVersionRecord.version_number == scheme.current_version_number, ) ) current_version = current_result.scalar_one_or_none() if current_version is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Current scheme version not found", ) next_version_number = current_version.version_number + 1 new_version = SchemeVersionRecord( scheme_version_id=uuid4().hex, scheme_id=scheme.scheme_id, version_number=next_version_number, status="draft", normalized_storage_path=current_version.normalized_storage_path, normalized_elements_count=current_version.normalized_elements_count, normalized_seats_count=current_version.normalized_seats_count, normalized_groups_count=current_version.normalized_groups_count, normalized_sectors_count=current_version.normalized_sectors_count, display_svg_storage_path=current_version.display_svg_storage_path, display_svg_status=current_version.display_svg_status, display_svg_generated_at=current_version.display_svg_generated_at, ) session.add(new_version) scheme.current_version_number = next_version_number scheme.status = "draft" scheme.published_at = None scheme.normalized_elements_count = current_version.normalized_elements_count scheme.normalized_seats_count = current_version.normalized_seats_count scheme.normalized_groups_count = current_version.normalized_groups_count scheme.normalized_sectors_count = current_version.normalized_sectors_count await session.commit() await session.refresh(new_version) return new_version