from datetime import datetime from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.future import select from sqlalchemy.orm import selectinload from sqlalchemy import func, text from app.models import ChoreHistory, FinancialAuditLog, Item, UserGroup, User from app.schemas.activity import Activity, ActivityEventType, ActivityUser async def get_group_activity(db: AsyncSession, group_id: int, limit: int, cursor: int = None) -> list[Activity]: queries = [] chore_history_stmt = ( select(ChoreHistory) .where(ChoreHistory.group_id == group_id) .options(selectinload(ChoreHistory.changed_by_user)) ) if cursor: chore_history_stmt = chore_history_stmt.where(ChoreHistory.timestamp < datetime.fromtimestamp(cursor)) queries.append(chore_history_stmt) # FinancialAuditLog has group_id through joins, which is complex. For now, we assume a direct or easy link. # This might need refinement based on actual relationships. # This is a placeholder as FinancialAuditLog doesn't have a direct group_id. # We will need to join through expenses/settlements, etc. # For now, this part will return empty. items_stmt = ( select(Item) .join(Item.list) .where(text("lists.group_id = :group_id")) .params(group_id=group_id) .options(selectinload(Item.added_by_user), selectinload(Item.completed_by_user)) ) if cursor: items_stmt = items_stmt.where(Item.created_at < datetime.fromtimestamp(cursor)) queries.append(items_stmt) results = [] for q in queries: res = await db.execute(q) results.extend(res.scalars().all()) activities = [] for item in results: if isinstance(item, ChoreHistory): if item.event_type.value == 'completed': user = item.changed_by_user activities.append(Activity( id=f"chore_history-{item.id}", event_type=ActivityEventType.CHORE_COMPLETED, timestamp=item.timestamp, user=ActivityUser(id=user.id, name=user.name), details={"chore_name": item.event_data.get("name", "Unknown chore")}, message=f"{user.name or 'User'} completed '{item.event_data.get('name', 'a chore')}'." )) elif isinstance(item, Item): user = item.added_by_user activities.append(Activity( id=f"item-added-{item.id}", event_type=ActivityEventType.ITEM_ADDED, timestamp=item.created_at, user=ActivityUser(id=user.id, name=user.name), details={"item_name": item.name, "list_id": item.list_id}, message=f"{user.name or 'User'} added '{item.name}' to a list." )) if item.is_complete and item.completed_by_user: c_user = item.completed_by_user activities.append(Activity( id=f"item-completed-{item.id}", event_type=ActivityEventType.ITEM_COMPLETED, timestamp=item.updated_at, # This is an approximation user=ActivityUser(id=c_user.id, name=c_user.name), details={"item_name": item.name, "list_id": item.list_id}, message=f"{c_user.name or 'User'} purchased '{item.name}'." )) activities.sort(key=lambda x: x.timestamp, reverse=True) return activities[:limit]