import json from datetime import datetime from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from app.db.models import Timeline, User from app.schemas.timeline import TimelineCreate, TimelineUpdate async def create_timeline( db: AsyncSession, class_id: int, author_id: int, data: TimelineCreate ) -> Timeline: post = Timeline( class_id=class_id, author_id=author_id, title=data.title, content=data.content, ) db.add(post) await db.commit() await db.refresh(post) return post async def update_timeline( db: AsyncSession, post: Timeline, data: TimelineUpdate ) -> Timeline: for field, value in data.model_dump(exclude_unset=True).items(): setattr(post, field, value) await db.commit() await db.refresh(post) return post async def delete_timeline(db: AsyncSession, post: Timeline): await db.delete(post) await db.commit() async def get_timeline_by_id(db: AsyncSession, post_id: int) -> Timeline | None: result = await db.execute(select(Timeline).where(Timeline.id == post_id)) return result.scalar_one_or_none() async def list_timelines( db: AsyncSession, class_id: int, page: int = 1, page_size: int = 20 ) -> tuple[list[Timeline], int]: total_result = await db.execute( select(func.count(Timeline.id)).where(Timeline.class_id == class_id) ) total = total_result.scalar() or 0 result = await db.execute( select(Timeline) .options(selectinload(Timeline.author)) .where(Timeline.class_id == class_id) .order_by(Timeline.created_at.desc()) .offset((page - 1) * page_size) .limit(page_size) ) posts = list(result.scalars().all()) return posts, total async def add_images_to_timeline(db: AsyncSession, post: Timeline, urls: list[str]): existing = post.get_image_urls_list() existing.extend(urls) post.set_image_urls_list(existing) await db.commit() await db.refresh(post)