from fastapi import HTTPException from sqlalchemy import select from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import joinedload from models.library import LibraryFile, Subject, Module from schemas.library import LibraryFileRequest, LibraryFileResponse async def list_files(db: AsyncSession) -> list[LibraryFileResponse]: stmt = ( select(LibraryFile) .options( joinedload(LibraryFile.subject), joinedload(LibraryFile.module), ) .order_by(LibraryFile.create_time.desc()) ) files = (await db.execute(stmt)).scalars().unique().all() return [ LibraryFileResponse( id=file.id, subject=file.subject.name, module=file.module.name, name=file.name, type=file.type, size=file.size, content=file.content, uploadTime=file.create_time.strftime("%Y-%m-%d %H:%M:%S"), ) for file in files ] async def add_file(db: AsyncSession, data: LibraryFileRequest) -> bool: try: subject_id = await get_or_create_subject(db, data.subject) module_id = await get_or_create_module(db, subject_id, data.module) file = LibraryFile( subject_id=subject_id, module_id=module_id, name=data.name, size=data.size, type=data.type, content=data.content, ) db.add(file) await db.commit() return True except SQLAlchemyError: await db.rollback() raise async def edit_file(db: AsyncSession, file_id: int, data: LibraryFileRequest) -> bool: try: result = await db.execute( select(LibraryFile).where(LibraryFile.id == file_id) ) file = result.scalar_one_or_none() if not file: return False subject_id = await get_or_create_subject(db, data.subject) module_id = await get_or_create_module(db, subject_id, data.module) file.subject_id = subject_id file.module_id = module_id file.name = data.name file.size = data.size file.type = data.type file.content = data.content await db.commit() return True except SQLAlchemyError: await db.rollback() raise async def get_file(db: AsyncSession, file_id: int) -> LibraryFileResponse: stmt = ( select(LibraryFile) .options( joinedload(LibraryFile.subject), joinedload(LibraryFile.module), ) .where(LibraryFile.id == file_id) ) file = (await db.execute(stmt)).scalar_one_or_none() if not file: raise HTTPException(status_code=404, detail="File not found") return LibraryFileResponse( id=file.id, subject=file.subject.name, module=file.module.name, name=file.name, type=file.type, size=file.size, content=file.content, uploadTime=file.create_time.strftime("%Y-%m-%d %H:%M:%S"), ) async def get_or_create_subject(db: AsyncSession, name: str) -> int: stmt = select(Subject).where(Subject.name == name) result = await db.execute(stmt) subject = result.scalar_one_or_none() if subject: return subject.id subject = Subject(name=name) db.add(subject) await db.flush() return subject.id async def get_or_create_module(db: AsyncSession, subject_id: int, name: str) -> int: stmt = select(Module).where( Module.subject_id == subject_id, Module.name == name, ) module = (await db.execute(stmt)).scalar_one_or_none() if module: return module.id module = Module(subject_id=subject_id, name=name) db.add(module) await db.flush() return module.id