199 lines
6.4 KiB
Python
199 lines
6.4 KiB
Python
from uuid import uuid4
|
|
|
|
from fastapi import HTTPException, status
|
|
from sqlalchemy import 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_scheme_from_upload(
|
|
*,
|
|
source_upload_id: str,
|
|
name: str,
|
|
normalized_elements_count: int,
|
|
normalized_seats_count: int,
|
|
normalized_groups_count: int,
|
|
normalized_sectors_count: int,
|
|
) -> str:
|
|
scheme_id = uuid4().hex
|
|
|
|
async with AsyncSessionLocal() as session:
|
|
row = SchemeRecord(
|
|
scheme_id=scheme_id,
|
|
source_upload_id=source_upload_id,
|
|
name=name,
|
|
status="draft",
|
|
current_version_number=1,
|
|
normalized_elements_count=normalized_elements_count,
|
|
normalized_seats_count=normalized_seats_count,
|
|
normalized_groups_count=normalized_groups_count,
|
|
normalized_sectors_count=normalized_sectors_count,
|
|
)
|
|
session.add(row)
|
|
await session.commit()
|
|
|
|
return scheme_id
|
|
|
|
|
|
async def list_scheme_records(limit: int = 50, offset: int = 0) -> list[SchemeRecord]:
|
|
async with AsyncSessionLocal() as session:
|
|
result = await session.execute(
|
|
select(SchemeRecord)
|
|
.order_by(desc(SchemeRecord.created_at), desc(SchemeRecord.id))
|
|
.limit(limit)
|
|
.offset(offset)
|
|
)
|
|
return list(result.scalars().all())
|
|
|
|
|
|
async def count_scheme_records() -> int:
|
|
async with AsyncSessionLocal() as session:
|
|
result = await session.execute(select(func.count()).select_from(SchemeRecord))
|
|
return int(result.scalar_one())
|
|
|
|
|
|
async def get_scheme_record_by_scheme_id(scheme_id: str) -> SchemeRecord:
|
|
async with AsyncSessionLocal() as session:
|
|
result = await session.execute(
|
|
select(SchemeRecord).where(SchemeRecord.scheme_id == scheme_id)
|
|
)
|
|
row = result.scalar_one_or_none()
|
|
|
|
if row is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Scheme not found",
|
|
)
|
|
|
|
return row
|
|
|
|
|
|
async def publish_scheme(scheme_id: str) -> SchemeRecord:
|
|
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",
|
|
)
|
|
|
|
version_result = await session.execute(
|
|
select(SchemeVersionRecord).where(
|
|
SchemeVersionRecord.scheme_id == scheme.scheme_id,
|
|
SchemeVersionRecord.version_number == scheme.current_version_number,
|
|
)
|
|
)
|
|
version = version_result.scalar_one_or_none()
|
|
|
|
if version is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Current scheme version not found",
|
|
)
|
|
|
|
scheme.status = "published"
|
|
scheme.published_at = func.now()
|
|
version.status = "published"
|
|
|
|
await session.commit()
|
|
await session.refresh(scheme)
|
|
|
|
return scheme
|
|
|
|
|
|
async def unpublish_scheme(scheme_id: str) -> SchemeRecord:
|
|
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",
|
|
)
|
|
|
|
version_result = await session.execute(
|
|
select(SchemeVersionRecord).where(
|
|
SchemeVersionRecord.scheme_id == scheme.scheme_id,
|
|
SchemeVersionRecord.version_number == scheme.current_version_number,
|
|
)
|
|
)
|
|
version = version_result.scalar_one_or_none()
|
|
|
|
if version is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Current scheme version not found",
|
|
)
|
|
|
|
scheme.status = "draft"
|
|
scheme.published_at = None
|
|
version.status = "draft"
|
|
|
|
await session.commit()
|
|
await session.refresh(scheme)
|
|
|
|
return scheme
|
|
|
|
|
|
async def rollback_scheme_to_version(scheme_id: str, target_version_number: int) -> SchemeRecord:
|
|
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",
|
|
)
|
|
|
|
target_result = await session.execute(
|
|
select(SchemeVersionRecord).where(
|
|
SchemeVersionRecord.scheme_id == scheme.scheme_id,
|
|
SchemeVersionRecord.version_number == target_version_number,
|
|
)
|
|
)
|
|
target_version = target_result.scalar_one_or_none()
|
|
|
|
if target_version is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Target scheme version 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 not None:
|
|
current_version.status = "draft"
|
|
|
|
target_version.status = "draft"
|
|
scheme.current_version_number = target_version.version_number
|
|
scheme.status = "draft"
|
|
scheme.published_at = None
|
|
|
|
scheme.normalized_elements_count = target_version.normalized_elements_count
|
|
scheme.normalized_seats_count = target_version.normalized_seats_count
|
|
scheme.normalized_groups_count = target_version.normalized_groups_count
|
|
scheme.normalized_sectors_count = target_version.normalized_sectors_count
|
|
|
|
await session.commit()
|
|
await session.refresh(scheme)
|
|
|
|
return scheme
|