
This commit adds new functionality for tracking user activities within the application, including: - Implementation of a new activity service to fetch and manage group activities. - Creation of a dedicated activity store to handle state management for activities. - Introduction of new API endpoints for retrieving paginated activity data. - Enhancements to the UI with new components for displaying activity feeds and items. - Refactoring of existing components to utilize the new activity features, improving user engagement and interaction. These changes aim to enhance the application's activity tracking capabilities and provide users with a comprehensive view of their interactions.
81 lines
3.5 KiB
Python
81 lines
3.5 KiB
Python
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] |